mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.simd] all: merge master (4c4cefc) into dev.simd
Merge List: + 2025-09-034c4cefc19acmd/gofmt: simplify logic to process arguments + 2025-09-03925a3cdcd1unicode/utf8: make DecodeRune{,InString} inlineable + 2025-09-033e596d448fmath: rename Modf parameter int to integer + 2025-09-022a7f1d47b0runtime: use one more address bit for tagged pointers + 2025-09-02b09068041acmd/dist: run racebench tests only in longtest mode + 2025-09-02355370ac52runtime: add comment for concatstring2 + 2025-09-021eec830f54go/doc: linkify interface methods + 2025-08-317bba745820cmd/compile: use generated loops instead of DUFFZERO on loong64 + 2025-08-31882335e2cbcmd/internal/obj/loong64: add LDPTR.{W/D} and STPTR.{W/D} instructions support + 2025-08-31d4b17f5869internal/runtime/atomic: reset wrong jump target in Cas{,64} on loong64 + 2025-08-316a08e80399net/http: skip redirecting in ServeMux when URL path for CONNECT is empty + 2025-08-298bcda6c79druntime/race: add race detector support for linux/riscv64 + 2025-08-298377adafc5cmd/cgo: split loadDWARF into two parts + 2025-08-29a7d9d5a80acmd/cgo: move typedefs and typedefList out of Package + 2025-08-291d459c4357all: delete more windows/arm remnants + 2025-08-2927ce6e4e26cmd/compile: remove sign extension before MULW on riscv64 + 2025-08-2984b070bfb1cmd/compile/internal/ssa: make oneBit function generic + 2025-08-29fe42628daeinternal/cpu: inline DebugOptions + 2025-08-2994b7d519bdnet: update document on limitation of iprawsock on Windows + 2025-08-29ba9e1ddccftesting: allow specify temp dir by GOTMPDIR environment variable + 2025-08-299f6936b8dacmd/link: disallow linkname of runtime.addmoduledata + 2025-08-2989d41d254abytes, strings: speed up TrimSpace + 2025-08-2938204e0872testing/synctest: call out common issues with tests + 2025-08-29252c901125os,syscall: pass file flags to CreateFile on Windows + 2025-08-2953515fb0a9crypto/tls: use hash.Cloner + 2025-08-2813bb48e6fbgo/constant: fix complex != unknown comparison + 2025-08-28ba1109feb5net: remove redundant cgoLookupCNAME return parameter + 2025-08-28f74ed44ed9net/http/httputil: remove redundant pw.Close() call in DumpRequestOut + 2025-08-28a9689d2e0btime: skip TestLongAdjustTimers in short mode on single CPU systems + 2025-08-28ebc763f76dsyscall: only get parent PID if SysProcAttr.Pdeathsig is set + 2025-08-287f1864b0a8strings: remove redundant "runs" from string.Fields docstring + 2025-08-2890c21fa5b6net/textproto: eliminate some bounds checks + 2025-08-27e47d88beaeos: return nil slice when ReadDir is used with a file on file_windows + 2025-08-276b837a64dbcmd/internal/obj/loong64: simplify buildop + 2025-08-27765905e3bddebug/elf: don't panic if symtab too small + 2025-08-272ee4b31242net/http: Ensure that CONNECT proxied requests respect MaxResponseHeaderBytes + 2025-08-27b21867b1a2net/http: require exact match for CrossSiteProtection bypass patterns + 2025-08-27d19e377f6ecmd/cgo: make it safe to run gcc in parallel + 2025-08-2749a2f3ed87net: allow zero value destination address in WriteMsgUDPAddrPort + 2025-08-26afc51ed007internall/poll: remove bufs field from Windows' poll.operation + 2025-08-26801b74eb95internal/poll: remove rsa field from Windows' poll.operation + 2025-08-26fa18c547cdsyscall: sort Windows env block in StartProcess + 2025-08-26bfd130db02internal/poll: don't use stack-allocated WSAMsg parameters + 2025-08-26dae9e456aeruntime: identify virtual memory layout for riscv64 + 2025-08-2525c2d4109fmath: use Trunc to implement Modf + 2025-08-254e05a070c4math: implement IsInf using Abs + 2025-08-251eed4f32a0math: optimize Signbit implementation slightly + 2025-08-25bd71b94659cmd/compile/internal: optimizing add+sll rule using ALSLV instruction on loong64 + 2025-08-25ea55ca3600runtime: skip doInit of plugins in runtime.main + 2025-08-259ae2f1fb57internal/trace: skip async preempt off tests on low end systems + 2025-08-25bbd5342a62net: fix cgoResSearch + 2025-08-25ed7f804775os: set full name for Roots created with Root.OpenRoot + 2025-08-25a21249436binternal/poll: use fdMutex to provide read/write locking on Windows + 2025-08-2444c5956bf7test/codegen: add Mul2 and DivPow2 test for loong64 + 2025-08-240aa8019e94test/codegen: add Mul* test for loong64 + 2025-08-2483420974b7test/codegen: add sqrt* abs and copysign test for loong64 + 2025-08-23f2db0dca0bnet/http/httptest: redirect example.com requests to server + 2025-08-22d86ec92499internal/syscall/windows: increase internal Windows O_ flags values + 2025-08-229d3f7fda70crypto/tls: fix quic comment typo + 2025-08-2278a05c541finternal/poll: don't pass non-nil WSAMsg.Name with 0 namelen on windows + 2025-08-2252c3f73fdaruntime/metrics: improve doc + 2025-08-22a076f49757os: fix Root.MkdirAll to handle race of directory creation + 2025-08-2298238fd495all: delete remaining windows/arm code + 2025-08-211ad30844d9cmd/asm: process forward jump to PCALIGN + 2025-08-2113c082601dinternal/poll: permit nil destination address in WriteMsg{Inet4,Inet6} + 2025-08-219b0a507735runtime: remove remaining windows/arm files and comments + 2025-08-211843f1e9c0cmd/compile: use zero register instead of specialized *zero instructions on loong64 + 2025-08-21e0870a0a12cmd/compile: simplify zerorange on loong64 + 2025-08-21fb8bbe46d5cmd/compile/internal/ssa: eliminate unnecessary extension operations + 2025-08-219632ba8160cmd/compile: optimize some patterns into revb2h/revb4h instruction on loong64 + 2025-08-218dcab6f450syscall: simplify execve handling on libc platforms + 2025-08-21ba840c1bf9cmd/compile: deduplication in the source code generated by mknode + 2025-08-21fa706ea50fcmd/compile: optimize rule (x + x) << c to x << c+1 on loong64 + 2025-08-21ffc85ee1f1cmd/internal/objabi,cmd/link: add support for additional riscv64 relocations Change-Id: I3896f74b1a3cc0a52b29ca48767bb0ba84620f71
This commit is contained in:
commit
7c8b9115bc
155 changed files with 3151 additions and 2796 deletions
2
doc/next/6-stdlib/99-minor/net/http/httptest/31054.md
Normal file
2
doc/next/6-stdlib/99-minor/net/http/httptest/31054.md
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
The HTTP client returned by [Server.Client] will now redirect requests for
|
||||||
|
`example.com` and any subdomains to the server being tested.
|
||||||
4
doc/next/6-stdlib/99-minor/os/73676.md
Normal file
4
doc/next/6-stdlib/99-minor/os/73676.md
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
On Windows, the [OpenFile] `flag` parameter can now contain any combination of
|
||||||
|
Windows-specific file flags, such as `FILE_FLAG_OVERLAPPED` and
|
||||||
|
`FILE_FLAG_SEQUENTIAL_SCAN`, for control of file or device caching behavior,
|
||||||
|
access modes, and other special-purpose flags.
|
||||||
|
|
@ -311,10 +311,7 @@ func (b *Reader) ReadRune() (r rune, size int, err error) {
|
||||||
if b.r == b.w {
|
if b.r == b.w {
|
||||||
return 0, 0, b.readErr()
|
return 0, 0, b.readErr()
|
||||||
}
|
}
|
||||||
r, size = rune(b.buf[b.r]), 1
|
r, size = utf8.DecodeRune(b.buf[b.r:b.w])
|
||||||
if r >= utf8.RuneSelf {
|
|
||||||
r, size = utf8.DecodeRune(b.buf[b.r:b.w])
|
|
||||||
}
|
|
||||||
b.r += size
|
b.r += size
|
||||||
b.lastByte = int(b.buf[b.r-1])
|
b.lastByte = int(b.buf[b.r-1])
|
||||||
b.lastRuneSize = size
|
b.lastRuneSize = size
|
||||||
|
|
|
||||||
|
|
@ -528,11 +528,7 @@ func FieldsFunc(s []byte, f func(rune) bool) [][]byte {
|
||||||
// more efficient, possibly due to cache effects.
|
// more efficient, possibly due to cache effects.
|
||||||
start := -1 // valid span start if >= 0
|
start := -1 // valid span start if >= 0
|
||||||
for i := 0; i < len(s); {
|
for i := 0; i < len(s); {
|
||||||
size := 1
|
r, size := utf8.DecodeRune(s[i:])
|
||||||
r := rune(s[i])
|
|
||||||
if r >= utf8.RuneSelf {
|
|
||||||
r, size = utf8.DecodeRune(s[i:])
|
|
||||||
}
|
|
||||||
if f(r) {
|
if f(r) {
|
||||||
if start >= 0 {
|
if start >= 0 {
|
||||||
spans = append(spans, span{start, i})
|
spans = append(spans, span{start, i})
|
||||||
|
|
@ -614,11 +610,7 @@ func Map(mapping func(r rune) rune, s []byte) []byte {
|
||||||
// fine. It could also shrink but that falls out naturally.
|
// fine. It could also shrink but that falls out naturally.
|
||||||
b := make([]byte, 0, len(s))
|
b := make([]byte, 0, len(s))
|
||||||
for i := 0; i < len(s); {
|
for i := 0; i < len(s); {
|
||||||
wid := 1
|
r, wid := utf8.DecodeRune(s[i:])
|
||||||
r := rune(s[i])
|
|
||||||
if r >= utf8.RuneSelf {
|
|
||||||
r, wid = utf8.DecodeRune(s[i:])
|
|
||||||
}
|
|
||||||
r = mapping(r)
|
r = mapping(r)
|
||||||
if r >= 0 {
|
if r >= 0 {
|
||||||
b = utf8.AppendRune(b, r)
|
b = utf8.AppendRune(b, r)
|
||||||
|
|
@ -917,11 +909,7 @@ func LastIndexFunc(s []byte, f func(r rune) bool) int {
|
||||||
func indexFunc(s []byte, f func(r rune) bool, truth bool) int {
|
func indexFunc(s []byte, f func(r rune) bool, truth bool) int {
|
||||||
start := 0
|
start := 0
|
||||||
for start < len(s) {
|
for start < len(s) {
|
||||||
wid := 1
|
r, wid := utf8.DecodeRune(s[start:])
|
||||||
r := rune(s[start])
|
|
||||||
if r >= utf8.RuneSelf {
|
|
||||||
r, wid = utf8.DecodeRune(s[start:])
|
|
||||||
}
|
|
||||||
if f(r) == truth {
|
if f(r) == truth {
|
||||||
return start
|
return start
|
||||||
}
|
}
|
||||||
|
|
@ -1052,10 +1040,7 @@ func trimLeftASCII(s []byte, as *asciiSet) []byte {
|
||||||
|
|
||||||
func trimLeftUnicode(s []byte, cutset string) []byte {
|
func trimLeftUnicode(s []byte, cutset string) []byte {
|
||||||
for len(s) > 0 {
|
for len(s) > 0 {
|
||||||
r, n := rune(s[0]), 1
|
r, n := utf8.DecodeRune(s)
|
||||||
if r >= utf8.RuneSelf {
|
|
||||||
r, n = utf8.DecodeRune(s)
|
|
||||||
}
|
|
||||||
if !containsRune(cutset, r) {
|
if !containsRune(cutset, r) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -1117,41 +1102,34 @@ func trimRightUnicode(s []byte, cutset string) []byte {
|
||||||
// TrimSpace returns a subslice of s by slicing off all leading and
|
// TrimSpace returns a subslice of s by slicing off all leading and
|
||||||
// trailing white space, as defined by Unicode.
|
// trailing white space, as defined by Unicode.
|
||||||
func TrimSpace(s []byte) []byte {
|
func TrimSpace(s []byte) []byte {
|
||||||
// Fast path for ASCII: look for the first ASCII non-space byte
|
// Fast path for ASCII: look for the first ASCII non-space byte.
|
||||||
start := 0
|
for lo, c := range s {
|
||||||
for ; start < len(s); start++ {
|
|
||||||
c := s[start]
|
|
||||||
if c >= utf8.RuneSelf {
|
if c >= utf8.RuneSelf {
|
||||||
// If we run into a non-ASCII byte, fall back to the
|
// If we run into a non-ASCII byte, fall back to the
|
||||||
// slower unicode-aware method on the remaining bytes
|
// slower unicode-aware method on the remaining bytes.
|
||||||
return TrimFunc(s[start:], unicode.IsSpace)
|
return TrimFunc(s[lo:], unicode.IsSpace)
|
||||||
}
|
}
|
||||||
if asciiSpace[c] == 0 {
|
if asciiSpace[c] != 0 {
|
||||||
break
|
continue
|
||||||
|
}
|
||||||
|
s = s[lo:]
|
||||||
|
// Now look for the first ASCII non-space byte from the end.
|
||||||
|
for hi := len(s) - 1; hi >= 0; hi-- {
|
||||||
|
c := s[hi]
|
||||||
|
if c >= utf8.RuneSelf {
|
||||||
|
return TrimFunc(s[:hi+1], unicode.IsSpace)
|
||||||
|
}
|
||||||
|
if asciiSpace[c] == 0 {
|
||||||
|
// At this point, s[:hi+1] starts and ends with ASCII
|
||||||
|
// non-space bytes, so we're done. Non-ASCII cases have
|
||||||
|
// already been handled above.
|
||||||
|
return s[:hi+1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Special case to preserve previous TrimLeftFunc behavior,
|
||||||
// Now look for the first ASCII non-space byte from the end
|
// returning nil instead of empty slice if all spaces.
|
||||||
stop := len(s)
|
return nil
|
||||||
for ; stop > start; stop-- {
|
|
||||||
c := s[stop-1]
|
|
||||||
if c >= utf8.RuneSelf {
|
|
||||||
return TrimFunc(s[start:stop], unicode.IsSpace)
|
|
||||||
}
|
|
||||||
if asciiSpace[c] == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point s[start:stop] starts and ends with an ASCII
|
|
||||||
// non-space bytes, so we're done. Non-ASCII cases have already
|
|
||||||
// been handled above.
|
|
||||||
if start == stop {
|
|
||||||
// Special case to preserve previous TrimLeftFunc behavior,
|
|
||||||
// returning nil instead of empty slice if all spaces.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return s[start:stop]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Runes interprets s as a sequence of UTF-8-encoded code points.
|
// Runes interprets s as a sequence of UTF-8-encoded code points.
|
||||||
|
|
@ -1258,19 +1236,10 @@ hasUnicode:
|
||||||
t = t[i:]
|
t = t[i:]
|
||||||
for len(s) != 0 && len(t) != 0 {
|
for len(s) != 0 && len(t) != 0 {
|
||||||
// Extract first rune from each.
|
// Extract first rune from each.
|
||||||
var sr, tr rune
|
sr, size := utf8.DecodeRune(s)
|
||||||
if s[0] < utf8.RuneSelf {
|
s = s[size:]
|
||||||
sr, s = rune(s[0]), s[1:]
|
tr, size := utf8.DecodeRune(t)
|
||||||
} else {
|
t = t[size:]
|
||||||
r, size := utf8.DecodeRune(s)
|
|
||||||
sr, s = r, s[size:]
|
|
||||||
}
|
|
||||||
if t[0] < utf8.RuneSelf {
|
|
||||||
tr, t = rune(t[0]), t[1:]
|
|
||||||
} else {
|
|
||||||
r, size := utf8.DecodeRune(t)
|
|
||||||
tr, t = r, t[size:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// If they match, keep going; if not, return false.
|
// If they match, keep going; if not, return false.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -117,11 +117,7 @@ func FieldsFuncSeq(s []byte, f func(rune) bool) iter.Seq[[]byte] {
|
||||||
return func(yield func([]byte) bool) {
|
return func(yield func([]byte) bool) {
|
||||||
start := -1
|
start := -1
|
||||||
for i := 0; i < len(s); {
|
for i := 0; i < len(s); {
|
||||||
size := 1
|
r, size := utf8.DecodeRune(s[i:])
|
||||||
r := rune(s[i])
|
|
||||||
if r >= utf8.RuneSelf {
|
|
||||||
r, size = utf8.DecodeRune(s[i:])
|
|
||||||
}
|
|
||||||
if f(r) {
|
if f(r) {
|
||||||
if start >= 0 {
|
if start >= 0 {
|
||||||
if !yield(s[start:i:i]) {
|
if !yield(s[start:i:i]) {
|
||||||
|
|
|
||||||
22
src/cmd/asm/internal/asm/testdata/loong64enc1.s
vendored
22
src/cmd/asm/internal/asm/testdata/loong64enc1.s
vendored
|
|
@ -260,6 +260,28 @@ lable2:
|
||||||
MOVV FCC0, R4 // 04dc1401
|
MOVV FCC0, R4 // 04dc1401
|
||||||
MOVV R4, FCC0 // 80d81401
|
MOVV R4, FCC0 // 80d81401
|
||||||
|
|
||||||
|
// LDPTR.{W/D} and STPTR.{W/D} instructions
|
||||||
|
MOVWP R5, -32768(R4) // 85008025
|
||||||
|
MOVWP R5, 32764(R4) // 85fc7f25
|
||||||
|
MOVWP R5, 32(R4) // 85200025
|
||||||
|
MOVWP R5, 4(R4) // 85040025
|
||||||
|
MOVWP R5, (R4) // 85000025
|
||||||
|
MOVVP R5, -32768(R4) // 85008027
|
||||||
|
MOVVP R5, 32764(R4) // 85fc7f27
|
||||||
|
MOVVP R5, 32(R4) // 85200027
|
||||||
|
MOVVP R5, 4(R4) // 85040027
|
||||||
|
MOVVP R5, (R4) // 85000027
|
||||||
|
MOVWP -32768(R5), R4 // a4008024
|
||||||
|
MOVWP 32764(R5), R4 // a4fc7f24
|
||||||
|
MOVWP 32(R5), R4 // a4200024
|
||||||
|
MOVWP 4(R5), R4 // a4040024
|
||||||
|
MOVWP (R5), R4 // a4000024
|
||||||
|
MOVVP -32768(R5), R4 // a4008026
|
||||||
|
MOVVP 32764(R5), R4 // a4fc7f26
|
||||||
|
MOVVP 32(R5), R4 // a4200026
|
||||||
|
MOVVP 4(R5), R4 // a4040026
|
||||||
|
MOVVP (R5), R4 // a4000026
|
||||||
|
|
||||||
// Loong64 atomic memory access instructions
|
// Loong64 atomic memory access instructions
|
||||||
AMSWAPB R14, (R13), R12 // ac395c38
|
AMSWAPB R14, (R13), R12 // ac395c38
|
||||||
AMSWAPH R14, (R13), R12 // acb95c38
|
AMSWAPH R14, (R13), R12 // acb95c38
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import (
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
"unicode"
|
"unicode"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
|
|
@ -194,13 +195,12 @@ func (p *Package) Translate(f *File) {
|
||||||
var conv typeConv
|
var conv typeConv
|
||||||
conv.Init(p.PtrSize, p.IntSize)
|
conv.Init(p.PtrSize, p.IntSize)
|
||||||
|
|
||||||
p.typedefs = map[string]bool{}
|
ft := fileTypedefs{typedefs: make(map[string]bool)}
|
||||||
p.typedefList = nil
|
|
||||||
numTypedefs := -1
|
numTypedefs := -1
|
||||||
for len(p.typedefs) > numTypedefs {
|
for len(ft.typedefs) > numTypedefs {
|
||||||
numTypedefs = len(p.typedefs)
|
numTypedefs = len(ft.typedefs)
|
||||||
// Also ask about any typedefs we've seen so far.
|
// Also ask about any typedefs we've seen so far.
|
||||||
for _, info := range p.typedefList {
|
for _, info := range ft.typedefList {
|
||||||
if f.Name[info.typedef] != nil {
|
if f.Name[info.typedef] != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -213,7 +213,8 @@ func (p *Package) Translate(f *File) {
|
||||||
}
|
}
|
||||||
needType := p.guessKinds(f)
|
needType := p.guessKinds(f)
|
||||||
if len(needType) > 0 {
|
if len(needType) > 0 {
|
||||||
p.loadDWARF(f, &conv, needType)
|
d := p.loadDWARF(f, &ft, needType)
|
||||||
|
p.recordTypes(f, d, &conv)
|
||||||
}
|
}
|
||||||
|
|
||||||
// In godefs mode we're OK with the typedefs, which
|
// In godefs mode we're OK with the typedefs, which
|
||||||
|
|
@ -522,7 +523,7 @@ func (p *Package) guessKinds(f *File) []*Name {
|
||||||
// loadDWARF parses the DWARF debug information generated
|
// loadDWARF parses the DWARF debug information generated
|
||||||
// by gcc to learn the details of the constants, variables, and types
|
// by gcc to learn the details of the constants, variables, and types
|
||||||
// being referred to as C.xxx.
|
// being referred to as C.xxx.
|
||||||
func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) {
|
func (p *Package) loadDWARF(f *File, ft *fileTypedefs, names []*Name) *debug {
|
||||||
// Extract the types from the DWARF section of an object
|
// Extract the types from the DWARF section of an object
|
||||||
// from a well-formed C program. Gcc only generates DWARF info
|
// from a well-formed C program. Gcc only generates DWARF info
|
||||||
// for symbols in the object file, so it is not enough to print the
|
// for symbols in the object file, so it is not enough to print the
|
||||||
|
|
@ -636,13 +637,28 @@ func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) {
|
||||||
fatalf("malformed __cgo__ name: %s", name)
|
fatalf("malformed __cgo__ name: %s", name)
|
||||||
}
|
}
|
||||||
types[i] = t.Type
|
types[i] = t.Type
|
||||||
p.recordTypedefs(t.Type, f.NamePos[names[i]])
|
ft.recordTypedefs(t.Type, f.NamePos[names[i]])
|
||||||
}
|
}
|
||||||
if e.Tag != dwarf.TagCompileUnit {
|
if e.Tag != dwarf.TagCompileUnit {
|
||||||
r.SkipChildren()
|
r.SkipChildren()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return &debug{names, types, ints, floats, strs}
|
||||||
|
}
|
||||||
|
|
||||||
|
// debug is the data extracted by running an iteration of loadDWARF on a file.
|
||||||
|
type debug struct {
|
||||||
|
names []*Name
|
||||||
|
types []dwarf.Type
|
||||||
|
ints []int64
|
||||||
|
floats []float64
|
||||||
|
strs []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Package) recordTypes(f *File, data *debug, conv *typeConv) {
|
||||||
|
names, types, ints, floats, strs := data.names, data.types, data.ints, data.floats, data.strs
|
||||||
|
|
||||||
// Record types and typedef information.
|
// Record types and typedef information.
|
||||||
for i, n := range names {
|
for i, n := range names {
|
||||||
if strings.HasSuffix(n.Go, "GetTypeID") && types[i].String() == "func() CFTypeID" {
|
if strings.HasSuffix(n.Go, "GetTypeID") && types[i].String() == "func() CFTypeID" {
|
||||||
|
|
@ -701,12 +717,17 @@ func (p *Package) loadDWARF(f *File, conv *typeConv, names []*Name) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// recordTypedefs remembers in p.typedefs all the typedefs used in dtypes and its children.
|
type fileTypedefs struct {
|
||||||
func (p *Package) recordTypedefs(dtype dwarf.Type, pos token.Pos) {
|
typedefs map[string]bool // type names that appear in the types of the objects we're interested in
|
||||||
p.recordTypedefs1(dtype, pos, map[dwarf.Type]bool{})
|
typedefList []typedefInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Package) recordTypedefs1(dtype dwarf.Type, pos token.Pos, visited map[dwarf.Type]bool) {
|
// recordTypedefs remembers in ft.typedefs all the typedefs used in dtypes and its children.
|
||||||
|
func (ft *fileTypedefs) recordTypedefs(dtype dwarf.Type, pos token.Pos) {
|
||||||
|
ft.recordTypedefs1(dtype, pos, map[dwarf.Type]bool{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ft *fileTypedefs) recordTypedefs1(dtype dwarf.Type, pos token.Pos, visited map[dwarf.Type]bool) {
|
||||||
if dtype == nil {
|
if dtype == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -720,25 +741,25 @@ func (p *Package) recordTypedefs1(dtype dwarf.Type, pos token.Pos, visited map[d
|
||||||
// Don't look inside builtin types. There be dragons.
|
// Don't look inside builtin types. There be dragons.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !p.typedefs[dt.Name] {
|
if !ft.typedefs[dt.Name] {
|
||||||
p.typedefs[dt.Name] = true
|
ft.typedefs[dt.Name] = true
|
||||||
p.typedefList = append(p.typedefList, typedefInfo{dt.Name, pos})
|
ft.typedefList = append(ft.typedefList, typedefInfo{dt.Name, pos})
|
||||||
p.recordTypedefs1(dt.Type, pos, visited)
|
ft.recordTypedefs1(dt.Type, pos, visited)
|
||||||
}
|
}
|
||||||
case *dwarf.PtrType:
|
case *dwarf.PtrType:
|
||||||
p.recordTypedefs1(dt.Type, pos, visited)
|
ft.recordTypedefs1(dt.Type, pos, visited)
|
||||||
case *dwarf.ArrayType:
|
case *dwarf.ArrayType:
|
||||||
p.recordTypedefs1(dt.Type, pos, visited)
|
ft.recordTypedefs1(dt.Type, pos, visited)
|
||||||
case *dwarf.QualType:
|
case *dwarf.QualType:
|
||||||
p.recordTypedefs1(dt.Type, pos, visited)
|
ft.recordTypedefs1(dt.Type, pos, visited)
|
||||||
case *dwarf.FuncType:
|
case *dwarf.FuncType:
|
||||||
p.recordTypedefs1(dt.ReturnType, pos, visited)
|
ft.recordTypedefs1(dt.ReturnType, pos, visited)
|
||||||
for _, a := range dt.ParamType {
|
for _, a := range dt.ParamType {
|
||||||
p.recordTypedefs1(a, pos, visited)
|
ft.recordTypedefs1(a, pos, visited)
|
||||||
}
|
}
|
||||||
case *dwarf.StructType:
|
case *dwarf.StructType:
|
||||||
for _, f := range dt.Field {
|
for _, l := range dt.Field {
|
||||||
p.recordTypedefs1(f.Type, pos, visited)
|
ft.recordTypedefs1(l.Type, pos, visited)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1756,20 +1777,23 @@ func gccMachine() []string {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var n atomic.Int64
|
||||||
|
|
||||||
func gccTmp() string {
|
func gccTmp() string {
|
||||||
return *objDir + "_cgo_.o"
|
c := strconv.Itoa(int(n.Add(1)))
|
||||||
|
return *objDir + "_cgo_" + c + ".o"
|
||||||
}
|
}
|
||||||
|
|
||||||
// gccCmd returns the gcc command line to use for compiling
|
// gccCmd returns the gcc command line to use for compiling
|
||||||
// the input.
|
// the input.
|
||||||
func (p *Package) gccCmd() []string {
|
func (p *Package) gccCmd(ofile string) []string {
|
||||||
c := append(gccBaseCmd,
|
c := append(gccBaseCmd,
|
||||||
"-w", // no warnings
|
"-w", // no warnings
|
||||||
"-Wno-error", // warnings are not errors
|
"-Wno-error", // warnings are not errors
|
||||||
"-o"+gccTmp(), // write object to tmp
|
"-o"+ofile, // write object to tmp
|
||||||
"-gdwarf-2", // generate DWARF v2 debugging symbols
|
"-gdwarf-2", // generate DWARF v2 debugging symbols
|
||||||
"-c", // do not link
|
"-c", // do not link
|
||||||
"-xc", // input language is C
|
"-xc", // input language is C
|
||||||
)
|
)
|
||||||
if p.GccIsClang {
|
if p.GccIsClang {
|
||||||
c = append(c,
|
c = append(c,
|
||||||
|
|
@ -1806,7 +1830,8 @@ func (p *Package) gccCmd() []string {
|
||||||
// gccDebug runs gcc -gdwarf-2 over the C program stdin and
|
// gccDebug runs gcc -gdwarf-2 over the C program stdin and
|
||||||
// returns the corresponding DWARF data and, if present, debug data block.
|
// returns the corresponding DWARF data and, if present, debug data block.
|
||||||
func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int64, floats []float64, strs []string) {
|
func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int64, floats []float64, strs []string) {
|
||||||
runGcc(stdin, p.gccCmd())
|
ofile := gccTmp()
|
||||||
|
runGcc(stdin, p.gccCmd(ofile))
|
||||||
|
|
||||||
isDebugInts := func(s string) bool {
|
isDebugInts := func(s string) bool {
|
||||||
// Some systems use leading _ to denote non-assembly symbols.
|
// Some systems use leading _ to denote non-assembly symbols.
|
||||||
|
|
@ -1856,11 +1881,11 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, err := macho.Open(gccTmp()); err == nil {
|
if f, err := macho.Open(ofile); err == nil {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
d, err := f.DWARF()
|
d, err := f.DWARF()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
fatalf("cannot load DWARF output from %s: %v", ofile, err)
|
||||||
}
|
}
|
||||||
bo := f.ByteOrder
|
bo := f.ByteOrder
|
||||||
if f.Symtab != nil {
|
if f.Symtab != nil {
|
||||||
|
|
@ -1934,11 +1959,11 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
|
||||||
return d, ints, floats, strs
|
return d, ints, floats, strs
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, err := elf.Open(gccTmp()); err == nil {
|
if f, err := elf.Open(ofile); err == nil {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
d, err := f.DWARF()
|
d, err := f.DWARF()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
fatalf("cannot load DWARF output from %s: %v", ofile, err)
|
||||||
}
|
}
|
||||||
bo := f.ByteOrder
|
bo := f.ByteOrder
|
||||||
symtab, err := f.Symbols()
|
symtab, err := f.Symbols()
|
||||||
|
|
@ -2034,11 +2059,11 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
|
||||||
return d, ints, floats, strs
|
return d, ints, floats, strs
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, err := pe.Open(gccTmp()); err == nil {
|
if f, err := pe.Open(ofile); err == nil {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
d, err := f.DWARF()
|
d, err := f.DWARF()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
fatalf("cannot load DWARF output from %s: %v", ofile, err)
|
||||||
}
|
}
|
||||||
bo := binary.LittleEndian
|
bo := binary.LittleEndian
|
||||||
for _, s := range f.Symbols {
|
for _, s := range f.Symbols {
|
||||||
|
|
@ -2106,11 +2131,11 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
|
||||||
return d, ints, floats, strs
|
return d, ints, floats, strs
|
||||||
}
|
}
|
||||||
|
|
||||||
if f, err := xcoff.Open(gccTmp()); err == nil {
|
if f, err := xcoff.Open(ofile); err == nil {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
d, err := f.DWARF()
|
d, err := f.DWARF()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fatalf("cannot load DWARF output from %s: %v", gccTmp(), err)
|
fatalf("cannot load DWARF output from %s: %v", ofile, err)
|
||||||
}
|
}
|
||||||
bo := binary.BigEndian
|
bo := binary.BigEndian
|
||||||
for _, s := range f.Symbols {
|
for _, s := range f.Symbols {
|
||||||
|
|
@ -2176,7 +2201,7 @@ func (p *Package) gccDebug(stdin []byte, nnames int) (d *dwarf.Data, ints []int6
|
||||||
buildStrings()
|
buildStrings()
|
||||||
return d, ints, floats, strs
|
return d, ints, floats, strs
|
||||||
}
|
}
|
||||||
fatalf("cannot parse gcc output %s as ELF, Mach-O, PE, XCOFF object", gccTmp())
|
fatalf("cannot parse gcc output %s as ELF, Mach-O, PE, XCOFF object", ofile)
|
||||||
panic("not reached")
|
panic("not reached")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2196,7 +2221,7 @@ func gccDefines(stdin []byte, gccOptions []string) string {
|
||||||
// gcc to fail.
|
// gcc to fail.
|
||||||
func (p *Package) gccErrors(stdin []byte, extraArgs ...string) string {
|
func (p *Package) gccErrors(stdin []byte, extraArgs ...string) string {
|
||||||
// TODO(rsc): require failure
|
// TODO(rsc): require failure
|
||||||
args := p.gccCmd()
|
args := p.gccCmd(gccTmp())
|
||||||
|
|
||||||
// Optimization options can confuse the error messages; remove them.
|
// Optimization options can confuse the error messages; remove them.
|
||||||
nargs := make([]string, 0, len(args)+len(extraArgs))
|
nargs := make([]string, 0, len(args)+len(extraArgs))
|
||||||
|
|
|
||||||
|
|
@ -422,3 +422,11 @@ func TestIssue67976(t *testing.T) {
|
||||||
globalSkip(t)
|
globalSkip(t)
|
||||||
goCmd(t, "build", "-buildmode=plugin", "-o", "issue67976.so", "./issue67976/plugin.go")
|
goCmd(t, "build", "-buildmode=plugin", "-o", "issue67976.so", "./issue67976/plugin.go")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIssue75102(t *testing.T) {
|
||||||
|
globalSkip(t)
|
||||||
|
// add gcflags different from the executable file to trigger plugin open failed.
|
||||||
|
goCmd(t, "build", "-gcflags=all=-N -l", "-buildmode=plugin", "-o", "issue75102.so", "./issue75102/plugin.go")
|
||||||
|
goCmd(t, "build", "-o", "issue75102.exe", "./issue75102/main.go")
|
||||||
|
run(t, "./issue75102.exe")
|
||||||
|
}
|
||||||
|
|
|
||||||
21
src/cmd/cgo/internal/testplugin/testdata/issue75102/main.go
vendored
Normal file
21
src/cmd/cgo/internal/testplugin/testdata/issue75102/main.go
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
_, err := plugin.Open("issue75102.so")
|
||||||
|
if err == nil {
|
||||||
|
panic("unexpected success to open a different version plugin")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Println("done")
|
||||||
|
}
|
||||||
11
src/cmd/cgo/internal/testplugin/testdata/issue75102/plugin.go
vendored
Normal file
11
src/cmd/cgo/internal/testplugin/testdata/issue75102/plugin.go
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
panic("unexpected call to init")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
|
@ -49,8 +49,6 @@ type Package struct {
|
||||||
GoFiles []string // list of Go files
|
GoFiles []string // list of Go files
|
||||||
GccFiles []string // list of gcc output files
|
GccFiles []string // list of gcc output files
|
||||||
Preamble string // collected preamble for _cgo_export.h
|
Preamble string // collected preamble for _cgo_export.h
|
||||||
typedefs map[string]bool // type names that appear in the types of the objects we're interested in
|
|
||||||
typedefList []typedefInfo
|
|
||||||
noCallbacks map[string]bool // C function names with #cgo nocallback directive
|
noCallbacks map[string]bool // C function names with #cgo nocallback directive
|
||||||
noEscapes map[string]bool // C function names with #cgo noescape directive
|
noEscapes map[string]bool // C function names with #cgo noescape directive
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,7 @@ func processType(t *ast.TypeSpec) {
|
||||||
var doChildrenWithHiddenBody strings.Builder
|
var doChildrenWithHiddenBody strings.Builder
|
||||||
var editChildrenBody strings.Builder
|
var editChildrenBody strings.Builder
|
||||||
var editChildrenWithHiddenBody strings.Builder
|
var editChildrenWithHiddenBody strings.Builder
|
||||||
|
var hasHidden bool
|
||||||
for _, f := range fields {
|
for _, f := range fields {
|
||||||
names := f.Names
|
names := f.Names
|
||||||
ft := f.Type
|
ft := f.Type
|
||||||
|
|
@ -309,6 +310,7 @@ func processType(t *ast.TypeSpec) {
|
||||||
"if n.%s != nil {\nn.%s = edit(n.%s).(%s%s)\n}\n", name, name, name, ptr, ft)
|
"if n.%s != nil {\nn.%s = edit(n.%s).(%s%s)\n}\n", name, name, name, ptr, ft)
|
||||||
}
|
}
|
||||||
if hidden {
|
if hidden {
|
||||||
|
hasHidden = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if isSlice {
|
if isSlice {
|
||||||
|
|
@ -327,19 +329,27 @@ func processType(t *ast.TypeSpec) {
|
||||||
}
|
}
|
||||||
fmt.Fprintf(&buf, "func (n *%s) copy() Node {\nc := *n\n", name)
|
fmt.Fprintf(&buf, "func (n *%s) copy() Node {\nc := *n\n", name)
|
||||||
buf.WriteString(copyBody.String())
|
buf.WriteString(copyBody.String())
|
||||||
fmt.Fprintf(&buf, "return &c\n}\n")
|
buf.WriteString("return &c\n}\n")
|
||||||
fmt.Fprintf(&buf, "func (n *%s) doChildren(do func(Node) bool) bool {\n", name)
|
fmt.Fprintf(&buf, "func (n *%s) doChildren(do func(Node) bool) bool {\n", name)
|
||||||
buf.WriteString(doChildrenBody.String())
|
buf.WriteString(doChildrenBody.String())
|
||||||
fmt.Fprintf(&buf, "return false\n}\n")
|
buf.WriteString("return false\n}\n")
|
||||||
fmt.Fprintf(&buf, "func (n *%s) doChildrenWithHidden(do func(Node) bool) bool {\n", name)
|
fmt.Fprintf(&buf, "func (n *%s) doChildrenWithHidden(do func(Node) bool) bool {\n", name)
|
||||||
buf.WriteString(doChildrenWithHiddenBody.String())
|
if hasHidden {
|
||||||
fmt.Fprintf(&buf, "return false\n}\n")
|
buf.WriteString(doChildrenWithHiddenBody.String())
|
||||||
|
buf.WriteString("return false\n}\n")
|
||||||
|
} else {
|
||||||
|
buf.WriteString("return n.doChildren(do)\n}\n")
|
||||||
|
}
|
||||||
fmt.Fprintf(&buf, "func (n *%s) editChildren(edit func(Node) Node) {\n", name)
|
fmt.Fprintf(&buf, "func (n *%s) editChildren(edit func(Node) Node) {\n", name)
|
||||||
buf.WriteString(editChildrenBody.String())
|
buf.WriteString(editChildrenBody.String())
|
||||||
fmt.Fprintf(&buf, "}\n")
|
buf.WriteString("}\n")
|
||||||
fmt.Fprintf(&buf, "func (n *%s) editChildrenWithHidden(edit func(Node) Node) {\n", name)
|
fmt.Fprintf(&buf, "func (n *%s) editChildrenWithHidden(edit func(Node) Node) {\n", name)
|
||||||
buf.WriteString(editChildrenWithHiddenBody.String())
|
if hasHidden {
|
||||||
fmt.Fprintf(&buf, "}\n")
|
buf.WriteString(editChildrenWithHiddenBody.String())
|
||||||
|
} else {
|
||||||
|
buf.WriteString("n.editChildren(edit)\n")
|
||||||
|
}
|
||||||
|
buf.WriteString("}\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateHelpers() {
|
func generateHelpers() {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -6,49 +6,23 @@ package loong64
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
"cmd/compile/internal/ir"
|
|
||||||
"cmd/compile/internal/objw"
|
"cmd/compile/internal/objw"
|
||||||
"cmd/compile/internal/types"
|
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/obj/loong64"
|
"cmd/internal/obj/loong64"
|
||||||
)
|
)
|
||||||
|
|
||||||
func zerorange(pp *objw.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
|
func zerorange(pp *objw.Progs, p *obj.Prog, off, cnt int64, _ *uint32) *obj.Prog {
|
||||||
if cnt == 0 {
|
if cnt%8 != 0 {
|
||||||
return p
|
panic("zeroed region not aligned")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust the frame to account for LR.
|
// Adjust the frame to account for LR.
|
||||||
off += base.Ctxt.Arch.FixedFrameSize
|
off += base.Ctxt.Arch.FixedFrameSize
|
||||||
|
|
||||||
if cnt < int64(4*types.PtrSize) {
|
for cnt != 0 {
|
||||||
for i := int64(0); i < cnt; i += int64(types.PtrSize) {
|
p = pp.Append(p, loong64.AMOVV, obj.TYPE_REG, loong64.REGZERO, 0, obj.TYPE_MEM, loong64.REGSP, off)
|
||||||
p = pp.Append(p, loong64.AMOVV, obj.TYPE_REG, loong64.REGZERO, 0, obj.TYPE_MEM, loong64.REGSP, off+i)
|
off += 8
|
||||||
}
|
cnt -= 8
|
||||||
} else if cnt <= int64(128*types.PtrSize) {
|
|
||||||
p = pp.Append(p, loong64.AADDV, obj.TYPE_CONST, 0, off, obj.TYPE_REG, loong64.REGRT1, 0)
|
|
||||||
p.Reg = loong64.REGSP
|
|
||||||
p = pp.Append(p, obj.ADUFFZERO, obj.TYPE_NONE, 0, 0, obj.TYPE_MEM, 0, 0)
|
|
||||||
p.To.Name = obj.NAME_EXTERN
|
|
||||||
p.To.Sym = ir.Syms.Duffzero
|
|
||||||
p.To.Offset = 8 * (128 - cnt/int64(types.PtrSize))
|
|
||||||
} else {
|
|
||||||
// ADDV $(off), SP, r1
|
|
||||||
// ADDV $cnt, r1, r2
|
|
||||||
// loop:
|
|
||||||
// MOVV R0, (r1)
|
|
||||||
// ADDV $Widthptr, r1
|
|
||||||
// BNE r1, r2, loop
|
|
||||||
p = pp.Append(p, loong64.AADDV, obj.TYPE_CONST, 0, off, obj.TYPE_REG, loong64.REGRT1, 0)
|
|
||||||
p.Reg = loong64.REGSP
|
|
||||||
p = pp.Append(p, loong64.AADDV, obj.TYPE_CONST, 0, cnt, obj.TYPE_REG, loong64.REGRT2, 0)
|
|
||||||
p.Reg = loong64.REGRT1
|
|
||||||
p = pp.Append(p, loong64.AMOVV, obj.TYPE_REG, loong64.REGZERO, 0, obj.TYPE_MEM, loong64.REGRT1, 0)
|
|
||||||
loop := p
|
|
||||||
p = pp.Append(p, loong64.AADDV, obj.TYPE_CONST, 0, int64(types.PtrSize), obj.TYPE_REG, loong64.REGRT1, 0)
|
|
||||||
p = pp.Append(p, loong64.ABNE, obj.TYPE_REG, loong64.REGRT1, 0, obj.TYPE_BRANCH, 0, 0)
|
|
||||||
p.Reg = loong64.REGRT2
|
|
||||||
p.To.SetTarget(loop)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return p
|
return p
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||||
p.To.Type = obj.TYPE_REG
|
p.To.Type = obj.TYPE_REG
|
||||||
p.To.Reg = y
|
p.To.Reg = y
|
||||||
case ssa.OpLOONG64MOVVnop,
|
case ssa.OpLOONG64MOVVnop,
|
||||||
|
ssa.OpLOONG64ZERO,
|
||||||
ssa.OpLOONG64LoweredRound32F,
|
ssa.OpLOONG64LoweredRound32F,
|
||||||
ssa.OpLOONG64LoweredRound64F:
|
ssa.OpLOONG64LoweredRound64F:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
|
|
@ -432,18 +433,6 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||||
p.To.Reg = v.Args[0].Reg()
|
p.To.Reg = v.Args[0].Reg()
|
||||||
p.To.Index = v.Args[1].Reg()
|
p.To.Index = v.Args[1].Reg()
|
||||||
|
|
||||||
case ssa.OpLOONG64MOVBstorezeroidx,
|
|
||||||
ssa.OpLOONG64MOVHstorezeroidx,
|
|
||||||
ssa.OpLOONG64MOVWstorezeroidx,
|
|
||||||
ssa.OpLOONG64MOVVstorezeroidx:
|
|
||||||
p := s.Prog(v.Op.Asm())
|
|
||||||
p.From.Type = obj.TYPE_REG
|
|
||||||
p.From.Reg = loong64.REGZERO
|
|
||||||
p.To.Type = obj.TYPE_MEM
|
|
||||||
p.To.Name = obj.NAME_NONE
|
|
||||||
p.To.Reg = v.Args[0].Reg()
|
|
||||||
p.To.Index = v.Args[1].Reg()
|
|
||||||
|
|
||||||
case ssa.OpLOONG64MOVBload,
|
case ssa.OpLOONG64MOVBload,
|
||||||
ssa.OpLOONG64MOVBUload,
|
ssa.OpLOONG64MOVBUload,
|
||||||
ssa.OpLOONG64MOVHload,
|
ssa.OpLOONG64MOVHload,
|
||||||
|
|
@ -471,16 +460,6 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Reg = v.Args[0].Reg()
|
p.To.Reg = v.Args[0].Reg()
|
||||||
ssagen.AddAux(&p.To, v)
|
ssagen.AddAux(&p.To, v)
|
||||||
case ssa.OpLOONG64MOVBstorezero,
|
|
||||||
ssa.OpLOONG64MOVHstorezero,
|
|
||||||
ssa.OpLOONG64MOVWstorezero,
|
|
||||||
ssa.OpLOONG64MOVVstorezero:
|
|
||||||
p := s.Prog(v.Op.Asm())
|
|
||||||
p.From.Type = obj.TYPE_REG
|
|
||||||
p.From.Reg = loong64.REGZERO
|
|
||||||
p.To.Type = obj.TYPE_MEM
|
|
||||||
p.To.Reg = v.Args[0].Reg()
|
|
||||||
ssagen.AddAux(&p.To, v)
|
|
||||||
case ssa.OpLOONG64MOVBreg,
|
case ssa.OpLOONG64MOVBreg,
|
||||||
ssa.OpLOONG64MOVBUreg,
|
ssa.OpLOONG64MOVBUreg,
|
||||||
ssa.OpLOONG64MOVHreg,
|
ssa.OpLOONG64MOVHreg,
|
||||||
|
|
@ -543,6 +522,7 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||||
ssa.OpLOONG64SQRTF,
|
ssa.OpLOONG64SQRTF,
|
||||||
ssa.OpLOONG64REVB2H,
|
ssa.OpLOONG64REVB2H,
|
||||||
ssa.OpLOONG64REVB2W,
|
ssa.OpLOONG64REVB2W,
|
||||||
|
ssa.OpLOONG64REVB4H,
|
||||||
ssa.OpLOONG64REVBV,
|
ssa.OpLOONG64REVBV,
|
||||||
ssa.OpLOONG64BITREV4B,
|
ssa.OpLOONG64BITREV4B,
|
||||||
ssa.OpLOONG64BITREVW,
|
ssa.OpLOONG64BITREVW,
|
||||||
|
|
@ -580,28 +560,97 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) {
|
||||||
p.To.Sym = ir.Syms.Duffzero
|
p.To.Sym = ir.Syms.Duffzero
|
||||||
p.To.Offset = v.AuxInt
|
p.To.Offset = v.AuxInt
|
||||||
case ssa.OpLOONG64LoweredZero:
|
case ssa.OpLOONG64LoweredZero:
|
||||||
// MOVx R0, (Rarg0)
|
ptrReg := v.Args[0].Reg()
|
||||||
// ADDV $sz, Rarg0
|
n := v.AuxInt
|
||||||
// BGEU Rarg1, Rarg0, -2(PC)
|
if n < 16 {
|
||||||
mov, sz := largestMove(v.AuxInt)
|
v.Fatalf("Zero too small %d", n)
|
||||||
p := s.Prog(mov)
|
}
|
||||||
|
|
||||||
|
// Generate Zeroing instructions.
|
||||||
|
var off int64
|
||||||
|
for n >= 8 {
|
||||||
|
// MOVV ZR, off(ptrReg)
|
||||||
|
zero8(s, ptrReg, off)
|
||||||
|
off += 8
|
||||||
|
n -= 8
|
||||||
|
}
|
||||||
|
if n != 0 {
|
||||||
|
// MOVV ZR, off+n-8(ptrReg)
|
||||||
|
zero8(s, ptrReg, off+n-8)
|
||||||
|
}
|
||||||
|
case ssa.OpLOONG64LoweredZeroLoop:
|
||||||
|
ptrReg := v.Args[0].Reg()
|
||||||
|
countReg := v.RegTmp()
|
||||||
|
var off int64
|
||||||
|
n := v.AuxInt
|
||||||
|
loopSize := int64(64)
|
||||||
|
if n < 3*loopSize {
|
||||||
|
// - a loop count of 0 won't work.
|
||||||
|
// - a loop count of 1 is useless.
|
||||||
|
// - a loop count of 2 is a code size ~tie
|
||||||
|
// 4 instructions to implement the loop
|
||||||
|
// 8 instructions in the loop body
|
||||||
|
// vs
|
||||||
|
// 16 instuctions in the straightline code
|
||||||
|
// Might as well use straightline code.
|
||||||
|
v.Fatalf("ZeroLoop size tool small %d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put iteration count in a register.
|
||||||
|
// MOVV $n/loopSize, countReg
|
||||||
|
p := s.Prog(loong64.AMOVV)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = n / loopSize
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = countReg
|
||||||
|
cntInit := p
|
||||||
|
|
||||||
|
// Zero loopSize bytes starting at ptrReg.
|
||||||
|
for range loopSize / 8 {
|
||||||
|
// MOVV ZR, off(ptrReg)
|
||||||
|
zero8(s, ptrReg, off)
|
||||||
|
off += 8
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment ptrReg by loopSize.
|
||||||
|
// ADDV $loopSize, ptrReg
|
||||||
|
p = s.Prog(loong64.AADDV)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = loopSize
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = ptrReg
|
||||||
|
|
||||||
|
// Decrement loop count.
|
||||||
|
// SUBV $1, countReg
|
||||||
|
p = s.Prog(loong64.ASUBV)
|
||||||
|
p.From.Type = obj.TYPE_CONST
|
||||||
|
p.From.Offset = 1
|
||||||
|
p.To.Type = obj.TYPE_REG
|
||||||
|
p.To.Reg = countReg
|
||||||
|
|
||||||
|
// Jump to loop header if we're not done yet.
|
||||||
|
// BNE countReg, loop header
|
||||||
|
p = s.Prog(loong64.ABNE)
|
||||||
p.From.Type = obj.TYPE_REG
|
p.From.Type = obj.TYPE_REG
|
||||||
p.From.Reg = loong64.REGZERO
|
p.From.Reg = countReg
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_BRANCH
|
||||||
p.To.Reg = v.Args[0].Reg()
|
p.To.SetTarget(cntInit.Link)
|
||||||
|
|
||||||
p2 := s.Prog(loong64.AADDVU)
|
// Multiples of the loop size are now done.
|
||||||
p2.From.Type = obj.TYPE_CONST
|
n %= loopSize
|
||||||
p2.From.Offset = sz
|
|
||||||
p2.To.Type = obj.TYPE_REG
|
|
||||||
p2.To.Reg = v.Args[0].Reg()
|
|
||||||
|
|
||||||
p3 := s.Prog(loong64.ABGEU)
|
off = 0
|
||||||
p3.From.Type = obj.TYPE_REG
|
// Write any fractional portion.
|
||||||
p3.From.Reg = v.Args[1].Reg()
|
for n >= 8 {
|
||||||
p3.Reg = v.Args[0].Reg()
|
// MOVV ZR, off(ptrReg)
|
||||||
p3.To.Type = obj.TYPE_BRANCH
|
zero8(s, ptrReg, off)
|
||||||
p3.To.SetTarget(p)
|
off += 8
|
||||||
|
n -= 8
|
||||||
|
}
|
||||||
|
|
||||||
|
if n != 0 {
|
||||||
|
zero8(s, ptrReg, off+n-8)
|
||||||
|
}
|
||||||
|
|
||||||
case ssa.OpLOONG64DUFFCOPY:
|
case ssa.OpLOONG64DUFFCOPY:
|
||||||
p := s.Prog(obj.ADUFFCOPY)
|
p := s.Prog(obj.ADUFFCOPY)
|
||||||
|
|
@ -1175,3 +1224,14 @@ func spillArgReg(pp *objw.Progs, p *obj.Prog, f *ssa.Func, t *types.Type, reg in
|
||||||
p.Pos = p.Pos.WithNotStmt()
|
p.Pos = p.Pos.WithNotStmt()
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// zero8 zeroes 8 bytes at reg+off.
|
||||||
|
func zero8(s *ssagen.State, reg int16, off int64) {
|
||||||
|
// MOVV ZR, off(reg)
|
||||||
|
p := s.Prog(loong64.AMOVV)
|
||||||
|
p.From.Type = obj.TYPE_REG
|
||||||
|
p.From.Reg = loong64.REGZERO
|
||||||
|
p.To.Type = obj.TYPE_MEM
|
||||||
|
p.To.Reg = reg
|
||||||
|
p.To.Offset = off
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,27 @@
|
||||||
(Rsh8x16 <t> x y) && !shiftIsBounded(v) => (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
|
(Rsh8x16 <t> x y) && !shiftIsBounded(v) => (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt16to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt16to64 y)))
|
||||||
(Rsh8x8 <t> x y) && !shiftIsBounded(v) => (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
|
(Rsh8x8 <t> x y) && !shiftIsBounded(v) => (SRAV (SignExt8to64 x) (OR <t> (NEGV <t> (SGTU (ZeroExt8to64 y) (MOVVconst <typ.UInt64> [63]))) (ZeroExt8to64 y)))
|
||||||
|
|
||||||
|
|
||||||
|
// revb2h
|
||||||
|
// ((x>>8) | (x<<8)) => (REVB2H x), the type of x is uint16
|
||||||
|
((OR|XOR|ADDV) <typ.UInt16> (SRLVconst [8] <typ.UInt16> x) (SLLVconst [8] <typ.UInt16> x)) => (REVB2H x)
|
||||||
|
|
||||||
|
// ((x & 0xff00ff00)>>8) | ((x & 0x00ff00ff)<<8), the type of x is uint32
|
||||||
|
((OR|XOR|ADDV) (SRLconst [8] (ANDconst [c1] x)) (SLLconst [8] (ANDconst [c2] x)))
|
||||||
|
&& uint32(c1) == 0xff00ff00 && uint32(c2) == 0x00ff00ff
|
||||||
|
=> (REVB2H x)
|
||||||
|
|
||||||
|
// revb4h
|
||||||
|
// ((x & 0xff00ff00ff00ff00)>>8) | ((x & 0x00ff00ff00ff00ff)<<8), the type of x is uint64
|
||||||
|
((OR|XOR|ADDV) (SRLVconst [8] (AND (MOVVconst [c1]) x)) (SLLVconst [8] (AND (MOVVconst [c2]) x)))
|
||||||
|
&& uint64(c1) == 0xff00ff00ff00ff00 && uint64(c2) == 0x00ff00ff00ff00ff
|
||||||
|
=> (REVB4H x)
|
||||||
|
|
||||||
|
// ((x & 0xff00ff00)>>8) | ((x & 0x00ff00ff)<<8), the type of x is uint64
|
||||||
|
((OR|XOR|ADDV) (SRLVconst [8] (AND (MOVVconst [c1]) x)) (SLLVconst [8] (ANDconst [c2] x)))
|
||||||
|
&& uint64(c1) == 0xff00ff00 && uint64(c2) == 0x00ff00ff
|
||||||
|
=> (REVB4H (ANDconst <x.Type> [0xffffffff] x))
|
||||||
|
|
||||||
// bitfield ops
|
// bitfield ops
|
||||||
|
|
||||||
// bstrpickv
|
// bstrpickv
|
||||||
|
|
@ -352,24 +373,8 @@
|
||||||
(MOVVstore [8] ptr (MOVVconst [0])
|
(MOVVstore [8] ptr (MOVVconst [0])
|
||||||
(MOVVstore ptr (MOVVconst [0]) mem))
|
(MOVVstore ptr (MOVVconst [0]) mem))
|
||||||
|
|
||||||
// strip off fractional word zeroing
|
(Zero [s] ptr mem) && s > 16 && s < 192 => (LoweredZero [s] ptr mem)
|
||||||
(Zero [s] ptr mem) && s%8 != 0 && s > 16 =>
|
(Zero [s] ptr mem) && s >= 192 => (LoweredZeroLoop [s] ptr mem)
|
||||||
(Zero [s%8]
|
|
||||||
(OffPtr <ptr.Type> ptr [s-s%8])
|
|
||||||
(Zero [s-s%8] ptr mem))
|
|
||||||
|
|
||||||
// medium zeroing uses a duff device
|
|
||||||
(Zero [s] ptr mem)
|
|
||||||
&& s%8 == 0 && s > 16 && s <= 8*128 =>
|
|
||||||
(DUFFZERO [8 * (128 - s/8)] ptr mem)
|
|
||||||
|
|
||||||
// large zeroing uses a loop
|
|
||||||
(Zero [s] ptr mem)
|
|
||||||
&& s%8 == 0 && s > 8*128 =>
|
|
||||||
(LoweredZero
|
|
||||||
ptr
|
|
||||||
(ADDVconst <ptr.Type> ptr [s-8])
|
|
||||||
mem)
|
|
||||||
|
|
||||||
// moves
|
// moves
|
||||||
(Move [0] _ _ mem) => mem
|
(Move [0] _ _ mem) => mem
|
||||||
|
|
@ -555,10 +560,6 @@
|
||||||
&& (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
&& (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
||||||
(MOV(B|H|W|V|F|D)store [off1+int32(off2)] {sym} ptr val mem)
|
(MOV(B|H|W|V|F|D)store [off1+int32(off2)] {sym} ptr val mem)
|
||||||
|
|
||||||
(MOV(B|H|W|V)storezero [off1] {sym} (ADDVconst [off2] ptr) mem) && is32Bit(int64(off1)+off2)
|
|
||||||
&& (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
|
||||||
(MOV(B|H|W|V)storezero [off1+int32(off2)] {sym} ptr mem)
|
|
||||||
|
|
||||||
(MOV(B|BU|H|HU|W|WU|V|F|D)load [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
(MOV(B|BU|H|HU|W|WU|V|F|D)load [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||||
&& is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
&& is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
||||||
(MOV(B|BU|H|HU|W|WU|V|F|D)load [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
|
(MOV(B|BU|H|HU|W|WU|V|F|D)load [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
|
||||||
|
|
@ -567,10 +568,6 @@
|
||||||
&& is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
&& is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
||||||
(MOV(B|H|W|V|F|D)store [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
|
(MOV(B|H|W|V|F|D)store [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr val mem)
|
||||||
|
|
||||||
(MOV(B|H|W|V)storezero [off1] {sym1} (MOVVaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
|
||||||
&& is32Bit(int64(off1)+int64(off2)) && (ptr.Op != OpSB || !config.ctxt.Flag_dynlink) =>
|
|
||||||
(MOV(B|H|W|V)storezero [off1+int32(off2)] {mergeSym(sym1,sym2)} ptr mem)
|
|
||||||
|
|
||||||
// don't extend after proper load
|
// don't extend after proper load
|
||||||
(MOVBreg x:(MOVBload _ _)) => (MOVVreg x)
|
(MOVBreg x:(MOVBload _ _)) => (MOVVreg x)
|
||||||
(MOVBUreg x:(MOVBUload _ _)) => (MOVVreg x)
|
(MOVBUreg x:(MOVBUload _ _)) => (MOVVreg x)
|
||||||
|
|
@ -587,6 +584,21 @@
|
||||||
(MOVWUreg x:(MOVBUload _ _)) => (MOVVreg x)
|
(MOVWUreg x:(MOVBUload _ _)) => (MOVVreg x)
|
||||||
(MOVWUreg x:(MOVHUload _ _)) => (MOVVreg x)
|
(MOVWUreg x:(MOVHUload _ _)) => (MOVVreg x)
|
||||||
(MOVWUreg x:(MOVWUload _ _)) => (MOVVreg x)
|
(MOVWUreg x:(MOVWUload _ _)) => (MOVVreg x)
|
||||||
|
(MOVBreg x:(MOVBloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVBUreg x:(MOVBUloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVHreg x:(MOVBloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVHreg x:(MOVBUloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVHreg x:(MOVHloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVHUreg x:(MOVBUloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVHUreg x:(MOVHUloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVWreg x:(MOVBloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVWreg x:(MOVBUloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVWreg x:(MOVHloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVWreg x:(MOVHUloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVWreg x:(MOVWloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVWUreg x:(MOVBUloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVWUreg x:(MOVHUloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
(MOVWUreg x:(MOVWUloadidx _ _ _)) => (MOVVreg x)
|
||||||
|
|
||||||
// fold double extensions
|
// fold double extensions
|
||||||
(MOVBreg x:(MOVBreg _)) => (MOVVreg x)
|
(MOVBreg x:(MOVBreg _)) => (MOVVreg x)
|
||||||
|
|
@ -618,11 +630,6 @@
|
||||||
(MOVWstore [off] {sym} ptr (MOVWreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
|
(MOVWstore [off] {sym} ptr (MOVWreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
|
||||||
(MOVWstore [off] {sym} ptr (MOVWUreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
|
(MOVWstore [off] {sym} ptr (MOVWUreg x) mem) => (MOVWstore [off] {sym} ptr x mem)
|
||||||
|
|
||||||
(MOVBstore [off] {sym} ptr (MOVVconst [0]) mem) => (MOVBstorezero [off] {sym} ptr mem)
|
|
||||||
(MOVHstore [off] {sym} ptr (MOVVconst [0]) mem) => (MOVHstorezero [off] {sym} ptr mem)
|
|
||||||
(MOVWstore [off] {sym} ptr (MOVVconst [0]) mem) => (MOVWstorezero [off] {sym} ptr mem)
|
|
||||||
(MOVVstore [off] {sym} ptr (MOVVconst [0]) mem) => (MOVVstorezero [off] {sym} ptr mem)
|
|
||||||
|
|
||||||
// register indexed load
|
// register indexed load
|
||||||
(MOVVload [off] {sym} (ADDV ptr idx) mem) && off == 0 && sym == nil => (MOVVloadidx ptr idx mem)
|
(MOVVload [off] {sym} (ADDV ptr idx) mem) && off == 0 && sym == nil => (MOVVloadidx ptr idx mem)
|
||||||
(MOVWUload [off] {sym} (ADDV ptr idx) mem) && off == 0 && sym == nil => (MOVWUloadidx ptr idx mem)
|
(MOVWUload [off] {sym} (ADDV ptr idx) mem) && off == 0 && sym == nil => (MOVWUloadidx ptr idx mem)
|
||||||
|
|
@ -672,24 +679,6 @@
|
||||||
(MOVDstoreidx ptr (MOVVconst [c]) val mem) && is32Bit(c) => (MOVDstore [int32(c)] ptr val mem)
|
(MOVDstoreidx ptr (MOVVconst [c]) val mem) && is32Bit(c) => (MOVDstore [int32(c)] ptr val mem)
|
||||||
(MOVDstoreidx (MOVVconst [c]) idx val mem) && is32Bit(c) => (MOVDstore [int32(c)] idx val mem)
|
(MOVDstoreidx (MOVVconst [c]) idx val mem) && is32Bit(c) => (MOVDstore [int32(c)] idx val mem)
|
||||||
|
|
||||||
// register indexed store zero
|
|
||||||
(MOVVstorezero [off] {sym} (ADDV ptr idx) mem) && off == 0 && sym == nil => (MOVVstorezeroidx ptr idx mem)
|
|
||||||
(MOVWstorezero [off] {sym} (ADDV ptr idx) mem) && off == 0 && sym == nil => (MOVWstorezeroidx ptr idx mem)
|
|
||||||
(MOVHstorezero [off] {sym} (ADDV ptr idx) mem) && off == 0 && sym == nil => (MOVHstorezeroidx ptr idx mem)
|
|
||||||
(MOVBstorezero [off] {sym} (ADDV ptr idx) mem) && off == 0 && sym == nil => (MOVBstorezeroidx ptr idx mem)
|
|
||||||
(MOVVstoreidx ptr idx (MOVVconst [0]) mem) => (MOVVstorezeroidx ptr idx mem)
|
|
||||||
(MOVWstoreidx ptr idx (MOVVconst [0]) mem) => (MOVWstorezeroidx ptr idx mem)
|
|
||||||
(MOVHstoreidx ptr idx (MOVVconst [0]) mem) => (MOVHstorezeroidx ptr idx mem)
|
|
||||||
(MOVBstoreidx ptr idx (MOVVconst [0]) mem) => (MOVBstorezeroidx ptr idx mem)
|
|
||||||
(MOVVstorezeroidx ptr (MOVVconst [c]) mem) && is32Bit(c) => (MOVVstorezero [int32(c)] ptr mem)
|
|
||||||
(MOVVstorezeroidx (MOVVconst [c]) idx mem) && is32Bit(c) => (MOVVstorezero [int32(c)] idx mem)
|
|
||||||
(MOVWstorezeroidx ptr (MOVVconst [c]) mem) && is32Bit(c) => (MOVWstorezero [int32(c)] ptr mem)
|
|
||||||
(MOVWstorezeroidx (MOVVconst [c]) idx mem) && is32Bit(c) => (MOVWstorezero [int32(c)] idx mem)
|
|
||||||
(MOVHstorezeroidx ptr (MOVVconst [c]) mem) && is32Bit(c) => (MOVHstorezero [int32(c)] ptr mem)
|
|
||||||
(MOVHstorezeroidx (MOVVconst [c]) idx mem) && is32Bit(c) => (MOVHstorezero [int32(c)] idx mem)
|
|
||||||
(MOVBstorezeroidx ptr (MOVVconst [c]) mem) && is32Bit(c) => (MOVBstorezero [int32(c)] ptr mem)
|
|
||||||
(MOVBstorezeroidx (MOVVconst [c]) idx mem) && is32Bit(c) => (MOVBstorezero [int32(c)] idx mem)
|
|
||||||
|
|
||||||
// if a register move has only 1 use, just use the same register without emitting instruction
|
// if a register move has only 1 use, just use the same register without emitting instruction
|
||||||
// MOVVnop doesn't emit instruction, only for ensuring the type.
|
// MOVVnop doesn't emit instruction, only for ensuring the type.
|
||||||
(MOVVreg x) && x.Uses == 1 => (MOVVnop x)
|
(MOVVreg x) && x.Uses == 1 => (MOVVnop x)
|
||||||
|
|
@ -749,6 +738,9 @@
|
||||||
(SRLVconst [rc] (MOVHUreg x)) && rc >= 16 => (MOVVconst [0])
|
(SRLVconst [rc] (MOVHUreg x)) && rc >= 16 => (MOVVconst [0])
|
||||||
(SRLVconst [rc] (MOVBUreg x)) && rc >= 8 => (MOVVconst [0])
|
(SRLVconst [rc] (MOVBUreg x)) && rc >= 8 => (MOVVconst [0])
|
||||||
|
|
||||||
|
// (x + x) << c -> x << c+1
|
||||||
|
((SLLV|SLL)const [c] (ADDV x x)) => ((SLLV|SLL)const [c+1] x)
|
||||||
|
|
||||||
// mul by constant
|
// mul by constant
|
||||||
(MULV _ (MOVVconst [0])) => (MOVVconst [0])
|
(MULV _ (MOVVconst [0])) => (MOVVconst [0])
|
||||||
(MULV x (MOVVconst [1])) => x
|
(MULV x (MOVVconst [1])) => x
|
||||||
|
|
@ -758,6 +750,8 @@
|
||||||
(MULV (NEGV x) (MOVVconst [c])) => (MULV x (MOVVconst [-c]))
|
(MULV (NEGV x) (MOVVconst [c])) => (MULV x (MOVVconst [-c]))
|
||||||
(MULV (NEGV x) (NEGV y)) => (MULV x y)
|
(MULV (NEGV x) (NEGV y)) => (MULV x y)
|
||||||
|
|
||||||
|
(ADDV x0 x1:(SLLVconst [c] y)) && x1.Uses == 1 && c > 0 && c <= 4 => (ADDshiftLLV x0 y [c])
|
||||||
|
|
||||||
// div by constant
|
// div by constant
|
||||||
(DIVVU x (MOVVconst [1])) => x
|
(DIVVU x (MOVVconst [1])) => x
|
||||||
(DIVVU x (MOVVconst [c])) && isPowerOfTwo(c) => (SRLVconst [log64(c)] x)
|
(DIVVU x (MOVVconst [c])) && isPowerOfTwo(c) => (SRLVconst [log64(c)] x)
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import "strings"
|
||||||
// so that regmask stays within int64
|
// so that regmask stays within int64
|
||||||
// Be careful when hand coding regmasks.
|
// Be careful when hand coding regmasks.
|
||||||
var regNamesLOONG64 = []string{
|
var regNamesLOONG64 = []string{
|
||||||
"R0", // constant 0
|
"ZERO", // constant 0
|
||||||
"R1",
|
"R1",
|
||||||
"SP", // aka R3
|
"SP", // aka R3
|
||||||
"R4",
|
"R4",
|
||||||
|
|
@ -131,18 +131,18 @@ func init() {
|
||||||
fp = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31")
|
fp = buildReg("F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 F21 F22 F23 F24 F25 F26 F27 F28 F29 F30 F31")
|
||||||
callerSave = gp | fp | buildReg("g") // runtime.setg (and anything calling it) may clobber g
|
callerSave = gp | fp | buildReg("g") // runtime.setg (and anything calling it) may clobber g
|
||||||
first16 = buildReg("R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19")
|
first16 = buildReg("R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19")
|
||||||
|
rz = buildReg("ZERO")
|
||||||
)
|
)
|
||||||
// Common regInfo
|
// Common regInfo
|
||||||
var (
|
var (
|
||||||
gp01 = regInfo{inputs: nil, outputs: []regMask{gp}}
|
gp01 = regInfo{inputs: nil, outputs: []regMask{gp}}
|
||||||
gp11 = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
|
gp11 = regInfo{inputs: []regMask{gpg}, outputs: []regMask{gp}}
|
||||||
gp11sp = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
|
gp11sp = regInfo{inputs: []regMask{gpspg}, outputs: []regMask{gp}}
|
||||||
gp21 = regInfo{inputs: []regMask{gpg, gpg}, outputs: []regMask{gp}}
|
gp21 = regInfo{inputs: []regMask{gpg, gpg | rz}, outputs: []regMask{gp}}
|
||||||
gpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
|
gpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}
|
||||||
gp2load = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
|
gp2load = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
|
||||||
gpstore = regInfo{inputs: []regMask{gpspsbg, gpg}}
|
gpstore = regInfo{inputs: []regMask{gpspsbg, gpg}}
|
||||||
gpstore0 = regInfo{inputs: []regMask{gpspsbg}}
|
gpstore2 = regInfo{inputs: []regMask{gpspsbg, gpg, gpg | rz}}
|
||||||
gpstore2 = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}}
|
|
||||||
gpxchg = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
|
gpxchg = regInfo{inputs: []regMask{gpspsbg, gpg}, outputs: []regMask{gp}}
|
||||||
gpcas = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}, outputs: []regMask{gp}}
|
gpcas = regInfo{inputs: []regMask{gpspsbg, gpg, gpg}, outputs: []regMask{gp}}
|
||||||
preldreg = regInfo{inputs: []regMask{gpspg}}
|
preldreg = regInfo{inputs: []regMask{gpspg}}
|
||||||
|
|
@ -177,6 +177,7 @@ func init() {
|
||||||
|
|
||||||
{name: "REVB2H", argLength: 1, reg: gp11, asm: "REVB2H"}, // Swap bytes: 0x11223344 -> 0x22114433 (sign extends to 64 bits)
|
{name: "REVB2H", argLength: 1, reg: gp11, asm: "REVB2H"}, // Swap bytes: 0x11223344 -> 0x22114433 (sign extends to 64 bits)
|
||||||
{name: "REVB2W", argLength: 1, reg: gp11, asm: "REVB2W"}, // Swap bytes: 0x1122334455667788 -> 0x4433221188776655
|
{name: "REVB2W", argLength: 1, reg: gp11, asm: "REVB2W"}, // Swap bytes: 0x1122334455667788 -> 0x4433221188776655
|
||||||
|
{name: "REVB4H", argLength: 1, reg: gp11, asm: "REVB4H"}, // Swap bytes: 0x1122334455667788 -> 0x2211443366558877
|
||||||
{name: "REVBV", argLength: 1, reg: gp11, asm: "REVBV"}, // Swap bytes: 0x1122334455667788 -> 0x8877665544332211
|
{name: "REVBV", argLength: 1, reg: gp11, asm: "REVBV"}, // Swap bytes: 0x1122334455667788 -> 0x8877665544332211
|
||||||
|
|
||||||
{name: "BITREV4B", argLength: 1, reg: gp11, asm: "BITREV4B"}, // Reverse the bits of each byte inside a 32-bit arg[0]
|
{name: "BITREV4B", argLength: 1, reg: gp11, asm: "BITREV4B"}, // Reverse the bits of each byte inside a 32-bit arg[0]
|
||||||
|
|
@ -304,12 +305,12 @@ func init() {
|
||||||
{name: "MOVFloadidx", argLength: 3, reg: fp2load, asm: "MOVF", typ: "Float32"}, // load 32-bit float from arg0 + arg1, arg2=mem.
|
{name: "MOVFloadidx", argLength: 3, reg: fp2load, asm: "MOVF", typ: "Float32"}, // load 32-bit float from arg0 + arg1, arg2=mem.
|
||||||
{name: "MOVDloadidx", argLength: 3, reg: fp2load, asm: "MOVD", typ: "Float64"}, // load 64-bit float from arg0 + arg1, arg2=mem.
|
{name: "MOVDloadidx", argLength: 3, reg: fp2load, asm: "MOVD", typ: "Float64"}, // load 64-bit float from arg0 + arg1, arg2=mem.
|
||||||
|
|
||||||
{name: "MOVBstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 1 byte of arg1 to arg0 + auxInt + aux. arg2=mem.
|
{name: "MOVBstore", argLength: 3, reg: regInfo{inputs: []regMask{gpspsbg, gpg | rz}}, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 1 byte of arg1 to arg0 + auxInt + aux. arg2=mem.
|
||||||
{name: "MOVHstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
|
{name: "MOVHstore", argLength: 3, reg: regInfo{inputs: []regMask{gpspsbg, gpg | rz}}, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
|
||||||
{name: "MOVWstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
|
{name: "MOVWstore", argLength: 3, reg: regInfo{inputs: []regMask{gpspsbg, gpg | rz}}, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
|
||||||
{name: "MOVVstore", argLength: 3, reg: gpstore, aux: "SymOff", asm: "MOVV", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
|
{name: "MOVVstore", argLength: 3, reg: regInfo{inputs: []regMask{gpspsbg, gpg | rz}}, aux: "SymOff", asm: "MOVV", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
|
||||||
{name: "MOVFstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVF", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
|
{name: "MOVFstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVF", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
|
||||||
{name: "MOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
|
{name: "MOVDstore", argLength: 3, reg: fpstore, aux: "SymOff", asm: "MOVD", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of arg1 to arg0 + auxInt + aux. arg2=mem.
|
||||||
|
|
||||||
// register indexed store
|
// register indexed store
|
||||||
{name: "MOVBstoreidx", argLength: 4, reg: gpstore2, asm: "MOVB", typ: "Mem"}, // store 1 byte of arg2 to arg0 + arg1, arg3 = mem.
|
{name: "MOVBstoreidx", argLength: 4, reg: gpstore2, asm: "MOVB", typ: "Mem"}, // store 1 byte of arg2 to arg0 + arg1, arg3 = mem.
|
||||||
|
|
@ -319,17 +320,6 @@ func init() {
|
||||||
{name: "MOVFstoreidx", argLength: 4, reg: fpstore2, asm: "MOVF", typ: "Mem"}, // store 32-bit float of arg2 to arg0 + arg1, arg3=mem.
|
{name: "MOVFstoreidx", argLength: 4, reg: fpstore2, asm: "MOVF", typ: "Mem"}, // store 32-bit float of arg2 to arg0 + arg1, arg3=mem.
|
||||||
{name: "MOVDstoreidx", argLength: 4, reg: fpstore2, asm: "MOVD", typ: "Mem"}, // store 64-bit float of arg2 to arg0 + arg1, arg3=mem.
|
{name: "MOVDstoreidx", argLength: 4, reg: fpstore2, asm: "MOVD", typ: "Mem"}, // store 64-bit float of arg2 to arg0 + arg1, arg3=mem.
|
||||||
|
|
||||||
{name: "MOVBstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVB", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 1 byte of zero to arg0 + auxInt + aux. arg1=mem.
|
|
||||||
{name: "MOVHstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVH", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 2 bytes of zero to arg0 + auxInt + aux. arg1=mem.
|
|
||||||
{name: "MOVWstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVW", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 4 bytes of zero to arg0 + auxInt + aux. arg1=mem.
|
|
||||||
{name: "MOVVstorezero", argLength: 2, reg: gpstore0, aux: "SymOff", asm: "MOVV", typ: "Mem", faultOnNilArg0: true, symEffect: "Write"}, // store 8 bytes of zero to arg0 + auxInt + aux. ar12=mem.
|
|
||||||
|
|
||||||
// register indexed store zero
|
|
||||||
{name: "MOVBstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVB", typ: "Mem"}, // store 1 byte of zero to arg0 + arg1, arg2 = mem.
|
|
||||||
{name: "MOVHstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVH", typ: "Mem"}, // store 2 bytes of zero to arg0 + arg1, arg2 = mem.
|
|
||||||
{name: "MOVWstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVW", typ: "Mem"}, // store 4 bytes of zero to arg0 + arg1, arg2 = mem.
|
|
||||||
{name: "MOVVstorezeroidx", argLength: 3, reg: gpstore, asm: "MOVV", typ: "Mem"}, // store 8 bytes of zero to arg0 + arg1, arg2 = mem.
|
|
||||||
|
|
||||||
// moves (no conversion)
|
// moves (no conversion)
|
||||||
{name: "MOVWfpgp", argLength: 1, reg: fpgp, asm: "MOVW"}, // move float32 to int32 (no conversion).
|
{name: "MOVWfpgp", argLength: 1, reg: fpgp, asm: "MOVW"}, // move float32 to int32 (no conversion).
|
||||||
{name: "MOVWgpfp", argLength: 1, reg: gpfp, asm: "MOVW"}, // move int32 to float32 (no conversion).
|
{name: "MOVWgpfp", argLength: 1, reg: gpfp, asm: "MOVW"}, // move int32 to float32 (no conversion).
|
||||||
|
|
@ -386,6 +376,21 @@ func init() {
|
||||||
faultOnNilArg0: true,
|
faultOnNilArg0: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// medium zeroing
|
||||||
|
// arg0 = address of memory to zero
|
||||||
|
// arg1 = mem
|
||||||
|
// auxint = number of bytes to zero
|
||||||
|
// returns mem
|
||||||
|
{
|
||||||
|
name: "LoweredZero",
|
||||||
|
aux: "Int64",
|
||||||
|
argLength: 2,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []regMask{gp},
|
||||||
|
},
|
||||||
|
faultOnNilArg0: true,
|
||||||
|
},
|
||||||
|
|
||||||
// duffcopy
|
// duffcopy
|
||||||
// arg0 = address of dst memory (in R21, changed as side effect)
|
// arg0 = address of dst memory (in R21, changed as side effect)
|
||||||
// arg1 = address of src memory (in R20, changed as side effect)
|
// arg1 = address of src memory (in R20, changed as side effect)
|
||||||
|
|
@ -405,25 +410,21 @@ func init() {
|
||||||
faultOnNilArg1: true,
|
faultOnNilArg1: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// large or unaligned zeroing
|
// large zeroing
|
||||||
// arg0 = address of memory to zero (in R20, changed as side effect)
|
// arg0 = address of memory to zero
|
||||||
// arg1 = address of the last element to zero
|
// arg1 = mem
|
||||||
// arg2 = mem
|
// auxint = number of bytes to zero
|
||||||
// auxint = alignment
|
|
||||||
// returns mem
|
// returns mem
|
||||||
// MOVx R0, (R20)
|
|
||||||
// ADDV $sz, R20
|
|
||||||
// BGEU Rarg1, R20, -2(PC)
|
|
||||||
{
|
{
|
||||||
name: "LoweredZero",
|
name: "LoweredZeroLoop",
|
||||||
aux: "Int64",
|
aux: "Int64",
|
||||||
argLength: 3,
|
argLength: 2,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []regMask{buildReg("R20"), gp},
|
inputs: []regMask{gp},
|
||||||
clobbers: buildReg("R20"),
|
clobbersArg0: true,
|
||||||
},
|
},
|
||||||
typ: "Mem",
|
|
||||||
faultOnNilArg0: true,
|
faultOnNilArg0: true,
|
||||||
|
needIntTemp: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// large or unaligned move
|
// large or unaligned move
|
||||||
|
|
@ -579,6 +580,7 @@ func init() {
|
||||||
{name: "PRELDX", argLength: 2, aux: "Int64", reg: preldreg, asm: "PRELDX", hasSideEffects: true},
|
{name: "PRELDX", argLength: 2, aux: "Int64", reg: preldreg, asm: "PRELDX", hasSideEffects: true},
|
||||||
|
|
||||||
{name: "ADDshiftLLV", argLength: 2, aux: "Int64", reg: gp21, asm: "ALSLV"}, // arg0 + arg1<<auxInt, the value of auxInt should be in the range [1, 4].
|
{name: "ADDshiftLLV", argLength: 2, aux: "Int64", reg: gp21, asm: "ALSLV"}, // arg0 + arg1<<auxInt, the value of auxInt should be in the range [1, 4].
|
||||||
|
{name: "ZERO", zeroWidth: true, fixedReg: true},
|
||||||
}
|
}
|
||||||
|
|
||||||
blocks := []blockData{
|
blocks := []blockData{
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,6 @@
|
||||||
|
|
||||||
(EQZ (XOR x y) yes no) => (BEQ x y yes no)
|
(EQZ (XOR x y) yes no) => (BEQ x y yes no)
|
||||||
(NEZ (XOR x y) yes no) => (BNE x y yes no)
|
(NEZ (XOR x y) yes no) => (BNE x y yes no)
|
||||||
|
|
||||||
|
// use zero register
|
||||||
|
(MOVVconst [0]) => (ZERO)
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,7 @@
|
||||||
(Mul64 ...) => (MUL ...)
|
(Mul64 ...) => (MUL ...)
|
||||||
(Mul64uhilo ...) => (LoweredMuluhilo ...)
|
(Mul64uhilo ...) => (LoweredMuluhilo ...)
|
||||||
(Mul64uover ...) => (LoweredMuluover ...)
|
(Mul64uover ...) => (LoweredMuluover ...)
|
||||||
(Mul32 ...) => (MULW ...)
|
(Mul(32|16|8) ...) => (MULW ...)
|
||||||
(Mul16 x y) => (MULW (SignExt16to32 x) (SignExt16to32 y))
|
|
||||||
(Mul8 x y) => (MULW (SignExt8to32 x) (SignExt8to32 y))
|
|
||||||
(Mul(64|32)F ...) => (FMUL(D|S) ...)
|
(Mul(64|32)F ...) => (FMUL(D|S) ...)
|
||||||
|
|
||||||
(Div(64|32)F ...) => (FDIV(D|S) ...)
|
(Div(64|32)F ...) => (FDIV(D|S) ...)
|
||||||
|
|
|
||||||
|
|
@ -1900,22 +1900,10 @@
|
||||||
(Neq(8|16|32|64) s:(Sub(8|16|32|64) x y) (Const(8|16|32|64) [0])) && s.Uses == 1 => (Neq(8|16|32|64) x y)
|
(Neq(8|16|32|64) s:(Sub(8|16|32|64) x y) (Const(8|16|32|64) [0])) && s.Uses == 1 => (Neq(8|16|32|64) x y)
|
||||||
|
|
||||||
// Optimize bitsets
|
// Optimize bitsets
|
||||||
(Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y])) && oneBit8(y)
|
(Eq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [y])) (Const(8|16|32|64) <t> [y])) && oneBit(y)
|
||||||
=> (Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
|
=> (Neq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [y])) (Const(8|16|32|64) <t> [0]))
|
||||||
(Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y])) && oneBit16(y)
|
(Neq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [y])) (Const(8|16|32|64) <t> [y])) && oneBit(y)
|
||||||
=> (Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
|
=> (Eq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [y])) (Const(8|16|32|64) <t> [0]))
|
||||||
(Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y])) && oneBit32(y)
|
|
||||||
=> (Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
|
|
||||||
(Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y])) && oneBit64(y)
|
|
||||||
=> (Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
|
|
||||||
(Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y])) && oneBit8(y)
|
|
||||||
=> (Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
|
|
||||||
(Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y])) && oneBit16(y)
|
|
||||||
=> (Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
|
|
||||||
(Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y])) && oneBit32(y)
|
|
||||||
=> (Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
|
|
||||||
(Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y])) && oneBit64(y)
|
|
||||||
=> (Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
|
|
||||||
|
|
||||||
// Reassociate expressions involving
|
// Reassociate expressions involving
|
||||||
// constants such that constants come first,
|
// constants such that constants come first,
|
||||||
|
|
|
||||||
|
|
@ -3144,6 +3144,7 @@ const (
|
||||||
OpLOONG64CTZV
|
OpLOONG64CTZV
|
||||||
OpLOONG64REVB2H
|
OpLOONG64REVB2H
|
||||||
OpLOONG64REVB2W
|
OpLOONG64REVB2W
|
||||||
|
OpLOONG64REVB4H
|
||||||
OpLOONG64REVBV
|
OpLOONG64REVBV
|
||||||
OpLOONG64BITREV4B
|
OpLOONG64BITREV4B
|
||||||
OpLOONG64BITREVW
|
OpLOONG64BITREVW
|
||||||
|
|
@ -3257,14 +3258,6 @@ const (
|
||||||
OpLOONG64MOVVstoreidx
|
OpLOONG64MOVVstoreidx
|
||||||
OpLOONG64MOVFstoreidx
|
OpLOONG64MOVFstoreidx
|
||||||
OpLOONG64MOVDstoreidx
|
OpLOONG64MOVDstoreidx
|
||||||
OpLOONG64MOVBstorezero
|
|
||||||
OpLOONG64MOVHstorezero
|
|
||||||
OpLOONG64MOVWstorezero
|
|
||||||
OpLOONG64MOVVstorezero
|
|
||||||
OpLOONG64MOVBstorezeroidx
|
|
||||||
OpLOONG64MOVHstorezeroidx
|
|
||||||
OpLOONG64MOVWstorezeroidx
|
|
||||||
OpLOONG64MOVVstorezeroidx
|
|
||||||
OpLOONG64MOVWfpgp
|
OpLOONG64MOVWfpgp
|
||||||
OpLOONG64MOVWgpfp
|
OpLOONG64MOVWgpfp
|
||||||
OpLOONG64MOVVfpgp
|
OpLOONG64MOVVfpgp
|
||||||
|
|
@ -3294,8 +3287,9 @@ const (
|
||||||
OpLOONG64CALLclosure
|
OpLOONG64CALLclosure
|
||||||
OpLOONG64CALLinter
|
OpLOONG64CALLinter
|
||||||
OpLOONG64DUFFZERO
|
OpLOONG64DUFFZERO
|
||||||
OpLOONG64DUFFCOPY
|
|
||||||
OpLOONG64LoweredZero
|
OpLOONG64LoweredZero
|
||||||
|
OpLOONG64DUFFCOPY
|
||||||
|
OpLOONG64LoweredZeroLoop
|
||||||
OpLOONG64LoweredMove
|
OpLOONG64LoweredMove
|
||||||
OpLOONG64LoweredAtomicLoad8
|
OpLOONG64LoweredAtomicLoad8
|
||||||
OpLOONG64LoweredAtomicLoad32
|
OpLOONG64LoweredAtomicLoad32
|
||||||
|
|
@ -3336,6 +3330,7 @@ const (
|
||||||
OpLOONG64PRELD
|
OpLOONG64PRELD
|
||||||
OpLOONG64PRELDX
|
OpLOONG64PRELDX
|
||||||
OpLOONG64ADDshiftLLV
|
OpLOONG64ADDshiftLLV
|
||||||
|
OpLOONG64ZERO
|
||||||
|
|
||||||
OpMIPSADD
|
OpMIPSADD
|
||||||
OpMIPSADDconst
|
OpMIPSADDconst
|
||||||
|
|
@ -46695,6 +46690,19 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "REVB4H",
|
||||||
|
argLen: 1,
|
||||||
|
asm: loong64.AREVB4H,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
},
|
||||||
|
outputs: []outputInfo{
|
||||||
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "REVBV",
|
name: "REVBV",
|
||||||
argLen: 1,
|
argLen: 1,
|
||||||
|
|
@ -46794,7 +46802,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -46822,7 +46830,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -46851,7 +46859,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -46866,7 +46874,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -46881,7 +46889,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -46895,7 +46903,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -46909,7 +46917,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -46923,7 +46931,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -46937,7 +46945,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47068,7 +47076,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47097,7 +47105,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47126,7 +47134,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47155,7 +47163,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47183,7 +47191,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47197,7 +47205,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47403,7 +47411,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47417,7 +47425,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47445,7 +47453,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47459,7 +47467,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47501,7 +47509,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47515,7 +47523,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47557,7 +47565,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47571,7 +47579,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47613,7 +47621,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47627,7 +47635,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47669,7 +47677,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -47697,7 +47705,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
|
@ -48143,7 +48151,7 @@ var opcodeTable = [...]opInfo{
|
||||||
asm: loong64.AMOVB,
|
asm: loong64.AMOVB,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -48157,7 +48165,7 @@ var opcodeTable = [...]opInfo{
|
||||||
asm: loong64.AMOVH,
|
asm: loong64.AMOVH,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -48171,7 +48179,7 @@ var opcodeTable = [...]opInfo{
|
||||||
asm: loong64.AMOVW,
|
asm: loong64.AMOVW,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -48185,7 +48193,7 @@ var opcodeTable = [...]opInfo{
|
||||||
asm: loong64.AMOVV,
|
asm: loong64.AMOVV,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -48225,7 +48233,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{2, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{2, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -48237,7 +48245,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{2, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{2, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -48249,7 +48257,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{2, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{2, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -48261,7 +48269,7 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{2, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{2, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -48290,102 +48298,6 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "MOVBstorezero",
|
|
||||||
auxType: auxSymOff,
|
|
||||||
argLen: 2,
|
|
||||||
faultOnNilArg0: true,
|
|
||||||
symEffect: SymWrite,
|
|
||||||
asm: loong64.AMOVB,
|
|
||||||
reg: regInfo{
|
|
||||||
inputs: []inputInfo{
|
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "MOVHstorezero",
|
|
||||||
auxType: auxSymOff,
|
|
||||||
argLen: 2,
|
|
||||||
faultOnNilArg0: true,
|
|
||||||
symEffect: SymWrite,
|
|
||||||
asm: loong64.AMOVH,
|
|
||||||
reg: regInfo{
|
|
||||||
inputs: []inputInfo{
|
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "MOVWstorezero",
|
|
||||||
auxType: auxSymOff,
|
|
||||||
argLen: 2,
|
|
||||||
faultOnNilArg0: true,
|
|
||||||
symEffect: SymWrite,
|
|
||||||
asm: loong64.AMOVW,
|
|
||||||
reg: regInfo{
|
|
||||||
inputs: []inputInfo{
|
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "MOVVstorezero",
|
|
||||||
auxType: auxSymOff,
|
|
||||||
argLen: 2,
|
|
||||||
faultOnNilArg0: true,
|
|
||||||
symEffect: SymWrite,
|
|
||||||
asm: loong64.AMOVV,
|
|
||||||
reg: regInfo{
|
|
||||||
inputs: []inputInfo{
|
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "MOVBstorezeroidx",
|
|
||||||
argLen: 3,
|
|
||||||
asm: loong64.AMOVB,
|
|
||||||
reg: regInfo{
|
|
||||||
inputs: []inputInfo{
|
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "MOVHstorezeroidx",
|
|
||||||
argLen: 3,
|
|
||||||
asm: loong64.AMOVH,
|
|
||||||
reg: regInfo{
|
|
||||||
inputs: []inputInfo{
|
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "MOVWstorezeroidx",
|
|
||||||
argLen: 3,
|
|
||||||
asm: loong64.AMOVW,
|
|
||||||
reg: regInfo{
|
|
||||||
inputs: []inputInfo{
|
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "MOVVstorezeroidx",
|
|
||||||
argLen: 3,
|
|
||||||
asm: loong64.AMOVV,
|
|
||||||
reg: regInfo{
|
|
||||||
inputs: []inputInfo{
|
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
|
||||||
{0, 4611686019501129724}, // SP R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31 SB
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "MOVWfpgp",
|
name: "MOVWfpgp",
|
||||||
argLen: 1,
|
argLen: 1,
|
||||||
|
|
@ -48758,6 +48670,17 @@ var opcodeTable = [...]opInfo{
|
||||||
clobbers: 524290, // R1 R20
|
clobbers: 524290, // R1 R20
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "LoweredZero",
|
||||||
|
auxType: auxInt64,
|
||||||
|
argLen: 2,
|
||||||
|
faultOnNilArg0: true,
|
||||||
|
reg: regInfo{
|
||||||
|
inputs: []inputInfo{
|
||||||
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "DUFFCOPY",
|
name: "DUFFCOPY",
|
||||||
auxType: auxInt64,
|
auxType: auxInt64,
|
||||||
|
|
@ -48773,16 +48696,16 @@ var opcodeTable = [...]opInfo{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "LoweredZero",
|
name: "LoweredZeroLoop",
|
||||||
auxType: auxInt64,
|
auxType: auxInt64,
|
||||||
argLen: 3,
|
argLen: 2,
|
||||||
|
needIntTemp: true,
|
||||||
faultOnNilArg0: true,
|
faultOnNilArg0: true,
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 524288}, // R20
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
|
||||||
},
|
},
|
||||||
clobbers: 524288, // R20
|
clobbersArg0: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -49316,13 +49239,20 @@ var opcodeTable = [...]opInfo{
|
||||||
reg: regInfo{
|
reg: regInfo{
|
||||||
inputs: []inputInfo{
|
inputs: []inputInfo{
|
||||||
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
{1, 1073741816}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
{1, 1073741817}, // ZERO R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 g R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
outputs: []outputInfo{
|
outputs: []outputInfo{
|
||||||
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
{0, 1071644664}, // R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R23 R24 R25 R26 R27 R28 R29 R31
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "ZERO",
|
||||||
|
argLen: 0,
|
||||||
|
zeroWidth: true,
|
||||||
|
fixedReg: true,
|
||||||
|
reg: regInfo{},
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: "ADD",
|
name: "ADD",
|
||||||
|
|
@ -72765,7 +72695,7 @@ var specialRegMaskARM64 = regMask(0)
|
||||||
var framepointerRegARM64 = int8(-1)
|
var framepointerRegARM64 = int8(-1)
|
||||||
var linkRegARM64 = int8(28)
|
var linkRegARM64 = int8(28)
|
||||||
var registersLOONG64 = [...]Register{
|
var registersLOONG64 = [...]Register{
|
||||||
{0, loong64.REG_R0, "R0"},
|
{0, loong64.REGZERO, "ZERO"},
|
||||||
{1, loong64.REG_R1, "R1"},
|
{1, loong64.REG_R1, "R1"},
|
||||||
{2, loong64.REGSP, "SP"},
|
{2, loong64.REGSP, "SP"},
|
||||||
{3, loong64.REG_R4, "R4"},
|
{3, loong64.REG_R4, "R4"},
|
||||||
|
|
|
||||||
|
|
@ -1438,7 +1438,7 @@ func (s *regAllocState) regalloc(f *Func) {
|
||||||
case OpSB:
|
case OpSB:
|
||||||
s.assignReg(s.SBReg, v, v)
|
s.assignReg(s.SBReg, v, v)
|
||||||
s.sb = v.ID
|
s.sb = v.ID
|
||||||
case OpARM64ZERO:
|
case OpARM64ZERO, OpLOONG64ZERO:
|
||||||
s.assignReg(s.ZeroIntReg, v, v)
|
s.assignReg(s.ZeroIntReg, v, v)
|
||||||
case OpAMD64Zero128, OpAMD64Zero256, OpAMD64Zero512:
|
case OpAMD64Zero128, OpAMD64Zero256, OpAMD64Zero512:
|
||||||
regspec := s.regspec(v)
|
regspec := s.regspec(v)
|
||||||
|
|
|
||||||
|
|
@ -470,11 +470,10 @@ func ntz32(x int32) int { return bits.TrailingZeros32(uint32(x)) }
|
||||||
func ntz16(x int16) int { return bits.TrailingZeros16(uint16(x)) }
|
func ntz16(x int16) int { return bits.TrailingZeros16(uint16(x)) }
|
||||||
func ntz8(x int8) int { return bits.TrailingZeros8(uint8(x)) }
|
func ntz8(x int8) int { return bits.TrailingZeros8(uint8(x)) }
|
||||||
|
|
||||||
func oneBit(x int64) bool { return x&(x-1) == 0 && x != 0 }
|
// oneBit reports whether x contains exactly one set bit.
|
||||||
func oneBit8(x int8) bool { return x&(x-1) == 0 && x != 0 }
|
func oneBit[T int8 | int16 | int32 | int64](x T) bool {
|
||||||
func oneBit16(x int16) bool { return x&(x-1) == 0 && x != 0 }
|
return x&(x-1) == 0 && x != 0
|
||||||
func oneBit32(x int32) bool { return x&(x-1) == 0 && x != 0 }
|
}
|
||||||
func oneBit64(x int64) bool { return x&(x-1) == 0 && x != 0 }
|
|
||||||
|
|
||||||
// nto returns the number of trailing ones.
|
// nto returns the number of trailing ones.
|
||||||
func nto(x int64) int64 {
|
func nto(x int64) int64 {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -4,11 +4,25 @@ package ssa
|
||||||
|
|
||||||
func rewriteValueLOONG64latelower(v *Value) bool {
|
func rewriteValueLOONG64latelower(v *Value) bool {
|
||||||
switch v.Op {
|
switch v.Op {
|
||||||
|
case OpLOONG64MOVVconst:
|
||||||
|
return rewriteValueLOONG64latelower_OpLOONG64MOVVconst(v)
|
||||||
case OpLOONG64SLLVconst:
|
case OpLOONG64SLLVconst:
|
||||||
return rewriteValueLOONG64latelower_OpLOONG64SLLVconst(v)
|
return rewriteValueLOONG64latelower_OpLOONG64SLLVconst(v)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
func rewriteValueLOONG64latelower_OpLOONG64MOVVconst(v *Value) bool {
|
||||||
|
// match: (MOVVconst [0])
|
||||||
|
// result: (ZERO)
|
||||||
|
for {
|
||||||
|
if auxIntToInt64(v.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpLOONG64ZERO)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
func rewriteValueLOONG64latelower_OpLOONG64SLLVconst(v *Value) bool {
|
func rewriteValueLOONG64latelower_OpLOONG64SLLVconst(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (SLLVconst [1] x)
|
// match: (SLLVconst [1] x)
|
||||||
|
|
|
||||||
|
|
@ -405,7 +405,8 @@ func rewriteValueRISCV64(v *Value) bool {
|
||||||
case OpMove:
|
case OpMove:
|
||||||
return rewriteValueRISCV64_OpMove(v)
|
return rewriteValueRISCV64_OpMove(v)
|
||||||
case OpMul16:
|
case OpMul16:
|
||||||
return rewriteValueRISCV64_OpMul16(v)
|
v.Op = OpRISCV64MULW
|
||||||
|
return true
|
||||||
case OpMul32:
|
case OpMul32:
|
||||||
v.Op = OpRISCV64MULW
|
v.Op = OpRISCV64MULW
|
||||||
return true
|
return true
|
||||||
|
|
@ -425,7 +426,8 @@ func rewriteValueRISCV64(v *Value) bool {
|
||||||
v.Op = OpRISCV64LoweredMuluover
|
v.Op = OpRISCV64LoweredMuluover
|
||||||
return true
|
return true
|
||||||
case OpMul8:
|
case OpMul8:
|
||||||
return rewriteValueRISCV64_OpMul8(v)
|
v.Op = OpRISCV64MULW
|
||||||
|
return true
|
||||||
case OpNeg16:
|
case OpNeg16:
|
||||||
v.Op = OpRISCV64NEG
|
v.Op = OpRISCV64NEG
|
||||||
return true
|
return true
|
||||||
|
|
@ -3255,44 +3257,6 @@ func rewriteValueRISCV64_OpMove(v *Value) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValueRISCV64_OpMul16(v *Value) bool {
|
|
||||||
v_1 := v.Args[1]
|
|
||||||
v_0 := v.Args[0]
|
|
||||||
b := v.Block
|
|
||||||
typ := &b.Func.Config.Types
|
|
||||||
// match: (Mul16 x y)
|
|
||||||
// result: (MULW (SignExt16to32 x) (SignExt16to32 y))
|
|
||||||
for {
|
|
||||||
x := v_0
|
|
||||||
y := v_1
|
|
||||||
v.reset(OpRISCV64MULW)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
|
|
||||||
v0.AddArg(x)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpSignExt16to32, typ.Int32)
|
|
||||||
v1.AddArg(y)
|
|
||||||
v.AddArg2(v0, v1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func rewriteValueRISCV64_OpMul8(v *Value) bool {
|
|
||||||
v_1 := v.Args[1]
|
|
||||||
v_0 := v.Args[0]
|
|
||||||
b := v.Block
|
|
||||||
typ := &b.Func.Config.Types
|
|
||||||
// match: (Mul8 x y)
|
|
||||||
// result: (MULW (SignExt8to32 x) (SignExt8to32 y))
|
|
||||||
for {
|
|
||||||
x := v_0
|
|
||||||
y := v_1
|
|
||||||
v.reset(OpRISCV64MULW)
|
|
||||||
v0 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
|
|
||||||
v0.AddArg(x)
|
|
||||||
v1 := b.NewValue0(v.Pos, OpSignExt8to32, typ.Int32)
|
|
||||||
v1.AddArg(y)
|
|
||||||
v.AddArg2(v0, v1)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func rewriteValueRISCV64_OpNeq16(v *Value) bool {
|
func rewriteValueRISCV64_OpNeq16(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
|
|
|
||||||
|
|
@ -8798,7 +8798,7 @@ func rewriteValuegeneric_OpEq16(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y]))
|
// match: (Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y]))
|
||||||
// cond: oneBit16(y)
|
// cond: oneBit(y)
|
||||||
// result: (Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
|
// result: (Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
|
||||||
for {
|
for {
|
||||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
|
@ -8815,7 +8815,7 @@ func rewriteValuegeneric_OpEq16(v *Value) bool {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
y := auxIntToInt16(v_0_1.AuxInt)
|
y := auxIntToInt16(v_0_1.AuxInt)
|
||||||
if v_1.Op != OpConst16 || v_1.Type != t || auxIntToInt16(v_1.AuxInt) != y || !(oneBit16(y)) {
|
if v_1.Op != OpConst16 || v_1.Type != t || auxIntToInt16(v_1.AuxInt) != y || !(oneBit(y)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpNeq16)
|
v.reset(OpNeq16)
|
||||||
|
|
@ -9662,7 +9662,7 @@ func rewriteValuegeneric_OpEq32(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y]))
|
// match: (Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y]))
|
||||||
// cond: oneBit32(y)
|
// cond: oneBit(y)
|
||||||
// result: (Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
|
// result: (Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
|
||||||
for {
|
for {
|
||||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
|
@ -9679,7 +9679,7 @@ func rewriteValuegeneric_OpEq32(v *Value) bool {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
y := auxIntToInt32(v_0_1.AuxInt)
|
y := auxIntToInt32(v_0_1.AuxInt)
|
||||||
if v_1.Op != OpConst32 || v_1.Type != t || auxIntToInt32(v_1.AuxInt) != y || !(oneBit32(y)) {
|
if v_1.Op != OpConst32 || v_1.Type != t || auxIntToInt32(v_1.AuxInt) != y || !(oneBit(y)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpNeq32)
|
v.reset(OpNeq32)
|
||||||
|
|
@ -10243,7 +10243,7 @@ func rewriteValuegeneric_OpEq64(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y]))
|
// match: (Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y]))
|
||||||
// cond: oneBit64(y)
|
// cond: oneBit(y)
|
||||||
// result: (Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
|
// result: (Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
|
||||||
for {
|
for {
|
||||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
|
@ -10260,7 +10260,7 @@ func rewriteValuegeneric_OpEq64(v *Value) bool {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
y := auxIntToInt64(v_0_1.AuxInt)
|
y := auxIntToInt64(v_0_1.AuxInt)
|
||||||
if v_1.Op != OpConst64 || v_1.Type != t || auxIntToInt64(v_1.AuxInt) != y || !(oneBit64(y)) {
|
if v_1.Op != OpConst64 || v_1.Type != t || auxIntToInt64(v_1.AuxInt) != y || !(oneBit(y)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpNeq64)
|
v.reset(OpNeq64)
|
||||||
|
|
@ -10665,7 +10665,7 @@ func rewriteValuegeneric_OpEq8(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y]))
|
// match: (Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y]))
|
||||||
// cond: oneBit8(y)
|
// cond: oneBit(y)
|
||||||
// result: (Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
|
// result: (Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
|
||||||
for {
|
for {
|
||||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
|
@ -10682,7 +10682,7 @@ func rewriteValuegeneric_OpEq8(v *Value) bool {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
y := auxIntToInt8(v_0_1.AuxInt)
|
y := auxIntToInt8(v_0_1.AuxInt)
|
||||||
if v_1.Op != OpConst8 || v_1.Type != t || auxIntToInt8(v_1.AuxInt) != y || !(oneBit8(y)) {
|
if v_1.Op != OpConst8 || v_1.Type != t || auxIntToInt8(v_1.AuxInt) != y || !(oneBit(y)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpNeq8)
|
v.reset(OpNeq8)
|
||||||
|
|
@ -20311,7 +20311,7 @@ func rewriteValuegeneric_OpNeq16(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y]))
|
// match: (Neq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [y]))
|
||||||
// cond: oneBit16(y)
|
// cond: oneBit(y)
|
||||||
// result: (Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
|
// result: (Eq16 (And16 <t> x (Const16 <t> [y])) (Const16 <t> [0]))
|
||||||
for {
|
for {
|
||||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
|
@ -20328,7 +20328,7 @@ func rewriteValuegeneric_OpNeq16(v *Value) bool {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
y := auxIntToInt16(v_0_1.AuxInt)
|
y := auxIntToInt16(v_0_1.AuxInt)
|
||||||
if v_1.Op != OpConst16 || v_1.Type != t || auxIntToInt16(v_1.AuxInt) != y || !(oneBit16(y)) {
|
if v_1.Op != OpConst16 || v_1.Type != t || auxIntToInt16(v_1.AuxInt) != y || !(oneBit(y)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpEq16)
|
v.reset(OpEq16)
|
||||||
|
|
@ -20498,7 +20498,7 @@ func rewriteValuegeneric_OpNeq32(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y]))
|
// match: (Neq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [y]))
|
||||||
// cond: oneBit32(y)
|
// cond: oneBit(y)
|
||||||
// result: (Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
|
// result: (Eq32 (And32 <t> x (Const32 <t> [y])) (Const32 <t> [0]))
|
||||||
for {
|
for {
|
||||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
|
@ -20515,7 +20515,7 @@ func rewriteValuegeneric_OpNeq32(v *Value) bool {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
y := auxIntToInt32(v_0_1.AuxInt)
|
y := auxIntToInt32(v_0_1.AuxInt)
|
||||||
if v_1.Op != OpConst32 || v_1.Type != t || auxIntToInt32(v_1.AuxInt) != y || !(oneBit32(y)) {
|
if v_1.Op != OpConst32 || v_1.Type != t || auxIntToInt32(v_1.AuxInt) != y || !(oneBit(y)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpEq32)
|
v.reset(OpEq32)
|
||||||
|
|
@ -20708,7 +20708,7 @@ func rewriteValuegeneric_OpNeq64(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y]))
|
// match: (Neq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [y]))
|
||||||
// cond: oneBit64(y)
|
// cond: oneBit(y)
|
||||||
// result: (Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
|
// result: (Eq64 (And64 <t> x (Const64 <t> [y])) (Const64 <t> [0]))
|
||||||
for {
|
for {
|
||||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
|
@ -20725,7 +20725,7 @@ func rewriteValuegeneric_OpNeq64(v *Value) bool {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
y := auxIntToInt64(v_0_1.AuxInt)
|
y := auxIntToInt64(v_0_1.AuxInt)
|
||||||
if v_1.Op != OpConst64 || v_1.Type != t || auxIntToInt64(v_1.AuxInt) != y || !(oneBit64(y)) {
|
if v_1.Op != OpConst64 || v_1.Type != t || auxIntToInt64(v_1.AuxInt) != y || !(oneBit(y)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpEq64)
|
v.reset(OpEq64)
|
||||||
|
|
@ -20918,7 +20918,7 @@ func rewriteValuegeneric_OpNeq8(v *Value) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// match: (Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y]))
|
// match: (Neq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [y]))
|
||||||
// cond: oneBit8(y)
|
// cond: oneBit(y)
|
||||||
// result: (Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
|
// result: (Eq8 (And8 <t> x (Const8 <t> [y])) (Const8 <t> [0]))
|
||||||
for {
|
for {
|
||||||
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
|
||||||
|
|
@ -20935,7 +20935,7 @@ func rewriteValuegeneric_OpNeq8(v *Value) bool {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
y := auxIntToInt8(v_0_1.AuxInt)
|
y := auxIntToInt8(v_0_1.AuxInt)
|
||||||
if v_1.Op != OpConst8 || v_1.Type != t || auxIntToInt8(v_1.AuxInt) != y || !(oneBit8(y)) {
|
if v_1.Op != OpConst8 || v_1.Type != t || auxIntToInt8(v_1.AuxInt) != y || !(oneBit(y)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
v.reset(OpEq8)
|
v.reset(OpEq8)
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,8 @@ func TestIntendedInlining(t *testing.T) {
|
||||||
"assemble64",
|
"assemble64",
|
||||||
},
|
},
|
||||||
"unicode/utf8": {
|
"unicode/utf8": {
|
||||||
|
"DecodeRune",
|
||||||
|
"DecodeRuneInString",
|
||||||
"FullRune",
|
"FullRune",
|
||||||
"FullRuneInString",
|
"FullRuneInString",
|
||||||
"RuneLen",
|
"RuneLen",
|
||||||
|
|
|
||||||
7
src/cmd/dist/test.go
vendored
7
src/cmd/dist/test.go
vendored
|
|
@ -677,7 +677,7 @@ func (t *tester) registerTests() {
|
||||||
}
|
}
|
||||||
t.registerStdTest(pkg)
|
t.registerStdTest(pkg)
|
||||||
}
|
}
|
||||||
if t.race {
|
if t.race && !t.short {
|
||||||
for _, pkg := range pkgs {
|
for _, pkg := range pkgs {
|
||||||
if t.packageHasBenchmarks(pkg) {
|
if t.packageHasBenchmarks(pkg) {
|
||||||
t.registerRaceBenchTest(pkg)
|
t.registerRaceBenchTest(pkg)
|
||||||
|
|
@ -1700,7 +1700,7 @@ func (t *tester) makeGOROOTUnwritable() (undo func()) {
|
||||||
func raceDetectorSupported(goos, goarch string) bool {
|
func raceDetectorSupported(goos, goarch string) bool {
|
||||||
switch goos {
|
switch goos {
|
||||||
case "linux":
|
case "linux":
|
||||||
return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64" || goarch == "s390x" || goarch == "loong64"
|
return goarch == "amd64" || goarch == "arm64" || goarch == "loong64" || goarch == "ppc64le" || goarch == "riscv64" || goarch == "s390x"
|
||||||
case "darwin":
|
case "darwin":
|
||||||
return goarch == "amd64" || goarch == "arm64"
|
return goarch == "amd64" || goarch == "arm64"
|
||||||
case "freebsd", "netbsd", "windows":
|
case "freebsd", "netbsd", "windows":
|
||||||
|
|
@ -1775,7 +1775,7 @@ func buildModeSupported(compiler, buildmode, goos, goarch string) bool {
|
||||||
"ios/amd64", "ios/arm64",
|
"ios/amd64", "ios/arm64",
|
||||||
"aix/ppc64",
|
"aix/ppc64",
|
||||||
"openbsd/arm64",
|
"openbsd/arm64",
|
||||||
"windows/386", "windows/amd64", "windows/arm", "windows/arm64":
|
"windows/386", "windows/amd64", "windows/arm64":
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
@ -1837,7 +1837,6 @@ func (t *tester) fipsSupported() bool {
|
||||||
switch {
|
switch {
|
||||||
case goarch == "wasm",
|
case goarch == "wasm",
|
||||||
goos == "windows" && goarch == "386",
|
goos == "windows" && goarch == "386",
|
||||||
goos == "windows" && goarch == "arm",
|
|
||||||
goos == "openbsd",
|
goos == "openbsd",
|
||||||
goos == "aix":
|
goos == "aix":
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
5
src/cmd/dist/util.go
vendored
5
src/cmd/dist/util.go
vendored
|
|
@ -366,9 +366,8 @@ func xgetgoarm() string {
|
||||||
// If we're building on an actual arm system, and not building
|
// If we're building on an actual arm system, and not building
|
||||||
// a cross-compiling toolchain, try to exec ourselves
|
// a cross-compiling toolchain, try to exec ourselves
|
||||||
// to detect whether VFP is supported and set the default GOARM.
|
// to detect whether VFP is supported and set the default GOARM.
|
||||||
// Windows requires ARMv7, so we can skip the check.
|
// We've always assumed Android is ARMv7.
|
||||||
// We've always assumed Android is ARMv7 too.
|
if gohostarch == "arm" && goarch == "arm" && goos == gohostos && goos != "android" {
|
||||||
if gohostarch == "arm" && goarch == "arm" && goos == gohostos && goos != "windows" && goos != "android" {
|
|
||||||
// Try to exec ourselves in a mode to detect VFP support.
|
// Try to exec ourselves in a mode to detect VFP support.
|
||||||
// Seeing how far it gets determines which instructions failed.
|
// Seeing how far it gets determines which instructions failed.
|
||||||
// The test is OS-agnostic.
|
// The test is OS-agnostic.
|
||||||
|
|
|
||||||
|
|
@ -121,8 +121,9 @@
|
||||||
// The default is GOMAXPROCS, normally the number of CPUs available.
|
// The default is GOMAXPROCS, normally the number of CPUs available.
|
||||||
// -race
|
// -race
|
||||||
// enable data race detection.
|
// enable data race detection.
|
||||||
// Supported only on linux/amd64, freebsd/amd64, darwin/amd64, darwin/arm64, windows/amd64,
|
// Supported only on darwin/amd64, darwin/arm64, freebsd/amd64, linux/amd64,
|
||||||
// linux/ppc64le and linux/arm64 (only for 48-bit VMA).
|
// linux/arm64 (only for 48-bit VMA), linux/ppc64le, linux/riscv64 and
|
||||||
|
// windows/amd64.
|
||||||
// -msan
|
// -msan
|
||||||
// enable interoperation with memory sanitizer.
|
// enable interoperation with memory sanitizer.
|
||||||
// Supported only on linux/amd64, linux/arm64, linux/loong64, freebsd/amd64
|
// Supported only on linux/amd64, linux/arm64, linux/loong64, freebsd/amd64
|
||||||
|
|
@ -2407,8 +2408,10 @@
|
||||||
// The name of checksum database to use and optionally its public key and
|
// The name of checksum database to use and optionally its public key and
|
||||||
// URL. See https://golang.org/ref/mod#authenticating.
|
// URL. See https://golang.org/ref/mod#authenticating.
|
||||||
// GOTMPDIR
|
// GOTMPDIR
|
||||||
// The directory where the go command will write
|
// Temporary directory used by the go command and testing package.
|
||||||
// temporary source files, packages, and binaries.
|
// Overrides the platform-specific temporary directory such as "/tmp".
|
||||||
|
// The go command and testing package will write temporary source files,
|
||||||
|
// packages, and binaries here.
|
||||||
// GOTOOLCHAIN
|
// GOTOOLCHAIN
|
||||||
// Controls which Go toolchain is used. See https://go.dev/doc/toolchain.
|
// Controls which Go toolchain is used. See https://go.dev/doc/toolchain.
|
||||||
// GOVCS
|
// GOVCS
|
||||||
|
|
|
||||||
|
|
@ -573,8 +573,10 @@ General-purpose environment variables:
|
||||||
The name of checksum database to use and optionally its public key and
|
The name of checksum database to use and optionally its public key and
|
||||||
URL. See https://golang.org/ref/mod#authenticating.
|
URL. See https://golang.org/ref/mod#authenticating.
|
||||||
GOTMPDIR
|
GOTMPDIR
|
||||||
The directory where the go command will write
|
Temporary directory used by the go command and testing package.
|
||||||
temporary source files, packages, and binaries.
|
Overrides the platform-specific temporary directory such as "/tmp".
|
||||||
|
The go command and testing package will write temporary source files,
|
||||||
|
packages, and binaries here.
|
||||||
GOTOOLCHAIN
|
GOTOOLCHAIN
|
||||||
Controls which Go toolchain is used. See https://go.dev/doc/toolchain.
|
Controls which Go toolchain is used. See https://go.dev/doc/toolchain.
|
||||||
GOVCS
|
GOVCS
|
||||||
|
|
|
||||||
|
|
@ -77,8 +77,9 @@ and test commands:
|
||||||
The default is GOMAXPROCS, normally the number of CPUs available.
|
The default is GOMAXPROCS, normally the number of CPUs available.
|
||||||
-race
|
-race
|
||||||
enable data race detection.
|
enable data race detection.
|
||||||
Supported only on linux/amd64, freebsd/amd64, darwin/amd64, darwin/arm64, windows/amd64,
|
Supported only on darwin/amd64, darwin/arm64, freebsd/amd64, linux/amd64,
|
||||||
linux/ppc64le and linux/arm64 (only for 48-bit VMA).
|
linux/arm64 (only for 48-bit VMA), linux/ppc64le, linux/riscv64 and
|
||||||
|
windows/amd64.
|
||||||
-msan
|
-msan
|
||||||
enable interoperation with memory sanitizer.
|
enable interoperation with memory sanitizer.
|
||||||
Supported only on linux/amd64, linux/arm64, linux/loong64, freebsd/amd64
|
Supported only on linux/amd64, linux/arm64, linux/loong64, freebsd/amd64
|
||||||
|
|
|
||||||
|
|
@ -87,10 +87,8 @@ func initParserMode() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isGoFile(f fs.DirEntry) bool {
|
func isGoFilename(name string) bool {
|
||||||
// ignore non-Go files
|
return !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
|
||||||
name := f.Name()
|
|
||||||
return !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") && !f.IsDir()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A sequencer performs concurrent tasks that may write output, but emits that
|
// A sequencer performs concurrent tasks that may write output, but emits that
|
||||||
|
|
@ -411,34 +409,30 @@ func gofmtMain(s *sequencer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
switch info, err := os.Stat(arg); {
|
// Walk each given argument as a directory tree.
|
||||||
case err != nil:
|
// If the argument is not a directory, it's always formatted as a Go file.
|
||||||
s.AddReport(err)
|
// If the argument is a directory, we walk it, ignoring non-Go files.
|
||||||
case !info.IsDir():
|
if err := filepath.WalkDir(arg, func(path string, d fs.DirEntry, err error) error {
|
||||||
// Non-directory arguments are always formatted.
|
switch {
|
||||||
arg := arg
|
case err != nil:
|
||||||
s.Add(fileWeight(arg, info), func(r *reporter) error {
|
return err
|
||||||
return processFile(arg, info, nil, r)
|
case d.IsDir():
|
||||||
})
|
return nil // simply recurse into directories
|
||||||
default:
|
case path == arg:
|
||||||
// Directories are walked, ignoring non-Go files.
|
// non-directories given as explicit arguments are always formatted
|
||||||
err := filepath.WalkDir(arg, func(path string, f fs.DirEntry, err error) error {
|
case !isGoFilename(d.Name()):
|
||||||
if err != nil || !isGoFile(f) {
|
return nil // skip walked non-Go files
|
||||||
return err
|
|
||||||
}
|
|
||||||
info, err := f.Info()
|
|
||||||
if err != nil {
|
|
||||||
s.AddReport(err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
s.Add(fileWeight(path, info), func(r *reporter) error {
|
|
||||||
return processFile(path, info, nil, r)
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
s.AddReport(err)
|
|
||||||
}
|
}
|
||||||
|
info, err := d.Info()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s.Add(fileWeight(path, info), func(r *reporter) error {
|
||||||
|
return processFile(path, info, nil, r)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}); err != nil {
|
||||||
|
s.AddReport(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ func genFilenames(t *testing.T, filenames chan<- string) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// don't descend into testdata directories
|
// don't descend into testdata directories
|
||||||
if isGoFile(d) && !strings.Contains(filepath.ToSlash(filename), "/testdata/") {
|
if !d.IsDir() && isGoFilename(d.Name()) && !strings.Contains(filepath.ToSlash(filename), "/testdata/") {
|
||||||
filenames <- filename
|
filenames <- filename
|
||||||
nfiles++
|
nfiles++
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -196,14 +196,8 @@ func EnableFIPS() bool {
|
||||||
// Perhaps the default should be changed back to -buildmode=exe,
|
// Perhaps the default should be changed back to -buildmode=exe,
|
||||||
// after which we could remove this case, but until then,
|
// after which we could remove this case, but until then,
|
||||||
// skip FIPS on windows-386.
|
// skip FIPS on windows-386.
|
||||||
//
|
if buildcfg.GOOS == "windows" && buildcfg.GOARCH == "386" {
|
||||||
// We don't know whether arm works, because it is too hard to get builder
|
return false
|
||||||
// time to test it. Disable since it's not important right now.
|
|
||||||
if buildcfg.GOOS == "windows" {
|
|
||||||
switch buildcfg.GOARCH {
|
|
||||||
case "386", "arm":
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AIX doesn't just work, and it's not worth fixing.
|
// AIX doesn't just work, and it's not worth fixing.
|
||||||
|
|
|
||||||
|
|
@ -666,6 +666,10 @@ const (
|
||||||
ABSTRPICKW
|
ABSTRPICKW
|
||||||
ABSTRPICKV
|
ABSTRPICKV
|
||||||
|
|
||||||
|
// 2.2.5.3
|
||||||
|
AMOVWP
|
||||||
|
AMOVVP
|
||||||
|
|
||||||
// 2.2.5.4. Prefetch Instructions
|
// 2.2.5.4. Prefetch Instructions
|
||||||
APRELD
|
APRELD
|
||||||
APRELDX
|
APRELDX
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,8 @@ var Anames = []string{
|
||||||
"BSTRINSV",
|
"BSTRINSV",
|
||||||
"BSTRPICKW",
|
"BSTRPICKW",
|
||||||
"BSTRPICKV",
|
"BSTRPICKV",
|
||||||
|
"MOVWP",
|
||||||
|
"MOVVP",
|
||||||
"PRELD",
|
"PRELD",
|
||||||
"PRELDX",
|
"PRELDX",
|
||||||
"CRCWBW",
|
"CRCWBW",
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,8 @@ var optab = []Optab{
|
||||||
{AMOVV, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
|
{AMOVV, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
|
||||||
{AMOVB, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
|
{AMOVB, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
|
||||||
{AMOVBU, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
|
{AMOVBU, C_REG, C_NONE, C_NONE, C_TLS_LE, C_NONE, 53, 16, 0, 0},
|
||||||
|
{AMOVWP, C_REG, C_NONE, C_NONE, C_SOREG, C_NONE, 73, 4, 0, 0},
|
||||||
|
{AMOVWP, C_REG, C_NONE, C_NONE, C_LOREG, C_NONE, 73, 4, 0, 0},
|
||||||
|
|
||||||
{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
|
{AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
|
||||||
{AMOVWU, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
|
{AMOVWU, C_LAUTO, C_NONE, C_NONE, C_REG, C_NONE, 36, 12, REGSP, 0},
|
||||||
|
|
@ -233,6 +235,8 @@ var optab = []Optab{
|
||||||
{AMOVV, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
|
{AMOVV, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
|
||||||
{AMOVB, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
|
{AMOVB, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
|
||||||
{AMOVBU, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
|
{AMOVBU, C_TLS_LE, C_NONE, C_NONE, C_REG, C_NONE, 54, 16, 0, 0},
|
||||||
|
{AMOVWP, C_SOREG, C_NONE, C_NONE, C_REG, C_NONE, 74, 4, 0, 0},
|
||||||
|
{AMOVWP, C_LOREG, C_NONE, C_NONE, C_REG, C_NONE, 74, 4, 0, 0},
|
||||||
|
|
||||||
{AMOVW, C_SACON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGSP, 0},
|
{AMOVW, C_SACON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGSP, 0},
|
||||||
{AMOVV, C_SACON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGSP, 0},
|
{AMOVV, C_SACON, C_NONE, C_NONE, C_REG, C_NONE, 3, 4, REGSP, 0},
|
||||||
|
|
@ -438,8 +442,6 @@ var optab = []Optab{
|
||||||
{obj.ANOP, C_FREG, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
|
{obj.ANOP, C_FREG, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0},
|
||||||
{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_BRAN, C_NONE, 11, 4, 0, 0}, // same as AJMP
|
{obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_BRAN, C_NONE, 11, 4, 0, 0}, // same as AJMP
|
||||||
{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_BRAN, C_NONE, 11, 4, 0, 0}, // same as AJMP
|
{obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_BRAN, C_NONE, 11, 4, 0, 0}, // same as AJMP
|
||||||
|
|
||||||
{obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var atomicInst = map[obj.As]uint32{
|
var atomicInst = map[obj.As]uint32{
|
||||||
|
|
@ -1303,31 +1305,27 @@ func buildop(ctxt *obj.Link) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var n int
|
for i := range C_NCLASS {
|
||||||
|
for j := range C_NCLASS {
|
||||||
for i := 0; i < C_NCLASS; i++ {
|
if cmp(j, i) {
|
||||||
for n = 0; n < C_NCLASS; n++ {
|
xcmp[i][j] = true
|
||||||
if cmp(n, i) {
|
|
||||||
xcmp[i][n] = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for n = 0; optab[n].as != obj.AXXX; n++ {
|
|
||||||
}
|
|
||||||
slices.SortFunc(optab[:n], ocmp)
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
r := optab[i].as
|
|
||||||
r0 := r & obj.AMask
|
|
||||||
start := i
|
|
||||||
for optab[i].as == r {
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
oprange[r0] = optab[start:i]
|
|
||||||
i--
|
|
||||||
|
|
||||||
switch r {
|
slices.SortFunc(optab, ocmp)
|
||||||
|
for i := 0; i < len(optab); i++ {
|
||||||
|
as, start := optab[i].as, i
|
||||||
|
for ; i < len(optab)-1; i++ {
|
||||||
|
if optab[i+1].as != as {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r0 := as & obj.AMask
|
||||||
|
oprange[r0] = optab[start : i+1]
|
||||||
|
switch as {
|
||||||
default:
|
default:
|
||||||
ctxt.Diag("unknown op in build: %v", r)
|
ctxt.Diag("unknown op in build: %v", as)
|
||||||
ctxt.DiagFlush()
|
ctxt.DiagFlush()
|
||||||
log.Fatalf("bad code")
|
log.Fatalf("bad code")
|
||||||
|
|
||||||
|
|
@ -1443,6 +1441,9 @@ func buildop(ctxt *obj.Link) {
|
||||||
case AMOVBU:
|
case AMOVBU:
|
||||||
opset(AMOVHU, r0)
|
opset(AMOVHU, r0)
|
||||||
|
|
||||||
|
case AMOVWP:
|
||||||
|
opset(AMOVVP, r0)
|
||||||
|
|
||||||
case AMUL:
|
case AMUL:
|
||||||
opset(AMULU, r0)
|
opset(AMULU, r0)
|
||||||
opset(AMULH, r0)
|
opset(AMULH, r0)
|
||||||
|
|
@ -1970,6 +1971,10 @@ func OP_16IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
|
||||||
return op | (i&0xFFFF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
|
return op | (i&0xFFFF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OP_14IRR(op uint32, i uint32, r2 uint32, r3 uint32) uint32 {
|
||||||
|
return op | (i&0x3FFF)<<10 | (r2&0x1F)<<5 | (r3&0x1F)<<0
|
||||||
|
}
|
||||||
|
|
||||||
func OP_12IR_5I(op uint32, i1 uint32, r2 uint32, i2 uint32) uint32 {
|
func OP_12IR_5I(op uint32, i1 uint32, r2 uint32, i2 uint32) uint32 {
|
||||||
return op | (i1&0xFFF)<<10 | (r2&0x1F)<<5 | (i2&0x1F)<<0
|
return op | (i1&0xFFF)<<10 | (r2&0x1F)<<5 | (i2&0x1F)<<0
|
||||||
}
|
}
|
||||||
|
|
@ -2899,6 +2904,20 @@ func (c *ctxt0) asmout(p *obj.Prog, o *Optab, out []uint32) {
|
||||||
o3 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
|
o3 = OP_12IRR(c.opirr(ALU52ID), uint32(v>>52), uint32(REGTMP), uint32(REGTMP))
|
||||||
}
|
}
|
||||||
o4 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
|
o4 = OP_RRR(c.oprrr(p.As), uint32(REGTMP), uint32(r), uint32(p.To.Reg))
|
||||||
|
|
||||||
|
case 73:
|
||||||
|
v := c.regoff(&p.To)
|
||||||
|
if v&3 != 0 {
|
||||||
|
c.ctxt.Diag("%v: offset must be a multiple of 4.\n", p)
|
||||||
|
}
|
||||||
|
o1 = OP_14IRR(c.opirr(p.As), uint32(v>>2), uint32(p.To.Reg), uint32(p.From.Reg))
|
||||||
|
|
||||||
|
case 74:
|
||||||
|
v := c.regoff(&p.From)
|
||||||
|
if v&3 != 0 {
|
||||||
|
c.ctxt.Diag("%v: offset must be a multiple of 4.\n", p)
|
||||||
|
}
|
||||||
|
o1 = OP_14IRR(c.opirr(-p.As), uint32(v>>2), uint32(p.From.Reg), uint32(p.To.Reg))
|
||||||
}
|
}
|
||||||
|
|
||||||
out[0] = o1
|
out[0] = o1
|
||||||
|
|
@ -4032,6 +4051,10 @@ func (c *ctxt0) opirr(a obj.As) uint32 {
|
||||||
return 0x0ad << 22
|
return 0x0ad << 22
|
||||||
case AMOVD:
|
case AMOVD:
|
||||||
return 0x0af << 22
|
return 0x0af << 22
|
||||||
|
case AMOVVP:
|
||||||
|
return 0x27 << 24 // stptr.d
|
||||||
|
case AMOVWP:
|
||||||
|
return 0x25 << 24 // stptr.w
|
||||||
case -AMOVB:
|
case -AMOVB:
|
||||||
return 0x0a0 << 22
|
return 0x0a0 << 22
|
||||||
case -AMOVBU:
|
case -AMOVBU:
|
||||||
|
|
@ -4050,6 +4073,10 @@ func (c *ctxt0) opirr(a obj.As) uint32 {
|
||||||
return 0x0ac << 22
|
return 0x0ac << 22
|
||||||
case -AMOVD:
|
case -AMOVD:
|
||||||
return 0x0ae << 22
|
return 0x0ae << 22
|
||||||
|
case -AMOVVP:
|
||||||
|
return 0x26 << 24 // ldptr.d
|
||||||
|
case -AMOVWP:
|
||||||
|
return 0x24 << 24 // ldptr.w
|
||||||
case -AVMOVQ:
|
case -AVMOVQ:
|
||||||
return 0x0b0 << 22 // vld
|
return 0x0b0 << 22 // vld
|
||||||
case -AXVMOVQ:
|
case -AXVMOVQ:
|
||||||
|
|
|
||||||
|
|
@ -289,6 +289,34 @@ Note: In the following sections 3.1 to 3.6, "ui4" (4-bit unsigned int immediate)
|
||||||
|
|
||||||
Go assembly | instruction Encoding
|
Go assembly | instruction Encoding
|
||||||
ALSLV $4, r4, r5, R6 | 002d9486
|
ALSLV $4, r4, r5, R6 | 002d9486
|
||||||
|
|
||||||
|
5. Note of special memory access instructions
|
||||||
|
Instruction format:
|
||||||
|
MOVWP offset(Rj), Rd
|
||||||
|
MOVVP offset(Rj), Rd
|
||||||
|
MOVWP Rd, offset(Rj)
|
||||||
|
MOVVP Rd, offset(Rj)
|
||||||
|
|
||||||
|
Mapping between Go and platform assembly:
|
||||||
|
Go assembly | platform assembly
|
||||||
|
MOVWP offset(Rj), Rd | ldptr.w rd, rj, si14
|
||||||
|
MOVVP offset(Rj), Rd | ldptr.d rd, rj, si14
|
||||||
|
MOVWP Rd, offset(Rj) | stptr.w rd, rj, si14
|
||||||
|
MOVVP Rd, offset(Rj) | stptr.d rd, rj, si14
|
||||||
|
|
||||||
|
note: In Go assembly, for ease of understanding, offset is a 16-bit immediate number representing
|
||||||
|
the actual address offset, but in platform assembly, it need a 14-bit immediate number.
|
||||||
|
si14 = offset>>2
|
||||||
|
|
||||||
|
The addressing calculation for the above instruction involves logically left-shifting the 14-bit
|
||||||
|
immediate number si14 by 2 bits, then sign-extending it, and finally adding it to the value in the
|
||||||
|
general-purpose register rj to obtain the sum.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
Go assembly | platform assembly
|
||||||
|
MOVWP 8(R4), R5 | ldptr.w r5, r4, $2
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package loong64
|
package loong64
|
||||||
|
|
|
||||||
|
|
@ -2120,19 +2120,6 @@ func span6(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
|
||||||
c0 := c
|
c0 := c
|
||||||
c = pjc.padJump(ctxt, s, p, c)
|
c = pjc.padJump(ctxt, s, p, c)
|
||||||
|
|
||||||
if p.As == obj.APCALIGN || p.As == obj.APCALIGNMAX {
|
|
||||||
v := obj.AlignmentPadding(c, p, ctxt, s)
|
|
||||||
if v > 0 {
|
|
||||||
s.Grow(int64(c) + int64(v))
|
|
||||||
fillnop(s.P[c:], int(v))
|
|
||||||
}
|
|
||||||
p.Pc = int64(c)
|
|
||||||
c += int32(v)
|
|
||||||
pPrev = p
|
|
||||||
continue
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if maxLoopPad > 0 && p.Back&branchLoopHead != 0 && c&(loopAlign-1) != 0 {
|
if maxLoopPad > 0 && p.Back&branchLoopHead != 0 && c&(loopAlign-1) != 0 {
|
||||||
// pad with NOPs
|
// pad with NOPs
|
||||||
v := -c & (loopAlign - 1)
|
v := -c & (loopAlign - 1)
|
||||||
|
|
@ -2165,6 +2152,18 @@ func span6(ctxt *obj.Link, s *obj.LSym, newprog obj.ProgAlloc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if p.As == obj.APCALIGN || p.As == obj.APCALIGNMAX {
|
||||||
|
v := obj.AlignmentPadding(c, p, ctxt, s)
|
||||||
|
if v > 0 {
|
||||||
|
s.Grow(int64(c) + int64(v))
|
||||||
|
fillnop(s.P[c:], int(v))
|
||||||
|
}
|
||||||
|
p.Pc = int64(c)
|
||||||
|
c += int32(v)
|
||||||
|
pPrev = p
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
p.Rel = nil
|
p.Rel = nil
|
||||||
|
|
||||||
p.Pc = int64(c)
|
p.Pc = int64(c)
|
||||||
|
|
|
||||||
|
|
@ -305,6 +305,14 @@ const (
|
||||||
// R_RISCV_BRANCH resolves a 12-bit PC-relative branch offset.
|
// R_RISCV_BRANCH resolves a 12-bit PC-relative branch offset.
|
||||||
R_RISCV_BRANCH
|
R_RISCV_BRANCH
|
||||||
|
|
||||||
|
// R_RISCV_ADD32 resolves a 32-bit label addition, being the stored value,
|
||||||
|
// plus the symbol address plus the addend (V + S + A).
|
||||||
|
R_RISCV_ADD32
|
||||||
|
|
||||||
|
// R_RISCV_SUB32 resolves a 32-bit label subtraction, being the stored value,
|
||||||
|
// minus the symbol address minus the addend (V - S - A).
|
||||||
|
R_RISCV_SUB32
|
||||||
|
|
||||||
// R_RISCV_RVC_BRANCH resolves an 8-bit PC-relative offset for a CB-type
|
// R_RISCV_RVC_BRANCH resolves an 8-bit PC-relative offset for a CB-type
|
||||||
// instruction.
|
// instruction.
|
||||||
R_RISCV_RVC_BRANCH
|
R_RISCV_RVC_BRANCH
|
||||||
|
|
|
||||||
|
|
@ -79,39 +79,41 @@ func _() {
|
||||||
_ = x[R_RISCV_PCREL_LO12_I-69]
|
_ = x[R_RISCV_PCREL_LO12_I-69]
|
||||||
_ = x[R_RISCV_PCREL_LO12_S-70]
|
_ = x[R_RISCV_PCREL_LO12_S-70]
|
||||||
_ = x[R_RISCV_BRANCH-71]
|
_ = x[R_RISCV_BRANCH-71]
|
||||||
_ = x[R_RISCV_RVC_BRANCH-72]
|
_ = x[R_RISCV_ADD32-72]
|
||||||
_ = x[R_RISCV_RVC_JUMP-73]
|
_ = x[R_RISCV_SUB32-73]
|
||||||
_ = x[R_PCRELDBL-74]
|
_ = x[R_RISCV_RVC_BRANCH-74]
|
||||||
_ = x[R_LOONG64_ADDR_HI-75]
|
_ = x[R_RISCV_RVC_JUMP-75]
|
||||||
_ = x[R_LOONG64_ADDR_LO-76]
|
_ = x[R_PCRELDBL-76]
|
||||||
_ = x[R_LOONG64_TLS_LE_HI-77]
|
_ = x[R_LOONG64_ADDR_HI-77]
|
||||||
_ = x[R_LOONG64_TLS_LE_LO-78]
|
_ = x[R_LOONG64_ADDR_LO-78]
|
||||||
_ = x[R_CALLLOONG64-79]
|
_ = x[R_LOONG64_TLS_LE_HI-79]
|
||||||
_ = x[R_LOONG64_TLS_IE_HI-80]
|
_ = x[R_LOONG64_TLS_LE_LO-80]
|
||||||
_ = x[R_LOONG64_TLS_IE_LO-81]
|
_ = x[R_CALLLOONG64-81]
|
||||||
_ = x[R_LOONG64_GOT_HI-82]
|
_ = x[R_LOONG64_TLS_IE_HI-82]
|
||||||
_ = x[R_LOONG64_GOT_LO-83]
|
_ = x[R_LOONG64_TLS_IE_LO-83]
|
||||||
_ = x[R_LOONG64_ADD64-84]
|
_ = x[R_LOONG64_GOT_HI-84]
|
||||||
_ = x[R_LOONG64_SUB64-85]
|
_ = x[R_LOONG64_GOT_LO-85]
|
||||||
_ = x[R_JMP16LOONG64-86]
|
_ = x[R_LOONG64_ADD64-86]
|
||||||
_ = x[R_JMP21LOONG64-87]
|
_ = x[R_LOONG64_SUB64-87]
|
||||||
_ = x[R_JMPLOONG64-88]
|
_ = x[R_JMP16LOONG64-88]
|
||||||
_ = x[R_ADDRMIPSU-89]
|
_ = x[R_JMP21LOONG64-89]
|
||||||
_ = x[R_ADDRMIPSTLS-90]
|
_ = x[R_JMPLOONG64-90]
|
||||||
_ = x[R_ADDRCUOFF-91]
|
_ = x[R_ADDRMIPSU-91]
|
||||||
_ = x[R_WASMIMPORT-92]
|
_ = x[R_ADDRMIPSTLS-92]
|
||||||
_ = x[R_XCOFFREF-93]
|
_ = x[R_ADDRCUOFF-93]
|
||||||
_ = x[R_PEIMAGEOFF-94]
|
_ = x[R_WASMIMPORT-94]
|
||||||
_ = x[R_INITORDER-95]
|
_ = x[R_XCOFFREF-95]
|
||||||
_ = x[R_DWTXTADDR_U1-96]
|
_ = x[R_PEIMAGEOFF-96]
|
||||||
_ = x[R_DWTXTADDR_U2-97]
|
_ = x[R_INITORDER-97]
|
||||||
_ = x[R_DWTXTADDR_U3-98]
|
_ = x[R_DWTXTADDR_U1-98]
|
||||||
_ = x[R_DWTXTADDR_U4-99]
|
_ = x[R_DWTXTADDR_U2-99]
|
||||||
|
_ = x[R_DWTXTADDR_U3-100]
|
||||||
|
_ = x[R_DWTXTADDR_U4-101]
|
||||||
}
|
}
|
||||||
|
|
||||||
const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USENAMEDMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_POWER_TLS_IE_PCREL34R_POWER_TLS_LE_TPREL34R_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_GOT_PCREL34R_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_ADDRPOWER_D34R_ADDRPOWER_PCREL34R_RISCV_JALR_RISCV_JAL_TRAMPR_RISCV_CALLR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IER_RISCV_TLS_LER_RISCV_GOT_HI20R_RISCV_GOT_PCREL_ITYPER_RISCV_PCREL_HI20R_RISCV_PCREL_LO12_IR_RISCV_PCREL_LO12_SR_RISCV_BRANCHR_RISCV_RVC_BRANCHR_RISCV_RVC_JUMPR_PCRELDBLR_LOONG64_ADDR_HIR_LOONG64_ADDR_LOR_LOONG64_TLS_LE_HIR_LOONG64_TLS_LE_LOR_CALLLOONG64R_LOONG64_TLS_IE_HIR_LOONG64_TLS_IE_LOR_LOONG64_GOT_HIR_LOONG64_GOT_LOR_LOONG64_ADD64R_LOONG64_SUB64R_JMP16LOONG64R_JMP21LOONG64R_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREFR_PEIMAGEOFFR_INITORDERR_DWTXTADDR_U1R_DWTXTADDR_U2R_DWTXTADDR_U3R_DWTXTADDR_U4"
|
const _RelocType_name = "R_ADDRR_ADDRPOWERR_ADDRARM64R_ADDRMIPSR_ADDROFFR_SIZER_CALLR_CALLARMR_CALLARM64R_CALLINDR_CALLPOWERR_CALLMIPSR_CONSTR_PCRELR_TLS_LER_TLS_IER_GOTOFFR_PLT0R_PLT1R_PLT2R_USEFIELDR_USETYPER_USEIFACER_USEIFACEMETHODR_USENAMEDMETHODR_METHODOFFR_KEEPR_POWER_TOCR_GOTPCRELR_JMPMIPSR_DWARFSECREFR_ARM64_TLS_LER_ARM64_TLS_IER_ARM64_GOTPCRELR_ARM64_GOTR_ARM64_PCRELR_ARM64_PCREL_LDST8R_ARM64_PCREL_LDST16R_ARM64_PCREL_LDST32R_ARM64_PCREL_LDST64R_ARM64_LDST8R_ARM64_LDST16R_ARM64_LDST32R_ARM64_LDST64R_ARM64_LDST128R_POWER_TLS_LER_POWER_TLS_IER_POWER_TLSR_POWER_TLS_IE_PCREL34R_POWER_TLS_LE_TPREL34R_ADDRPOWER_DSR_ADDRPOWER_GOTR_ADDRPOWER_GOT_PCREL34R_ADDRPOWER_PCRELR_ADDRPOWER_TOCRELR_ADDRPOWER_TOCREL_DSR_ADDRPOWER_D34R_ADDRPOWER_PCREL34R_RISCV_JALR_RISCV_JAL_TRAMPR_RISCV_CALLR_RISCV_PCREL_ITYPER_RISCV_PCREL_STYPER_RISCV_TLS_IER_RISCV_TLS_LER_RISCV_GOT_HI20R_RISCV_GOT_PCREL_ITYPER_RISCV_PCREL_HI20R_RISCV_PCREL_LO12_IR_RISCV_PCREL_LO12_SR_RISCV_BRANCHR_RISCV_ADD32R_RISCV_SUB32R_RISCV_RVC_BRANCHR_RISCV_RVC_JUMPR_PCRELDBLR_LOONG64_ADDR_HIR_LOONG64_ADDR_LOR_LOONG64_TLS_LE_HIR_LOONG64_TLS_LE_LOR_CALLLOONG64R_LOONG64_TLS_IE_HIR_LOONG64_TLS_IE_LOR_LOONG64_GOT_HIR_LOONG64_GOT_LOR_LOONG64_ADD64R_LOONG64_SUB64R_JMP16LOONG64R_JMP21LOONG64R_JMPLOONG64R_ADDRMIPSUR_ADDRMIPSTLSR_ADDRCUOFFR_WASMIMPORTR_XCOFFREFR_PEIMAGEOFFR_INITORDERR_DWTXTADDR_U1R_DWTXTADDR_U2R_DWTXTADDR_U3R_DWTXTADDR_U4"
|
||||||
|
|
||||||
var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 226, 237, 243, 254, 264, 273, 286, 300, 314, 330, 341, 354, 373, 393, 413, 433, 446, 460, 474, 488, 503, 517, 531, 542, 564, 586, 600, 615, 638, 655, 673, 694, 709, 728, 739, 756, 768, 787, 806, 820, 834, 850, 873, 891, 911, 931, 945, 963, 979, 989, 1006, 1023, 1042, 1061, 1074, 1093, 1112, 1128, 1144, 1159, 1174, 1188, 1202, 1214, 1225, 1238, 1249, 1261, 1271, 1283, 1294, 1308, 1322, 1336, 1350}
|
var _RelocType_index = [...]uint16{0, 6, 17, 28, 38, 47, 53, 59, 68, 79, 88, 99, 109, 116, 123, 131, 139, 147, 153, 159, 165, 175, 184, 194, 210, 226, 237, 243, 254, 264, 273, 286, 300, 314, 330, 341, 354, 373, 393, 413, 433, 446, 460, 474, 488, 503, 517, 531, 542, 564, 586, 600, 615, 638, 655, 673, 694, 709, 728, 739, 756, 768, 787, 806, 820, 834, 850, 873, 891, 911, 931, 945, 958, 971, 989, 1005, 1015, 1032, 1049, 1068, 1087, 1100, 1119, 1138, 1154, 1170, 1185, 1200, 1214, 1228, 1240, 1251, 1264, 1275, 1287, 1297, 1309, 1320, 1334, 1348, 1362, 1376}
|
||||||
|
|
||||||
func (i RelocType) String() string {
|
func (i RelocType) String() string {
|
||||||
i -= 1
|
i -= 1
|
||||||
|
|
|
||||||
|
|
@ -1178,6 +1178,7 @@ func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) {
|
||||||
RISCV64 | uint32(elf.R_RISCV_SET32)<<16,
|
RISCV64 | uint32(elf.R_RISCV_SET32)<<16,
|
||||||
RISCV64 | uint32(elf.R_RISCV_SUB32)<<16,
|
RISCV64 | uint32(elf.R_RISCV_SUB32)<<16,
|
||||||
RISCV64 | uint32(elf.R_RISCV_32_PCREL)<<16,
|
RISCV64 | uint32(elf.R_RISCV_32_PCREL)<<16,
|
||||||
|
RISCV64 | uint32(elf.R_RISCV_JAL)<<16,
|
||||||
RISCV64 | uint32(elf.R_RISCV_RELAX)<<16:
|
RISCV64 | uint32(elf.R_RISCV_RELAX)<<16:
|
||||||
return 4, 4, nil
|
return 4, 4, nil
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2440,6 +2440,7 @@ var blockedLinknames = map[string][]string{
|
||||||
// Others
|
// Others
|
||||||
"net.newWindowsFile": {"net"}, // pushed from os
|
"net.newWindowsFile": {"net"}, // pushed from os
|
||||||
"testing/synctest.testingSynctestTest": {"testing/synctest"}, // pushed from testing
|
"testing/synctest.testingSynctestTest": {"testing/synctest"}, // pushed from testing
|
||||||
|
"runtime.addmoduledata": {}, // disallow all package
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if a linkname reference to symbol s from pkg is allowed
|
// check if a linkname reference to symbol s from pkg is allowed
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,26 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
|
||||||
su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_LO12_S)
|
su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_LO12_S)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_32_PCREL):
|
||||||
|
su := ldr.MakeSymbolUpdater(s)
|
||||||
|
su.SetRelocType(rIdx, objabi.R_PCREL)
|
||||||
|
return true
|
||||||
|
|
||||||
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_64):
|
||||||
|
su := ldr.MakeSymbolUpdater(s)
|
||||||
|
su.SetRelocType(rIdx, objabi.R_ADDR)
|
||||||
|
return true
|
||||||
|
|
||||||
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_ADD32):
|
||||||
|
su := ldr.MakeSymbolUpdater(s)
|
||||||
|
su.SetRelocType(rIdx, objabi.R_RISCV_ADD32)
|
||||||
|
return true
|
||||||
|
|
||||||
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_SUB32):
|
||||||
|
su := ldr.MakeSymbolUpdater(s)
|
||||||
|
su.SetRelocType(rIdx, objabi.R_RISCV_SUB32)
|
||||||
|
return true
|
||||||
|
|
||||||
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_RVC_BRANCH):
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_RVC_BRANCH):
|
||||||
su := ldr.MakeSymbolUpdater(s)
|
su := ldr.MakeSymbolUpdater(s)
|
||||||
su.SetRelocType(rIdx, objabi.R_RISCV_RVC_BRANCH)
|
su.SetRelocType(rIdx, objabi.R_RISCV_RVC_BRANCH)
|
||||||
|
|
@ -137,6 +157,11 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
|
||||||
// Ignore relaxations, at least for now.
|
// Ignore relaxations, at least for now.
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_JAL):
|
||||||
|
su := ldr.MakeSymbolUpdater(s)
|
||||||
|
su.SetRelocType(rIdx, objabi.R_RISCV_JAL)
|
||||||
|
return true
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if r.Type() >= objabi.ElfRelocOffset {
|
if r.Type() >= objabi.ElfRelocOffset {
|
||||||
ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
|
ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
|
||||||
|
|
@ -639,6 +664,14 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
|
||||||
second = (second &^ secondImmMask) | int64(uint32(secondImm))
|
second = (second &^ secondImmMask) | int64(uint32(secondImm))
|
||||||
|
|
||||||
return second<<32 | auipc, 0, true
|
return second<<32 | auipc, 0, true
|
||||||
|
|
||||||
|
case objabi.R_RISCV_ADD32:
|
||||||
|
addr := val + ldr.SymValue(rs) + r.Add()
|
||||||
|
return int64(uint32(addr)), 0, true
|
||||||
|
|
||||||
|
case objabi.R_RISCV_SUB32:
|
||||||
|
addr := val - ldr.SymValue(rs) - r.Add()
|
||||||
|
return int64(uint32(addr)), 0, true
|
||||||
}
|
}
|
||||||
|
|
||||||
return val, 0, false
|
return val, 0, false
|
||||||
|
|
|
||||||
|
|
@ -1613,6 +1613,7 @@ func TestCheckLinkname(t *testing.T) {
|
||||||
{"coro2.go", false},
|
{"coro2.go", false},
|
||||||
// pull linkname of a builtin symbol is not ok
|
// pull linkname of a builtin symbol is not ok
|
||||||
{"builtin.go", false},
|
{"builtin.go", false},
|
||||||
|
{"addmoduledata.go", false},
|
||||||
// legacy bad linkname is ok, for now
|
// legacy bad linkname is ok, for now
|
||||||
{"fastrand.go", true},
|
{"fastrand.go", true},
|
||||||
{"badlinkname.go", true},
|
{"badlinkname.go", true},
|
||||||
|
|
|
||||||
18
src/cmd/link/testdata/linkname/addmoduledata.go
vendored
Normal file
18
src/cmd/link/testdata/linkname/addmoduledata.go
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2025 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Linkname runtime.addmoduledata is not allowed.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:linkname addmoduledata runtime.addmoduledata
|
||||||
|
func addmoduledata()
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
addmoduledata()
|
||||||
|
}
|
||||||
|
|
@ -46,7 +46,6 @@ func Supported() error {
|
||||||
switch {
|
switch {
|
||||||
case runtime.GOARCH == "wasm",
|
case runtime.GOARCH == "wasm",
|
||||||
runtime.GOOS == "windows" && runtime.GOARCH == "386",
|
runtime.GOOS == "windows" && runtime.GOARCH == "386",
|
||||||
runtime.GOOS == "windows" && runtime.GOARCH == "arm",
|
|
||||||
runtime.GOOS == "openbsd", // due to -fexecute-only, see #70880
|
runtime.GOOS == "openbsd", // due to -fexecute-only, see #70880
|
||||||
runtime.GOOS == "aix":
|
runtime.GOOS == "aix":
|
||||||
return errors.New("FIPS 140-3 mode is not supported on " + runtime.GOOS + "-" + runtime.GOARCH)
|
return errors.New("FIPS 140-3 mode is not supported on " + runtime.GOOS + "-" + runtime.GOARCH)
|
||||||
|
|
|
||||||
|
|
@ -468,10 +468,17 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// cloneHash uses the encoding.BinaryMarshaler and encoding.BinaryUnmarshaler
|
// cloneHash uses [hash.Cloner] to clone in. If [hash.Cloner]
|
||||||
|
// is not implemented or not supported, then it falls back to the
|
||||||
|
// [encoding.BinaryMarshaler] and [encoding.BinaryUnmarshaler]
|
||||||
// interfaces implemented by standard library hashes to clone the state of in
|
// interfaces implemented by standard library hashes to clone the state of in
|
||||||
// to a new instance of h. It returns nil if the operation fails.
|
// to a new instance of h. It returns nil if the operation fails.
|
||||||
func cloneHash(in hash.Hash, h crypto.Hash) hash.Hash {
|
func cloneHash(in hash.Hash, h crypto.Hash) hash.Hash {
|
||||||
|
if cloner, ok := in.(hash.Cloner); ok {
|
||||||
|
if out, err := cloner.Clone(); err == nil {
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
}
|
||||||
// Recreate the interface to avoid importing encoding.
|
// Recreate the interface to avoid importing encoding.
|
||||||
type binaryMarshaler interface {
|
type binaryMarshaler interface {
|
||||||
MarshalBinary() (data []byte, err error)
|
MarshalBinary() (data []byte, err error)
|
||||||
|
|
|
||||||
|
|
@ -221,7 +221,7 @@ func (q *QUICConn) NextEvent() QUICEvent {
|
||||||
qs := q.conn.quic
|
qs := q.conn.quic
|
||||||
if last := qs.nextEvent - 1; last >= 0 && len(qs.events[last].Data) > 0 {
|
if last := qs.nextEvent - 1; last >= 0 && len(qs.events[last].Data) > 0 {
|
||||||
// Write over some of the previous event's data,
|
// Write over some of the previous event's data,
|
||||||
// to catch callers erroniously retaining it.
|
// to catch callers erroneously retaining it.
|
||||||
qs.events[last].Data[0] = 0
|
qs.events[last].Data[0] = 0
|
||||||
}
|
}
|
||||||
if qs.nextEvent >= len(qs.events) && qs.waitingForDrain {
|
if qs.nextEvent >= len(qs.events) && qs.waitingForDrain {
|
||||||
|
|
|
||||||
|
|
@ -692,6 +692,9 @@ func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
|
||||||
if len(data)%Sym64Size != 0 {
|
if len(data)%Sym64Size != 0 {
|
||||||
return nil, nil, errors.New("length of symbol section is not a multiple of Sym64Size")
|
return nil, nil, errors.New("length of symbol section is not a multiple of Sym64Size")
|
||||||
}
|
}
|
||||||
|
if len(data) == 0 {
|
||||||
|
return nil, nil, ErrNoSymbols
|
||||||
|
}
|
||||||
|
|
||||||
strdata, err := f.stringTable(symtabSection.Link)
|
strdata, err := f.stringTable(symtabSection.Link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -1214,10 +1214,6 @@ func unquoteBytes(s []byte) (t []byte, ok bool) {
|
||||||
if c == '\\' || c == '"' || c < ' ' {
|
if c == '\\' || c == '"' || c < ' ' {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if c < utf8.RuneSelf {
|
|
||||||
r++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
rr, size := utf8.DecodeRune(s[r:])
|
rr, size := utf8.DecodeRune(s[r:])
|
||||||
if rr == utf8.RuneError && size == 1 {
|
if rr == utf8.RuneError && size == 1 {
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -346,10 +346,7 @@ func (f *fmt) truncate(b []byte) []byte {
|
||||||
if n < 0 {
|
if n < 0 {
|
||||||
return b[:i]
|
return b[:i]
|
||||||
}
|
}
|
||||||
wid := 1
|
_, wid := utf8.DecodeRune(b[i:])
|
||||||
if b[i] >= utf8.RuneSelf {
|
|
||||||
_, wid = utf8.DecodeRune(b[i:])
|
|
||||||
}
|
|
||||||
i += wid
|
i += wid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1145,10 +1145,7 @@ formatLoop:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
verb, size := rune(format[i]), 1
|
verb, size := utf8.DecodeRuneInString(format[i:])
|
||||||
if verb >= utf8.RuneSelf {
|
|
||||||
verb, size = utf8.DecodeRuneInString(format[i:])
|
|
||||||
}
|
|
||||||
i += size
|
i += size
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
|
|
||||||
|
|
@ -1083,7 +1083,10 @@ func match0(x, y Value) (_, _ Value) {
|
||||||
return rtof(x1), y
|
return rtof(x1), y
|
||||||
}
|
}
|
||||||
case complexVal:
|
case complexVal:
|
||||||
return vtoc(x), y
|
switch x1 := x.(type) {
|
||||||
|
case int64Val, intVal, ratVal, floatVal:
|
||||||
|
return vtoc(x1), y
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// force unknown and invalid values into "x position" in callers of match
|
// force unknown and invalid values into "x position" in callers of match
|
||||||
|
|
|
||||||
|
|
@ -617,6 +617,9 @@ func TestUnknown(t *testing.T) {
|
||||||
if got := Compare(x, token.EQL, y); got {
|
if got := Compare(x, token.EQL, y); got {
|
||||||
t.Errorf("%s == %s: got true; want false", x, y)
|
t.Errorf("%s == %s: got true; want false", x, y)
|
||||||
}
|
}
|
||||||
|
if got := Compare(x, token.NEQ, y); got {
|
||||||
|
t.Errorf("%s != %s: got true; want false", x, y)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,12 @@ func TestComment(t *testing.T) {
|
||||||
pkg := New(pkgs["pkgdoc"], "testdata/pkgdoc", 0)
|
pkg := New(pkgs["pkgdoc"], "testdata/pkgdoc", 0)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
input = "[T] and [U] are types, and [T.M] is a method, but [V] is a broken link. [rand.Int] and [crand.Reader] are things. [G.M1] and [G.M2] are generic methods.\n"
|
input = "[T] and [U] are types, and [T.M] is a method, but [V] is a broken link. [rand.Int] and [crand.Reader] are things. [G.M1] and [G.M2] are generic methods. [I.F] is an interface method and [I.V] is a broken link.\n"
|
||||||
wantHTML = `<p><a href="#T">T</a> and <a href="#U">U</a> are types, and <a href="#T.M">T.M</a> is a method, but [V] is a broken link. <a href="/math/rand#Int">rand.Int</a> and <a href="/crypto/rand#Reader">crand.Reader</a> are things. <a href="#G.M1">G.M1</a> and <a href="#G.M2">G.M2</a> are generic methods.` + "\n"
|
wantHTML = `<p><a href="#T">T</a> and <a href="#U">U</a> are types, and <a href="#T.M">T.M</a> is a method, but [V] is a broken link. <a href="/math/rand#Int">rand.Int</a> and <a href="/crypto/rand#Reader">crand.Reader</a> are things. <a href="#G.M1">G.M1</a> and <a href="#G.M2">G.M2</a> are generic methods. <a href="#I.F">I.F</a> is an interface method and [I.V] is a broken link.` + "\n"
|
||||||
wantOldHTML = "<p>[T] and [U] are <i>types</i>, and [T.M] is a method, but [V] is a broken link. [rand.Int] and [crand.Reader] are things. [G.M1] and [G.M2] are generic methods.\n"
|
wantOldHTML = "<p>[T] and [U] are <i>types</i>, and [T.M] is a method, but [V] is a broken link. [rand.Int] and [crand.Reader] are things. [G.M1] and [G.M2] are generic methods. [I.F] is an interface method and [I.V] is a broken link.\n"
|
||||||
wantMarkdown = "[T](#T) and [U](#U) are types, and [T.M](#T.M) is a method, but \\[V] is a broken link. [rand.Int](/math/rand#Int) and [crand.Reader](/crypto/rand#Reader) are things. [G.M1](#G.M1) and [G.M2](#G.M2) are generic methods.\n"
|
wantMarkdown = "[T](#T) and [U](#U) are types, and [T.M](#T.M) is a method, but \\[V] is a broken link. [rand.Int](/math/rand#Int) and [crand.Reader](/crypto/rand#Reader) are things. [G.M1](#G.M1) and [G.M2](#G.M2) are generic methods. [I.F](#I.F) is an interface method and \\[I.V] is a broken link.\n"
|
||||||
wantText = "T and U are types, and T.M is a method, but [V] is a broken link. rand.Int and\ncrand.Reader are things. G.M1 and G.M2 are generic methods.\n"
|
wantText = "T and U are types, and T.M is a method, but [V] is a broken link. rand.Int and\ncrand.Reader are things. G.M1 and G.M2 are generic methods. I.F is an interface\nmethod and [I.V] is a broken link.\n"
|
||||||
wantOldText = "[T] and [U] are types, and [T.M] is a method, but [V] is a broken link.\n[rand.Int] and [crand.Reader] are things. [G.M1] and [G.M2] are generic methods.\n"
|
wantOldText = "[T] and [U] are types, and [T.M] is a method, but [V] is a broken link.\n[rand.Int] and [crand.Reader] are things. [G.M1] and [G.M2] are generic methods.\n[I.F] is an interface method and [I.V] is a broken link.\n"
|
||||||
wantSynopsis = "T and U are types, and T.M is a method, but [V] is a broken link."
|
wantSynopsis = "T and U are types, and T.M is a method, but [V] is a broken link."
|
||||||
wantOldSynopsis = "[T] and [U] are types, and [T.M] is a method, but [V] is a broken link."
|
wantOldSynopsis = "[T] and [U] are types, and [T.M] is a method, but [V] is a broken link."
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -167,6 +167,7 @@ func (p *Package) collectTypes(types []*Type) {
|
||||||
p.collectValues(t.Vars)
|
p.collectValues(t.Vars)
|
||||||
p.collectFuncs(t.Funcs)
|
p.collectFuncs(t.Funcs)
|
||||||
p.collectFuncs(t.Methods)
|
p.collectFuncs(t.Methods)
|
||||||
|
p.collectInterfaceMethods(t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,6 +185,33 @@ func (p *Package) collectFuncs(funcs []*Func) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// collectInterfaceMethods adds methods of interface types within t to p.syms.
|
||||||
|
// Note that t.Methods will contain methods of non-interface types, but not interface types.
|
||||||
|
// Adding interface methods to t.Methods might make sense, but would cause us to
|
||||||
|
// include those methods in the documentation index. Adding interface methods to p.syms
|
||||||
|
// here allows us to linkify references like [io.Reader.Read] without making any other
|
||||||
|
// changes to the documentation formatting at this time.
|
||||||
|
//
|
||||||
|
// If we do start adding interface methods to t.Methods in the future,
|
||||||
|
// collectInterfaceMethods can be dropped as redundant with collectFuncs(t.Methods).
|
||||||
|
func (p *Package) collectInterfaceMethods(t *Type) {
|
||||||
|
for _, s := range t.Decl.Specs {
|
||||||
|
spec, ok := s.(*ast.TypeSpec)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
list, isStruct := fields(spec.Type)
|
||||||
|
if isStruct {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, field := range list {
|
||||||
|
for _, name := range field.Names {
|
||||||
|
p.syms[t.Name+"."+name.Name] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewFromFiles computes documentation for a package.
|
// NewFromFiles computes documentation for a package.
|
||||||
//
|
//
|
||||||
// The package is specified by a list of *ast.Files and corresponding
|
// The package is specified by a list of *ast.Files and corresponding
|
||||||
|
|
|
||||||
6
src/go/doc/testdata/pkgdoc/doc.go
vendored
6
src/go/doc/testdata/pkgdoc/doc.go
vendored
|
|
@ -20,5 +20,9 @@ var _ = crand.Reader
|
||||||
|
|
||||||
type G[T any] struct{ x T }
|
type G[T any] struct{ x T }
|
||||||
|
|
||||||
func (g G[T]) M1() {}
|
func (g G[T]) M1() {}
|
||||||
func (g *G[T]) M2() {}
|
func (g *G[T]) M2() {}
|
||||||
|
|
||||||
|
type I interface {
|
||||||
|
F()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,6 @@ package cpu
|
||||||
|
|
||||||
import _ "unsafe" // for linkname
|
import _ "unsafe" // for linkname
|
||||||
|
|
||||||
// DebugOptions is set to true by the runtime if the OS supports reading
|
|
||||||
// GODEBUG early in runtime startup.
|
|
||||||
// This should not be changed after it is initialized.
|
|
||||||
var DebugOptions bool
|
|
||||||
|
|
||||||
// CacheLinePad is used to pad structs to avoid false sharing.
|
// CacheLinePad is used to pad structs to avoid false sharing.
|
||||||
type CacheLinePad struct{ _ [CacheLinePadSize]byte }
|
type CacheLinePad struct{ _ [CacheLinePadSize]byte }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,14 @@ import (
|
||||||
"internal/godebug"
|
"internal/godebug"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MustHaveDebugOptionsSupport(t *testing.T) {
|
func MustHaveDebugOptionsSupport(t *testing.T) {
|
||||||
if !DebugOptions {
|
switch runtime.GOOS {
|
||||||
|
case "aix", "darwin", "ios", "dragonfly", "freebsd", "netbsd", "openbsd", "illumos", "solaris", "linux":
|
||||||
|
default:
|
||||||
t.Skipf("skipping test: cpu feature options not supported by OS")
|
t.Skipf("skipping test: cpu feature options not supported by OS")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ func (p OSArch) String() string {
|
||||||
func RaceDetectorSupported(goos, goarch string) bool {
|
func RaceDetectorSupported(goos, goarch string) bool {
|
||||||
switch goos {
|
switch goos {
|
||||||
case "linux":
|
case "linux":
|
||||||
return goarch == "amd64" || goarch == "ppc64le" || goarch == "arm64" || goarch == "s390x" || goarch == "loong64"
|
return goarch == "amd64" || goarch == "arm64" || goarch == "loong64" || goarch == "ppc64le" || goarch == "riscv64" || goarch == "s390x"
|
||||||
case "darwin":
|
case "darwin":
|
||||||
return goarch == "amd64" || goarch == "arm64"
|
return goarch == "amd64" || goarch == "arm64"
|
||||||
case "freebsd", "netbsd", "windows":
|
case "freebsd", "netbsd", "windows":
|
||||||
|
|
|
||||||
|
|
@ -251,6 +251,23 @@ func (fd *FD) writeUnlock() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// readWriteLock adds a reference to fd and locks fd for reading and writing.
|
||||||
|
// It returns an error when fd cannot be used for reading and writing.
|
||||||
|
func (fd *FD) readWriteLock() error {
|
||||||
|
if !fd.fdmu.rwlock(true) || !fd.fdmu.rwlock(false) {
|
||||||
|
return errClosing(fd.isFile)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// readWriteUnlock removes a reference from fd and unlocks fd for reading and writing.
|
||||||
|
// It also closes fd when the state of fd is set to closed and there
|
||||||
|
// is no remaining reference.
|
||||||
|
func (fd *FD) readWriteUnlock() {
|
||||||
|
fd.fdmu.rwunlock(true)
|
||||||
|
fd.fdmu.rwunlock(false)
|
||||||
|
}
|
||||||
|
|
||||||
// closing returns true if fd is closing.
|
// closing returns true if fd is closing.
|
||||||
func (fd *FD) closing() bool {
|
func (fd *FD) closing() bool {
|
||||||
return atomic.LoadUint64(&fd.fdmu.state)&mutexClosed != 0
|
return atomic.LoadUint64(&fd.fdmu.state)&mutexClosed != 0
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,7 @@ type operation struct {
|
||||||
mode int32
|
mode int32
|
||||||
|
|
||||||
// fields used only by net package
|
// fields used only by net package
|
||||||
buf syscall.WSABuf
|
buf syscall.WSABuf
|
||||||
rsa *syscall.RawSockaddrAny
|
|
||||||
bufs []syscall.WSABuf
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *operation) setEvent() {
|
func (o *operation) setEvent() {
|
||||||
|
|
@ -114,49 +112,97 @@ func (o *operation) InitBuf(buf []byte) {
|
||||||
o.buf.Buf = unsafe.SliceData(buf)
|
o.buf.Buf = unsafe.SliceData(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *operation) InitBufs(buf *[][]byte) {
|
var wsaBufsPool = sync.Pool{
|
||||||
if o.bufs == nil {
|
New: func() any {
|
||||||
o.bufs = make([]syscall.WSABuf, 0, len(*buf))
|
buf := make([]syscall.WSABuf, 0, 16)
|
||||||
} else {
|
return &buf
|
||||||
o.bufs = o.bufs[:0]
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newWSABufs(buf *[][]byte) *[]syscall.WSABuf {
|
||||||
|
bufsPtr := wsaBufsPool.Get().(*[]syscall.WSABuf)
|
||||||
|
*bufsPtr = (*bufsPtr)[:0]
|
||||||
for _, b := range *buf {
|
for _, b := range *buf {
|
||||||
if len(b) == 0 {
|
if len(b) == 0 {
|
||||||
o.bufs = append(o.bufs, syscall.WSABuf{})
|
*bufsPtr = append(*bufsPtr, syscall.WSABuf{})
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for len(b) > maxRW {
|
for len(b) > maxRW {
|
||||||
o.bufs = append(o.bufs, syscall.WSABuf{Len: maxRW, Buf: &b[0]})
|
*bufsPtr = append(*bufsPtr, syscall.WSABuf{Len: maxRW, Buf: &b[0]})
|
||||||
b = b[maxRW:]
|
b = b[maxRW:]
|
||||||
}
|
}
|
||||||
if len(b) > 0 {
|
if len(b) > 0 {
|
||||||
o.bufs = append(o.bufs, syscall.WSABuf{Len: uint32(len(b)), Buf: &b[0]})
|
*bufsPtr = append(*bufsPtr, syscall.WSABuf{Len: uint32(len(b)), Buf: &b[0]})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return bufsPtr
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearBufs clears all pointers to Buffers parameter captured
|
func freeWSABufs(bufsPtr *[]syscall.WSABuf) {
|
||||||
// by InitBufs, so it can be released by garbage collector.
|
// Clear pointers to buffers so they can be released by garbage collector.
|
||||||
func (o *operation) ClearBufs() {
|
bufs := *bufsPtr
|
||||||
for i := range o.bufs {
|
for i := range bufs {
|
||||||
o.bufs[i].Buf = nil
|
bufs[i].Buf = nil
|
||||||
}
|
}
|
||||||
o.bufs = o.bufs[:0]
|
// Proper usage of a sync.Pool requires each entry to have approximately
|
||||||
|
// the same memory cost. To obtain this property when the stored type
|
||||||
|
// contains a variably-sized buffer, we add a hard limit on the maximum buffer
|
||||||
|
// to place back in the pool.
|
||||||
|
//
|
||||||
|
// See https://go.dev/issue/23199
|
||||||
|
if cap(*bufsPtr) > 128 {
|
||||||
|
*bufsPtr = nil
|
||||||
|
}
|
||||||
|
wsaBufsPool.Put(bufsPtr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWSAMsg(p []byte, oob []byte, flags int) windows.WSAMsg {
|
// wsaMsgPool is a pool of WSAMsg structures that can only hold a single WSABuf.
|
||||||
return windows.WSAMsg{
|
var wsaMsgPool = sync.Pool{
|
||||||
Buffers: &syscall.WSABuf{
|
New: func() any {
|
||||||
Len: uint32(len(p)),
|
return &windows.WSAMsg{
|
||||||
Buf: unsafe.SliceData(p),
|
Buffers: &syscall.WSABuf{},
|
||||||
},
|
BufferCount: 1,
|
||||||
BufferCount: 1,
|
}
|
||||||
Control: syscall.WSABuf{
|
},
|
||||||
Len: uint32(len(oob)),
|
}
|
||||||
Buf: unsafe.SliceData(oob),
|
|
||||||
},
|
// newWSAMsg creates a new WSAMsg with the provided parameters.
|
||||||
Flags: uint32(flags),
|
// Use [freeWSAMsg] to free it.
|
||||||
|
func newWSAMsg(p []byte, oob []byte, flags int, rsa *syscall.RawSockaddrAny) *windows.WSAMsg {
|
||||||
|
// The returned object can't be allocated in the stack because it is accessed asynchronously
|
||||||
|
// by Windows in between several system calls. If the stack frame is moved while that happens,
|
||||||
|
// then Windows may access invalid memory.
|
||||||
|
// TODO(qmuntal): investigate using runtime.Pinner keeping this path allocation-free.
|
||||||
|
|
||||||
|
// Use a pool to reuse allocations.
|
||||||
|
msg := wsaMsgPool.Get().(*windows.WSAMsg)
|
||||||
|
msg.Buffers.Len = uint32(len(p))
|
||||||
|
msg.Buffers.Buf = unsafe.SliceData(p)
|
||||||
|
msg.Control = syscall.WSABuf{
|
||||||
|
Len: uint32(len(oob)),
|
||||||
|
Buf: unsafe.SliceData(oob),
|
||||||
}
|
}
|
||||||
|
msg.Flags = uint32(flags)
|
||||||
|
msg.Name = syscall.Pointer(unsafe.Pointer(rsa))
|
||||||
|
if rsa != nil {
|
||||||
|
msg.Namelen = int32(unsafe.Sizeof(*rsa))
|
||||||
|
} else {
|
||||||
|
msg.Namelen = 0
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
|
func freeWSAMsg(msg *windows.WSAMsg) {
|
||||||
|
// Clear pointers to buffers so they can be released by garbage collector.
|
||||||
|
msg.Buffers.Len = 0
|
||||||
|
msg.Buffers.Buf = nil
|
||||||
|
wsaMsgPool.Put(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wsaRsaPool = sync.Pool{
|
||||||
|
New: func() any {
|
||||||
|
return new(syscall.RawSockaddrAny)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// waitIO waits for the IO operation o to complete.
|
// waitIO waits for the IO operation o to complete.
|
||||||
|
|
@ -276,9 +322,6 @@ type FD struct {
|
||||||
// I/O poller.
|
// I/O poller.
|
||||||
pd pollDesc
|
pd pollDesc
|
||||||
|
|
||||||
// Used to implement pread/pwrite.
|
|
||||||
l sync.Mutex
|
|
||||||
|
|
||||||
// The file offset for the next read or write.
|
// The file offset for the next read or write.
|
||||||
// Overlapped IO operations don't use the real file pointer,
|
// Overlapped IO operations don't use the real file pointer,
|
||||||
// so we need to keep track of the offset ourselves.
|
// so we need to keep track of the offset ourselves.
|
||||||
|
|
@ -316,7 +359,7 @@ type FD struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// setOffset sets the offset fields of the overlapped object
|
// setOffset sets the offset fields of the overlapped object
|
||||||
// to the given offset. The fd.l lock must be held.
|
// to the given offset. The fd read/write lock must be held.
|
||||||
//
|
//
|
||||||
// Overlapped IO operations don't update the offset fields
|
// Overlapped IO operations don't update the offset fields
|
||||||
// of the overlapped object nor the file pointer automatically,
|
// of the overlapped object nor the file pointer automatically,
|
||||||
|
|
@ -476,13 +519,16 @@ const maxRW = 1 << 30 // 1GB is large enough and keeps subsequent reads aligned
|
||||||
|
|
||||||
// Read implements io.Reader.
|
// Read implements io.Reader.
|
||||||
func (fd *FD) Read(buf []byte) (int, error) {
|
func (fd *FD) Read(buf []byte) (int, error) {
|
||||||
if err := fd.readLock(); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
defer fd.readUnlock()
|
|
||||||
if fd.kind == kindFile {
|
if fd.kind == kindFile {
|
||||||
fd.l.Lock()
|
if err := fd.readWriteLock(); err != nil {
|
||||||
defer fd.l.Unlock()
|
return 0, err
|
||||||
|
}
|
||||||
|
defer fd.readWriteUnlock()
|
||||||
|
} else {
|
||||||
|
if err := fd.readLock(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer fd.readUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(buf) > maxRW {
|
if len(buf) > maxRW {
|
||||||
|
|
@ -609,19 +655,16 @@ func (fd *FD) Pread(b []byte, off int64) (int, error) {
|
||||||
// Pread does not work with pipes
|
// Pread does not work with pipes
|
||||||
return 0, syscall.ESPIPE
|
return 0, syscall.ESPIPE
|
||||||
}
|
}
|
||||||
// Call incref, not readLock, because since pread specifies the
|
|
||||||
// offset it is independent from other reads.
|
if err := fd.readWriteLock(); err != nil {
|
||||||
if err := fd.incref(); err != nil {
|
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
defer fd.decref()
|
defer fd.readWriteUnlock()
|
||||||
|
|
||||||
if len(b) > maxRW {
|
if len(b) > maxRW {
|
||||||
b = b[:maxRW]
|
b = b[:maxRW]
|
||||||
}
|
}
|
||||||
|
|
||||||
fd.l.Lock()
|
|
||||||
defer fd.l.Unlock()
|
|
||||||
if fd.isBlocking {
|
if fd.isBlocking {
|
||||||
curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
|
curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -668,20 +711,19 @@ func (fd *FD) ReadFrom(buf []byte) (int, syscall.Sockaddr, error) {
|
||||||
defer fd.readUnlock()
|
defer fd.readUnlock()
|
||||||
o := &fd.rop
|
o := &fd.rop
|
||||||
o.InitBuf(buf)
|
o.InitBuf(buf)
|
||||||
|
rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
|
||||||
|
defer wsaRsaPool.Put(rsa)
|
||||||
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
||||||
if o.rsa == nil {
|
rsan := int32(unsafe.Sizeof(*rsa))
|
||||||
o.rsa = new(syscall.RawSockaddrAny)
|
|
||||||
}
|
|
||||||
rsan := int32(unsafe.Sizeof(*o.rsa))
|
|
||||||
var flags uint32
|
var flags uint32
|
||||||
err = syscall.WSARecvFrom(fd.Sysfd, &o.buf, 1, &qty, &flags, o.rsa, &rsan, &o.o, nil)
|
err = syscall.WSARecvFrom(fd.Sysfd, &o.buf, 1, &qty, &flags, rsa, &rsan, &o.o, nil)
|
||||||
return qty, err
|
return qty, err
|
||||||
})
|
})
|
||||||
err = fd.eofError(n, err)
|
err = fd.eofError(n, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, nil, err
|
return n, nil, err
|
||||||
}
|
}
|
||||||
sa, _ := o.rsa.Sockaddr()
|
sa, _ := rsa.Sockaddr()
|
||||||
return n, sa, nil
|
return n, sa, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -699,20 +741,19 @@ func (fd *FD) ReadFromInet4(buf []byte, sa4 *syscall.SockaddrInet4) (int, error)
|
||||||
defer fd.readUnlock()
|
defer fd.readUnlock()
|
||||||
o := &fd.rop
|
o := &fd.rop
|
||||||
o.InitBuf(buf)
|
o.InitBuf(buf)
|
||||||
|
rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
|
||||||
|
defer wsaRsaPool.Put(rsa)
|
||||||
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
||||||
if o.rsa == nil {
|
rsan := int32(unsafe.Sizeof(*rsa))
|
||||||
o.rsa = new(syscall.RawSockaddrAny)
|
|
||||||
}
|
|
||||||
rsan := int32(unsafe.Sizeof(*o.rsa))
|
|
||||||
var flags uint32
|
var flags uint32
|
||||||
err = syscall.WSARecvFrom(fd.Sysfd, &o.buf, 1, &qty, &flags, o.rsa, &rsan, &o.o, nil)
|
err = syscall.WSARecvFrom(fd.Sysfd, &o.buf, 1, &qty, &flags, rsa, &rsan, &o.o, nil)
|
||||||
return qty, err
|
return qty, err
|
||||||
})
|
})
|
||||||
err = fd.eofError(n, err)
|
err = fd.eofError(n, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
rawToSockaddrInet4(o.rsa, sa4)
|
rawToSockaddrInet4(rsa, sa4)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -730,32 +771,34 @@ func (fd *FD) ReadFromInet6(buf []byte, sa6 *syscall.SockaddrInet6) (int, error)
|
||||||
defer fd.readUnlock()
|
defer fd.readUnlock()
|
||||||
o := &fd.rop
|
o := &fd.rop
|
||||||
o.InitBuf(buf)
|
o.InitBuf(buf)
|
||||||
|
rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
|
||||||
|
defer wsaRsaPool.Put(rsa)
|
||||||
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
||||||
if o.rsa == nil {
|
rsan := int32(unsafe.Sizeof(*rsa))
|
||||||
o.rsa = new(syscall.RawSockaddrAny)
|
|
||||||
}
|
|
||||||
rsan := int32(unsafe.Sizeof(*o.rsa))
|
|
||||||
var flags uint32
|
var flags uint32
|
||||||
err = syscall.WSARecvFrom(fd.Sysfd, &o.buf, 1, &qty, &flags, o.rsa, &rsan, &o.o, nil)
|
err = syscall.WSARecvFrom(fd.Sysfd, &o.buf, 1, &qty, &flags, rsa, &rsan, &o.o, nil)
|
||||||
return qty, err
|
return qty, err
|
||||||
})
|
})
|
||||||
err = fd.eofError(n, err)
|
err = fd.eofError(n, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
rawToSockaddrInet6(o.rsa, sa6)
|
rawToSockaddrInet6(rsa, sa6)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write implements io.Writer.
|
// Write implements io.Writer.
|
||||||
func (fd *FD) Write(buf []byte) (int, error) {
|
func (fd *FD) Write(buf []byte) (int, error) {
|
||||||
if err := fd.writeLock(); err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
defer fd.writeUnlock()
|
|
||||||
if fd.kind == kindFile {
|
if fd.kind == kindFile {
|
||||||
fd.l.Lock()
|
if err := fd.readWriteLock(); err != nil {
|
||||||
defer fd.l.Unlock()
|
return 0, err
|
||||||
|
}
|
||||||
|
defer fd.readWriteUnlock()
|
||||||
|
} else {
|
||||||
|
if err := fd.writeLock(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer fd.writeUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
var ntotal int
|
var ntotal int
|
||||||
|
|
@ -848,15 +891,12 @@ func (fd *FD) Pwrite(buf []byte, off int64) (int, error) {
|
||||||
// Pwrite does not work with pipes
|
// Pwrite does not work with pipes
|
||||||
return 0, syscall.ESPIPE
|
return 0, syscall.ESPIPE
|
||||||
}
|
}
|
||||||
// Call incref, not writeLock, because since pwrite specifies the
|
|
||||||
// offset it is independent from other writes.
|
if err := fd.readWriteLock(); err != nil {
|
||||||
if err := fd.incref(); err != nil {
|
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
defer fd.decref()
|
defer fd.readWriteUnlock()
|
||||||
|
|
||||||
fd.l.Lock()
|
|
||||||
defer fd.l.Unlock()
|
|
||||||
if fd.isBlocking {
|
if fd.isBlocking {
|
||||||
curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
|
curoffset, err := syscall.Seek(fd.Sysfd, 0, io.SeekCurrent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -912,13 +952,12 @@ func (fd *FD) Writev(buf *[][]byte) (int64, error) {
|
||||||
if race.Enabled {
|
if race.Enabled {
|
||||||
race.ReleaseMerge(unsafe.Pointer(&ioSync))
|
race.ReleaseMerge(unsafe.Pointer(&ioSync))
|
||||||
}
|
}
|
||||||
o := &fd.wop
|
bufs := newWSABufs(buf)
|
||||||
o.InitBufs(buf)
|
defer freeWSABufs(bufs)
|
||||||
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
n, err := fd.execIO(&fd.wop, func(o *operation) (qty uint32, err error) {
|
||||||
err = syscall.WSASend(fd.Sysfd, &o.bufs[0], uint32(len(o.bufs)), &qty, 0, &o.o, nil)
|
err = syscall.WSASend(fd.Sysfd, &(*bufs)[0], uint32(len(*bufs)), &qty, 0, &o.o, nil)
|
||||||
return qty, err
|
return qty, err
|
||||||
})
|
})
|
||||||
o.ClearBufs()
|
|
||||||
TestHookDidWritev(n)
|
TestHookDidWritev(n)
|
||||||
consume(buf, int64(n))
|
consume(buf, int64(n))
|
||||||
return int64(n), err
|
return int64(n), err
|
||||||
|
|
@ -1119,13 +1158,10 @@ func (fd *FD) Seek(offset int64, whence int) (int64, error) {
|
||||||
if fd.kind == kindPipe {
|
if fd.kind == kindPipe {
|
||||||
return 0, syscall.ESPIPE
|
return 0, syscall.ESPIPE
|
||||||
}
|
}
|
||||||
if err := fd.incref(); err != nil {
|
if err := fd.readWriteLock(); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
defer fd.decref()
|
defer fd.readWriteUnlock()
|
||||||
|
|
||||||
fd.l.Lock()
|
|
||||||
defer fd.l.Unlock()
|
|
||||||
|
|
||||||
if !fd.isBlocking && whence == io.SeekCurrent {
|
if !fd.isBlocking && whence == io.SeekCurrent {
|
||||||
// Windows doesn't keep the file pointer for overlapped file handles.
|
// Windows doesn't keep the file pointer for overlapped file handles.
|
||||||
|
|
@ -1299,21 +1335,18 @@ func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.S
|
||||||
p = p[:maxRW]
|
p = p[:maxRW]
|
||||||
}
|
}
|
||||||
|
|
||||||
o := &fd.rop
|
rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
|
||||||
if o.rsa == nil {
|
defer wsaRsaPool.Put(rsa)
|
||||||
o.rsa = new(syscall.RawSockaddrAny)
|
msg := newWSAMsg(p, oob, flags, rsa)
|
||||||
}
|
defer freeWSAMsg(msg)
|
||||||
msg := newWSAMsg(p, oob, flags)
|
n, err := fd.execIO(&fd.rop, func(o *operation) (qty uint32, err error) {
|
||||||
msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
|
err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
|
||||||
msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
|
|
||||||
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
|
||||||
err = windows.WSARecvMsg(fd.Sysfd, &msg, &qty, &o.o, nil)
|
|
||||||
return qty, err
|
return qty, err
|
||||||
})
|
})
|
||||||
err = fd.eofError(n, err)
|
err = fd.eofError(n, err)
|
||||||
var sa syscall.Sockaddr
|
var sa syscall.Sockaddr
|
||||||
if err == nil {
|
if err == nil {
|
||||||
sa, err = o.rsa.Sockaddr()
|
sa, err = rsa.Sockaddr()
|
||||||
}
|
}
|
||||||
return n, int(msg.Control.Len), int(msg.Flags), sa, err
|
return n, int(msg.Control.Len), int(msg.Flags), sa, err
|
||||||
}
|
}
|
||||||
|
|
@ -1329,20 +1362,17 @@ func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.Sockadd
|
||||||
p = p[:maxRW]
|
p = p[:maxRW]
|
||||||
}
|
}
|
||||||
|
|
||||||
o := &fd.rop
|
rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
|
||||||
if o.rsa == nil {
|
defer wsaRsaPool.Put(rsa)
|
||||||
o.rsa = new(syscall.RawSockaddrAny)
|
msg := newWSAMsg(p, oob, flags, rsa)
|
||||||
}
|
defer freeWSAMsg(msg)
|
||||||
msg := newWSAMsg(p, oob, flags)
|
n, err := fd.execIO(&fd.rop, func(o *operation) (qty uint32, err error) {
|
||||||
msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
|
err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
|
||||||
msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
|
|
||||||
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
|
||||||
err = windows.WSARecvMsg(fd.Sysfd, &msg, &qty, &o.o, nil)
|
|
||||||
return qty, err
|
return qty, err
|
||||||
})
|
})
|
||||||
err = fd.eofError(n, err)
|
err = fd.eofError(n, err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rawToSockaddrInet4(o.rsa, sa4)
|
rawToSockaddrInet4(rsa, sa4)
|
||||||
}
|
}
|
||||||
return n, int(msg.Control.Len), int(msg.Flags), err
|
return n, int(msg.Control.Len), int(msg.Flags), err
|
||||||
}
|
}
|
||||||
|
|
@ -1358,20 +1388,17 @@ func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.Sockadd
|
||||||
p = p[:maxRW]
|
p = p[:maxRW]
|
||||||
}
|
}
|
||||||
|
|
||||||
o := &fd.rop
|
rsa := wsaRsaPool.Get().(*syscall.RawSockaddrAny)
|
||||||
if o.rsa == nil {
|
defer wsaRsaPool.Put(rsa)
|
||||||
o.rsa = new(syscall.RawSockaddrAny)
|
msg := newWSAMsg(p, oob, flags, rsa)
|
||||||
}
|
defer freeWSAMsg(msg)
|
||||||
msg := newWSAMsg(p, oob, flags)
|
n, err := fd.execIO(&fd.rop, func(o *operation) (qty uint32, err error) {
|
||||||
msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
|
err = windows.WSARecvMsg(fd.Sysfd, msg, &qty, &o.o, nil)
|
||||||
msg.Namelen = int32(unsafe.Sizeof(*o.rsa))
|
|
||||||
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
|
||||||
err = windows.WSARecvMsg(fd.Sysfd, &msg, &qty, &o.o, nil)
|
|
||||||
return qty, err
|
return qty, err
|
||||||
})
|
})
|
||||||
err = fd.eofError(n, err)
|
err = fd.eofError(n, err)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rawToSockaddrInet6(o.rsa, sa6)
|
rawToSockaddrInet6(rsa, sa6)
|
||||||
}
|
}
|
||||||
return n, int(msg.Control.Len), int(msg.Flags), err
|
return n, int(msg.Control.Len), int(msg.Flags), err
|
||||||
}
|
}
|
||||||
|
|
@ -1387,21 +1414,22 @@ func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, err
|
||||||
}
|
}
|
||||||
defer fd.writeUnlock()
|
defer fd.writeUnlock()
|
||||||
|
|
||||||
o := &fd.wop
|
var rsa *syscall.RawSockaddrAny
|
||||||
msg := newWSAMsg(p, oob, 0)
|
|
||||||
if sa != nil {
|
if sa != nil {
|
||||||
if o.rsa == nil {
|
rsa = wsaRsaPool.Get().(*syscall.RawSockaddrAny)
|
||||||
o.rsa = new(syscall.RawSockaddrAny)
|
defer wsaRsaPool.Put(rsa)
|
||||||
}
|
}
|
||||||
len, err := sockaddrToRaw(o.rsa, sa)
|
msg := newWSAMsg(p, oob, 0, rsa)
|
||||||
|
defer freeWSAMsg(msg)
|
||||||
|
if sa != nil {
|
||||||
|
var err error
|
||||||
|
msg.Namelen, err = sockaddrToRaw(rsa, sa)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, 0, err
|
return 0, 0, err
|
||||||
}
|
}
|
||||||
msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
|
|
||||||
msg.Namelen = len
|
|
||||||
}
|
}
|
||||||
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
n, err := fd.execIO(&fd.wop, func(o *operation) (qty uint32, err error) {
|
||||||
err = windows.WSASendMsg(fd.Sysfd, &msg, 0, nil, &o.o, nil)
|
err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
|
||||||
return qty, err
|
return qty, err
|
||||||
})
|
})
|
||||||
return n, int(msg.Control.Len), err
|
return n, int(msg.Control.Len), err
|
||||||
|
|
@ -1418,16 +1446,18 @@ func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (in
|
||||||
}
|
}
|
||||||
defer fd.writeUnlock()
|
defer fd.writeUnlock()
|
||||||
|
|
||||||
o := &fd.wop
|
var rsa *syscall.RawSockaddrAny
|
||||||
if o.rsa == nil {
|
if sa != nil {
|
||||||
o.rsa = new(syscall.RawSockaddrAny)
|
rsa = wsaRsaPool.Get().(*syscall.RawSockaddrAny)
|
||||||
|
defer wsaRsaPool.Put(rsa)
|
||||||
}
|
}
|
||||||
len := sockaddrInet4ToRaw(o.rsa, sa)
|
msg := newWSAMsg(p, oob, 0, rsa)
|
||||||
msg := newWSAMsg(p, oob, 0)
|
defer freeWSAMsg(msg)
|
||||||
msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
|
if sa != nil {
|
||||||
msg.Namelen = len
|
msg.Namelen = sockaddrInet4ToRaw(rsa, sa)
|
||||||
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
}
|
||||||
err = windows.WSASendMsg(fd.Sysfd, &msg, 0, nil, &o.o, nil)
|
n, err := fd.execIO(&fd.wop, func(o *operation) (qty uint32, err error) {
|
||||||
|
err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
|
||||||
return qty, err
|
return qty, err
|
||||||
})
|
})
|
||||||
return n, int(msg.Control.Len), err
|
return n, int(msg.Control.Len), err
|
||||||
|
|
@ -1444,16 +1474,18 @@ func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (in
|
||||||
}
|
}
|
||||||
defer fd.writeUnlock()
|
defer fd.writeUnlock()
|
||||||
|
|
||||||
o := &fd.wop
|
var rsa *syscall.RawSockaddrAny
|
||||||
if o.rsa == nil {
|
if sa != nil {
|
||||||
o.rsa = new(syscall.RawSockaddrAny)
|
rsa = wsaRsaPool.Get().(*syscall.RawSockaddrAny)
|
||||||
|
defer wsaRsaPool.Put(rsa)
|
||||||
}
|
}
|
||||||
msg := newWSAMsg(p, oob, 0)
|
msg := newWSAMsg(p, oob, 0, rsa)
|
||||||
len := sockaddrInet6ToRaw(o.rsa, sa)
|
defer freeWSAMsg(msg)
|
||||||
msg.Name = (syscall.Pointer)(unsafe.Pointer(o.rsa))
|
if sa != nil {
|
||||||
msg.Namelen = len
|
msg.Namelen = sockaddrInet6ToRaw(rsa, sa)
|
||||||
n, err := fd.execIO(o, func(o *operation) (qty uint32, err error) {
|
}
|
||||||
err = windows.WSASendMsg(fd.Sysfd, &msg, 0, nil, &o.o, nil)
|
n, err := fd.execIO(&fd.wop, func(o *operation) (qty uint32, err error) {
|
||||||
|
err = windows.WSASendMsg(fd.Sysfd, msg, 0, nil, &o.o, nil)
|
||||||
return qty, err
|
return qty, err
|
||||||
})
|
})
|
||||||
return n, int(msg.Control.Len), err
|
return n, int(msg.Control.Len), err
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ TEXT ·Cas(SB), NOSPLIT, $0-17
|
||||||
MOVW new+12(FP), R6
|
MOVW new+12(FP), R6
|
||||||
|
|
||||||
MOVBU internal∕cpu·Loong64+const_offsetLOONG64HasLAMCAS(SB), R8
|
MOVBU internal∕cpu·Loong64+const_offsetLOONG64HasLAMCAS(SB), R8
|
||||||
BEQ R8, cas_again
|
BEQ R8, ll_sc
|
||||||
MOVV R5, R7 // backup old value
|
MOVV R5, R7 // backup old value
|
||||||
AMCASDBW R6, (R4), R5
|
AMCASDBW R6, (R4), R5
|
||||||
BNE R7, R5, cas_fail0
|
BNE R7, R5, cas_fail0
|
||||||
|
|
@ -30,6 +30,7 @@ cas_fail0:
|
||||||
MOVB R0, ret+16(FP)
|
MOVB R0, ret+16(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
ll_sc:
|
||||||
// Implemented using the ll-sc instruction pair
|
// Implemented using the ll-sc instruction pair
|
||||||
DBAR $0x14 // LoadAcquire barrier
|
DBAR $0x14 // LoadAcquire barrier
|
||||||
cas_again:
|
cas_again:
|
||||||
|
|
@ -60,7 +61,7 @@ TEXT ·Cas64(SB), NOSPLIT, $0-25
|
||||||
MOVV new+16(FP), R6
|
MOVV new+16(FP), R6
|
||||||
|
|
||||||
MOVBU internal∕cpu·Loong64+const_offsetLOONG64HasLAMCAS(SB), R8
|
MOVBU internal∕cpu·Loong64+const_offsetLOONG64HasLAMCAS(SB), R8
|
||||||
BEQ R8, cas64_again
|
BEQ R8, ll_sc_64
|
||||||
MOVV R5, R7 // backup old value
|
MOVV R5, R7 // backup old value
|
||||||
AMCASDBV R6, (R4), R5
|
AMCASDBV R6, (R4), R5
|
||||||
BNE R7, R5, cas64_fail0
|
BNE R7, R5, cas64_fail0
|
||||||
|
|
@ -71,6 +72,7 @@ cas64_fail0:
|
||||||
MOVB R0, ret+24(FP)
|
MOVB R0, ret+24(FP)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
ll_sc_64:
|
||||||
// Implemented using the ll-sc instruction pair
|
// Implemented using the ll-sc instruction pair
|
||||||
DBAR $0x14
|
DBAR $0x14
|
||||||
cas64_again:
|
cas64_again:
|
||||||
|
|
|
||||||
|
|
@ -1,77 +0,0 @@
|
||||||
// Copyright 2025 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
#include "go_asm.h"
|
|
||||||
#include "go_tls.h"
|
|
||||||
#include "textflag.h"
|
|
||||||
#include "time_windows.h"
|
|
||||||
|
|
||||||
TEXT ·StdCall<ABIInternal>(SB),NOSPLIT,$0
|
|
||||||
B ·asmstdcall(SB)
|
|
||||||
|
|
||||||
TEXT ·asmstdcall(SB),NOSPLIT|NOFRAME,$0
|
|
||||||
MOVM.DB.W [R4, R5, R14], (R13) // push {r4, r5, lr}
|
|
||||||
MOVW R0, R4 // put fn * in r4
|
|
||||||
MOVW R13, R5 // save stack pointer in r5
|
|
||||||
|
|
||||||
// SetLastError(0)
|
|
||||||
MOVW $0, R0
|
|
||||||
MRC 15, 0, R1, C13, C0, 2
|
|
||||||
MOVW R0, 0x34(R1)
|
|
||||||
|
|
||||||
MOVW 8(R4), R12 // fn->Args
|
|
||||||
|
|
||||||
// Do we have more than 4 arguments?
|
|
||||||
MOVW 4(R4), R0 // fn->n
|
|
||||||
SUB.S $4, R0, R2
|
|
||||||
BLE loadregs
|
|
||||||
|
|
||||||
// Reserve stack space for remaining args
|
|
||||||
SUB R2<<2, R13
|
|
||||||
BIC $0x7, R13 // alignment for ABI
|
|
||||||
|
|
||||||
// R0: count of arguments
|
|
||||||
// R1:
|
|
||||||
// R2: loop counter, from 0 to (n-4)
|
|
||||||
// R3: scratch
|
|
||||||
// R4: pointer to StdCallInfo struct
|
|
||||||
// R12: fn->args
|
|
||||||
MOVW $0, R2
|
|
||||||
stackargs:
|
|
||||||
ADD $4, R2, R3 // r3 = args[4 + i]
|
|
||||||
MOVW R3<<2(R12), R3
|
|
||||||
MOVW R3, R2<<2(R13) // stack[i] = r3
|
|
||||||
|
|
||||||
ADD $1, R2 // i++
|
|
||||||
SUB $4, R0, R3 // while (i < (n - 4))
|
|
||||||
CMP R3, R2
|
|
||||||
BLT stackargs
|
|
||||||
|
|
||||||
loadregs:
|
|
||||||
CMP $3, R0
|
|
||||||
MOVW.GT 12(R12), R3
|
|
||||||
|
|
||||||
CMP $2, R0
|
|
||||||
MOVW.GT 8(R12), R2
|
|
||||||
|
|
||||||
CMP $1, R0
|
|
||||||
MOVW.GT 4(R12), R1
|
|
||||||
|
|
||||||
CMP $0, R0
|
|
||||||
MOVW.GT 0(R12), R0
|
|
||||||
|
|
||||||
BIC $0x7, R13 // alignment for ABI
|
|
||||||
MOVW 0(R4), R12 // branch to fn->fn
|
|
||||||
BL (R12)
|
|
||||||
|
|
||||||
MOVW R5, R13 // free stack space
|
|
||||||
MOVW R0, 12(R4) // save return value to fn->r1
|
|
||||||
MOVW R1, 16(R4)
|
|
||||||
|
|
||||||
// GetLastError
|
|
||||||
MRC 15, 0, R1, C13, C0, 2
|
|
||||||
MOVW 0x34(R1), R0
|
|
||||||
MOVW R0, 20(R4) // store in fn->err
|
|
||||||
|
|
||||||
MOVM.IA.W (R13), [R4, R5, R15]
|
|
||||||
|
|
@ -11,18 +11,23 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Openat flags supported by syscall.Open.
|
||||||
|
const (
|
||||||
|
O_DIRECTORY = 0x04000 // target must be a directory
|
||||||
|
)
|
||||||
|
|
||||||
// Openat flags not supported by syscall.Open.
|
// Openat flags not supported by syscall.Open.
|
||||||
//
|
//
|
||||||
// These are invented values.
|
// These are invented values, use values in the 33-63 bit range
|
||||||
|
// to avoid overlap with flags and attributes supported by [syscall.Open].
|
||||||
//
|
//
|
||||||
// When adding a new flag here, add an unexported version to
|
// When adding a new flag here, add an unexported version to
|
||||||
// the set of invented O_ values in syscall/types_windows.go
|
// the set of invented O_ values in syscall/types_windows.go
|
||||||
// to avoid overlap.
|
// to avoid overlap.
|
||||||
const (
|
const (
|
||||||
O_DIRECTORY = 0x100000 // target must be a directory
|
O_NOFOLLOW_ANY = 0x200000000 // disallow symlinks anywhere in the path
|
||||||
O_NOFOLLOW_ANY = 0x20000000 // disallow symlinks anywhere in the path
|
O_OPEN_REPARSE = 0x400000000 // FILE_OPEN_REPARSE_POINT, used by Lstat
|
||||||
O_OPEN_REPARSE = 0x40000000 // FILE_OPEN_REPARSE_POINT, used by Lstat
|
O_WRITE_ATTRS = 0x800000000 // FILE_WRITE_ATTRIBUTES, used by Chmod
|
||||||
O_WRITE_ATTRS = 0x80000000 // FILE_WRITE_ATTRIBUTES, used by Chmod
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Openat(dirfd syscall.Handle, name string, flag uint64, perm uint32) (_ syscall.Handle, e1 error) {
|
func Openat(dirfd syscall.Handle, name string, flag uint64, perm uint32) (_ syscall.Handle, e1 error) {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsNonblock returns whether the file descriptor fd is opened
|
// IsNonblock returns whether the file descriptor fd is opened
|
||||||
// in non-blocking mode, that is, the [syscall.FILE_FLAG_OVERLAPPED] flag
|
// in non-blocking mode, that is, the [windows.O_FILE_FLAG_OVERLAPPED] flag
|
||||||
// was set when the file was opened.
|
// was set when the file was opened.
|
||||||
func IsNonblock(fd syscall.Handle) (nonblocking bool, err error) {
|
func IsNonblock(fd syscall.Handle) (nonblocking bool, err error) {
|
||||||
var info FILE_MODE_INFORMATION
|
var info FILE_MODE_INFORMATION
|
||||||
|
|
|
||||||
|
|
@ -164,6 +164,22 @@ type SECURITY_QUALITY_OF_SERVICE struct {
|
||||||
EffectiveOnly byte
|
EffectiveOnly byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// File flags for [os.OpenFile]. The O_ prefix is used to indicate
|
||||||
|
// that these flags are specific to the OpenFile function.
|
||||||
|
const (
|
||||||
|
O_FILE_FLAG_OPEN_NO_RECALL = 0x00100000
|
||||||
|
O_FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
|
||||||
|
O_FILE_FLAG_SESSION_AWARE = 0x00800000
|
||||||
|
O_FILE_FLAG_POSIX_SEMANTICS = 0x01000000
|
||||||
|
O_FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
|
||||||
|
O_FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
|
||||||
|
O_FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000
|
||||||
|
O_FILE_FLAG_RANDOM_ACCESS = 0x10000000
|
||||||
|
O_FILE_FLAG_NO_BUFFERING = 0x20000000
|
||||||
|
O_FILE_FLAG_OVERLAPPED = 0x40000000
|
||||||
|
O_FILE_FLAG_WRITE_THROUGH = 0x80000000
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// CreateDisposition flags for NtCreateFile and NtCreateNamedPipeFile.
|
// CreateDisposition flags for NtCreateFile and NtCreateNamedPipeFile.
|
||||||
FILE_SUPERSEDE = 0x00000000
|
FILE_SUPERSEDE = 0x00000000
|
||||||
|
|
|
||||||
|
|
@ -694,6 +694,9 @@ func testTraceProg(t *testing.T, progName string, extra func(t *testing.T, trace
|
||||||
runTest(t, false, "")
|
runTest(t, false, "")
|
||||||
})
|
})
|
||||||
t.Run("AsyncPreemptOff", func(t *testing.T) {
|
t.Run("AsyncPreemptOff", func(t *testing.T) {
|
||||||
|
if testing.Short() && runtime.NumCPU() < 2 {
|
||||||
|
t.Skip("skipping trace async preempt off tests in short mode")
|
||||||
|
}
|
||||||
runTest(t, false, "asyncpreemptoff=1")
|
runTest(t, false, "asyncpreemptoff=1")
|
||||||
})
|
})
|
||||||
t.Run("Stress", func(t *testing.T) {
|
t.Run("Stress", func(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,12 @@ func IsInf(f float64, sign int) bool {
|
||||||
// To avoid the floating-point hardware, could use:
|
// To avoid the floating-point hardware, could use:
|
||||||
// x := Float64bits(f);
|
// x := Float64bits(f);
|
||||||
// return sign >= 0 && x == uvinf || sign <= 0 && x == uvneginf;
|
// return sign >= 0 && x == uvinf || sign <= 0 && x == uvneginf;
|
||||||
return sign >= 0 && f > MaxFloat64 || sign <= 0 && f < -MaxFloat64
|
if sign == 0 {
|
||||||
|
f = Abs(f)
|
||||||
|
} else if sign < 0 {
|
||||||
|
f = -f
|
||||||
|
}
|
||||||
|
return f > MaxFloat64
|
||||||
}
|
}
|
||||||
|
|
||||||
// normalize returns a normal number y and exponent exp
|
// normalize returns a normal number y and exponent exp
|
||||||
|
|
|
||||||
|
|
@ -66,11 +66,18 @@ func Trunc(x float64) float64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
func trunc(x float64) float64 {
|
func trunc(x float64) float64 {
|
||||||
if x == 0 || IsNaN(x) || IsInf(x, 0) {
|
if Abs(x) < 1 {
|
||||||
return x
|
return Copysign(0, x)
|
||||||
}
|
}
|
||||||
d, _ := Modf(x)
|
|
||||||
return d
|
b := Float64bits(x)
|
||||||
|
e := uint(b>>shift)&mask - bias
|
||||||
|
|
||||||
|
// Keep the top 12+e bits, the integer part; clear the rest.
|
||||||
|
if e < 64-12 {
|
||||||
|
b &^= 1<<(64-12-e) - 1
|
||||||
|
}
|
||||||
|
return Float64frombits(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Round returns the nearest integer, rounding half away from zero.
|
// Round returns the nearest integer, rounding half away from zero.
|
||||||
|
|
|
||||||
|
|
@ -11,33 +11,8 @@ package math
|
||||||
//
|
//
|
||||||
// Modf(±Inf) = ±Inf, NaN
|
// Modf(±Inf) = ±Inf, NaN
|
||||||
// Modf(NaN) = NaN, NaN
|
// Modf(NaN) = NaN, NaN
|
||||||
func Modf(f float64) (int float64, frac float64) {
|
func Modf(f float64) (integer float64, fractional float64) {
|
||||||
if haveArchModf {
|
integer = Trunc(f)
|
||||||
return archModf(f)
|
fractional = Copysign(f-integer, f)
|
||||||
}
|
|
||||||
return modf(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func modf(f float64) (int float64, frac float64) {
|
|
||||||
if f < 1 {
|
|
||||||
switch {
|
|
||||||
case f < 0:
|
|
||||||
int, frac = Modf(-f)
|
|
||||||
return -int, -frac
|
|
||||||
case f == 0:
|
|
||||||
return f, f // Return -0, -0 when f == -0
|
|
||||||
}
|
|
||||||
return 0, f
|
|
||||||
}
|
|
||||||
|
|
||||||
x := Float64bits(f)
|
|
||||||
e := uint(x>>shift)&mask - bias
|
|
||||||
|
|
||||||
// Keep the top 12+e bits, the integer part; clear the rest.
|
|
||||||
if e < 64-12 {
|
|
||||||
x &^= 1<<(64-12-e) - 1
|
|
||||||
}
|
|
||||||
int = Float64frombits(x)
|
|
||||||
frac = f - int
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
// Copyright 2016 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
#include "textflag.h"
|
|
||||||
|
|
||||||
// func archModf(f float64) (int float64, frac float64)
|
|
||||||
TEXT ·archModf(SB),NOSPLIT,$0
|
|
||||||
MOVD f+0(FP), R0
|
|
||||||
FMOVD R0, F0
|
|
||||||
FRINTZD F0, F1
|
|
||||||
FMOVD F1, int+8(FP)
|
|
||||||
FSUBD F1, F0
|
|
||||||
FMOVD F0, R1
|
|
||||||
AND $(1<<63), R0
|
|
||||||
ORR R0, R1 // must have same sign
|
|
||||||
MOVD R1, frac+16(FP)
|
|
||||||
RET
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build arm64 || ppc64 || ppc64le
|
|
||||||
|
|
||||||
package math
|
|
||||||
|
|
||||||
const haveArchModf = true
|
|
||||||
|
|
||||||
func archModf(f float64) (int float64, frac float64)
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build !arm64 && !ppc64 && !ppc64le
|
|
||||||
|
|
||||||
package math
|
|
||||||
|
|
||||||
const haveArchModf = false
|
|
||||||
|
|
||||||
func archModf(f float64) (int float64, frac float64) {
|
|
||||||
panic("not implemented")
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
// Copyright 2017 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
//go:build ppc64 || ppc64le
|
|
||||||
|
|
||||||
#include "textflag.h"
|
|
||||||
|
|
||||||
// func archModf(f float64) (int float64, frac float64)
|
|
||||||
TEXT ·archModf(SB),NOSPLIT,$0
|
|
||||||
FMOVD f+0(FP), F0
|
|
||||||
FRIZ F0, F1
|
|
||||||
FMOVD F1, int+8(FP)
|
|
||||||
FSUB F1, F0, F2
|
|
||||||
FCPSGN F2, F0, F2
|
|
||||||
FMOVD F2, frac+16(FP)
|
|
||||||
RET
|
|
||||||
|
|
@ -6,5 +6,5 @@ package math
|
||||||
|
|
||||||
// Signbit reports whether x is negative or negative zero.
|
// Signbit reports whether x is negative or negative zero.
|
||||||
func Signbit(x float64) bool {
|
func Signbit(x float64) bool {
|
||||||
return Float64bits(x)&(1<<63) != 0
|
return int64(Float64bits(x)) < 0
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ func cgoLookupIP(ctx context.Context, network, name string) (addrs []IPAddr, err
|
||||||
panic("cgo stub: cgo not available")
|
panic("cgo stub: cgo not available")
|
||||||
}
|
}
|
||||||
|
|
||||||
func cgoLookupCNAME(ctx context.Context, name string) (cname string, err error, completed bool) {
|
func cgoLookupCNAME(ctx context.Context, name string) (cname string, err error) {
|
||||||
panic("cgo stub: cgo not available")
|
panic("cgo stub: cgo not available")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -297,16 +297,16 @@ func cgoSockaddr(ip IP, zone string) (*_C_struct_sockaddr, _C_socklen_t) {
|
||||||
return nil, 0
|
return nil, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func cgoLookupCNAME(ctx context.Context, name string) (cname string, err error, completed bool) {
|
func cgoLookupCNAME(ctx context.Context, name string) (cname string, err error) {
|
||||||
resources, err := resSearch(ctx, name, int(dnsmessage.TypeCNAME), int(dnsmessage.ClassINET))
|
resources, err := resSearch(ctx, name, int(dnsmessage.TypeCNAME), int(dnsmessage.ClassINET))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return "", err
|
||||||
}
|
}
|
||||||
cname, err = parseCNAMEFromResources(resources)
|
cname, err = parseCNAMEFromResources(resources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err, false
|
return "", err
|
||||||
}
|
}
|
||||||
return cname, nil, true
|
return cname, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// resSearch will make a call to the 'res_nsearch' routine in the C library
|
// resSearch will make a call to the 'res_nsearch' routine in the C library
|
||||||
|
|
@ -351,7 +351,7 @@ func cgoResSearch(hostname string, rtype, class int) ([]dnsmessage.Resource, err
|
||||||
|
|
||||||
var size int
|
var size int
|
||||||
for {
|
for {
|
||||||
size := _C_res_nsearch(state, (*_C_char)(unsafe.Pointer(s)), class, rtype, buf, bufSize)
|
size = _C_res_nsearch(state, (*_C_char)(unsafe.Pointer(s)), class, rtype, buf, bufSize)
|
||||||
if size <= 0 || size > 0xffff {
|
if size <= 0 || size > 0xffff {
|
||||||
return nil, errors.New("res_nsearch failure")
|
return nil, errors.New("res_nsearch failure")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ package net
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"internal/testenv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -67,3 +68,12 @@ func TestCgoLookupPTRWithCancel(t *testing.T) {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCgoLookupCNAME(t *testing.T) {
|
||||||
|
mustHaveExternalNetwork(t)
|
||||||
|
testenv.SkipFlakyNet(t)
|
||||||
|
defer dnsWaitGroup.Wait()
|
||||||
|
if _, err := cgoLookupCNAME(t.Context(), "www.iana.org."); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1227,7 +1227,7 @@ func testClientTimeout(t *testing.T, mode testMode) {
|
||||||
t.Logf("timeout before response received")
|
t.Logf("timeout before response received")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if runtime.GOOS == "windows" && strings.HasPrefix(runtime.GOARCH, "arm") {
|
if runtime.GOOS == "windows" && runtime.GOARCH == "arm64" {
|
||||||
testenv.SkipFlaky(t, 43120)
|
testenv.SkipFlaky(t, 43120)
|
||||||
}
|
}
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -1256,7 +1256,7 @@ func testClientTimeout(t *testing.T, mode testMode) {
|
||||||
t.Errorf("ReadAll error = %q; expected some context.DeadlineExceeded", err)
|
t.Errorf("ReadAll error = %q; expected some context.DeadlineExceeded", err)
|
||||||
}
|
}
|
||||||
if got := ne.Error(); !strings.Contains(got, "(Client.Timeout") {
|
if got := ne.Error(); !strings.Contains(got, "(Client.Timeout") {
|
||||||
if runtime.GOOS == "windows" && strings.HasPrefix(runtime.GOARCH, "arm") {
|
if runtime.GOOS == "windows" && runtime.GOARCH == "arm64" {
|
||||||
testenv.SkipFlaky(t, 43120)
|
testenv.SkipFlaky(t, 43120)
|
||||||
}
|
}
|
||||||
t.Errorf("error string = %q; missing timeout substring", got)
|
t.Errorf("error string = %q; missing timeout substring", got)
|
||||||
|
|
@ -1302,7 +1302,7 @@ func testClientTimeout_Headers(t *testing.T, mode testMode) {
|
||||||
t.Errorf("ReadAll error = %q; expected some context.DeadlineExceeded", err)
|
t.Errorf("ReadAll error = %q; expected some context.DeadlineExceeded", err)
|
||||||
}
|
}
|
||||||
if got := ne.Error(); !strings.Contains(got, "Client.Timeout exceeded") {
|
if got := ne.Error(); !strings.Contains(got, "Client.Timeout exceeded") {
|
||||||
if runtime.GOOS == "windows" && strings.HasPrefix(runtime.GOARCH, "arm") {
|
if runtime.GOOS == "windows" && runtime.GOARCH == "arm64" {
|
||||||
testenv.SkipFlaky(t, 43120)
|
testenv.SkipFlaky(t, 43120)
|
||||||
}
|
}
|
||||||
t.Errorf("error string = %q; missing timeout substring", got)
|
t.Errorf("error string = %q; missing timeout substring", got)
|
||||||
|
|
|
||||||
|
|
@ -77,13 +77,21 @@ func (c *CrossOriginProtection) AddTrustedOrigin(origin string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var noopHandler = HandlerFunc(func(w ResponseWriter, r *Request) {})
|
type noopHandler struct{}
|
||||||
|
|
||||||
|
func (noopHandler) ServeHTTP(ResponseWriter, *Request) {}
|
||||||
|
|
||||||
|
var sentinelHandler Handler = &noopHandler{}
|
||||||
|
|
||||||
// AddInsecureBypassPattern permits all requests that match the given pattern.
|
// AddInsecureBypassPattern permits all requests that match the given pattern.
|
||||||
// The pattern syntax and precedence rules are the same as [ServeMux].
|
|
||||||
//
|
//
|
||||||
// AddInsecureBypassPattern can be called concurrently with other methods
|
// The pattern syntax and precedence rules are the same as [ServeMux]. Only
|
||||||
// or request handling, and applies to future requests.
|
// requests that match the pattern directly are permitted. Those that ServeMux
|
||||||
|
// would redirect to a pattern (e.g. after cleaning the path or adding a
|
||||||
|
// trailing slash) are not.
|
||||||
|
//
|
||||||
|
// AddInsecureBypassPattern can be called concurrently with other methods or
|
||||||
|
// request handling, and applies to future requests.
|
||||||
func (c *CrossOriginProtection) AddInsecureBypassPattern(pattern string) {
|
func (c *CrossOriginProtection) AddInsecureBypassPattern(pattern string) {
|
||||||
var bypass *ServeMux
|
var bypass *ServeMux
|
||||||
|
|
||||||
|
|
@ -99,7 +107,7 @@ func (c *CrossOriginProtection) AddInsecureBypassPattern(pattern string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bypass.Handle(pattern, noopHandler)
|
bypass.Handle(pattern, sentinelHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetDenyHandler sets a handler to invoke when a request is rejected.
|
// SetDenyHandler sets a handler to invoke when a request is rejected.
|
||||||
|
|
@ -172,7 +180,7 @@ var (
|
||||||
// be deferred until the last moment.
|
// be deferred until the last moment.
|
||||||
func (c *CrossOriginProtection) isRequestExempt(req *Request) bool {
|
func (c *CrossOriginProtection) isRequestExempt(req *Request) bool {
|
||||||
if bypass := c.bypass.Load(); bypass != nil {
|
if bypass := c.bypass.Load(); bypass != nil {
|
||||||
if _, pattern := bypass.Handler(req); pattern != "" {
|
if h, _ := bypass.Handler(req); h == sentinelHandler {
|
||||||
// The request matches a bypass pattern.
|
// The request matches a bypass pattern.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,11 @@ func TestCrossOriginProtectionPatternBypass(t *testing.T) {
|
||||||
protection := http.NewCrossOriginProtection()
|
protection := http.NewCrossOriginProtection()
|
||||||
protection.AddInsecureBypassPattern("/bypass/")
|
protection.AddInsecureBypassPattern("/bypass/")
|
||||||
protection.AddInsecureBypassPattern("/only/{foo}")
|
protection.AddInsecureBypassPattern("/only/{foo}")
|
||||||
|
protection.AddInsecureBypassPattern("/no-trailing")
|
||||||
|
protection.AddInsecureBypassPattern("/yes-trailing/")
|
||||||
|
protection.AddInsecureBypassPattern("PUT /put-only/")
|
||||||
|
protection.AddInsecureBypassPattern("GET /get-only/")
|
||||||
|
protection.AddInsecureBypassPattern("POST /post-only/")
|
||||||
handler := protection.Handler(okHandler)
|
handler := protection.Handler(okHandler)
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
|
@ -126,13 +131,23 @@ func TestCrossOriginProtectionPatternBypass(t *testing.T) {
|
||||||
{"non-bypass path without sec-fetch-site", "/api/", "", http.StatusForbidden},
|
{"non-bypass path without sec-fetch-site", "/api/", "", http.StatusForbidden},
|
||||||
{"non-bypass path with cross-site", "/api/", "cross-site", http.StatusForbidden},
|
{"non-bypass path with cross-site", "/api/", "cross-site", http.StatusForbidden},
|
||||||
|
|
||||||
{"redirect to bypass path without ..", "/foo/../bypass/bar", "", http.StatusOK},
|
{"redirect to bypass path without ..", "/foo/../bypass/bar", "", http.StatusForbidden},
|
||||||
{"redirect to bypass path with trailing slash", "/bypass", "", http.StatusOK},
|
{"redirect to bypass path with trailing slash", "/bypass", "", http.StatusForbidden},
|
||||||
{"redirect to non-bypass path with ..", "/foo/../api/bar", "", http.StatusForbidden},
|
{"redirect to non-bypass path with ..", "/foo/../api/bar", "", http.StatusForbidden},
|
||||||
{"redirect to non-bypass path with trailing slash", "/api", "", http.StatusForbidden},
|
{"redirect to non-bypass path with trailing slash", "/api", "", http.StatusForbidden},
|
||||||
|
|
||||||
{"wildcard bypass", "/only/123", "", http.StatusOK},
|
{"wildcard bypass", "/only/123", "", http.StatusOK},
|
||||||
{"non-wildcard", "/only/123/foo", "", http.StatusForbidden},
|
{"non-wildcard", "/only/123/foo", "", http.StatusForbidden},
|
||||||
|
|
||||||
|
// https://go.dev/issue/75054
|
||||||
|
{"no trailing slash exact match", "/no-trailing", "", http.StatusOK},
|
||||||
|
{"no trailing slash with slash", "/no-trailing/", "", http.StatusForbidden},
|
||||||
|
{"yes trailing slash exact match", "/yes-trailing/", "", http.StatusOK},
|
||||||
|
{"yes trailing slash without slash", "/yes-trailing", "", http.StatusForbidden},
|
||||||
|
|
||||||
|
{"method-specific hit", "/post-only/", "", http.StatusOK},
|
||||||
|
{"method-specific miss (PUT)", "/put-only/", "", http.StatusForbidden},
|
||||||
|
{"method-specific miss (GET)", "/get-only/", "", http.StatusForbidden},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
package httptest
|
package httptest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"flag"
|
"flag"
|
||||||
|
|
@ -126,8 +127,24 @@ func (s *Server) Start() {
|
||||||
if s.URL != "" {
|
if s.URL != "" {
|
||||||
panic("Server already started")
|
panic("Server already started")
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.client == nil {
|
if s.client == nil {
|
||||||
s.client = &http.Client{Transport: &http.Transport{}}
|
tr := &http.Transport{}
|
||||||
|
dialer := net.Dialer{}
|
||||||
|
// User code may set either of Dial or DialContext, with DialContext taking precedence.
|
||||||
|
// We set DialContext here to preserve any context values that are passed in,
|
||||||
|
// but fall back to Dial if the user has set it.
|
||||||
|
tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
if tr.Dial != nil {
|
||||||
|
return tr.Dial(network, addr)
|
||||||
|
}
|
||||||
|
if addr == "example.com:80" || strings.HasSuffix(addr, ".example.com:80") {
|
||||||
|
addr = s.Listener.Addr().String()
|
||||||
|
}
|
||||||
|
return dialer.DialContext(ctx, network, addr)
|
||||||
|
}
|
||||||
|
s.client = &http.Client{Transport: tr}
|
||||||
|
|
||||||
}
|
}
|
||||||
s.URL = "http://" + s.Listener.Addr().String()
|
s.URL = "http://" + s.Listener.Addr().String()
|
||||||
s.wrap()
|
s.wrap()
|
||||||
|
|
@ -173,12 +190,23 @@ func (s *Server) StartTLS() {
|
||||||
}
|
}
|
||||||
certpool := x509.NewCertPool()
|
certpool := x509.NewCertPool()
|
||||||
certpool.AddCert(s.certificate)
|
certpool.AddCert(s.certificate)
|
||||||
s.client.Transport = &http.Transport{
|
tr := &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{
|
TLSClientConfig: &tls.Config{
|
||||||
RootCAs: certpool,
|
RootCAs: certpool,
|
||||||
},
|
},
|
||||||
ForceAttemptHTTP2: s.EnableHTTP2,
|
ForceAttemptHTTP2: s.EnableHTTP2,
|
||||||
}
|
}
|
||||||
|
dialer := net.Dialer{}
|
||||||
|
tr.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
|
if tr.Dial != nil {
|
||||||
|
return tr.Dial(network, addr)
|
||||||
|
}
|
||||||
|
if addr == "example.com:443" || strings.HasSuffix(addr, ".example.com:443") {
|
||||||
|
addr = s.Listener.Addr().String()
|
||||||
|
}
|
||||||
|
return dialer.DialContext(ctx, network, addr)
|
||||||
|
}
|
||||||
|
s.client.Transport = tr
|
||||||
s.Listener = tls.NewListener(s.Listener, s.TLS)
|
s.Listener = tls.NewListener(s.Listener, s.TLS)
|
||||||
s.URL = "https://" + s.Listener.Addr().String()
|
s.URL = "https://" + s.Listener.Addr().String()
|
||||||
s.wrap()
|
s.wrap()
|
||||||
|
|
@ -300,6 +328,8 @@ func (s *Server) Certificate() *x509.Certificate {
|
||||||
// It is configured to trust the server's TLS test certificate and will
|
// It is configured to trust the server's TLS test certificate and will
|
||||||
// close its idle connections on [Server.Close].
|
// close its idle connections on [Server.Close].
|
||||||
// Use Server.URL as the base URL to send requests to the server.
|
// Use Server.URL as the base URL to send requests to the server.
|
||||||
|
// The returned client will also redirect any requests to "example.com"
|
||||||
|
// or its subdomains to the server.
|
||||||
func (s *Server) Client() *http.Client {
|
func (s *Server) Client() *http.Client {
|
||||||
return s.client
|
return s.client
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -293,3 +293,40 @@ func TestTLSServerWithHTTP2(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClientExampleCom(t *testing.T) {
|
||||||
|
modes := []struct {
|
||||||
|
proto string
|
||||||
|
host string
|
||||||
|
}{
|
||||||
|
{"http", "example.com"},
|
||||||
|
{"http", "foo.example.com"},
|
||||||
|
{"https", "example.com"},
|
||||||
|
{"https", "foo.example.com"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range modes {
|
||||||
|
t.Run(tt.proto+" "+tt.host, func(t *testing.T) {
|
||||||
|
cst := NewUnstartedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set("requested-hostname", r.Host)
|
||||||
|
}))
|
||||||
|
switch tt.proto {
|
||||||
|
case "https":
|
||||||
|
cst.EnableHTTP2 = true
|
||||||
|
cst.StartTLS()
|
||||||
|
default:
|
||||||
|
cst.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
defer cst.Close()
|
||||||
|
|
||||||
|
res, err := cst.Client().Get(tt.proto + "://" + tt.host)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to make request: %v", err)
|
||||||
|
}
|
||||||
|
if got, want := res.Header.Get("requested-hostname"), tt.host; got != want {
|
||||||
|
t.Fatalf("Requested hostname mismatch\ngot: %q\nwant: %q", got, want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,6 @@ func DumpRequestOut(req *http.Request, body bool) ([]byte, error) {
|
||||||
|
|
||||||
req.Body = save
|
req.Body = save
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pw.Close()
|
|
||||||
dr.err = err
|
dr.err = err
|
||||||
close(quitReadCh)
|
close(quitReadCh)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -2759,9 +2759,12 @@ func (mux *ServeMux) matchOrRedirect(host, method, path string, u *url.URL) (_ *
|
||||||
defer mux.mu.RUnlock()
|
defer mux.mu.RUnlock()
|
||||||
|
|
||||||
n, matches := mux.tree.match(host, method, path)
|
n, matches := mux.tree.match(host, method, path)
|
||||||
// If we have an exact match, or we were asked not to try trailing-slash redirection,
|
// We can terminate here if any of the following is true:
|
||||||
// or the URL already has a trailing slash, then we're done.
|
// - We have an exact match already.
|
||||||
if !exactMatch(n, path) && u != nil && !strings.HasSuffix(path, "/") {
|
// - We were asked not to try trailing slash redirection.
|
||||||
|
// - The URL already has a trailing slash.
|
||||||
|
// - The URL is an empty string.
|
||||||
|
if !exactMatch(n, path) && u != nil && !strings.HasSuffix(path, "/") && path != "" {
|
||||||
// If there is an exact match with a trailing slash, then redirect.
|
// If there is an exact match with a trailing slash, then redirect.
|
||||||
path += "/"
|
path += "/"
|
||||||
n2, _ := mux.tree.match(host, method, path)
|
n2, _ := mux.tree.match(host, method, path)
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ func TestFindHandler(t *testing.T) {
|
||||||
{"GET", "/foo/x", "&http.handler{i:2}"},
|
{"GET", "/foo/x", "&http.handler{i:2}"},
|
||||||
{"GET", "/bar/x", "&http.handler{i:4}"},
|
{"GET", "/bar/x", "&http.handler{i:4}"},
|
||||||
{"GET", "/bar", `&http.redirectHandler{url:"/bar/", code:301}`},
|
{"GET", "/bar", `&http.redirectHandler{url:"/bar/", code:301}`},
|
||||||
|
{"CONNECT", "", "(http.HandlerFunc)(.*)"},
|
||||||
{"CONNECT", "/", "&http.handler{i:1}"},
|
{"CONNECT", "/", "&http.handler{i:1}"},
|
||||||
{"CONNECT", "//", "&http.handler{i:1}"},
|
{"CONNECT", "//", "&http.handler{i:1}"},
|
||||||
{"CONNECT", "//foo", "&http.handler{i:5}"},
|
{"CONNECT", "//foo", "&http.handler{i:5}"},
|
||||||
|
|
@ -112,7 +113,7 @@ func TestFindHandler(t *testing.T) {
|
||||||
r.URL = &url.URL{Path: test.path}
|
r.URL = &url.URL{Path: test.path}
|
||||||
gotH, _, _, _ := mux.findHandler(&r)
|
gotH, _, _, _ := mux.findHandler(&r)
|
||||||
got := fmt.Sprintf("%#v", gotH)
|
got := fmt.Sprintf("%#v", gotH)
|
||||||
if got != test.wantHandler {
|
if !regexp.MustCompile(test.wantHandler).MatchString(got) {
|
||||||
t.Errorf("%s %q: got %q, want %q", test.method, test.path, got, test.wantHandler)
|
t.Errorf("%s %q: got %q, want %q", test.method, test.path, got, test.wantHandler)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -325,6 +325,13 @@ func (t *Transport) readBufferSize() int {
|
||||||
return 4 << 10
|
return 4 << 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *Transport) maxHeaderResponseSize() int64 {
|
||||||
|
if t.MaxResponseHeaderBytes > 0 {
|
||||||
|
return t.MaxResponseHeaderBytes
|
||||||
|
}
|
||||||
|
return 10 << 20 // conservative default; same as http2
|
||||||
|
}
|
||||||
|
|
||||||
// Clone returns a deep copy of t's exported fields.
|
// Clone returns a deep copy of t's exported fields.
|
||||||
func (t *Transport) Clone() *Transport {
|
func (t *Transport) Clone() *Transport {
|
||||||
t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)
|
t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)
|
||||||
|
|
@ -1871,7 +1878,7 @@ func (t *Transport) dialConn(ctx context.Context, cm connectMethod) (pconn *pers
|
||||||
}
|
}
|
||||||
// Okay to use and discard buffered reader here, because
|
// Okay to use and discard buffered reader here, because
|
||||||
// TLS server will not speak until spoken to.
|
// TLS server will not speak until spoken to.
|
||||||
br := bufio.NewReader(conn)
|
br := bufio.NewReader(&io.LimitedReader{R: conn, N: t.maxHeaderResponseSize()})
|
||||||
resp, err = ReadResponse(br, connectReq)
|
resp, err = ReadResponse(br, connectReq)
|
||||||
}()
|
}()
|
||||||
select {
|
select {
|
||||||
|
|
@ -2108,10 +2115,7 @@ type persistConn struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pc *persistConn) maxHeaderResponseSize() int64 {
|
func (pc *persistConn) maxHeaderResponseSize() int64 {
|
||||||
if v := pc.t.MaxResponseHeaderBytes; v != 0 {
|
return pc.t.maxHeaderResponseSize()
|
||||||
return v
|
|
||||||
}
|
|
||||||
return 10 << 20 // conservative default; same as http2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pc *persistConn) Read(p []byte) (n int, err error) {
|
func (pc *persistConn) Read(p []byte) (n int, err error) {
|
||||||
|
|
|
||||||
|
|
@ -1550,6 +1550,72 @@ func TestTransportProxy(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue 74633: verify that a client will not indefinitely read a response from
|
||||||
|
// a proxy server that writes an infinite byte of stream, rather than
|
||||||
|
// responding with 200 OK.
|
||||||
|
func TestProxyWithInfiniteHeader(t *testing.T) {
|
||||||
|
defer afterTest(t)
|
||||||
|
|
||||||
|
ln := newLocalListener(t)
|
||||||
|
defer ln.Close()
|
||||||
|
cancelc := make(chan struct{})
|
||||||
|
defer close(cancelc)
|
||||||
|
|
||||||
|
// Simulate a malicious / misbehaving proxy that writes an unlimited number
|
||||||
|
// of bytes rather than responding with 200 OK.
|
||||||
|
go func() {
|
||||||
|
c, err := ln.Accept()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Accept: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer c.Close()
|
||||||
|
// Read the CONNECT request
|
||||||
|
br := bufio.NewReader(c)
|
||||||
|
cr, err := ReadRequest(br)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("proxy server failed to read CONNECT request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if cr.Method != "CONNECT" {
|
||||||
|
t.Errorf("unexpected method %q", cr.Method)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep writing bytes until the test exits.
|
||||||
|
for {
|
||||||
|
// runtime.Gosched() is needed here. Otherwise, this test might
|
||||||
|
// livelock in environments like WASM, where the one single thread
|
||||||
|
// we have could be hogged by the infinite loop of writing bytes.
|
||||||
|
runtime.Gosched()
|
||||||
|
select {
|
||||||
|
case <-cancelc:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
c.Write([]byte("infinite stream of bytes"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
c := &Client{
|
||||||
|
Transport: &Transport{
|
||||||
|
Proxy: func(*Request) (*url.URL, error) {
|
||||||
|
return url.Parse("http://" + ln.Addr().String())
|
||||||
|
},
|
||||||
|
// Limit MaxResponseHeaderBytes so the test returns quicker.
|
||||||
|
MaxResponseHeaderBytes: 1024,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
req, err := NewRequest("GET", "https://golang.fake.tld/", nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
_, err = c.Do(req)
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("unexpected Get success")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestOnProxyConnectResponse(t *testing.T) {
|
func TestOnProxyConnectResponse(t *testing.T) {
|
||||||
|
|
||||||
var tcases = []struct {
|
var tcases = []struct {
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,12 @@ import (
|
||||||
// BUG(mikio): On JS and Plan 9, methods and functions related
|
// BUG(mikio): On JS and Plan 9, methods and functions related
|
||||||
// to IPConn are not implemented.
|
// to IPConn are not implemented.
|
||||||
|
|
||||||
|
// BUG: On Windows, raw IP sockets are restricted by the operating system.
|
||||||
|
// Sending TCP data, sending UDP data with invalid source addresses,
|
||||||
|
// and calling bind with TCP protocol don't work.
|
||||||
|
//
|
||||||
|
// See Winsock reference for details.
|
||||||
|
|
||||||
func ipAddrFromAddr(addr netip.Addr) *IPAddr {
|
func ipAddrFromAddr(addr netip.Addr) *IPAddr {
|
||||||
return &IPAddr{
|
return &IPAddr{
|
||||||
IP: addr.AsSlice(),
|
IP: addr.AsSlice(),
|
||||||
|
|
|
||||||
|
|
@ -260,9 +260,6 @@ func addrPortToSockaddrInet6(ap netip.AddrPort) (syscall.SockaddrInet6, error) {
|
||||||
// to an IPv4-mapped IPv6 address.
|
// to an IPv4-mapped IPv6 address.
|
||||||
// The error message is kept consistent with ipToSockaddrInet6.
|
// The error message is kept consistent with ipToSockaddrInet6.
|
||||||
addr := ap.Addr()
|
addr := ap.Addr()
|
||||||
if !addr.IsValid() {
|
|
||||||
return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: addr.String()}
|
|
||||||
}
|
|
||||||
sa := syscall.SockaddrInet6{
|
sa := syscall.SockaddrInet6{
|
||||||
Addr: addr.As16(),
|
Addr: addr.As16(),
|
||||||
Port: int(ap.Port()),
|
Port: int(ap.Port()),
|
||||||
|
|
|
||||||
|
|
@ -87,8 +87,8 @@ func (r *Resolver) lookupPort(ctx context.Context, network, service string) (int
|
||||||
func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) {
|
func (r *Resolver) lookupCNAME(ctx context.Context, name string) (string, error) {
|
||||||
order, conf := systemConf().hostLookupOrder(r, name)
|
order, conf := systemConf().hostLookupOrder(r, name)
|
||||||
if order == hostLookupCgo {
|
if order == hostLookupCgo {
|
||||||
if cname, err, ok := cgoLookupCNAME(ctx, name); ok {
|
if cname, err := cgoLookupCNAME(ctx, name); err == nil {
|
||||||
return cname, err
|
return cname, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return r.goLookupCNAME(ctx, name, order, conf)
|
return r.goLookupCNAME(ctx, name, order, conf)
|
||||||
|
|
|
||||||
|
|
@ -1082,11 +1082,19 @@ func (ffd *fakeNetFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int
|
||||||
return n, 0, err
|
return n, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ffd *fakeNetFD) writeMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (n int, oobn int, err error) {
|
func (ffd *fakeNetFD) writeMsgInet4(p []byte, oob []byte, sa4 *syscall.SockaddrInet4) (n int, oobn int, err error) {
|
||||||
|
var sa syscall.Sockaddr
|
||||||
|
if sa4 != nil {
|
||||||
|
sa = sa4
|
||||||
|
}
|
||||||
return ffd.writeMsg(p, oob, sa)
|
return ffd.writeMsg(p, oob, sa)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ffd *fakeNetFD) writeMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (n int, oobn int, err error) {
|
func (ffd *fakeNetFD) writeMsgInet6(p []byte, oob []byte, sa6 *syscall.SockaddrInet6) (n int, oobn int, err error) {
|
||||||
|
var sa syscall.Sockaddr
|
||||||
|
if sa6 != nil {
|
||||||
|
sa = sa6
|
||||||
|
}
|
||||||
return ffd.writeMsg(p, oob, sa)
|
return ffd.writeMsg(p, oob, sa)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -110,11 +110,12 @@ func trim(s []byte) []byte {
|
||||||
for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
|
for i < len(s) && (s[i] == ' ' || s[i] == '\t') {
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
n := len(s)
|
s = s[i:]
|
||||||
for n > i && (s[n-1] == ' ' || s[n-1] == '\t') {
|
n := len(s) - 1
|
||||||
|
for n >= 0 && (s[n] == ' ' || s[n] == '\t') {
|
||||||
n--
|
n--
|
||||||
}
|
}
|
||||||
return s[i:n]
|
return s[:n+1]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadContinuedLineBytes is like [Reader.ReadContinuedLine] but
|
// ReadContinuedLineBytes is like [Reader.ReadContinuedLine] but
|
||||||
|
|
|
||||||
|
|
@ -186,17 +186,25 @@ func (c *UDPConn) writeMsgAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn
|
||||||
|
|
||||||
switch c.fd.family {
|
switch c.fd.family {
|
||||||
case syscall.AF_INET:
|
case syscall.AF_INET:
|
||||||
sa, err := addrPortToSockaddrInet4(addr)
|
var sap *syscall.SockaddrInet4
|
||||||
if err != nil {
|
if addr.IsValid() {
|
||||||
return 0, 0, err
|
sa, err := addrPortToSockaddrInet4(addr)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
sap = &sa
|
||||||
}
|
}
|
||||||
return c.fd.writeMsgInet4(b, oob, &sa)
|
return c.fd.writeMsgInet4(b, oob, sap)
|
||||||
case syscall.AF_INET6:
|
case syscall.AF_INET6:
|
||||||
sa, err := addrPortToSockaddrInet6(addr)
|
var sap *syscall.SockaddrInet6
|
||||||
if err != nil {
|
if addr.IsValid() {
|
||||||
return 0, 0, err
|
sa, err := addrPortToSockaddrInet6(addr)
|
||||||
|
if err != nil {
|
||||||
|
return 0, 0, err
|
||||||
|
}
|
||||||
|
sap = &sa
|
||||||
}
|
}
|
||||||
return c.fd.writeMsgInet6(b, oob, &sa)
|
return c.fd.writeMsgInet6(b, oob, sap)
|
||||||
default:
|
default:
|
||||||
return 0, 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()}
|
return 0, 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -141,36 +141,37 @@ func testWriteToConn(t *testing.T, raddr string) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
rap := ra.AddrPort()
|
||||||
|
|
||||||
|
assertErrWriteToConnected := func(t *testing.T, err error) {
|
||||||
|
t.Helper()
|
||||||
|
if e, ok := err.(*OpError); !ok || e.Err != ErrWriteToConnected {
|
||||||
|
t.Errorf("got %v; want ErrWriteToConnected", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
b := []byte("CONNECTED-MODE SOCKET")
|
b := []byte("CONNECTED-MODE SOCKET")
|
||||||
|
_, err = c.(*UDPConn).WriteToUDPAddrPort(b, rap)
|
||||||
|
assertErrWriteToConnected(t, err)
|
||||||
_, err = c.(*UDPConn).WriteToUDP(b, ra)
|
_, err = c.(*UDPConn).WriteToUDP(b, ra)
|
||||||
if err == nil {
|
assertErrWriteToConnected(t, err)
|
||||||
t.Fatal("should fail")
|
|
||||||
}
|
|
||||||
if err != nil && err.(*OpError).Err != ErrWriteToConnected {
|
|
||||||
t.Fatalf("should fail as ErrWriteToConnected: %v", err)
|
|
||||||
}
|
|
||||||
_, err = c.(*UDPConn).WriteTo(b, ra)
|
_, err = c.(*UDPConn).WriteTo(b, ra)
|
||||||
if err == nil {
|
assertErrWriteToConnected(t, err)
|
||||||
t.Fatal("should fail")
|
|
||||||
}
|
|
||||||
if err != nil && err.(*OpError).Err != ErrWriteToConnected {
|
|
||||||
t.Fatalf("should fail as ErrWriteToConnected: %v", err)
|
|
||||||
}
|
|
||||||
_, err = c.Write(b)
|
_, err = c.Write(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Errorf("c.Write(b) = %v; want nil", err)
|
||||||
}
|
}
|
||||||
_, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra)
|
_, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, ra)
|
||||||
if err == nil {
|
assertErrWriteToConnected(t, err)
|
||||||
t.Fatal("should fail")
|
|
||||||
}
|
|
||||||
if err != nil && err.(*OpError).Err != ErrWriteToConnected {
|
|
||||||
t.Fatalf("should fail as ErrWriteToConnected: %v", err)
|
|
||||||
}
|
|
||||||
_, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil)
|
_, _, err = c.(*UDPConn).WriteMsgUDP(b, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Errorf("c.WriteMsgUDP(b, nil, nil) = %v; want nil", err)
|
||||||
|
}
|
||||||
|
_, _, err = c.(*UDPConn).WriteMsgUDPAddrPort(b, nil, rap)
|
||||||
|
assertErrWriteToConnected(t, err)
|
||||||
|
_, _, err = c.(*UDPConn).WriteMsgUDPAddrPort(b, nil, netip.AddrPort{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("c.WriteMsgUDPAddrPort(b, nil, netip.AddrPort{}) = %v; want nil", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -120,12 +120,12 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, &PathError{Op: "open", Path: name, Err: err}
|
return nil, &PathError{Op: "open", Path: name, Err: err}
|
||||||
}
|
}
|
||||||
// syscall.Open always returns a non-blocking handle.
|
nonblocking := flag&windows.O_FILE_FLAG_OVERLAPPED != 0
|
||||||
return newFile(r, name, "file", false), nil
|
return newFile(r, name, "file", nonblocking), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func openDirNolog(name string) (*File, error) {
|
func openDirNolog(name string) (*File, error) {
|
||||||
return openFileNolog(name, O_RDONLY, 0)
|
return openFileNolog(name, O_RDONLY|windows.O_DIRECTORY, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (file *file) close() error {
|
func (file *file) close() error {
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue