mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.typeparams] merge master into dev.typeparams
On top of the merge, the following fixes were applied: + Debug["G"] changed to Debug.G, following golang.org/cl/263539. + issue42058a.go and issue42058b.go were skipped in types2/stdlib_test.go. go/types does not produce errors related to channel element size. Change-Id: I59fc84e12a2d728ef789fdc616f7afe80e451283
This commit is contained in:
commit
5bfd2964a6
636 changed files with 20765 additions and 19446 deletions
228
api/except.txt
228
api/except.txt
|
|
@ -2,12 +2,56 @@ pkg encoding/json, method (*RawMessage) MarshalJSON() ([]uint8, error)
|
||||||
pkg math/big, const MaxBase = 36
|
pkg math/big, const MaxBase = 36
|
||||||
pkg math/big, type Word uintptr
|
pkg math/big, type Word uintptr
|
||||||
pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)
|
pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)
|
||||||
|
pkg os (linux-arm), const O_SYNC = 1052672
|
||||||
|
pkg os (linux-arm), const O_SYNC = 4096
|
||||||
|
pkg os (linux-arm-cgo), const O_SYNC = 1052672
|
||||||
|
pkg os (linux-arm-cgo), const O_SYNC = 4096
|
||||||
|
pkg os, const ModeAppend FileMode
|
||||||
|
pkg os, const ModeCharDevice FileMode
|
||||||
|
pkg os, const ModeDevice FileMode
|
||||||
|
pkg os, const ModeDir FileMode
|
||||||
|
pkg os, const ModeExclusive FileMode
|
||||||
|
pkg os, const ModeIrregular FileMode
|
||||||
|
pkg os, const ModeNamedPipe FileMode
|
||||||
|
pkg os, const ModePerm FileMode
|
||||||
|
pkg os, const ModeSetgid FileMode
|
||||||
|
pkg os, const ModeSetuid FileMode
|
||||||
|
pkg os, const ModeSocket FileMode
|
||||||
|
pkg os, const ModeSticky FileMode
|
||||||
|
pkg os, const ModeSymlink FileMode
|
||||||
|
pkg os, const ModeTemporary FileMode
|
||||||
pkg os, const ModeType = 2399141888
|
pkg os, const ModeType = 2399141888
|
||||||
pkg os, const ModeType = 2399666176
|
pkg os, const ModeType = 2399666176
|
||||||
pkg os (linux-arm), const O_SYNC = 4096
|
pkg os, const ModeType FileMode
|
||||||
pkg os (linux-arm-cgo), const O_SYNC = 4096
|
pkg os, func Chmod(string, FileMode) error
|
||||||
pkg os (linux-arm), const O_SYNC = 1052672
|
pkg os, func Lstat(string) (FileInfo, error)
|
||||||
pkg os (linux-arm-cgo), const O_SYNC = 1052672
|
pkg os, func Mkdir(string, FileMode) error
|
||||||
|
pkg os, func MkdirAll(string, FileMode) error
|
||||||
|
pkg os, func OpenFile(string, int, FileMode) (*File, error)
|
||||||
|
pkg os, func SameFile(FileInfo, FileInfo) bool
|
||||||
|
pkg os, func Stat(string) (FileInfo, error)
|
||||||
|
pkg os, method (*File) Chmod(FileMode) error
|
||||||
|
pkg os, method (*File) Readdir(int) ([]FileInfo, error)
|
||||||
|
pkg os, method (*File) Stat() (FileInfo, error)
|
||||||
|
pkg os, method (*PathError) Error() string
|
||||||
|
pkg os, method (*PathError) Timeout() bool
|
||||||
|
pkg os, method (*PathError) Unwrap() error
|
||||||
|
pkg os, method (FileMode) IsDir() bool
|
||||||
|
pkg os, method (FileMode) IsRegular() bool
|
||||||
|
pkg os, method (FileMode) Perm() FileMode
|
||||||
|
pkg os, method (FileMode) String() string
|
||||||
|
pkg os, type FileInfo interface { IsDir, ModTime, Mode, Name, Size, Sys }
|
||||||
|
pkg os, type FileInfo interface, IsDir() bool
|
||||||
|
pkg os, type FileInfo interface, ModTime() time.Time
|
||||||
|
pkg os, type FileInfo interface, Mode() FileMode
|
||||||
|
pkg os, type FileInfo interface, Name() string
|
||||||
|
pkg os, type FileInfo interface, Size() int64
|
||||||
|
pkg os, type FileInfo interface, Sys() interface{}
|
||||||
|
pkg os, type FileMode uint32
|
||||||
|
pkg os, type PathError struct
|
||||||
|
pkg os, type PathError struct, Err error
|
||||||
|
pkg os, type PathError struct, Op string
|
||||||
|
pkg os, type PathError struct, Path string
|
||||||
pkg syscall (darwin-amd64), const ImplementsGetwd = false
|
pkg syscall (darwin-amd64), const ImplementsGetwd = false
|
||||||
pkg syscall (darwin-amd64), func Fchflags(string, int) error
|
pkg syscall (darwin-amd64), func Fchflags(string, int) error
|
||||||
pkg syscall (darwin-amd64-cgo), const ImplementsGetwd = false
|
pkg syscall (darwin-amd64-cgo), const ImplementsGetwd = false
|
||||||
|
|
@ -18,22 +62,72 @@ pkg syscall (freebsd-386), const ELAST = 94
|
||||||
pkg syscall (freebsd-386), const ImplementsGetwd = false
|
pkg syscall (freebsd-386), const ImplementsGetwd = false
|
||||||
pkg syscall (freebsd-386), const O_CLOEXEC = 0
|
pkg syscall (freebsd-386), const O_CLOEXEC = 0
|
||||||
pkg syscall (freebsd-386), func Fchflags(string, int) error
|
pkg syscall (freebsd-386), func Fchflags(string, int) error
|
||||||
|
pkg syscall (freebsd-386), func Mknod(string, uint32, int) error
|
||||||
|
pkg syscall (freebsd-386), type Dirent struct, Fileno uint32
|
||||||
|
pkg syscall (freebsd-386), type Dirent struct, Namlen uint8
|
||||||
|
pkg syscall (freebsd-386), type Stat_t struct, Blksize uint32
|
||||||
|
pkg syscall (freebsd-386), type Stat_t struct, Dev uint32
|
||||||
|
pkg syscall (freebsd-386), type Stat_t struct, Gen uint32
|
||||||
|
pkg syscall (freebsd-386), type Stat_t struct, Ino uint32
|
||||||
|
pkg syscall (freebsd-386), type Stat_t struct, Lspare int32
|
||||||
|
pkg syscall (freebsd-386), type Stat_t struct, Nlink uint16
|
||||||
|
pkg syscall (freebsd-386), type Stat_t struct, Pad_cgo_0 [8]uint8
|
||||||
|
pkg syscall (freebsd-386), type Stat_t struct, Rdev uint32
|
||||||
|
pkg syscall (freebsd-386), type Statfs_t struct, Mntfromname [88]int8
|
||||||
|
pkg syscall (freebsd-386), type Statfs_t struct, Mntonname [88]int8
|
||||||
pkg syscall (freebsd-386-cgo), const AF_MAX = 38
|
pkg syscall (freebsd-386-cgo), const AF_MAX = 38
|
||||||
pkg syscall (freebsd-386-cgo), const DLT_MATCHING_MAX = 242
|
pkg syscall (freebsd-386-cgo), const DLT_MATCHING_MAX = 242
|
||||||
pkg syscall (freebsd-386-cgo), const ELAST = 94
|
pkg syscall (freebsd-386-cgo), const ELAST = 94
|
||||||
pkg syscall (freebsd-386-cgo), const ImplementsGetwd = false
|
pkg syscall (freebsd-386-cgo), const ImplementsGetwd = false
|
||||||
pkg syscall (freebsd-386-cgo), const O_CLOEXEC = 0
|
pkg syscall (freebsd-386-cgo), const O_CLOEXEC = 0
|
||||||
|
pkg syscall (freebsd-386-cgo), func Mknod(string, uint32, int) error
|
||||||
|
pkg syscall (freebsd-386-cgo), type Dirent struct, Fileno uint32
|
||||||
|
pkg syscall (freebsd-386-cgo), type Dirent struct, Namlen uint8
|
||||||
|
pkg syscall (freebsd-386-cgo), type Stat_t struct, Blksize uint32
|
||||||
|
pkg syscall (freebsd-386-cgo), type Stat_t struct, Dev uint32
|
||||||
|
pkg syscall (freebsd-386-cgo), type Stat_t struct, Gen uint32
|
||||||
|
pkg syscall (freebsd-386-cgo), type Stat_t struct, Ino uint32
|
||||||
|
pkg syscall (freebsd-386-cgo), type Stat_t struct, Lspare int32
|
||||||
|
pkg syscall (freebsd-386-cgo), type Stat_t struct, Nlink uint16
|
||||||
|
pkg syscall (freebsd-386-cgo), type Stat_t struct, Pad_cgo_0 [8]uint8
|
||||||
|
pkg syscall (freebsd-386-cgo), type Stat_t struct, Rdev uint32
|
||||||
|
pkg syscall (freebsd-386-cgo), type Statfs_t struct, Mntfromname [88]int8
|
||||||
|
pkg syscall (freebsd-386-cgo), type Statfs_t struct, Mntonname [88]int8
|
||||||
pkg syscall (freebsd-amd64), const AF_MAX = 38
|
pkg syscall (freebsd-amd64), const AF_MAX = 38
|
||||||
pkg syscall (freebsd-amd64), const DLT_MATCHING_MAX = 242
|
pkg syscall (freebsd-amd64), const DLT_MATCHING_MAX = 242
|
||||||
pkg syscall (freebsd-amd64), const ELAST = 94
|
pkg syscall (freebsd-amd64), const ELAST = 94
|
||||||
pkg syscall (freebsd-amd64), const ImplementsGetwd = false
|
pkg syscall (freebsd-amd64), const ImplementsGetwd = false
|
||||||
pkg syscall (freebsd-amd64), const O_CLOEXEC = 0
|
pkg syscall (freebsd-amd64), const O_CLOEXEC = 0
|
||||||
pkg syscall (freebsd-amd64), func Fchflags(string, int) error
|
pkg syscall (freebsd-amd64), func Fchflags(string, int) error
|
||||||
|
pkg syscall (freebsd-amd64), func Mknod(string, uint32, int) error
|
||||||
|
pkg syscall (freebsd-amd64), type Dirent struct, Fileno uint32
|
||||||
|
pkg syscall (freebsd-amd64), type Dirent struct, Namlen uint8
|
||||||
|
pkg syscall (freebsd-amd64), type Stat_t struct, Blksize uint32
|
||||||
|
pkg syscall (freebsd-amd64), type Stat_t struct, Dev uint32
|
||||||
|
pkg syscall (freebsd-amd64), type Stat_t struct, Gen uint32
|
||||||
|
pkg syscall (freebsd-amd64), type Stat_t struct, Ino uint32
|
||||||
|
pkg syscall (freebsd-amd64), type Stat_t struct, Lspare int32
|
||||||
|
pkg syscall (freebsd-amd64), type Stat_t struct, Nlink uint16
|
||||||
|
pkg syscall (freebsd-amd64), type Stat_t struct, Rdev uint32
|
||||||
|
pkg syscall (freebsd-amd64), type Statfs_t struct, Mntfromname [88]int8
|
||||||
|
pkg syscall (freebsd-amd64), type Statfs_t struct, Mntonname [88]int8
|
||||||
pkg syscall (freebsd-amd64-cgo), const AF_MAX = 38
|
pkg syscall (freebsd-amd64-cgo), const AF_MAX = 38
|
||||||
pkg syscall (freebsd-amd64-cgo), const DLT_MATCHING_MAX = 242
|
pkg syscall (freebsd-amd64-cgo), const DLT_MATCHING_MAX = 242
|
||||||
pkg syscall (freebsd-amd64-cgo), const ELAST = 94
|
pkg syscall (freebsd-amd64-cgo), const ELAST = 94
|
||||||
pkg syscall (freebsd-amd64-cgo), const ImplementsGetwd = false
|
pkg syscall (freebsd-amd64-cgo), const ImplementsGetwd = false
|
||||||
pkg syscall (freebsd-amd64-cgo), const O_CLOEXEC = 0
|
pkg syscall (freebsd-amd64-cgo), const O_CLOEXEC = 0
|
||||||
|
pkg syscall (freebsd-amd64-cgo), func Mknod(string, uint32, int) error
|
||||||
|
pkg syscall (freebsd-amd64-cgo), type Dirent struct, Fileno uint32
|
||||||
|
pkg syscall (freebsd-amd64-cgo), type Dirent struct, Namlen uint8
|
||||||
|
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Blksize uint32
|
||||||
|
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Dev uint32
|
||||||
|
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Gen uint32
|
||||||
|
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Ino uint32
|
||||||
|
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Lspare int32
|
||||||
|
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Nlink uint16
|
||||||
|
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Rdev uint32
|
||||||
|
pkg syscall (freebsd-amd64-cgo), type Statfs_t struct, Mntfromname [88]int8
|
||||||
|
pkg syscall (freebsd-amd64-cgo), type Statfs_t struct, Mntonname [88]int8
|
||||||
pkg syscall (freebsd-arm), const AF_MAX = 38
|
pkg syscall (freebsd-arm), const AF_MAX = 38
|
||||||
pkg syscall (freebsd-arm), const BIOCGRTIMEOUT = 1074545262
|
pkg syscall (freebsd-arm), const BIOCGRTIMEOUT = 1074545262
|
||||||
pkg syscall (freebsd-arm), const BIOCSRTIMEOUT = 2148287085
|
pkg syscall (freebsd-arm), const BIOCSRTIMEOUT = 2148287085
|
||||||
|
|
@ -62,10 +156,22 @@ pkg syscall (freebsd-arm), const SizeofSockaddrDatalink = 56
|
||||||
pkg syscall (freebsd-arm), const SizeofSockaddrUnix = 108
|
pkg syscall (freebsd-arm), const SizeofSockaddrUnix = 108
|
||||||
pkg syscall (freebsd-arm), const TIOCTIMESTAMP = 1074558041
|
pkg syscall (freebsd-arm), const TIOCTIMESTAMP = 1074558041
|
||||||
pkg syscall (freebsd-arm), func Fchflags(string, int) error
|
pkg syscall (freebsd-arm), func Fchflags(string, int) error
|
||||||
|
pkg syscall (freebsd-arm), func Mknod(string, uint32, int) error
|
||||||
pkg syscall (freebsd-arm), type BpfHdr struct, Pad_cgo_0 [2]uint8
|
pkg syscall (freebsd-arm), type BpfHdr struct, Pad_cgo_0 [2]uint8
|
||||||
|
pkg syscall (freebsd-arm), type Dirent struct, Fileno uint32
|
||||||
|
pkg syscall (freebsd-arm), type Dirent struct, Namlen uint8
|
||||||
pkg syscall (freebsd-arm), type RawSockaddrDatalink struct, Pad_cgo_0 [2]uint8
|
pkg syscall (freebsd-arm), type RawSockaddrDatalink struct, Pad_cgo_0 [2]uint8
|
||||||
pkg syscall (freebsd-arm), type RawSockaddrUnix struct, Pad_cgo_0 [2]uint8
|
pkg syscall (freebsd-arm), type RawSockaddrUnix struct, Pad_cgo_0 [2]uint8
|
||||||
|
pkg syscall (freebsd-arm), type Stat_t struct, Blksize uint32
|
||||||
|
pkg syscall (freebsd-arm), type Stat_t struct, Dev uint32
|
||||||
|
pkg syscall (freebsd-arm), type Stat_t struct, Gen uint32
|
||||||
|
pkg syscall (freebsd-arm), type Stat_t struct, Ino uint32
|
||||||
|
pkg syscall (freebsd-arm), type Stat_t struct, Lspare int32
|
||||||
|
pkg syscall (freebsd-arm), type Stat_t struct, Nlink uint16
|
||||||
pkg syscall (freebsd-arm), type Stat_t struct, Pad_cgo_0 [4]uint8
|
pkg syscall (freebsd-arm), type Stat_t struct, Pad_cgo_0 [4]uint8
|
||||||
|
pkg syscall (freebsd-arm), type Stat_t struct, Rdev uint32
|
||||||
|
pkg syscall (freebsd-arm), type Statfs_t struct, Mntfromname [88]int8
|
||||||
|
pkg syscall (freebsd-arm), type Statfs_t struct, Mntonname [88]int8
|
||||||
pkg syscall (freebsd-arm-cgo), const AF_MAX = 38
|
pkg syscall (freebsd-arm-cgo), const AF_MAX = 38
|
||||||
pkg syscall (freebsd-arm-cgo), const BIOCGRTIMEOUT = 1074545262
|
pkg syscall (freebsd-arm-cgo), const BIOCGRTIMEOUT = 1074545262
|
||||||
pkg syscall (freebsd-arm-cgo), const BIOCSRTIMEOUT = 2148287085
|
pkg syscall (freebsd-arm-cgo), const BIOCSRTIMEOUT = 2148287085
|
||||||
|
|
@ -94,10 +200,22 @@ pkg syscall (freebsd-arm-cgo), const SizeofSockaddrDatalink = 56
|
||||||
pkg syscall (freebsd-arm-cgo), const SizeofSockaddrUnix = 108
|
pkg syscall (freebsd-arm-cgo), const SizeofSockaddrUnix = 108
|
||||||
pkg syscall (freebsd-arm-cgo), const TIOCTIMESTAMP = 1074558041
|
pkg syscall (freebsd-arm-cgo), const TIOCTIMESTAMP = 1074558041
|
||||||
pkg syscall (freebsd-arm-cgo), func Fchflags(string, int) error
|
pkg syscall (freebsd-arm-cgo), func Fchflags(string, int) error
|
||||||
|
pkg syscall (freebsd-arm-cgo), func Mknod(string, uint32, int) error
|
||||||
pkg syscall (freebsd-arm-cgo), type BpfHdr struct, Pad_cgo_0 [2]uint8
|
pkg syscall (freebsd-arm-cgo), type BpfHdr struct, Pad_cgo_0 [2]uint8
|
||||||
|
pkg syscall (freebsd-arm-cgo), type Dirent struct, Fileno uint32
|
||||||
|
pkg syscall (freebsd-arm-cgo), type Dirent struct, Namlen uint8
|
||||||
pkg syscall (freebsd-arm-cgo), type RawSockaddrDatalink struct, Pad_cgo_0 [2]uint8
|
pkg syscall (freebsd-arm-cgo), type RawSockaddrDatalink struct, Pad_cgo_0 [2]uint8
|
||||||
pkg syscall (freebsd-arm-cgo), type RawSockaddrUnix struct, Pad_cgo_0 [2]uint8
|
pkg syscall (freebsd-arm-cgo), type RawSockaddrUnix struct, Pad_cgo_0 [2]uint8
|
||||||
|
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Blksize uint32
|
||||||
|
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Dev uint32
|
||||||
|
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Gen uint32
|
||||||
|
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Ino uint32
|
||||||
|
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Lspare int32
|
||||||
|
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Nlink uint16
|
||||||
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Pad_cgo_0 [4]uint8
|
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Pad_cgo_0 [4]uint8
|
||||||
|
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Rdev uint32
|
||||||
|
pkg syscall (freebsd-arm-cgo), type Statfs_t struct, Mntfromname [88]int8
|
||||||
|
pkg syscall (freebsd-arm-cgo), type Statfs_t struct, Mntonname [88]int8
|
||||||
pkg syscall (linux-386), type Cmsghdr struct, X__cmsg_data [0]uint8
|
pkg syscall (linux-386), type Cmsghdr struct, X__cmsg_data [0]uint8
|
||||||
pkg syscall (linux-386-cgo), type Cmsghdr struct, X__cmsg_data [0]uint8
|
pkg syscall (linux-386-cgo), type Cmsghdr struct, X__cmsg_data [0]uint8
|
||||||
pkg syscall (linux-amd64), type Cmsghdr struct, X__cmsg_data [0]uint8
|
pkg syscall (linux-amd64), type Cmsghdr struct, X__cmsg_data [0]uint8
|
||||||
|
|
@ -109,10 +227,10 @@ pkg syscall (netbsd-386-cgo), const ImplementsGetwd = false
|
||||||
pkg syscall (netbsd-amd64), const ImplementsGetwd = false
|
pkg syscall (netbsd-amd64), const ImplementsGetwd = false
|
||||||
pkg syscall (netbsd-amd64-cgo), const ImplementsGetwd = false
|
pkg syscall (netbsd-amd64-cgo), const ImplementsGetwd = false
|
||||||
pkg syscall (netbsd-arm), const ImplementsGetwd = false
|
pkg syscall (netbsd-arm), const ImplementsGetwd = false
|
||||||
pkg syscall (netbsd-arm-cgo), const ImplementsGetwd = false
|
|
||||||
pkg syscall (netbsd-arm), const SizeofIfData = 132
|
pkg syscall (netbsd-arm), const SizeofIfData = 132
|
||||||
pkg syscall (netbsd-arm), func Fchflags(string, int) error
|
pkg syscall (netbsd-arm), func Fchflags(string, int) error
|
||||||
pkg syscall (netbsd-arm), type IfMsghdr struct, Pad_cgo_1 [4]uint8
|
pkg syscall (netbsd-arm), type IfMsghdr struct, Pad_cgo_1 [4]uint8
|
||||||
|
pkg syscall (netbsd-arm-cgo), const ImplementsGetwd = false
|
||||||
pkg syscall (netbsd-arm-cgo), const SizeofIfData = 132
|
pkg syscall (netbsd-arm-cgo), const SizeofIfData = 132
|
||||||
pkg syscall (netbsd-arm-cgo), func Fchflags(string, int) error
|
pkg syscall (netbsd-arm-cgo), func Fchflags(string, int) error
|
||||||
pkg syscall (netbsd-arm-cgo), type IfMsghdr struct, Pad_cgo_1 [4]uint8
|
pkg syscall (netbsd-arm-cgo), type IfMsghdr struct, Pad_cgo_1 [4]uint8
|
||||||
|
|
@ -140,6 +258,7 @@ pkg syscall (openbsd-386), const SYS_GETITIMER = 86
|
||||||
pkg syscall (openbsd-386), const SYS_GETRUSAGE = 117
|
pkg syscall (openbsd-386), const SYS_GETRUSAGE = 117
|
||||||
pkg syscall (openbsd-386), const SYS_GETTIMEOFDAY = 116
|
pkg syscall (openbsd-386), const SYS_GETTIMEOFDAY = 116
|
||||||
pkg syscall (openbsd-386), const SYS_KEVENT = 270
|
pkg syscall (openbsd-386), const SYS_KEVENT = 270
|
||||||
|
pkg syscall (openbsd-386), const SYS_KILL = 37
|
||||||
pkg syscall (openbsd-386), const SYS_LSTAT = 293
|
pkg syscall (openbsd-386), const SYS_LSTAT = 293
|
||||||
pkg syscall (openbsd-386), const SYS_NANOSLEEP = 240
|
pkg syscall (openbsd-386), const SYS_NANOSLEEP = 240
|
||||||
pkg syscall (openbsd-386), const SYS_SELECT = 93
|
pkg syscall (openbsd-386), const SYS_SELECT = 93
|
||||||
|
|
@ -193,6 +312,7 @@ pkg syscall (openbsd-386-cgo), const SYS_GETITIMER = 86
|
||||||
pkg syscall (openbsd-386-cgo), const SYS_GETRUSAGE = 117
|
pkg syscall (openbsd-386-cgo), const SYS_GETRUSAGE = 117
|
||||||
pkg syscall (openbsd-386-cgo), const SYS_GETTIMEOFDAY = 116
|
pkg syscall (openbsd-386-cgo), const SYS_GETTIMEOFDAY = 116
|
||||||
pkg syscall (openbsd-386-cgo), const SYS_KEVENT = 270
|
pkg syscall (openbsd-386-cgo), const SYS_KEVENT = 270
|
||||||
|
pkg syscall (openbsd-386-cgo), const SYS_KILL = 37
|
||||||
pkg syscall (openbsd-386-cgo), const SYS_LSTAT = 293
|
pkg syscall (openbsd-386-cgo), const SYS_LSTAT = 293
|
||||||
pkg syscall (openbsd-386-cgo), const SYS_NANOSLEEP = 240
|
pkg syscall (openbsd-386-cgo), const SYS_NANOSLEEP = 240
|
||||||
pkg syscall (openbsd-386-cgo), const SYS_SELECT = 93
|
pkg syscall (openbsd-386-cgo), const SYS_SELECT = 93
|
||||||
|
|
@ -257,6 +377,7 @@ pkg syscall (openbsd-amd64), const SYS_GETITIMER = 86
|
||||||
pkg syscall (openbsd-amd64), const SYS_GETRUSAGE = 117
|
pkg syscall (openbsd-amd64), const SYS_GETRUSAGE = 117
|
||||||
pkg syscall (openbsd-amd64), const SYS_GETTIMEOFDAY = 116
|
pkg syscall (openbsd-amd64), const SYS_GETTIMEOFDAY = 116
|
||||||
pkg syscall (openbsd-amd64), const SYS_KEVENT = 270
|
pkg syscall (openbsd-amd64), const SYS_KEVENT = 270
|
||||||
|
pkg syscall (openbsd-amd64), const SYS_KILL = 37
|
||||||
pkg syscall (openbsd-amd64), const SYS_LSTAT = 293
|
pkg syscall (openbsd-amd64), const SYS_LSTAT = 293
|
||||||
pkg syscall (openbsd-amd64), const SYS_NANOSLEEP = 240
|
pkg syscall (openbsd-amd64), const SYS_NANOSLEEP = 240
|
||||||
pkg syscall (openbsd-amd64), const SYS_SELECT = 93
|
pkg syscall (openbsd-amd64), const SYS_SELECT = 93
|
||||||
|
|
@ -320,6 +441,7 @@ pkg syscall (openbsd-amd64-cgo), const SYS_GETITIMER = 86
|
||||||
pkg syscall (openbsd-amd64-cgo), const SYS_GETRUSAGE = 117
|
pkg syscall (openbsd-amd64-cgo), const SYS_GETRUSAGE = 117
|
||||||
pkg syscall (openbsd-amd64-cgo), const SYS_GETTIMEOFDAY = 116
|
pkg syscall (openbsd-amd64-cgo), const SYS_GETTIMEOFDAY = 116
|
||||||
pkg syscall (openbsd-amd64-cgo), const SYS_KEVENT = 270
|
pkg syscall (openbsd-amd64-cgo), const SYS_KEVENT = 270
|
||||||
|
pkg syscall (openbsd-amd64-cgo), const SYS_KILL = 37
|
||||||
pkg syscall (openbsd-amd64-cgo), const SYS_LSTAT = 293
|
pkg syscall (openbsd-amd64-cgo), const SYS_LSTAT = 293
|
||||||
pkg syscall (openbsd-amd64-cgo), const SYS_NANOSLEEP = 240
|
pkg syscall (openbsd-amd64-cgo), const SYS_NANOSLEEP = 240
|
||||||
pkg syscall (openbsd-amd64-cgo), const SYS_SELECT = 93
|
pkg syscall (openbsd-amd64-cgo), const SYS_SELECT = 93
|
||||||
|
|
@ -348,19 +470,6 @@ pkg syscall (openbsd-amd64-cgo), type Statfs_t struct, F_spare [3]uint32
|
||||||
pkg syscall (openbsd-amd64-cgo), type Statfs_t struct, Pad_cgo_1 [4]uint8
|
pkg syscall (openbsd-amd64-cgo), type Statfs_t struct, Pad_cgo_1 [4]uint8
|
||||||
pkg syscall (openbsd-amd64-cgo), type Timespec struct, Pad_cgo_0 [4]uint8
|
pkg syscall (openbsd-amd64-cgo), type Timespec struct, Pad_cgo_0 [4]uint8
|
||||||
pkg syscall (openbsd-amd64-cgo), type Timespec struct, Sec int32
|
pkg syscall (openbsd-amd64-cgo), type Timespec struct, Sec int32
|
||||||
pkg testing, func RegisterCover(Cover)
|
|
||||||
pkg testing, func MainStart(func(string, string) (bool, error), []InternalTest, []InternalBenchmark, []InternalExample) *M
|
|
||||||
pkg text/template/parse, type DotNode bool
|
|
||||||
pkg text/template/parse, type Node interface { Copy, String, Type }
|
|
||||||
pkg unicode, const Version = "6.2.0"
|
|
||||||
pkg unicode, const Version = "6.3.0"
|
|
||||||
pkg unicode, const Version = "7.0.0"
|
|
||||||
pkg unicode, const Version = "8.0.0"
|
|
||||||
pkg syscall (openbsd-386), const SYS_KILL = 37
|
|
||||||
pkg syscall (openbsd-386-cgo), const SYS_KILL = 37
|
|
||||||
pkg syscall (openbsd-amd64), const SYS_KILL = 37
|
|
||||||
pkg syscall (openbsd-amd64-cgo), const SYS_KILL = 37
|
|
||||||
pkg unicode, const Version = "9.0.0"
|
|
||||||
pkg syscall (windows-386), const TOKEN_ALL_ACCESS = 983295
|
pkg syscall (windows-386), const TOKEN_ALL_ACCESS = 983295
|
||||||
pkg syscall (windows-386), type AddrinfoW struct, Addr uintptr
|
pkg syscall (windows-386), type AddrinfoW struct, Addr uintptr
|
||||||
pkg syscall (windows-386), type CertChainPolicyPara struct, ExtraPolicyPara uintptr
|
pkg syscall (windows-386), type CertChainPolicyPara struct, ExtraPolicyPara uintptr
|
||||||
|
|
@ -379,81 +488,16 @@ pkg syscall (windows-amd64), type CertRevocationInfo struct, CrlInfo uintptr
|
||||||
pkg syscall (windows-amd64), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
pkg syscall (windows-amd64), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
||||||
pkg syscall (windows-amd64), type CertSimpleChain struct, TrustListInfo uintptr
|
pkg syscall (windows-amd64), type CertSimpleChain struct, TrustListInfo uintptr
|
||||||
pkg syscall (windows-amd64), type RawSockaddrAny struct, Pad [96]int8
|
pkg syscall (windows-amd64), type RawSockaddrAny struct, Pad [96]int8
|
||||||
pkg syscall (freebsd-386), func Mknod(string, uint32, int) error
|
pkg testing, func MainStart(func(string, string) (bool, error), []InternalTest, []InternalBenchmark, []InternalExample) *M
|
||||||
pkg syscall (freebsd-386), type Dirent struct, Fileno uint32
|
pkg testing, func RegisterCover(Cover)
|
||||||
pkg syscall (freebsd-386), type Dirent struct, Namlen uint8
|
|
||||||
pkg syscall (freebsd-386), type Stat_t struct, Blksize uint32
|
|
||||||
pkg syscall (freebsd-386), type Stat_t struct, Dev uint32
|
|
||||||
pkg syscall (freebsd-386), type Stat_t struct, Gen uint32
|
|
||||||
pkg syscall (freebsd-386), type Stat_t struct, Ino uint32
|
|
||||||
pkg syscall (freebsd-386), type Stat_t struct, Lspare int32
|
|
||||||
pkg syscall (freebsd-386), type Stat_t struct, Nlink uint16
|
|
||||||
pkg syscall (freebsd-386), type Stat_t struct, Pad_cgo_0 [8]uint8
|
|
||||||
pkg syscall (freebsd-386), type Stat_t struct, Rdev uint32
|
|
||||||
pkg syscall (freebsd-386), type Statfs_t struct, Mntfromname [88]int8
|
|
||||||
pkg syscall (freebsd-386), type Statfs_t struct, Mntonname [88]int8
|
|
||||||
pkg syscall (freebsd-386-cgo), func Mknod(string, uint32, int) error
|
|
||||||
pkg syscall (freebsd-386-cgo), type Dirent struct, Fileno uint32
|
|
||||||
pkg syscall (freebsd-386-cgo), type Dirent struct, Namlen uint8
|
|
||||||
pkg syscall (freebsd-386-cgo), type Stat_t struct, Blksize uint32
|
|
||||||
pkg syscall (freebsd-386-cgo), type Stat_t struct, Dev uint32
|
|
||||||
pkg syscall (freebsd-386-cgo), type Stat_t struct, Gen uint32
|
|
||||||
pkg syscall (freebsd-386-cgo), type Stat_t struct, Ino uint32
|
|
||||||
pkg syscall (freebsd-386-cgo), type Stat_t struct, Lspare int32
|
|
||||||
pkg syscall (freebsd-386-cgo), type Stat_t struct, Nlink uint16
|
|
||||||
pkg syscall (freebsd-386-cgo), type Stat_t struct, Pad_cgo_0 [8]uint8
|
|
||||||
pkg syscall (freebsd-386-cgo), type Stat_t struct, Rdev uint32
|
|
||||||
pkg syscall (freebsd-386-cgo), type Statfs_t struct, Mntfromname [88]int8
|
|
||||||
pkg syscall (freebsd-386-cgo), type Statfs_t struct, Mntonname [88]int8
|
|
||||||
pkg syscall (freebsd-amd64), func Mknod(string, uint32, int) error
|
|
||||||
pkg syscall (freebsd-amd64), type Dirent struct, Fileno uint32
|
|
||||||
pkg syscall (freebsd-amd64), type Dirent struct, Namlen uint8
|
|
||||||
pkg syscall (freebsd-amd64), type Stat_t struct, Blksize uint32
|
|
||||||
pkg syscall (freebsd-amd64), type Stat_t struct, Dev uint32
|
|
||||||
pkg syscall (freebsd-amd64), type Stat_t struct, Gen uint32
|
|
||||||
pkg syscall (freebsd-amd64), type Stat_t struct, Ino uint32
|
|
||||||
pkg syscall (freebsd-amd64), type Stat_t struct, Lspare int32
|
|
||||||
pkg syscall (freebsd-amd64), type Stat_t struct, Nlink uint16
|
|
||||||
pkg syscall (freebsd-amd64), type Stat_t struct, Rdev uint32
|
|
||||||
pkg syscall (freebsd-amd64), type Statfs_t struct, Mntfromname [88]int8
|
|
||||||
pkg syscall (freebsd-amd64), type Statfs_t struct, Mntonname [88]int8
|
|
||||||
pkg syscall (freebsd-amd64-cgo), func Mknod(string, uint32, int) error
|
|
||||||
pkg syscall (freebsd-amd64-cgo), type Dirent struct, Fileno uint32
|
|
||||||
pkg syscall (freebsd-amd64-cgo), type Dirent struct, Namlen uint8
|
|
||||||
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Blksize uint32
|
|
||||||
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Dev uint32
|
|
||||||
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Gen uint32
|
|
||||||
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Ino uint32
|
|
||||||
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Lspare int32
|
|
||||||
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Nlink uint16
|
|
||||||
pkg syscall (freebsd-amd64-cgo), type Stat_t struct, Rdev uint32
|
|
||||||
pkg syscall (freebsd-amd64-cgo), type Statfs_t struct, Mntfromname [88]int8
|
|
||||||
pkg syscall (freebsd-amd64-cgo), type Statfs_t struct, Mntonname [88]int8
|
|
||||||
pkg syscall (freebsd-arm), func Mknod(string, uint32, int) error
|
|
||||||
pkg syscall (freebsd-arm), type Dirent struct, Fileno uint32
|
|
||||||
pkg syscall (freebsd-arm), type Dirent struct, Namlen uint8
|
|
||||||
pkg syscall (freebsd-arm), type Stat_t struct, Blksize uint32
|
|
||||||
pkg syscall (freebsd-arm), type Stat_t struct, Dev uint32
|
|
||||||
pkg syscall (freebsd-arm), type Stat_t struct, Gen uint32
|
|
||||||
pkg syscall (freebsd-arm), type Stat_t struct, Ino uint32
|
|
||||||
pkg syscall (freebsd-arm), type Stat_t struct, Lspare int32
|
|
||||||
pkg syscall (freebsd-arm), type Stat_t struct, Nlink uint16
|
|
||||||
pkg syscall (freebsd-arm), type Stat_t struct, Rdev uint32
|
|
||||||
pkg syscall (freebsd-arm), type Statfs_t struct, Mntfromname [88]int8
|
|
||||||
pkg syscall (freebsd-arm), type Statfs_t struct, Mntonname [88]int8
|
|
||||||
pkg syscall (freebsd-arm-cgo), func Mknod(string, uint32, int) error
|
|
||||||
pkg syscall (freebsd-arm-cgo), type Dirent struct, Fileno uint32
|
|
||||||
pkg syscall (freebsd-arm-cgo), type Dirent struct, Namlen uint8
|
|
||||||
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Blksize uint32
|
|
||||||
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Dev uint32
|
|
||||||
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Gen uint32
|
|
||||||
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Ino uint32
|
|
||||||
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Lspare int32
|
|
||||||
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Nlink uint16
|
|
||||||
pkg syscall (freebsd-arm-cgo), type Stat_t struct, Rdev uint32
|
|
||||||
pkg syscall (freebsd-arm-cgo), type Statfs_t struct, Mntfromname [88]int8
|
|
||||||
pkg syscall (freebsd-arm-cgo), type Statfs_t struct, Mntonname [88]int8
|
|
||||||
pkg text/scanner, const GoTokens = 1012
|
pkg text/scanner, const GoTokens = 1012
|
||||||
|
pkg text/template/parse, type DotNode bool
|
||||||
|
pkg text/template/parse, type Node interface { Copy, String, Type }
|
||||||
pkg unicode, const Version = "10.0.0"
|
pkg unicode, const Version = "10.0.0"
|
||||||
pkg unicode, const Version = "11.0.0"
|
pkg unicode, const Version = "11.0.0"
|
||||||
pkg unicode, const Version = "12.0.0"
|
pkg unicode, const Version = "12.0.0"
|
||||||
|
pkg unicode, const Version = "6.2.0"
|
||||||
|
pkg unicode, const Version = "6.3.0"
|
||||||
|
pkg unicode, const Version = "7.0.0"
|
||||||
|
pkg unicode, const Version = "8.0.0"
|
||||||
|
pkg unicode, const Version = "9.0.0"
|
||||||
|
|
|
||||||
328
api/next.txt
328
api/next.txt
|
|
@ -1,8 +1,321 @@
|
||||||
pkg unicode, const Version = "13.0.0"
|
pkg debug/elf, const DT_ADDRRNGHI = 1879047935
|
||||||
pkg unicode, var Chorasmian *RangeTable
|
pkg debug/elf, const DT_ADDRRNGHI DynTag
|
||||||
pkg unicode, var Dives_Akuru *RangeTable
|
pkg debug/elf, const DT_ADDRRNGLO = 1879047680
|
||||||
pkg unicode, var Khitan_Small_Script *RangeTable
|
pkg debug/elf, const DT_ADDRRNGLO DynTag
|
||||||
pkg unicode, var Yezidi *RangeTable
|
pkg debug/elf, const DT_AUDIT = 1879047932
|
||||||
|
pkg debug/elf, const DT_AUDIT DynTag
|
||||||
|
pkg debug/elf, const DT_AUXILIARY = 2147483645
|
||||||
|
pkg debug/elf, const DT_AUXILIARY DynTag
|
||||||
|
pkg debug/elf, const DT_CHECKSUM = 1879047672
|
||||||
|
pkg debug/elf, const DT_CHECKSUM DynTag
|
||||||
|
pkg debug/elf, const DT_CONFIG = 1879047930
|
||||||
|
pkg debug/elf, const DT_CONFIG DynTag
|
||||||
|
pkg debug/elf, const DT_DEPAUDIT = 1879047931
|
||||||
|
pkg debug/elf, const DT_DEPAUDIT DynTag
|
||||||
|
pkg debug/elf, const DT_FEATURE = 1879047676
|
||||||
|
pkg debug/elf, const DT_FEATURE DynTag
|
||||||
|
pkg debug/elf, const DT_FILTER = 2147483647
|
||||||
|
pkg debug/elf, const DT_FILTER DynTag
|
||||||
|
pkg debug/elf, const DT_FLAGS_1 = 1879048187
|
||||||
|
pkg debug/elf, const DT_FLAGS_1 DynTag
|
||||||
|
pkg debug/elf, const DT_GNU_CONFLICT = 1879047928
|
||||||
|
pkg debug/elf, const DT_GNU_CONFLICT DynTag
|
||||||
|
pkg debug/elf, const DT_GNU_CONFLICTSZ = 1879047670
|
||||||
|
pkg debug/elf, const DT_GNU_CONFLICTSZ DynTag
|
||||||
|
pkg debug/elf, const DT_GNU_HASH = 1879047925
|
||||||
|
pkg debug/elf, const DT_GNU_HASH DynTag
|
||||||
|
pkg debug/elf, const DT_GNU_LIBLIST = 1879047929
|
||||||
|
pkg debug/elf, const DT_GNU_LIBLIST DynTag
|
||||||
|
pkg debug/elf, const DT_GNU_LIBLISTSZ = 1879047671
|
||||||
|
pkg debug/elf, const DT_GNU_LIBLISTSZ DynTag
|
||||||
|
pkg debug/elf, const DT_GNU_PRELINKED = 1879047669
|
||||||
|
pkg debug/elf, const DT_GNU_PRELINKED DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_AUX_DYNAMIC = 1879048241
|
||||||
|
pkg debug/elf, const DT_MIPS_AUX_DYNAMIC DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_BASE_ADDRESS = 1879048198
|
||||||
|
pkg debug/elf, const DT_MIPS_BASE_ADDRESS DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_COMPACT_SIZE = 1879048239
|
||||||
|
pkg debug/elf, const DT_MIPS_COMPACT_SIZE DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_CONFLICT = 1879048200
|
||||||
|
pkg debug/elf, const DT_MIPS_CONFLICT DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_CONFLICTNO = 1879048203
|
||||||
|
pkg debug/elf, const DT_MIPS_CONFLICTNO DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_CXX_FLAGS = 1879048226
|
||||||
|
pkg debug/elf, const DT_MIPS_CXX_FLAGS DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_CLASS = 1879048215
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_CLASS DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM = 1879048224
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM_NO = 1879048225
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_CLASSSYM_NO DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_CLASS_NO = 1879048216
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_CLASS_NO DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_INSTANCE = 1879048217
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_INSTANCE DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_INSTANCE_NO = 1879048218
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_INSTANCE_NO DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_RELOC = 1879048219
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_RELOC DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_RELOC_NO = 1879048220
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_RELOC_NO DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_SYM = 1879048221
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_SYM DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_SYM_NO = 1879048222
|
||||||
|
pkg debug/elf, const DT_MIPS_DELTA_SYM_NO DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_DYNSTR_ALIGN = 1879048235
|
||||||
|
pkg debug/elf, const DT_MIPS_DYNSTR_ALIGN DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_FLAGS = 1879048197
|
||||||
|
pkg debug/elf, const DT_MIPS_FLAGS DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_GOTSYM = 1879048211
|
||||||
|
pkg debug/elf, const DT_MIPS_GOTSYM DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_GP_VALUE = 1879048240
|
||||||
|
pkg debug/elf, const DT_MIPS_GP_VALUE DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_HIDDEN_GOTIDX = 1879048231
|
||||||
|
pkg debug/elf, const DT_MIPS_HIDDEN_GOTIDX DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_HIPAGENO = 1879048212
|
||||||
|
pkg debug/elf, const DT_MIPS_HIPAGENO DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_ICHECKSUM = 1879048195
|
||||||
|
pkg debug/elf, const DT_MIPS_ICHECKSUM DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_INTERFACE = 1879048234
|
||||||
|
pkg debug/elf, const DT_MIPS_INTERFACE DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_INTERFACE_SIZE = 1879048236
|
||||||
|
pkg debug/elf, const DT_MIPS_INTERFACE_SIZE DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_IVERSION = 1879048196
|
||||||
|
pkg debug/elf, const DT_MIPS_IVERSION DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_LIBLIST = 1879048201
|
||||||
|
pkg debug/elf, const DT_MIPS_LIBLIST DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_LIBLISTNO = 1879048208
|
||||||
|
pkg debug/elf, const DT_MIPS_LIBLISTNO DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_LOCALPAGE_GOTIDX = 1879048229
|
||||||
|
pkg debug/elf, const DT_MIPS_LOCALPAGE_GOTIDX DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_LOCAL_GOTIDX = 1879048230
|
||||||
|
pkg debug/elf, const DT_MIPS_LOCAL_GOTIDX DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_LOCAL_GOTNO = 1879048202
|
||||||
|
pkg debug/elf, const DT_MIPS_LOCAL_GOTNO DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_MSYM = 1879048199
|
||||||
|
pkg debug/elf, const DT_MIPS_MSYM DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_OPTIONS = 1879048233
|
||||||
|
pkg debug/elf, const DT_MIPS_OPTIONS DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_PERF_SUFFIX = 1879048238
|
||||||
|
pkg debug/elf, const DT_MIPS_PERF_SUFFIX DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_PIXIE_INIT = 1879048227
|
||||||
|
pkg debug/elf, const DT_MIPS_PIXIE_INIT DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_PLTGOT = 1879048242
|
||||||
|
pkg debug/elf, const DT_MIPS_PLTGOT DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_PROTECTED_GOTIDX = 1879048232
|
||||||
|
pkg debug/elf, const DT_MIPS_PROTECTED_GOTIDX DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_RLD_MAP = 1879048214
|
||||||
|
pkg debug/elf, const DT_MIPS_RLD_MAP DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_RLD_MAP_REL = 1879048245
|
||||||
|
pkg debug/elf, const DT_MIPS_RLD_MAP_REL DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_RLD_TEXT_RESOLVE_ADDR = 1879048237
|
||||||
|
pkg debug/elf, const DT_MIPS_RLD_TEXT_RESOLVE_ADDR DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_RLD_VERSION = 1879048193
|
||||||
|
pkg debug/elf, const DT_MIPS_RLD_VERSION DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_RWPLT = 1879048244
|
||||||
|
pkg debug/elf, const DT_MIPS_RWPLT DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_SYMBOL_LIB = 1879048228
|
||||||
|
pkg debug/elf, const DT_MIPS_SYMBOL_LIB DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_SYMTABNO = 1879048209
|
||||||
|
pkg debug/elf, const DT_MIPS_SYMTABNO DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_TIME_STAMP = 1879048194
|
||||||
|
pkg debug/elf, const DT_MIPS_TIME_STAMP DynTag
|
||||||
|
pkg debug/elf, const DT_MIPS_UNREFEXTNO = 1879048210
|
||||||
|
pkg debug/elf, const DT_MIPS_UNREFEXTNO DynTag
|
||||||
|
pkg debug/elf, const DT_MOVEENT = 1879047674
|
||||||
|
pkg debug/elf, const DT_MOVEENT DynTag
|
||||||
|
pkg debug/elf, const DT_MOVESZ = 1879047675
|
||||||
|
pkg debug/elf, const DT_MOVESZ DynTag
|
||||||
|
pkg debug/elf, const DT_MOVETAB = 1879047934
|
||||||
|
pkg debug/elf, const DT_MOVETAB DynTag
|
||||||
|
pkg debug/elf, const DT_PLTPAD = 1879047933
|
||||||
|
pkg debug/elf, const DT_PLTPAD DynTag
|
||||||
|
pkg debug/elf, const DT_PLTPADSZ = 1879047673
|
||||||
|
pkg debug/elf, const DT_PLTPADSZ DynTag
|
||||||
|
pkg debug/elf, const DT_POSFLAG_1 = 1879047677
|
||||||
|
pkg debug/elf, const DT_POSFLAG_1 DynTag
|
||||||
|
pkg debug/elf, const DT_PPC64_GLINK = 1879048192
|
||||||
|
pkg debug/elf, const DT_PPC64_GLINK DynTag
|
||||||
|
pkg debug/elf, const DT_PPC64_OPD = 1879048193
|
||||||
|
pkg debug/elf, const DT_PPC64_OPD DynTag
|
||||||
|
pkg debug/elf, const DT_PPC64_OPDSZ = 1879048194
|
||||||
|
pkg debug/elf, const DT_PPC64_OPDSZ DynTag
|
||||||
|
pkg debug/elf, const DT_PPC64_OPT = 1879048195
|
||||||
|
pkg debug/elf, const DT_PPC64_OPT DynTag
|
||||||
|
pkg debug/elf, const DT_PPC_GOT = 1879048192
|
||||||
|
pkg debug/elf, const DT_PPC_GOT DynTag
|
||||||
|
pkg debug/elf, const DT_PPC_OPT = 1879048193
|
||||||
|
pkg debug/elf, const DT_PPC_OPT DynTag
|
||||||
|
pkg debug/elf, const DT_RELACOUNT = 1879048185
|
||||||
|
pkg debug/elf, const DT_RELACOUNT DynTag
|
||||||
|
pkg debug/elf, const DT_RELCOUNT = 1879048186
|
||||||
|
pkg debug/elf, const DT_RELCOUNT DynTag
|
||||||
|
pkg debug/elf, const DT_SPARC_REGISTER = 1879048193
|
||||||
|
pkg debug/elf, const DT_SPARC_REGISTER DynTag
|
||||||
|
pkg debug/elf, const DT_SYMINENT = 1879047679
|
||||||
|
pkg debug/elf, const DT_SYMINENT DynTag
|
||||||
|
pkg debug/elf, const DT_SYMINFO = 1879047935
|
||||||
|
pkg debug/elf, const DT_SYMINFO DynTag
|
||||||
|
pkg debug/elf, const DT_SYMINSZ = 1879047678
|
||||||
|
pkg debug/elf, const DT_SYMINSZ DynTag
|
||||||
|
pkg debug/elf, const DT_SYMTAB_SHNDX = 34
|
||||||
|
pkg debug/elf, const DT_SYMTAB_SHNDX DynTag
|
||||||
|
pkg debug/elf, const DT_TLSDESC_GOT = 1879047927
|
||||||
|
pkg debug/elf, const DT_TLSDESC_GOT DynTag
|
||||||
|
pkg debug/elf, const DT_TLSDESC_PLT = 1879047926
|
||||||
|
pkg debug/elf, const DT_TLSDESC_PLT DynTag
|
||||||
|
pkg debug/elf, const DT_USED = 2147483646
|
||||||
|
pkg debug/elf, const DT_USED DynTag
|
||||||
|
pkg debug/elf, const DT_VALRNGHI = 1879047679
|
||||||
|
pkg debug/elf, const DT_VALRNGHI DynTag
|
||||||
|
pkg debug/elf, const DT_VALRNGLO = 1879047424
|
||||||
|
pkg debug/elf, const DT_VALRNGLO DynTag
|
||||||
|
pkg debug/elf, const DT_VERDEF = 1879048188
|
||||||
|
pkg debug/elf, const DT_VERDEF DynTag
|
||||||
|
pkg debug/elf, const DT_VERDEFNUM = 1879048189
|
||||||
|
pkg debug/elf, const DT_VERDEFNUM DynTag
|
||||||
|
pkg debug/elf, const PT_AARCH64_ARCHEXT = 1879048192
|
||||||
|
pkg debug/elf, const PT_AARCH64_ARCHEXT ProgType
|
||||||
|
pkg debug/elf, const PT_AARCH64_UNWIND = 1879048193
|
||||||
|
pkg debug/elf, const PT_AARCH64_UNWIND ProgType
|
||||||
|
pkg debug/elf, const PT_ARM_ARCHEXT = 1879048192
|
||||||
|
pkg debug/elf, const PT_ARM_ARCHEXT ProgType
|
||||||
|
pkg debug/elf, const PT_ARM_EXIDX = 1879048193
|
||||||
|
pkg debug/elf, const PT_ARM_EXIDX ProgType
|
||||||
|
pkg debug/elf, const PT_GNU_EH_FRAME = 1685382480
|
||||||
|
pkg debug/elf, const PT_GNU_EH_FRAME ProgType
|
||||||
|
pkg debug/elf, const PT_GNU_MBIND_HI = 1685386580
|
||||||
|
pkg debug/elf, const PT_GNU_MBIND_HI ProgType
|
||||||
|
pkg debug/elf, const PT_GNU_MBIND_LO = 1685382485
|
||||||
|
pkg debug/elf, const PT_GNU_MBIND_LO ProgType
|
||||||
|
pkg debug/elf, const PT_GNU_PROPERTY = 1685382483
|
||||||
|
pkg debug/elf, const PT_GNU_PROPERTY ProgType
|
||||||
|
pkg debug/elf, const PT_GNU_RELRO = 1685382482
|
||||||
|
pkg debug/elf, const PT_GNU_RELRO ProgType
|
||||||
|
pkg debug/elf, const PT_GNU_STACK = 1685382481
|
||||||
|
pkg debug/elf, const PT_GNU_STACK ProgType
|
||||||
|
pkg debug/elf, const PT_MIPS_ABIFLAGS = 1879048195
|
||||||
|
pkg debug/elf, const PT_MIPS_ABIFLAGS ProgType
|
||||||
|
pkg debug/elf, const PT_MIPS_OPTIONS = 1879048194
|
||||||
|
pkg debug/elf, const PT_MIPS_OPTIONS ProgType
|
||||||
|
pkg debug/elf, const PT_MIPS_REGINFO = 1879048192
|
||||||
|
pkg debug/elf, const PT_MIPS_REGINFO ProgType
|
||||||
|
pkg debug/elf, const PT_MIPS_RTPROC = 1879048193
|
||||||
|
pkg debug/elf, const PT_MIPS_RTPROC ProgType
|
||||||
|
pkg debug/elf, const PT_OPENBSD_BOOTDATA = 1705253862
|
||||||
|
pkg debug/elf, const PT_OPENBSD_BOOTDATA ProgType
|
||||||
|
pkg debug/elf, const PT_OPENBSD_RANDOMIZE = 1705237478
|
||||||
|
pkg debug/elf, const PT_OPENBSD_RANDOMIZE ProgType
|
||||||
|
pkg debug/elf, const PT_OPENBSD_WXNEEDED = 1705237479
|
||||||
|
pkg debug/elf, const PT_OPENBSD_WXNEEDED ProgType
|
||||||
|
pkg debug/elf, const PT_PAX_FLAGS = 1694766464
|
||||||
|
pkg debug/elf, const PT_PAX_FLAGS ProgType
|
||||||
|
pkg debug/elf, const PT_S390_PGSTE = 1879048192
|
||||||
|
pkg debug/elf, const PT_S390_PGSTE ProgType
|
||||||
|
pkg debug/elf, const PT_SUNWSTACK = 1879048187
|
||||||
|
pkg debug/elf, const PT_SUNWSTACK ProgType
|
||||||
|
pkg debug/elf, const PT_SUNW_EH_FRAME = 1685382480
|
||||||
|
pkg debug/elf, const PT_SUNW_EH_FRAME ProgType
|
||||||
|
pkg flag, func Func(string, string, func(string) error)
|
||||||
|
pkg flag, method (*FlagSet) Func(string, string, func(string) error)
|
||||||
|
pkg go/build, type Package struct, IgnoredOtherFiles []string
|
||||||
|
pkg io, type ReadSeekCloser interface { Close, Read, Seek }
|
||||||
|
pkg io, type ReadSeekCloser interface, Close() error
|
||||||
|
pkg io, type ReadSeekCloser interface, Read([]uint8) (int, error)
|
||||||
|
pkg io, type ReadSeekCloser interface, Seek(int64, int) (int64, error)
|
||||||
|
pkg io/fs, const ModeAppend = 1073741824
|
||||||
|
pkg io/fs, const ModeAppend FileMode
|
||||||
|
pkg io/fs, const ModeCharDevice = 2097152
|
||||||
|
pkg io/fs, const ModeCharDevice FileMode
|
||||||
|
pkg io/fs, const ModeDevice = 67108864
|
||||||
|
pkg io/fs, const ModeDevice FileMode
|
||||||
|
pkg io/fs, const ModeDir = 2147483648
|
||||||
|
pkg io/fs, const ModeDir FileMode
|
||||||
|
pkg io/fs, const ModeExclusive = 536870912
|
||||||
|
pkg io/fs, const ModeExclusive FileMode
|
||||||
|
pkg io/fs, const ModeIrregular = 524288
|
||||||
|
pkg io/fs, const ModeIrregular FileMode
|
||||||
|
pkg io/fs, const ModeNamedPipe = 33554432
|
||||||
|
pkg io/fs, const ModeNamedPipe FileMode
|
||||||
|
pkg io/fs, const ModePerm = 511
|
||||||
|
pkg io/fs, const ModePerm FileMode
|
||||||
|
pkg io/fs, const ModeSetgid = 4194304
|
||||||
|
pkg io/fs, const ModeSetgid FileMode
|
||||||
|
pkg io/fs, const ModeSetuid = 8388608
|
||||||
|
pkg io/fs, const ModeSetuid FileMode
|
||||||
|
pkg io/fs, const ModeSocket = 16777216
|
||||||
|
pkg io/fs, const ModeSocket FileMode
|
||||||
|
pkg io/fs, const ModeSticky = 1048576
|
||||||
|
pkg io/fs, const ModeSticky FileMode
|
||||||
|
pkg io/fs, const ModeSymlink = 134217728
|
||||||
|
pkg io/fs, const ModeSymlink FileMode
|
||||||
|
pkg io/fs, const ModeTemporary = 268435456
|
||||||
|
pkg io/fs, const ModeTemporary FileMode
|
||||||
|
pkg io/fs, const ModeType = 2401763328
|
||||||
|
pkg io/fs, const ModeType FileMode
|
||||||
|
pkg io/fs, method (*PathError) Error() string
|
||||||
|
pkg io/fs, method (*PathError) Timeout() bool
|
||||||
|
pkg io/fs, method (*PathError) Unwrap() error
|
||||||
|
pkg io/fs, method (FileMode) IsDir() bool
|
||||||
|
pkg io/fs, method (FileMode) IsRegular() bool
|
||||||
|
pkg io/fs, method (FileMode) Perm() FileMode
|
||||||
|
pkg io/fs, method (FileMode) String() string
|
||||||
|
pkg io/fs, method (FileMode) Type() FileMode
|
||||||
|
pkg io/fs, type FileInfo interface { IsDir, ModTime, Mode, Name, Size, Sys }
|
||||||
|
pkg io/fs, type FileInfo interface, IsDir() bool
|
||||||
|
pkg io/fs, type FileInfo interface, ModTime() time.Time
|
||||||
|
pkg io/fs, type FileInfo interface, Mode() FileMode
|
||||||
|
pkg io/fs, type FileInfo interface, Name() string
|
||||||
|
pkg io/fs, type FileInfo interface, Size() int64
|
||||||
|
pkg io/fs, type FileInfo interface, Sys() interface{}
|
||||||
|
pkg io/fs, type FileMode uint32
|
||||||
|
pkg io/fs, type PathError struct
|
||||||
|
pkg io/fs, type PathError struct, Err error
|
||||||
|
pkg io/fs, type PathError struct, Op string
|
||||||
|
pkg io/fs, type PathError struct, Path string
|
||||||
|
pkg io/fs, var ErrClosed error
|
||||||
|
pkg io/fs, var ErrExist error
|
||||||
|
pkg io/fs, var ErrInvalid error
|
||||||
|
pkg io/fs, var ErrNotExist error
|
||||||
|
pkg io/fs, var ErrPermission error
|
||||||
|
pkg net, var ErrClosed error
|
||||||
|
pkg net/http, type Transport struct, GetProxyConnectHeader func(context.Context, *url.URL, string) (Header, error)
|
||||||
|
pkg os, const ModeAppend fs.FileMode
|
||||||
|
pkg os, const ModeCharDevice fs.FileMode
|
||||||
|
pkg os, const ModeDevice fs.FileMode
|
||||||
|
pkg os, const ModeDir fs.FileMode
|
||||||
|
pkg os, const ModeExclusive fs.FileMode
|
||||||
|
pkg os, const ModeIrregular fs.FileMode
|
||||||
|
pkg os, const ModeNamedPipe fs.FileMode
|
||||||
|
pkg os, const ModePerm fs.FileMode
|
||||||
|
pkg os, const ModeSetgid fs.FileMode
|
||||||
|
pkg os, const ModeSetuid fs.FileMode
|
||||||
|
pkg os, const ModeSocket fs.FileMode
|
||||||
|
pkg os, const ModeSticky fs.FileMode
|
||||||
|
pkg os, const ModeSymlink fs.FileMode
|
||||||
|
pkg os, const ModeTemporary fs.FileMode
|
||||||
|
pkg os, const ModeType fs.FileMode
|
||||||
|
pkg os, func Chmod(string, fs.FileMode) error
|
||||||
|
pkg os, func Lstat(string) (fs.FileInfo, error)
|
||||||
|
pkg os, func Mkdir(string, fs.FileMode) error
|
||||||
|
pkg os, func MkdirAll(string, fs.FileMode) error
|
||||||
|
pkg os, func OpenFile(string, int, fs.FileMode) (*File, error)
|
||||||
|
pkg os, func SameFile(fs.FileInfo, fs.FileInfo) bool
|
||||||
|
pkg os, func Stat(string) (fs.FileInfo, error)
|
||||||
|
pkg os, method (*File) Chmod(fs.FileMode) error
|
||||||
|
pkg os, method (*File) ReadDir(int) ([]DirEntry, error)
|
||||||
|
pkg os, method (*File) Readdir(int) ([]fs.FileInfo, error)
|
||||||
|
pkg os, method (*File) Stat() (fs.FileInfo, error)
|
||||||
|
pkg os, type DirEntry interface { Info, IsDir, Name, Type }
|
||||||
|
pkg os, type DirEntry interface, Info() (fs.FileInfo, error)
|
||||||
|
pkg os, type DirEntry interface, IsDir() bool
|
||||||
|
pkg os, type DirEntry interface, Name() string
|
||||||
|
pkg os, type DirEntry interface, Type() fs.FileMode
|
||||||
|
pkg os, type FileInfo = fs.FileInfo
|
||||||
|
pkg os, type FileMode = fs.FileMode
|
||||||
|
pkg os, type PathError = fs.PathError
|
||||||
|
pkg os/signal, func NotifyContext(context.Context, ...os.Signal) (context.Context, context.CancelFunc)
|
||||||
|
pkg testing/iotest, func ErrReader(error) io.Reader
|
||||||
pkg text/template/parse, const NodeComment = 20
|
pkg text/template/parse, const NodeComment = 20
|
||||||
pkg text/template/parse, const NodeComment NodeType
|
pkg text/template/parse, const NodeComment NodeType
|
||||||
pkg text/template/parse, const ParseComments = 1
|
pkg text/template/parse, const ParseComments = 1
|
||||||
|
|
@ -17,3 +330,8 @@ pkg text/template/parse, type CommentNode struct, embedded NodeType
|
||||||
pkg text/template/parse, type CommentNode struct, embedded Pos
|
pkg text/template/parse, type CommentNode struct, embedded Pos
|
||||||
pkg text/template/parse, type Mode uint
|
pkg text/template/parse, type Mode uint
|
||||||
pkg text/template/parse, type Tree struct, Mode Mode
|
pkg text/template/parse, type Tree struct, Mode Mode
|
||||||
|
pkg unicode, const Version = "13.0.0"
|
||||||
|
pkg unicode, var Chorasmian *RangeTable
|
||||||
|
pkg unicode, var Dives_Akuru *RangeTable
|
||||||
|
pkg unicode, var Khitan_Small_Script *RangeTable
|
||||||
|
pkg unicode, var Yezidi *RangeTable
|
||||||
|
|
|
||||||
|
|
@ -454,6 +454,8 @@ environmental variable is set accordingly.</p>
|
||||||
<li>GODEBUG=gctrace=1 prints garbage collector events at
|
<li>GODEBUG=gctrace=1 prints garbage collector events at
|
||||||
each collection, summarizing the amount of memory collected
|
each collection, summarizing the amount of memory collected
|
||||||
and the length of the pause.</li>
|
and the length of the pause.</li>
|
||||||
|
<li>GODEBUG=inittrace=1 prints a summary of execution time and memory allocation
|
||||||
|
information for completed package initilization work.</li>
|
||||||
<li>GODEBUG=schedtrace=X prints scheduling events every X milliseconds.</li>
|
<li>GODEBUG=schedtrace=X prints scheduling events every X milliseconds.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,15 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
by <code>go</code> <code>mod</code> <code>vendor</code> since Go 1.11.
|
by <code>go</code> <code>mod</code> <code>vendor</code> since Go 1.11.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h4 id="toolexec">The <code>-toolexec</code> build flag</h4>
|
||||||
|
|
||||||
|
<p><!-- golang.org/cl/263357 -->
|
||||||
|
When the <code>-toolexec</code> build flag is specified to use a program when
|
||||||
|
invoking toolchain programs like compile or asm, the environment variable
|
||||||
|
<code>TOOLEXEC_IMPORTPATH</code> is now set to the import path of the package
|
||||||
|
being built.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="cgo">Cgo</h3>
|
<h3 id="cgo">Cgo</h3>
|
||||||
|
|
||||||
<p> <!-- CL 252378 -->
|
<p> <!-- CL 252378 -->
|
||||||
|
|
@ -181,6 +190,14 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
TODO
|
TODO
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<h3 id="crypto/hmac"><a href="/pkg/crypto/hmac">crypto/hmac</a></h3>
|
||||||
|
|
||||||
|
<p><!-- CL 261960 -->
|
||||||
|
<a href="/pkg/crypto/hmac/#New">New</a> will now panic if separate calls to
|
||||||
|
the hash generation function fail to return new values. Previously, the
|
||||||
|
behavior was undefined and invalid outputs were sometimes generated.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="crypto/tls"><a href="/pkg/crypto/tls">crypto/tls</a></h3>
|
<h3 id="crypto/tls"><a href="/pkg/crypto/tls">crypto/tls</a></h3>
|
||||||
|
|
||||||
<p><!-- CL 256897 -->
|
<p><!-- CL 256897 -->
|
||||||
|
|
@ -201,6 +218,21 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
contain strings with characters within the ASCII range.
|
contain strings with characters within the ASCII range.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 259697 -->
|
||||||
|
<a href="/pkg/crypto/x509/#CreateCertificate">CreateCertificate</a> now
|
||||||
|
verifies the generated certificate's signature using the signer's
|
||||||
|
public key. If the signature is invalid, an error is returned, instead
|
||||||
|
of a malformed certificate.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="encoding/json"><a href="/pkg/encoding/json">encoding/json</a></h3>
|
||||||
|
|
||||||
|
<p><!-- CL 263619 -->
|
||||||
|
The error message for
|
||||||
|
<a href="/pkg/encoding/json/#SyntaxError">SyntaxError</a>
|
||||||
|
now begins with "json: ", matching the other errors in the package.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="net"><a href="/pkg/net/">net</a></h3>
|
<h3 id="net"><a href="/pkg/net/">net</a></h3>
|
||||||
|
|
||||||
<p><!-- CL 250357 -->
|
<p><!-- CL 250357 -->
|
||||||
|
|
@ -213,6 +245,12 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
with <code>"use of closed network connection"</code>.
|
with <code>"use of closed network connection"</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 255898 -->
|
||||||
|
In previous Go releases the default TCP listener backlog size on Linux systems,
|
||||||
|
set by <code>/proc/sys/net/core/somaxconn</code>, was limited to a maximum of <code>65535</code>.
|
||||||
|
On Linux kernel version 4.1 and above, the maximum is now <code>4294967295</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="reflect"><a href="/pkg/reflect/">reflect</a></h3>
|
<h3 id="reflect"><a href="/pkg/reflect/">reflect</a></h3>
|
||||||
|
|
||||||
<p><!-- CL 259237, golang.org/issue/22075 -->
|
<p><!-- CL 259237, golang.org/issue/22075 -->
|
||||||
|
|
@ -273,6 +311,20 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
</dd>
|
</dd>
|
||||||
</dl><!-- crypto/x509 -->
|
</dl><!-- crypto/x509 -->
|
||||||
|
|
||||||
|
<dl id="encoding/xml"><dt><a href="/pkg/encoding/xml/">encoding/xml</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 264024 -->
|
||||||
|
The encoder has always taken care to avoid using namespace prefixes
|
||||||
|
beginning with <code>xml</code>, which are reserved by the XML
|
||||||
|
specification.
|
||||||
|
Now, following the specification more closely, that check is
|
||||||
|
case-insensitive, so that prefixes beginning
|
||||||
|
with <code>XML</code>, <code>XmL</code>, and so on are also
|
||||||
|
avoided.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- encoding/xml -->
|
||||||
|
|
||||||
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
|
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- CL 233637 -->
|
<p><!-- CL 233637 -->
|
||||||
|
|
@ -309,3 +361,16 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
</p>
|
</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dl><!-- runtime/debug -->
|
</dl><!-- runtime/debug -->
|
||||||
|
|
||||||
|
<dl id="strconv"><dt><a href="/pkg/strconv/">strconv</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 260858 -->
|
||||||
|
<a href="/pkg/strconv/#ParseFloat"><code>ParseFloat</code></a> now uses
|
||||||
|
the <a
|
||||||
|
href="https://nigeltao.github.io/blog/2020/eisel-lemire.html">Eisel-Lemire
|
||||||
|
algorithm</a>, improving performance by up to a factor of 2. This can
|
||||||
|
also speed up decoding textual formats like <a
|
||||||
|
href="/pkg/encoding/json/"><code>encoding/json</code></a>.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- strconv -->
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@
|
||||||
# Consult https://www.iana.org/time-zones for the latest versions.
|
# Consult https://www.iana.org/time-zones for the latest versions.
|
||||||
|
|
||||||
# Versions to use.
|
# Versions to use.
|
||||||
CODE=2020a
|
CODE=2020b
|
||||||
DATA=2020a
|
DATA=2020b
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
rm -rf work
|
rm -rf work
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -3,6 +3,7 @@
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !windows,!static
|
// +build !windows,!static
|
||||||
|
// +build !darwin !internal_pie,!arm64
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,11 @@
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !windows,!static
|
// +build !windows,!static
|
||||||
|
// +build !darwin !internal_pie,!arm64
|
||||||
|
|
||||||
|
// Excluded in darwin internal linking PIE mode, as dynamic export is not
|
||||||
|
// supported.
|
||||||
|
// Excluded in internal linking mode on darwin/arm64, as it is always PIE.
|
||||||
|
|
||||||
package cgotest
|
package cgotest
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build windows static
|
// +build windows static darwin,internal_pie darwin,arm64
|
||||||
|
|
||||||
package cgotest
|
package cgotest
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!global.crypto) {
|
if (!global.crypto && global.require) {
|
||||||
const nodeCrypto = require("crypto");
|
const nodeCrypto = require("crypto");
|
||||||
global.crypto = {
|
global.crypto = {
|
||||||
getRandomValues(b) {
|
getRandomValues(b) {
|
||||||
|
|
@ -110,6 +110,9 @@
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (!global.crypto) {
|
||||||
|
throw new Error("global.crypto is not available, polyfill required (getRandomValues only)");
|
||||||
|
}
|
||||||
|
|
||||||
if (!global.performance) {
|
if (!global.performance) {
|
||||||
global.performance = {
|
global.performance = {
|
||||||
|
|
@ -120,13 +123,19 @@
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!global.TextEncoder) {
|
if (!global.TextEncoder && global.require) {
|
||||||
global.TextEncoder = require("util").TextEncoder;
|
global.TextEncoder = require("util").TextEncoder;
|
||||||
}
|
}
|
||||||
|
if (!global.TextEncoder) {
|
||||||
|
throw new Error("global.TextEncoder is not available, polyfill required");
|
||||||
|
}
|
||||||
|
|
||||||
if (!global.TextDecoder) {
|
if (!global.TextDecoder && global.require) {
|
||||||
global.TextDecoder = require("util").TextDecoder;
|
global.TextDecoder = require("util").TextDecoder;
|
||||||
}
|
}
|
||||||
|
if (!global.TextDecoder) {
|
||||||
|
throw new Error("global.TextDecoder is not available, polyfill required");
|
||||||
|
}
|
||||||
|
|
||||||
// End of polyfills for common API.
|
// End of polyfills for common API.
|
||||||
|
|
||||||
|
|
@ -255,6 +264,7 @@
|
||||||
|
|
||||||
// func wasmExit(code int32)
|
// func wasmExit(code int32)
|
||||||
"runtime.wasmExit": (sp) => {
|
"runtime.wasmExit": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
const code = this.mem.getInt32(sp + 8, true);
|
const code = this.mem.getInt32(sp + 8, true);
|
||||||
this.exited = true;
|
this.exited = true;
|
||||||
delete this._inst;
|
delete this._inst;
|
||||||
|
|
@ -267,6 +277,7 @@
|
||||||
|
|
||||||
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
|
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
|
||||||
"runtime.wasmWrite": (sp) => {
|
"runtime.wasmWrite": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
const fd = getInt64(sp + 8);
|
const fd = getInt64(sp + 8);
|
||||||
const p = getInt64(sp + 16);
|
const p = getInt64(sp + 16);
|
||||||
const n = this.mem.getInt32(sp + 24, true);
|
const n = this.mem.getInt32(sp + 24, true);
|
||||||
|
|
@ -275,16 +286,19 @@
|
||||||
|
|
||||||
// func resetMemoryDataView()
|
// func resetMemoryDataView()
|
||||||
"runtime.resetMemoryDataView": (sp) => {
|
"runtime.resetMemoryDataView": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
this.mem = new DataView(this._inst.exports.mem.buffer);
|
this.mem = new DataView(this._inst.exports.mem.buffer);
|
||||||
},
|
},
|
||||||
|
|
||||||
// func nanotime1() int64
|
// func nanotime1() int64
|
||||||
"runtime.nanotime1": (sp) => {
|
"runtime.nanotime1": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
|
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
|
||||||
},
|
},
|
||||||
|
|
||||||
// func walltime1() (sec int64, nsec int32)
|
// func walltime1() (sec int64, nsec int32)
|
||||||
"runtime.walltime1": (sp) => {
|
"runtime.walltime1": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
const msec = (new Date).getTime();
|
const msec = (new Date).getTime();
|
||||||
setInt64(sp + 8, msec / 1000);
|
setInt64(sp + 8, msec / 1000);
|
||||||
this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true);
|
this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true);
|
||||||
|
|
@ -292,6 +306,7 @@
|
||||||
|
|
||||||
// func scheduleTimeoutEvent(delay int64) int32
|
// func scheduleTimeoutEvent(delay int64) int32
|
||||||
"runtime.scheduleTimeoutEvent": (sp) => {
|
"runtime.scheduleTimeoutEvent": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
const id = this._nextCallbackTimeoutID;
|
const id = this._nextCallbackTimeoutID;
|
||||||
this._nextCallbackTimeoutID++;
|
this._nextCallbackTimeoutID++;
|
||||||
this._scheduledTimeouts.set(id, setTimeout(
|
this._scheduledTimeouts.set(id, setTimeout(
|
||||||
|
|
@ -311,6 +326,7 @@
|
||||||
|
|
||||||
// func clearTimeoutEvent(id int32)
|
// func clearTimeoutEvent(id int32)
|
||||||
"runtime.clearTimeoutEvent": (sp) => {
|
"runtime.clearTimeoutEvent": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
const id = this.mem.getInt32(sp + 8, true);
|
const id = this.mem.getInt32(sp + 8, true);
|
||||||
clearTimeout(this._scheduledTimeouts.get(id));
|
clearTimeout(this._scheduledTimeouts.get(id));
|
||||||
this._scheduledTimeouts.delete(id);
|
this._scheduledTimeouts.delete(id);
|
||||||
|
|
@ -318,11 +334,13 @@
|
||||||
|
|
||||||
// func getRandomData(r []byte)
|
// func getRandomData(r []byte)
|
||||||
"runtime.getRandomData": (sp) => {
|
"runtime.getRandomData": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
crypto.getRandomValues(loadSlice(sp + 8));
|
crypto.getRandomValues(loadSlice(sp + 8));
|
||||||
},
|
},
|
||||||
|
|
||||||
// func finalizeRef(v ref)
|
// func finalizeRef(v ref)
|
||||||
"syscall/js.finalizeRef": (sp) => {
|
"syscall/js.finalizeRef": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
const id = this.mem.getUint32(sp + 8, true);
|
const id = this.mem.getUint32(sp + 8, true);
|
||||||
this._goRefCounts[id]--;
|
this._goRefCounts[id]--;
|
||||||
if (this._goRefCounts[id] === 0) {
|
if (this._goRefCounts[id] === 0) {
|
||||||
|
|
@ -335,44 +353,51 @@
|
||||||
|
|
||||||
// func stringVal(value string) ref
|
// func stringVal(value string) ref
|
||||||
"syscall/js.stringVal": (sp) => {
|
"syscall/js.stringVal": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
storeValue(sp + 24, loadString(sp + 8));
|
storeValue(sp + 24, loadString(sp + 8));
|
||||||
},
|
},
|
||||||
|
|
||||||
// func valueGet(v ref, p string) ref
|
// func valueGet(v ref, p string) ref
|
||||||
"syscall/js.valueGet": (sp) => {
|
"syscall/js.valueGet": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16));
|
const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16));
|
||||||
sp = this._inst.exports.getsp(); // see comment above
|
sp = this._inst.exports.getsp() >>> 0; // see comment above
|
||||||
storeValue(sp + 32, result);
|
storeValue(sp + 32, result);
|
||||||
},
|
},
|
||||||
|
|
||||||
// func valueSet(v ref, p string, x ref)
|
// func valueSet(v ref, p string, x ref)
|
||||||
"syscall/js.valueSet": (sp) => {
|
"syscall/js.valueSet": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
|
Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
|
||||||
},
|
},
|
||||||
|
|
||||||
// func valueDelete(v ref, p string)
|
// func valueDelete(v ref, p string)
|
||||||
"syscall/js.valueDelete": (sp) => {
|
"syscall/js.valueDelete": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16));
|
Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16));
|
||||||
},
|
},
|
||||||
|
|
||||||
// func valueIndex(v ref, i int) ref
|
// func valueIndex(v ref, i int) ref
|
||||||
"syscall/js.valueIndex": (sp) => {
|
"syscall/js.valueIndex": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
|
storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
|
||||||
},
|
},
|
||||||
|
|
||||||
// valueSetIndex(v ref, i int, x ref)
|
// valueSetIndex(v ref, i int, x ref)
|
||||||
"syscall/js.valueSetIndex": (sp) => {
|
"syscall/js.valueSetIndex": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
|
Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
|
||||||
},
|
},
|
||||||
|
|
||||||
// func valueCall(v ref, m string, args []ref) (ref, bool)
|
// func valueCall(v ref, m string, args []ref) (ref, bool)
|
||||||
"syscall/js.valueCall": (sp) => {
|
"syscall/js.valueCall": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
try {
|
try {
|
||||||
const v = loadValue(sp + 8);
|
const v = loadValue(sp + 8);
|
||||||
const m = Reflect.get(v, loadString(sp + 16));
|
const m = Reflect.get(v, loadString(sp + 16));
|
||||||
const args = loadSliceOfValues(sp + 32);
|
const args = loadSliceOfValues(sp + 32);
|
||||||
const result = Reflect.apply(m, v, args);
|
const result = Reflect.apply(m, v, args);
|
||||||
sp = this._inst.exports.getsp(); // see comment above
|
sp = this._inst.exports.getsp() >>> 0; // see comment above
|
||||||
storeValue(sp + 56, result);
|
storeValue(sp + 56, result);
|
||||||
this.mem.setUint8(sp + 64, 1);
|
this.mem.setUint8(sp + 64, 1);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -383,11 +408,12 @@
|
||||||
|
|
||||||
// func valueInvoke(v ref, args []ref) (ref, bool)
|
// func valueInvoke(v ref, args []ref) (ref, bool)
|
||||||
"syscall/js.valueInvoke": (sp) => {
|
"syscall/js.valueInvoke": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
try {
|
try {
|
||||||
const v = loadValue(sp + 8);
|
const v = loadValue(sp + 8);
|
||||||
const args = loadSliceOfValues(sp + 16);
|
const args = loadSliceOfValues(sp + 16);
|
||||||
const result = Reflect.apply(v, undefined, args);
|
const result = Reflect.apply(v, undefined, args);
|
||||||
sp = this._inst.exports.getsp(); // see comment above
|
sp = this._inst.exports.getsp() >>> 0; // see comment above
|
||||||
storeValue(sp + 40, result);
|
storeValue(sp + 40, result);
|
||||||
this.mem.setUint8(sp + 48, 1);
|
this.mem.setUint8(sp + 48, 1);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -398,11 +424,12 @@
|
||||||
|
|
||||||
// func valueNew(v ref, args []ref) (ref, bool)
|
// func valueNew(v ref, args []ref) (ref, bool)
|
||||||
"syscall/js.valueNew": (sp) => {
|
"syscall/js.valueNew": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
try {
|
try {
|
||||||
const v = loadValue(sp + 8);
|
const v = loadValue(sp + 8);
|
||||||
const args = loadSliceOfValues(sp + 16);
|
const args = loadSliceOfValues(sp + 16);
|
||||||
const result = Reflect.construct(v, args);
|
const result = Reflect.construct(v, args);
|
||||||
sp = this._inst.exports.getsp(); // see comment above
|
sp = this._inst.exports.getsp() >>> 0; // see comment above
|
||||||
storeValue(sp + 40, result);
|
storeValue(sp + 40, result);
|
||||||
this.mem.setUint8(sp + 48, 1);
|
this.mem.setUint8(sp + 48, 1);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|
@ -413,11 +440,13 @@
|
||||||
|
|
||||||
// func valueLength(v ref) int
|
// func valueLength(v ref) int
|
||||||
"syscall/js.valueLength": (sp) => {
|
"syscall/js.valueLength": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
|
setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
|
||||||
},
|
},
|
||||||
|
|
||||||
// valuePrepareString(v ref) (ref, int)
|
// valuePrepareString(v ref) (ref, int)
|
||||||
"syscall/js.valuePrepareString": (sp) => {
|
"syscall/js.valuePrepareString": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
const str = encoder.encode(String(loadValue(sp + 8)));
|
const str = encoder.encode(String(loadValue(sp + 8)));
|
||||||
storeValue(sp + 16, str);
|
storeValue(sp + 16, str);
|
||||||
setInt64(sp + 24, str.length);
|
setInt64(sp + 24, str.length);
|
||||||
|
|
@ -425,17 +454,20 @@
|
||||||
|
|
||||||
// valueLoadString(v ref, b []byte)
|
// valueLoadString(v ref, b []byte)
|
||||||
"syscall/js.valueLoadString": (sp) => {
|
"syscall/js.valueLoadString": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
const str = loadValue(sp + 8);
|
const str = loadValue(sp + 8);
|
||||||
loadSlice(sp + 16).set(str);
|
loadSlice(sp + 16).set(str);
|
||||||
},
|
},
|
||||||
|
|
||||||
// func valueInstanceOf(v ref, t ref) bool
|
// func valueInstanceOf(v ref, t ref) bool
|
||||||
"syscall/js.valueInstanceOf": (sp) => {
|
"syscall/js.valueInstanceOf": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0);
|
this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0);
|
||||||
},
|
},
|
||||||
|
|
||||||
// func copyBytesToGo(dst []byte, src ref) (int, bool)
|
// func copyBytesToGo(dst []byte, src ref) (int, bool)
|
||||||
"syscall/js.copyBytesToGo": (sp) => {
|
"syscall/js.copyBytesToGo": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
const dst = loadSlice(sp + 8);
|
const dst = loadSlice(sp + 8);
|
||||||
const src = loadValue(sp + 32);
|
const src = loadValue(sp + 32);
|
||||||
if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {
|
if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {
|
||||||
|
|
@ -450,6 +482,7 @@
|
||||||
|
|
||||||
// func copyBytesToJS(dst ref, src []byte) (int, bool)
|
// func copyBytesToJS(dst ref, src []byte) (int, bool)
|
||||||
"syscall/js.copyBytesToJS": (sp) => {
|
"syscall/js.copyBytesToJS": (sp) => {
|
||||||
|
sp >>>= 0;
|
||||||
const dst = loadValue(sp + 8);
|
const dst = loadValue(sp + 8);
|
||||||
const src = loadSlice(sp + 16);
|
const src = loadSlice(sp + 16);
|
||||||
if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {
|
if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {
|
||||||
|
|
|
||||||
|
|
@ -13,8 +13,8 @@ package tar
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
|
||||||
"path"
|
"path"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
@ -525,12 +525,12 @@ func (h Header) allowedFormats() (format Format, paxHdrs map[string]string, err
|
||||||
return format, paxHdrs, err
|
return format, paxHdrs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileInfo returns an os.FileInfo for the Header.
|
// FileInfo returns an fs.FileInfo for the Header.
|
||||||
func (h *Header) FileInfo() os.FileInfo {
|
func (h *Header) FileInfo() fs.FileInfo {
|
||||||
return headerFileInfo{h}
|
return headerFileInfo{h}
|
||||||
}
|
}
|
||||||
|
|
||||||
// headerFileInfo implements os.FileInfo.
|
// headerFileInfo implements fs.FileInfo.
|
||||||
type headerFileInfo struct {
|
type headerFileInfo struct {
|
||||||
h *Header
|
h *Header
|
||||||
}
|
}
|
||||||
|
|
@ -549,57 +549,57 @@ func (fi headerFileInfo) Name() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mode returns the permission and mode bits for the headerFileInfo.
|
// Mode returns the permission and mode bits for the headerFileInfo.
|
||||||
func (fi headerFileInfo) Mode() (mode os.FileMode) {
|
func (fi headerFileInfo) Mode() (mode fs.FileMode) {
|
||||||
// Set file permission bits.
|
// Set file permission bits.
|
||||||
mode = os.FileMode(fi.h.Mode).Perm()
|
mode = fs.FileMode(fi.h.Mode).Perm()
|
||||||
|
|
||||||
// Set setuid, setgid and sticky bits.
|
// Set setuid, setgid and sticky bits.
|
||||||
if fi.h.Mode&c_ISUID != 0 {
|
if fi.h.Mode&c_ISUID != 0 {
|
||||||
mode |= os.ModeSetuid
|
mode |= fs.ModeSetuid
|
||||||
}
|
}
|
||||||
if fi.h.Mode&c_ISGID != 0 {
|
if fi.h.Mode&c_ISGID != 0 {
|
||||||
mode |= os.ModeSetgid
|
mode |= fs.ModeSetgid
|
||||||
}
|
}
|
||||||
if fi.h.Mode&c_ISVTX != 0 {
|
if fi.h.Mode&c_ISVTX != 0 {
|
||||||
mode |= os.ModeSticky
|
mode |= fs.ModeSticky
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set file mode bits; clear perm, setuid, setgid, and sticky bits.
|
// Set file mode bits; clear perm, setuid, setgid, and sticky bits.
|
||||||
switch m := os.FileMode(fi.h.Mode) &^ 07777; m {
|
switch m := fs.FileMode(fi.h.Mode) &^ 07777; m {
|
||||||
case c_ISDIR:
|
case c_ISDIR:
|
||||||
mode |= os.ModeDir
|
mode |= fs.ModeDir
|
||||||
case c_ISFIFO:
|
case c_ISFIFO:
|
||||||
mode |= os.ModeNamedPipe
|
mode |= fs.ModeNamedPipe
|
||||||
case c_ISLNK:
|
case c_ISLNK:
|
||||||
mode |= os.ModeSymlink
|
mode |= fs.ModeSymlink
|
||||||
case c_ISBLK:
|
case c_ISBLK:
|
||||||
mode |= os.ModeDevice
|
mode |= fs.ModeDevice
|
||||||
case c_ISCHR:
|
case c_ISCHR:
|
||||||
mode |= os.ModeDevice
|
mode |= fs.ModeDevice
|
||||||
mode |= os.ModeCharDevice
|
mode |= fs.ModeCharDevice
|
||||||
case c_ISSOCK:
|
case c_ISSOCK:
|
||||||
mode |= os.ModeSocket
|
mode |= fs.ModeSocket
|
||||||
}
|
}
|
||||||
|
|
||||||
switch fi.h.Typeflag {
|
switch fi.h.Typeflag {
|
||||||
case TypeSymlink:
|
case TypeSymlink:
|
||||||
mode |= os.ModeSymlink
|
mode |= fs.ModeSymlink
|
||||||
case TypeChar:
|
case TypeChar:
|
||||||
mode |= os.ModeDevice
|
mode |= fs.ModeDevice
|
||||||
mode |= os.ModeCharDevice
|
mode |= fs.ModeCharDevice
|
||||||
case TypeBlock:
|
case TypeBlock:
|
||||||
mode |= os.ModeDevice
|
mode |= fs.ModeDevice
|
||||||
case TypeDir:
|
case TypeDir:
|
||||||
mode |= os.ModeDir
|
mode |= fs.ModeDir
|
||||||
case TypeFifo:
|
case TypeFifo:
|
||||||
mode |= os.ModeNamedPipe
|
mode |= fs.ModeNamedPipe
|
||||||
}
|
}
|
||||||
|
|
||||||
return mode
|
return mode
|
||||||
}
|
}
|
||||||
|
|
||||||
// sysStat, if non-nil, populates h from system-dependent fields of fi.
|
// sysStat, if non-nil, populates h from system-dependent fields of fi.
|
||||||
var sysStat func(fi os.FileInfo, h *Header) error
|
var sysStat func(fi fs.FileInfo, h *Header) error
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Mode constants from the USTAR spec:
|
// Mode constants from the USTAR spec:
|
||||||
|
|
@ -623,10 +623,10 @@ const (
|
||||||
// If fi describes a symlink, FileInfoHeader records link as the link target.
|
// If fi describes a symlink, FileInfoHeader records link as the link target.
|
||||||
// If fi describes a directory, a slash is appended to the name.
|
// If fi describes a directory, a slash is appended to the name.
|
||||||
//
|
//
|
||||||
// Since os.FileInfo's Name method only returns the base name of
|
// Since fs.FileInfo's Name method only returns the base name of
|
||||||
// the file it describes, it may be necessary to modify Header.Name
|
// the file it describes, it may be necessary to modify Header.Name
|
||||||
// to provide the full path name of the file.
|
// to provide the full path name of the file.
|
||||||
func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
|
func FileInfoHeader(fi fs.FileInfo, link string) (*Header, error) {
|
||||||
if fi == nil {
|
if fi == nil {
|
||||||
return nil, errors.New("archive/tar: FileInfo is nil")
|
return nil, errors.New("archive/tar: FileInfo is nil")
|
||||||
}
|
}
|
||||||
|
|
@ -643,29 +643,29 @@ func FileInfoHeader(fi os.FileInfo, link string) (*Header, error) {
|
||||||
case fi.IsDir():
|
case fi.IsDir():
|
||||||
h.Typeflag = TypeDir
|
h.Typeflag = TypeDir
|
||||||
h.Name += "/"
|
h.Name += "/"
|
||||||
case fm&os.ModeSymlink != 0:
|
case fm&fs.ModeSymlink != 0:
|
||||||
h.Typeflag = TypeSymlink
|
h.Typeflag = TypeSymlink
|
||||||
h.Linkname = link
|
h.Linkname = link
|
||||||
case fm&os.ModeDevice != 0:
|
case fm&fs.ModeDevice != 0:
|
||||||
if fm&os.ModeCharDevice != 0 {
|
if fm&fs.ModeCharDevice != 0 {
|
||||||
h.Typeflag = TypeChar
|
h.Typeflag = TypeChar
|
||||||
} else {
|
} else {
|
||||||
h.Typeflag = TypeBlock
|
h.Typeflag = TypeBlock
|
||||||
}
|
}
|
||||||
case fm&os.ModeNamedPipe != 0:
|
case fm&fs.ModeNamedPipe != 0:
|
||||||
h.Typeflag = TypeFifo
|
h.Typeflag = TypeFifo
|
||||||
case fm&os.ModeSocket != 0:
|
case fm&fs.ModeSocket != 0:
|
||||||
return nil, fmt.Errorf("archive/tar: sockets not supported")
|
return nil, fmt.Errorf("archive/tar: sockets not supported")
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm)
|
return nil, fmt.Errorf("archive/tar: unknown file mode %v", fm)
|
||||||
}
|
}
|
||||||
if fm&os.ModeSetuid != 0 {
|
if fm&fs.ModeSetuid != 0 {
|
||||||
h.Mode |= c_ISUID
|
h.Mode |= c_ISUID
|
||||||
}
|
}
|
||||||
if fm&os.ModeSetgid != 0 {
|
if fm&fs.ModeSetgid != 0 {
|
||||||
h.Mode |= c_ISGID
|
h.Mode |= c_ISGID
|
||||||
}
|
}
|
||||||
if fm&os.ModeSticky != 0 {
|
if fm&fs.ModeSticky != 0 {
|
||||||
h.Mode |= c_ISVTX
|
h.Mode |= c_ISVTX
|
||||||
}
|
}
|
||||||
// If possible, populate additional fields from OS-specific
|
// If possible, populate additional fields from OS-specific
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ package tar
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -104,7 +103,7 @@ func (tr *Reader) next() (*Header, error) {
|
||||||
continue // This is a meta header affecting the next header
|
continue // This is a meta header affecting the next header
|
||||||
case TypeGNULongName, TypeGNULongLink:
|
case TypeGNULongName, TypeGNULongLink:
|
||||||
format.mayOnlyBe(FormatGNU)
|
format.mayOnlyBe(FormatGNU)
|
||||||
realname, err := ioutil.ReadAll(tr)
|
realname, err := io.ReadAll(tr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +293,7 @@ func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) {
|
||||||
// parsePAX parses PAX headers.
|
// parsePAX parses PAX headers.
|
||||||
// If an extended header (type 'x') is invalid, ErrHeader is returned
|
// If an extended header (type 'x') is invalid, ErrHeader is returned
|
||||||
func parsePAX(r io.Reader) (map[string]string, error) {
|
func parsePAX(r io.Reader) (map[string]string, error) {
|
||||||
buf, err := ioutil.ReadAll(r)
|
buf, err := io.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -850,7 +849,7 @@ func discard(r io.Reader, n int64) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
copySkipped, err := io.CopyN(ioutil.Discard, r, n-seekSkipped)
|
copySkipped, err := io.CopyN(io.Discard, r, n-seekSkipped)
|
||||||
if err == io.EOF && seekSkipped+copySkipped < n {
|
if err == io.EOF && seekSkipped+copySkipped < n {
|
||||||
err = io.ErrUnexpectedEOF
|
err = io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -865,7 +865,7 @@ func TestReadTruncation(t *testing.T) {
|
||||||
}
|
}
|
||||||
cnt++
|
cnt++
|
||||||
if s2 == "manual" {
|
if s2 == "manual" {
|
||||||
if _, err = tr.writeTo(ioutil.Discard); err != nil {
|
if _, err = tr.writeTo(io.Discard); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
package tar
|
package tar
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"io/fs"
|
||||||
"os/user"
|
"os/user"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
@ -23,7 +23,7 @@ func init() {
|
||||||
// The downside is that renaming uname or gname by the OS never takes effect.
|
// The downside is that renaming uname or gname by the OS never takes effect.
|
||||||
var userMap, groupMap sync.Map // map[int]string
|
var userMap, groupMap sync.Map // map[int]string
|
||||||
|
|
||||||
func statUnix(fi os.FileInfo, h *Header) error {
|
func statUnix(fi fs.FileInfo, h *Header) error {
|
||||||
sys, ok := fi.Sys().(*syscall.Stat_t)
|
sys, ok := fi.Sys().(*syscall.Stat_t)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -327,7 +328,7 @@ func TestRoundTrip(t *testing.T) {
|
||||||
if !reflect.DeepEqual(rHdr, hdr) {
|
if !reflect.DeepEqual(rHdr, hdr) {
|
||||||
t.Errorf("Header mismatch.\n got %+v\nwant %+v", rHdr, hdr)
|
t.Errorf("Header mismatch.\n got %+v\nwant %+v", rHdr, hdr)
|
||||||
}
|
}
|
||||||
rData, err := ioutil.ReadAll(tr)
|
rData, err := io.ReadAll(tr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Read: %v", err)
|
t.Fatalf("Read: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -338,7 +339,7 @@ func TestRoundTrip(t *testing.T) {
|
||||||
|
|
||||||
type headerRoundTripTest struct {
|
type headerRoundTripTest struct {
|
||||||
h *Header
|
h *Header
|
||||||
fm os.FileMode
|
fm fs.FileMode
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHeaderRoundTrip(t *testing.T) {
|
func TestHeaderRoundTrip(t *testing.T) {
|
||||||
|
|
@ -361,7 +362,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
||||||
ModTime: time.Unix(1360600852, 0),
|
ModTime: time.Unix(1360600852, 0),
|
||||||
Typeflag: TypeSymlink,
|
Typeflag: TypeSymlink,
|
||||||
},
|
},
|
||||||
fm: 0777 | os.ModeSymlink,
|
fm: 0777 | fs.ModeSymlink,
|
||||||
}, {
|
}, {
|
||||||
// character device node.
|
// character device node.
|
||||||
h: &Header{
|
h: &Header{
|
||||||
|
|
@ -371,7 +372,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
||||||
ModTime: time.Unix(1360578951, 0),
|
ModTime: time.Unix(1360578951, 0),
|
||||||
Typeflag: TypeChar,
|
Typeflag: TypeChar,
|
||||||
},
|
},
|
||||||
fm: 0666 | os.ModeDevice | os.ModeCharDevice,
|
fm: 0666 | fs.ModeDevice | fs.ModeCharDevice,
|
||||||
}, {
|
}, {
|
||||||
// block device node.
|
// block device node.
|
||||||
h: &Header{
|
h: &Header{
|
||||||
|
|
@ -381,7 +382,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
||||||
ModTime: time.Unix(1360578954, 0),
|
ModTime: time.Unix(1360578954, 0),
|
||||||
Typeflag: TypeBlock,
|
Typeflag: TypeBlock,
|
||||||
},
|
},
|
||||||
fm: 0660 | os.ModeDevice,
|
fm: 0660 | fs.ModeDevice,
|
||||||
}, {
|
}, {
|
||||||
// directory.
|
// directory.
|
||||||
h: &Header{
|
h: &Header{
|
||||||
|
|
@ -391,7 +392,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
||||||
ModTime: time.Unix(1360601116, 0),
|
ModTime: time.Unix(1360601116, 0),
|
||||||
Typeflag: TypeDir,
|
Typeflag: TypeDir,
|
||||||
},
|
},
|
||||||
fm: 0755 | os.ModeDir,
|
fm: 0755 | fs.ModeDir,
|
||||||
}, {
|
}, {
|
||||||
// fifo node.
|
// fifo node.
|
||||||
h: &Header{
|
h: &Header{
|
||||||
|
|
@ -401,7 +402,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
||||||
ModTime: time.Unix(1360578949, 0),
|
ModTime: time.Unix(1360578949, 0),
|
||||||
Typeflag: TypeFifo,
|
Typeflag: TypeFifo,
|
||||||
},
|
},
|
||||||
fm: 0600 | os.ModeNamedPipe,
|
fm: 0600 | fs.ModeNamedPipe,
|
||||||
}, {
|
}, {
|
||||||
// setuid.
|
// setuid.
|
||||||
h: &Header{
|
h: &Header{
|
||||||
|
|
@ -411,7 +412,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
||||||
ModTime: time.Unix(1355405093, 0),
|
ModTime: time.Unix(1355405093, 0),
|
||||||
Typeflag: TypeReg,
|
Typeflag: TypeReg,
|
||||||
},
|
},
|
||||||
fm: 0755 | os.ModeSetuid,
|
fm: 0755 | fs.ModeSetuid,
|
||||||
}, {
|
}, {
|
||||||
// setguid.
|
// setguid.
|
||||||
h: &Header{
|
h: &Header{
|
||||||
|
|
@ -421,7 +422,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
||||||
ModTime: time.Unix(1360602346, 0),
|
ModTime: time.Unix(1360602346, 0),
|
||||||
Typeflag: TypeReg,
|
Typeflag: TypeReg,
|
||||||
},
|
},
|
||||||
fm: 0750 | os.ModeSetgid,
|
fm: 0750 | fs.ModeSetgid,
|
||||||
}, {
|
}, {
|
||||||
// sticky.
|
// sticky.
|
||||||
h: &Header{
|
h: &Header{
|
||||||
|
|
@ -431,7 +432,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
||||||
ModTime: time.Unix(1360602540, 0),
|
ModTime: time.Unix(1360602540, 0),
|
||||||
Typeflag: TypeReg,
|
Typeflag: TypeReg,
|
||||||
},
|
},
|
||||||
fm: 0600 | os.ModeSticky,
|
fm: 0600 | fs.ModeSticky,
|
||||||
}, {
|
}, {
|
||||||
// hard link.
|
// hard link.
|
||||||
h: &Header{
|
h: &Header{
|
||||||
|
|
@ -804,9 +805,9 @@ func Benchmark(b *testing.B) {
|
||||||
b.Run(v.label, func(b *testing.B) {
|
b.Run(v.label, func(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
// Writing to ioutil.Discard because we want to
|
// Writing to io.Discard because we want to
|
||||||
// test purely the writer code and not bring in disk performance into this.
|
// test purely the writer code and not bring in disk performance into this.
|
||||||
tw := NewWriter(ioutil.Discard)
|
tw := NewWriter(io.Discard)
|
||||||
for _, file := range v.files {
|
for _, file := range v.files {
|
||||||
if err := tw.WriteHeader(file.hdr); err != nil {
|
if err := tw.WriteHeader(file.hdr); err != nil {
|
||||||
b.Errorf("unexpected WriteHeader error: %v", err)
|
b.Errorf("unexpected WriteHeader error: %v", err)
|
||||||
|
|
@ -844,7 +845,7 @@ func Benchmark(b *testing.B) {
|
||||||
if _, err := tr.Next(); err != nil {
|
if _, err := tr.Next(); err != nil {
|
||||||
b.Errorf("unexpected Next error: %v", err)
|
b.Errorf("unexpected Next error: %v", err)
|
||||||
}
|
}
|
||||||
if _, err := io.Copy(ioutil.Discard, tr); err != nil {
|
if _, err := io.Copy(io.Discard, tr); err != nil {
|
||||||
b.Errorf("unexpected Copy error : %v", err)
|
b.Errorf("unexpected Copy error : %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,12 @@ import (
|
||||||
"hash"
|
"hash"
|
||||||
"hash/crc32"
|
"hash/crc32"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -21,18 +26,28 @@ var (
|
||||||
ErrChecksum = errors.New("zip: checksum error")
|
ErrChecksum = errors.New("zip: checksum error")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// A Reader serves content from a ZIP archive.
|
||||||
type Reader struct {
|
type Reader struct {
|
||||||
r io.ReaderAt
|
r io.ReaderAt
|
||||||
File []*File
|
File []*File
|
||||||
Comment string
|
Comment string
|
||||||
decompressors map[uint16]Decompressor
|
decompressors map[uint16]Decompressor
|
||||||
|
|
||||||
|
// fileList is a list of files sorted by ename,
|
||||||
|
// for use by the Open method.
|
||||||
|
fileListOnce sync.Once
|
||||||
|
fileList []fileListEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A ReadCloser is a Reader that must be closed when no longer needed.
|
||||||
type ReadCloser struct {
|
type ReadCloser struct {
|
||||||
f *os.File
|
f *os.File
|
||||||
Reader
|
Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A File is a single file in a ZIP archive.
|
||||||
|
// The file information is in the embedded FileHeader.
|
||||||
|
// The file content can be accessed by calling Open.
|
||||||
type File struct {
|
type File struct {
|
||||||
FileHeader
|
FileHeader
|
||||||
zip *Reader
|
zip *Reader
|
||||||
|
|
@ -187,6 +202,10 @@ type checksumReader struct {
|
||||||
err error // sticky error
|
err error // sticky error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *checksumReader) Stat() (fs.FileInfo, error) {
|
||||||
|
return headerFileInfo{&r.f.FileHeader}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *checksumReader) Read(b []byte) (n int, err error) {
|
func (r *checksumReader) Read(b []byte) (n int, err error) {
|
||||||
if r.err != nil {
|
if r.err != nil {
|
||||||
return 0, r.err
|
return 0, r.err
|
||||||
|
|
@ -607,3 +626,173 @@ func (b *readBuf) sub(n int) readBuf {
|
||||||
*b = (*b)[n:]
|
*b = (*b)[n:]
|
||||||
return b2
|
return b2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A fileListEntry is a File and its ename.
|
||||||
|
// If file == nil, the fileListEntry describes a directory, without metadata.
|
||||||
|
type fileListEntry struct {
|
||||||
|
name string
|
||||||
|
file *File // nil for directories
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileInfoDirEntry interface {
|
||||||
|
fs.FileInfo
|
||||||
|
fs.DirEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *fileListEntry) stat() fileInfoDirEntry {
|
||||||
|
if e.file != nil {
|
||||||
|
return headerFileInfo{&e.file.FileHeader}
|
||||||
|
}
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only used for directories.
|
||||||
|
func (f *fileListEntry) Name() string { _, elem, _ := split(f.name); return elem }
|
||||||
|
func (f *fileListEntry) Size() int64 { return 0 }
|
||||||
|
func (f *fileListEntry) ModTime() time.Time { return time.Time{} }
|
||||||
|
func (f *fileListEntry) Mode() fs.FileMode { return fs.ModeDir | 0555 }
|
||||||
|
func (f *fileListEntry) Type() fs.FileMode { return fs.ModeDir }
|
||||||
|
func (f *fileListEntry) IsDir() bool { return true }
|
||||||
|
func (f *fileListEntry) Sys() interface{} { return nil }
|
||||||
|
|
||||||
|
func (f *fileListEntry) Info() (fs.FileInfo, error) { return f, nil }
|
||||||
|
|
||||||
|
// toValidName coerces name to be a valid name for fs.FS.Open.
|
||||||
|
func toValidName(name string) string {
|
||||||
|
name = strings.ReplaceAll(name, `\`, `/`)
|
||||||
|
p := path.Clean(name)
|
||||||
|
if strings.HasPrefix(p, "/") {
|
||||||
|
p = p[len("/"):]
|
||||||
|
}
|
||||||
|
for strings.HasPrefix(name, "../") {
|
||||||
|
p = p[len("../"):]
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) initFileList() {
|
||||||
|
r.fileListOnce.Do(func() {
|
||||||
|
dirs := make(map[string]bool)
|
||||||
|
for _, file := range r.File {
|
||||||
|
name := toValidName(file.Name)
|
||||||
|
for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) {
|
||||||
|
dirs[dir] = true
|
||||||
|
}
|
||||||
|
r.fileList = append(r.fileList, fileListEntry{name, file})
|
||||||
|
}
|
||||||
|
for dir := range dirs {
|
||||||
|
r.fileList = append(r.fileList, fileListEntry{dir + "/", nil})
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(r.fileList, func(i, j int) bool { return fileEntryLess(r.fileList[i].name, r.fileList[j].name) })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileEntryLess(x, y string) bool {
|
||||||
|
xdir, xelem, _ := split(x)
|
||||||
|
ydir, yelem, _ := split(y)
|
||||||
|
return xdir < ydir || xdir == ydir && xelem < yelem
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open opens the named file in the ZIP archive,
|
||||||
|
// using the semantics of io.FS.Open:
|
||||||
|
// paths are always slash separated, with no
|
||||||
|
// leading / or ../ elements.
|
||||||
|
func (r *Reader) Open(name string) (fs.File, error) {
|
||||||
|
r.initFileList()
|
||||||
|
|
||||||
|
e := r.openLookup(name)
|
||||||
|
if e == nil || !fs.ValidPath(name) {
|
||||||
|
return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist}
|
||||||
|
}
|
||||||
|
if e.file == nil || strings.HasSuffix(e.file.Name, "/") {
|
||||||
|
return &openDir{e, r.openReadDir(name), 0}, nil
|
||||||
|
}
|
||||||
|
rc, err := e.file.Open()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return rc.(fs.File), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func split(name string) (dir, elem string, isDir bool) {
|
||||||
|
if name[len(name)-1] == '/' {
|
||||||
|
isDir = true
|
||||||
|
name = name[:len(name)-1]
|
||||||
|
}
|
||||||
|
i := len(name) - 1
|
||||||
|
for i >= 0 && name[i] != '/' {
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
if i < 0 {
|
||||||
|
return ".", name, isDir
|
||||||
|
}
|
||||||
|
return name[:i], name[i+1:], isDir
|
||||||
|
}
|
||||||
|
|
||||||
|
var dotFile = &fileListEntry{name: "./"}
|
||||||
|
|
||||||
|
func (r *Reader) openLookup(name string) *fileListEntry {
|
||||||
|
if name == "." {
|
||||||
|
return dotFile
|
||||||
|
}
|
||||||
|
|
||||||
|
dir, elem, _ := split(name)
|
||||||
|
files := r.fileList
|
||||||
|
i := sort.Search(len(files), func(i int) bool {
|
||||||
|
idir, ielem, _ := split(files[i].name)
|
||||||
|
return idir > dir || idir == dir && ielem >= elem
|
||||||
|
})
|
||||||
|
if i < len(files) {
|
||||||
|
fname := files[i].name
|
||||||
|
if fname == name || len(fname) == len(name)+1 && fname[len(name)] == '/' && fname[:len(name)] == name {
|
||||||
|
return &files[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Reader) openReadDir(dir string) []fileListEntry {
|
||||||
|
files := r.fileList
|
||||||
|
i := sort.Search(len(files), func(i int) bool {
|
||||||
|
idir, _, _ := split(files[i].name)
|
||||||
|
return idir >= dir
|
||||||
|
})
|
||||||
|
j := sort.Search(len(files), func(j int) bool {
|
||||||
|
jdir, _, _ := split(files[j].name)
|
||||||
|
return jdir > dir
|
||||||
|
})
|
||||||
|
return files[i:j]
|
||||||
|
}
|
||||||
|
|
||||||
|
type openDir struct {
|
||||||
|
e *fileListEntry
|
||||||
|
files []fileListEntry
|
||||||
|
offset int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *openDir) Close() error { return nil }
|
||||||
|
func (d *openDir) Stat() (fs.FileInfo, error) { return d.e.stat(), nil }
|
||||||
|
|
||||||
|
func (d *openDir) Read([]byte) (int, error) {
|
||||||
|
return 0, &fs.PathError{Op: "read", Path: d.e.name, Err: errors.New("is a directory")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *openDir) ReadDir(count int) ([]fs.DirEntry, error) {
|
||||||
|
n := len(d.files) - d.offset
|
||||||
|
if count > 0 && n > count {
|
||||||
|
n = count
|
||||||
|
}
|
||||||
|
if n == 0 {
|
||||||
|
if count <= 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return nil, io.EOF
|
||||||
|
}
|
||||||
|
list := make([]fs.DirEntry, n)
|
||||||
|
for i := range list {
|
||||||
|
list[i] = d.files[d.offset+i].stat()
|
||||||
|
}
|
||||||
|
d.offset += n
|
||||||
|
return list, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,14 @@ import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"internal/obscuretestdata"
|
"internal/obscuretestdata"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"testing/fstest"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -30,7 +32,7 @@ type ZipTest struct {
|
||||||
|
|
||||||
type ZipTestFile struct {
|
type ZipTestFile struct {
|
||||||
Name string
|
Name string
|
||||||
Mode os.FileMode
|
Mode fs.FileMode
|
||||||
NonUTF8 bool
|
NonUTF8 bool
|
||||||
ModTime time.Time
|
ModTime time.Time
|
||||||
Modified time.Time
|
Modified time.Time
|
||||||
|
|
@ -107,7 +109,7 @@ var tests = []ZipTest{
|
||||||
Name: "symlink",
|
Name: "symlink",
|
||||||
Content: []byte("../target"),
|
Content: []byte("../target"),
|
||||||
Modified: time.Date(2012, 2, 3, 19, 56, 48, 0, timeZone(-2*time.Hour)),
|
Modified: time.Date(2012, 2, 3, 19, 56, 48, 0, timeZone(-2*time.Hour)),
|
||||||
Mode: 0777 | os.ModeSymlink,
|
Mode: 0777 | fs.ModeSymlink,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -149,7 +151,7 @@ var tests = []ZipTest{
|
||||||
Name: "dir/empty/",
|
Name: "dir/empty/",
|
||||||
Content: []byte{},
|
Content: []byte{},
|
||||||
Modified: time.Date(2011, 12, 8, 10, 8, 6, 0, time.UTC),
|
Modified: time.Date(2011, 12, 8, 10, 8, 6, 0, time.UTC),
|
||||||
Mode: os.ModeDir | 0777,
|
Mode: fs.ModeDir | 0777,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "readonly",
|
Name: "readonly",
|
||||||
|
|
@ -179,7 +181,7 @@ var tests = []ZipTest{
|
||||||
Name: "dir/empty/",
|
Name: "dir/empty/",
|
||||||
Content: []byte{},
|
Content: []byte{},
|
||||||
Modified: time.Date(2011, 12, 8, 10, 8, 6, 0, timeZone(0)),
|
Modified: time.Date(2011, 12, 8, 10, 8, 6, 0, timeZone(0)),
|
||||||
Mode: os.ModeDir | 0777,
|
Mode: fs.ModeDir | 0777,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "readonly",
|
Name: "readonly",
|
||||||
|
|
@ -645,7 +647,7 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testFileMode(t *testing.T, f *File, want os.FileMode) {
|
func testFileMode(t *testing.T, f *File, want fs.FileMode) {
|
||||||
mode := f.Mode()
|
mode := f.Mode()
|
||||||
if want == 0 {
|
if want == 0 {
|
||||||
t.Errorf("%s mode: got %v, want none", f.Name, mode)
|
t.Errorf("%s mode: got %v, want none", f.Name, mode)
|
||||||
|
|
@ -928,7 +930,7 @@ func returnBigZipBytes() (r io.ReaderAt, size int64) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
b, err = ioutil.ReadAll(f)
|
b, err = io.ReadAll(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -985,7 +987,7 @@ func TestIssue10957(t *testing.T) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if f.UncompressedSize64 < 1e6 {
|
if f.UncompressedSize64 < 1e6 {
|
||||||
n, err := io.Copy(ioutil.Discard, r)
|
n, err := io.Copy(io.Discard, r)
|
||||||
if i == 3 && err != io.ErrUnexpectedEOF {
|
if i == 3 && err != io.ErrUnexpectedEOF {
|
||||||
t.Errorf("File[3] error = %v; want io.ErrUnexpectedEOF", err)
|
t.Errorf("File[3] error = %v; want io.ErrUnexpectedEOF", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1027,7 +1029,7 @@ func TestIssue11146(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
_, err = ioutil.ReadAll(r)
|
_, err = io.ReadAll(r)
|
||||||
if err != io.ErrUnexpectedEOF {
|
if err != io.ErrUnexpectedEOF {
|
||||||
t.Errorf("File[0] error = %v; want io.ErrUnexpectedEOF", err)
|
t.Errorf("File[0] error = %v; want io.ErrUnexpectedEOF", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1070,3 +1072,13 @@ func TestIssue12449(t *testing.T) {
|
||||||
t.Errorf("Error reading the archive: %v", err)
|
t.Errorf("Error reading the archive: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFS(t *testing.T) {
|
||||||
|
z, err := OpenReader("testdata/unix.zip")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := fstest.TestFS(z, "hello", "dir/bar", "dir/empty", "readonly"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import (
|
||||||
"compress/flate"
|
"compress/flate"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -111,7 +110,7 @@ func init() {
|
||||||
compressors.Store(Store, Compressor(func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }))
|
compressors.Store(Store, Compressor(func(w io.Writer) (io.WriteCloser, error) { return &nopCloser{w}, nil }))
|
||||||
compressors.Store(Deflate, Compressor(func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }))
|
compressors.Store(Deflate, Compressor(func(w io.Writer) (io.WriteCloser, error) { return newFlateWriter(w), nil }))
|
||||||
|
|
||||||
decompressors.Store(Store, Decompressor(ioutil.NopCloser))
|
decompressors.Store(Store, Decompressor(io.NopCloser))
|
||||||
decompressors.Store(Deflate, Decompressor(newFlateReader))
|
decompressors.Store(Deflate, Decompressor(newFlateReader))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ fields must be used instead.
|
||||||
package zip
|
package zip
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"io/fs"
|
||||||
"path"
|
"path"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -137,12 +137,12 @@ type FileHeader struct {
|
||||||
ExternalAttrs uint32 // Meaning depends on CreatorVersion
|
ExternalAttrs uint32 // Meaning depends on CreatorVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileInfo returns an os.FileInfo for the FileHeader.
|
// FileInfo returns an fs.FileInfo for the FileHeader.
|
||||||
func (h *FileHeader) FileInfo() os.FileInfo {
|
func (h *FileHeader) FileInfo() fs.FileInfo {
|
||||||
return headerFileInfo{h}
|
return headerFileInfo{h}
|
||||||
}
|
}
|
||||||
|
|
||||||
// headerFileInfo implements os.FileInfo.
|
// headerFileInfo implements fs.FileInfo.
|
||||||
type headerFileInfo struct {
|
type headerFileInfo struct {
|
||||||
fh *FileHeader
|
fh *FileHeader
|
||||||
}
|
}
|
||||||
|
|
@ -161,17 +161,20 @@ func (fi headerFileInfo) ModTime() time.Time {
|
||||||
}
|
}
|
||||||
return fi.fh.Modified.UTC()
|
return fi.fh.Modified.UTC()
|
||||||
}
|
}
|
||||||
func (fi headerFileInfo) Mode() os.FileMode { return fi.fh.Mode() }
|
func (fi headerFileInfo) Mode() fs.FileMode { return fi.fh.Mode() }
|
||||||
|
func (fi headerFileInfo) Type() fs.FileMode { return fi.fh.Mode().Type() }
|
||||||
func (fi headerFileInfo) Sys() interface{} { return fi.fh }
|
func (fi headerFileInfo) Sys() interface{} { return fi.fh }
|
||||||
|
|
||||||
|
func (fi headerFileInfo) Info() (fs.FileInfo, error) { return fi, nil }
|
||||||
|
|
||||||
// FileInfoHeader creates a partially-populated FileHeader from an
|
// FileInfoHeader creates a partially-populated FileHeader from an
|
||||||
// os.FileInfo.
|
// fs.FileInfo.
|
||||||
// Because os.FileInfo's Name method returns only the base name of
|
// Because fs.FileInfo's Name method returns only the base name of
|
||||||
// the file it describes, it may be necessary to modify the Name field
|
// the file it describes, it may be necessary to modify the Name field
|
||||||
// of the returned header to provide the full path name of the file.
|
// of the returned header to provide the full path name of the file.
|
||||||
// If compression is desired, callers should set the FileHeader.Method
|
// If compression is desired, callers should set the FileHeader.Method
|
||||||
// field; it is unset by default.
|
// field; it is unset by default.
|
||||||
func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) {
|
func FileInfoHeader(fi fs.FileInfo) (*FileHeader, error) {
|
||||||
size := fi.Size()
|
size := fi.Size()
|
||||||
fh := &FileHeader{
|
fh := &FileHeader{
|
||||||
Name: fi.Name(),
|
Name: fi.Name(),
|
||||||
|
|
@ -280,7 +283,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// Mode returns the permission and mode bits for the FileHeader.
|
// Mode returns the permission and mode bits for the FileHeader.
|
||||||
func (h *FileHeader) Mode() (mode os.FileMode) {
|
func (h *FileHeader) Mode() (mode fs.FileMode) {
|
||||||
switch h.CreatorVersion >> 8 {
|
switch h.CreatorVersion >> 8 {
|
||||||
case creatorUnix, creatorMacOSX:
|
case creatorUnix, creatorMacOSX:
|
||||||
mode = unixModeToFileMode(h.ExternalAttrs >> 16)
|
mode = unixModeToFileMode(h.ExternalAttrs >> 16)
|
||||||
|
|
@ -288,18 +291,18 @@ func (h *FileHeader) Mode() (mode os.FileMode) {
|
||||||
mode = msdosModeToFileMode(h.ExternalAttrs)
|
mode = msdosModeToFileMode(h.ExternalAttrs)
|
||||||
}
|
}
|
||||||
if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' {
|
if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' {
|
||||||
mode |= os.ModeDir
|
mode |= fs.ModeDir
|
||||||
}
|
}
|
||||||
return mode
|
return mode
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMode changes the permission and mode bits for the FileHeader.
|
// SetMode changes the permission and mode bits for the FileHeader.
|
||||||
func (h *FileHeader) SetMode(mode os.FileMode) {
|
func (h *FileHeader) SetMode(mode fs.FileMode) {
|
||||||
h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8
|
h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8
|
||||||
h.ExternalAttrs = fileModeToUnixMode(mode) << 16
|
h.ExternalAttrs = fileModeToUnixMode(mode) << 16
|
||||||
|
|
||||||
// set MSDOS attributes too, as the original zip does.
|
// set MSDOS attributes too, as the original zip does.
|
||||||
if mode&os.ModeDir != 0 {
|
if mode&fs.ModeDir != 0 {
|
||||||
h.ExternalAttrs |= msdosDir
|
h.ExternalAttrs |= msdosDir
|
||||||
}
|
}
|
||||||
if mode&0200 == 0 {
|
if mode&0200 == 0 {
|
||||||
|
|
@ -312,9 +315,9 @@ func (h *FileHeader) isZip64() bool {
|
||||||
return h.CompressedSize64 >= uint32max || h.UncompressedSize64 >= uint32max
|
return h.CompressedSize64 >= uint32max || h.UncompressedSize64 >= uint32max
|
||||||
}
|
}
|
||||||
|
|
||||||
func msdosModeToFileMode(m uint32) (mode os.FileMode) {
|
func msdosModeToFileMode(m uint32) (mode fs.FileMode) {
|
||||||
if m&msdosDir != 0 {
|
if m&msdosDir != 0 {
|
||||||
mode = os.ModeDir | 0777
|
mode = fs.ModeDir | 0777
|
||||||
} else {
|
} else {
|
||||||
mode = 0666
|
mode = 0666
|
||||||
}
|
}
|
||||||
|
|
@ -324,64 +327,64 @@ func msdosModeToFileMode(m uint32) (mode os.FileMode) {
|
||||||
return mode
|
return mode
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileModeToUnixMode(mode os.FileMode) uint32 {
|
func fileModeToUnixMode(mode fs.FileMode) uint32 {
|
||||||
var m uint32
|
var m uint32
|
||||||
switch mode & os.ModeType {
|
switch mode & fs.ModeType {
|
||||||
default:
|
default:
|
||||||
m = s_IFREG
|
m = s_IFREG
|
||||||
case os.ModeDir:
|
case fs.ModeDir:
|
||||||
m = s_IFDIR
|
m = s_IFDIR
|
||||||
case os.ModeSymlink:
|
case fs.ModeSymlink:
|
||||||
m = s_IFLNK
|
m = s_IFLNK
|
||||||
case os.ModeNamedPipe:
|
case fs.ModeNamedPipe:
|
||||||
m = s_IFIFO
|
m = s_IFIFO
|
||||||
case os.ModeSocket:
|
case fs.ModeSocket:
|
||||||
m = s_IFSOCK
|
m = s_IFSOCK
|
||||||
case os.ModeDevice:
|
case fs.ModeDevice:
|
||||||
if mode&os.ModeCharDevice != 0 {
|
if mode&fs.ModeCharDevice != 0 {
|
||||||
m = s_IFCHR
|
m = s_IFCHR
|
||||||
} else {
|
} else {
|
||||||
m = s_IFBLK
|
m = s_IFBLK
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if mode&os.ModeSetuid != 0 {
|
if mode&fs.ModeSetuid != 0 {
|
||||||
m |= s_ISUID
|
m |= s_ISUID
|
||||||
}
|
}
|
||||||
if mode&os.ModeSetgid != 0 {
|
if mode&fs.ModeSetgid != 0 {
|
||||||
m |= s_ISGID
|
m |= s_ISGID
|
||||||
}
|
}
|
||||||
if mode&os.ModeSticky != 0 {
|
if mode&fs.ModeSticky != 0 {
|
||||||
m |= s_ISVTX
|
m |= s_ISVTX
|
||||||
}
|
}
|
||||||
return m | uint32(mode&0777)
|
return m | uint32(mode&0777)
|
||||||
}
|
}
|
||||||
|
|
||||||
func unixModeToFileMode(m uint32) os.FileMode {
|
func unixModeToFileMode(m uint32) fs.FileMode {
|
||||||
mode := os.FileMode(m & 0777)
|
mode := fs.FileMode(m & 0777)
|
||||||
switch m & s_IFMT {
|
switch m & s_IFMT {
|
||||||
case s_IFBLK:
|
case s_IFBLK:
|
||||||
mode |= os.ModeDevice
|
mode |= fs.ModeDevice
|
||||||
case s_IFCHR:
|
case s_IFCHR:
|
||||||
mode |= os.ModeDevice | os.ModeCharDevice
|
mode |= fs.ModeDevice | fs.ModeCharDevice
|
||||||
case s_IFDIR:
|
case s_IFDIR:
|
||||||
mode |= os.ModeDir
|
mode |= fs.ModeDir
|
||||||
case s_IFIFO:
|
case s_IFIFO:
|
||||||
mode |= os.ModeNamedPipe
|
mode |= fs.ModeNamedPipe
|
||||||
case s_IFLNK:
|
case s_IFLNK:
|
||||||
mode |= os.ModeSymlink
|
mode |= fs.ModeSymlink
|
||||||
case s_IFREG:
|
case s_IFREG:
|
||||||
// nothing to do
|
// nothing to do
|
||||||
case s_IFSOCK:
|
case s_IFSOCK:
|
||||||
mode |= os.ModeSocket
|
mode |= fs.ModeSocket
|
||||||
}
|
}
|
||||||
if m&s_ISGID != 0 {
|
if m&s_ISGID != 0 {
|
||||||
mode |= os.ModeSetgid
|
mode |= fs.ModeSetgid
|
||||||
}
|
}
|
||||||
if m&s_ISUID != 0 {
|
if m&s_ISUID != 0 {
|
||||||
mode |= os.ModeSetuid
|
mode |= fs.ModeSetuid
|
||||||
}
|
}
|
||||||
if m&s_ISVTX != 0 {
|
if m&s_ISVTX != 0 {
|
||||||
mode |= os.ModeSticky
|
mode |= fs.ModeSticky
|
||||||
}
|
}
|
||||||
return mode
|
return mode
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -23,7 +23,7 @@ type WriteTest struct {
|
||||||
Name string
|
Name string
|
||||||
Data []byte
|
Data []byte
|
||||||
Method uint16
|
Method uint16
|
||||||
Mode os.FileMode
|
Mode fs.FileMode
|
||||||
}
|
}
|
||||||
|
|
||||||
var writeTests = []WriteTest{
|
var writeTests = []WriteTest{
|
||||||
|
|
@ -43,19 +43,19 @@ var writeTests = []WriteTest{
|
||||||
Name: "setuid",
|
Name: "setuid",
|
||||||
Data: []byte("setuid file"),
|
Data: []byte("setuid file"),
|
||||||
Method: Deflate,
|
Method: Deflate,
|
||||||
Mode: 0755 | os.ModeSetuid,
|
Mode: 0755 | fs.ModeSetuid,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "setgid",
|
Name: "setgid",
|
||||||
Data: []byte("setgid file"),
|
Data: []byte("setgid file"),
|
||||||
Method: Deflate,
|
Method: Deflate,
|
||||||
Mode: 0755 | os.ModeSetgid,
|
Mode: 0755 | fs.ModeSetgid,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "symlink",
|
Name: "symlink",
|
||||||
Data: []byte("../link/target"),
|
Data: []byte("../link/target"),
|
||||||
Method: Deflate,
|
Method: Deflate,
|
||||||
Mode: 0755 | os.ModeSymlink,
|
Mode: 0755 | fs.ModeSymlink,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -301,7 +301,7 @@ func TestWriterFlush(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWriterDir(t *testing.T) {
|
func TestWriterDir(t *testing.T) {
|
||||||
w := NewWriter(ioutil.Discard)
|
w := NewWriter(io.Discard)
|
||||||
dw, err := w.Create("dir/")
|
dw, err := w.Create("dir/")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|
@ -380,7 +380,7 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("opening:", err)
|
t.Fatal("opening:", err)
|
||||||
}
|
}
|
||||||
b, err := ioutil.ReadAll(rc)
|
b, err := io.ReadAll(rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("reading:", err)
|
t.Fatal("reading:", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import (
|
||||||
"hash"
|
"hash"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -620,7 +619,7 @@ func testZip64(t testing.TB, size int64) *rleBuffer {
|
||||||
t.Fatal("read:", err)
|
t.Fatal("read:", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gotEnd, err := ioutil.ReadAll(rc)
|
gotEnd, err := io.ReadAll(rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("read end:", err)
|
t.Fatal("read end:", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"testing/iotest"
|
"testing/iotest"
|
||||||
|
|
@ -886,7 +885,7 @@ func TestReadEmptyBuffer(t *testing.T) {
|
||||||
|
|
||||||
func TestLinesAfterRead(t *testing.T) {
|
func TestLinesAfterRead(t *testing.T) {
|
||||||
l := NewReaderSize(bytes.NewReader([]byte("foo")), minReadBufferSize)
|
l := NewReaderSize(bytes.NewReader([]byte("foo")), minReadBufferSize)
|
||||||
_, err := ioutil.ReadAll(l)
|
_, err := io.ReadAll(l)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
|
@ -1130,7 +1129,7 @@ func TestWriterReadFromCounts(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A writeCountingDiscard is like ioutil.Discard and counts the number of times
|
// A writeCountingDiscard is like io.Discard and counts the number of times
|
||||||
// Write is called on it.
|
// Write is called on it.
|
||||||
type writeCountingDiscard int
|
type writeCountingDiscard int
|
||||||
|
|
||||||
|
|
@ -1300,7 +1299,7 @@ func TestReaderReset(t *testing.T) {
|
||||||
t.Errorf("buf = %q; want foo", buf)
|
t.Errorf("buf = %q; want foo", buf)
|
||||||
}
|
}
|
||||||
r.Reset(strings.NewReader("bar bar"))
|
r.Reset(strings.NewReader("bar bar"))
|
||||||
all, err := ioutil.ReadAll(r)
|
all, err := io.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -1645,13 +1644,13 @@ func BenchmarkReaderWriteToOptimal(b *testing.B) {
|
||||||
buf := make([]byte, bufSize)
|
buf := make([]byte, bufSize)
|
||||||
r := bytes.NewReader(buf)
|
r := bytes.NewReader(buf)
|
||||||
srcReader := NewReaderSize(onlyReader{r}, 1<<10)
|
srcReader := NewReaderSize(onlyReader{r}, 1<<10)
|
||||||
if _, ok := ioutil.Discard.(io.ReaderFrom); !ok {
|
if _, ok := io.Discard.(io.ReaderFrom); !ok {
|
||||||
b.Fatal("ioutil.Discard doesn't support ReaderFrom")
|
b.Fatal("io.Discard doesn't support ReaderFrom")
|
||||||
}
|
}
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
r.Seek(0, io.SeekStart)
|
r.Seek(0, io.SeekStart)
|
||||||
srcReader.Reset(onlyReader{r})
|
srcReader.Reset(onlyReader{r})
|
||||||
n, err := srcReader.WriteTo(ioutil.Discard)
|
n, err := srcReader.WriteTo(io.Discard)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -1722,7 +1721,7 @@ func BenchmarkReaderEmpty(b *testing.B) {
|
||||||
str := strings.Repeat("x", 16<<10)
|
str := strings.Repeat("x", 16<<10)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
br := NewReader(strings.NewReader(str))
|
br := NewReader(strings.NewReader(str))
|
||||||
n, err := io.Copy(ioutil.Discard, br)
|
n, err := io.Copy(io.Discard, br)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.Fatal(err)
|
b.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -1737,7 +1736,7 @@ func BenchmarkWriterEmpty(b *testing.B) {
|
||||||
str := strings.Repeat("x", 1<<10)
|
str := strings.Repeat("x", 1<<10)
|
||||||
bs := []byte(str)
|
bs := []byte(str)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
bw := NewWriter(ioutil.Discard)
|
bw := NewWriter(io.Discard)
|
||||||
bw.Flush()
|
bw.Flush()
|
||||||
bw.WriteByte('a')
|
bw.WriteByte('a')
|
||||||
bw.Flush()
|
bw.Flush()
|
||||||
|
|
@ -1752,7 +1751,7 @@ func BenchmarkWriterEmpty(b *testing.B) {
|
||||||
|
|
||||||
func BenchmarkWriterFlush(b *testing.B) {
|
func BenchmarkWriterFlush(b *testing.B) {
|
||||||
b.ReportAllocs()
|
b.ReportAllocs()
|
||||||
bw := NewWriter(ioutil.Discard)
|
bw := NewWriter(io.Discard)
|
||||||
str := strings.Repeat("x", 50)
|
str := strings.Repeat("x", 50)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
bw.WriteString(str)
|
bw.WriteString(str)
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import (
|
||||||
. "bytes"
|
. "bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
@ -235,7 +234,7 @@ func TestReaderCopyNothing(t *testing.T) {
|
||||||
type justWriter struct {
|
type justWriter struct {
|
||||||
io.Writer
|
io.Writer
|
||||||
}
|
}
|
||||||
discard := justWriter{ioutil.Discard} // hide ReadFrom
|
discard := justWriter{io.Discard} // hide ReadFrom
|
||||||
|
|
||||||
var with, withOut nErr
|
var with, withOut nErr
|
||||||
with.n, with.err = io.Copy(discard, NewReader(nil))
|
with.n, with.err = io.Copy(discard, NewReader(nil))
|
||||||
|
|
@ -248,7 +247,7 @@ func TestReaderCopyNothing(t *testing.T) {
|
||||||
// tests that Len is affected by reads, but Size is not.
|
// tests that Len is affected by reads, but Size is not.
|
||||||
func TestReaderLenSize(t *testing.T) {
|
func TestReaderLenSize(t *testing.T) {
|
||||||
r := NewReader([]byte("abc"))
|
r := NewReader([]byte("abc"))
|
||||||
io.CopyN(ioutil.Discard, r, 1)
|
io.CopyN(io.Discard, r, 1)
|
||||||
if r.Len() != 2 {
|
if r.Len() != 2 {
|
||||||
t.Errorf("Len = %d; want 2", r.Len())
|
t.Errorf("Len = %d; want 2", r.Len())
|
||||||
}
|
}
|
||||||
|
|
@ -268,7 +267,7 @@ func TestReaderReset(t *testing.T) {
|
||||||
if err := r.UnreadRune(); err == nil {
|
if err := r.UnreadRune(); err == nil {
|
||||||
t.Errorf("UnreadRune: expected error, got nil")
|
t.Errorf("UnreadRune: expected error, got nil")
|
||||||
}
|
}
|
||||||
buf, err := ioutil.ReadAll(r)
|
buf, err := io.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("ReadAll: unexpected error: %v", err)
|
t.Errorf("ReadAll: unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -314,7 +313,7 @@ func TestReaderZero(t *testing.T) {
|
||||||
t.Errorf("UnreadRune: got nil, want error")
|
t.Errorf("UnreadRune: got nil, want error")
|
||||||
}
|
}
|
||||||
|
|
||||||
if n, err := (&Reader{}).WriteTo(ioutil.Discard); n != 0 || err != nil {
|
if n, err := (&Reader{}).WriteTo(io.Discard); n != 0 || err != nil {
|
||||||
t.Errorf("WriteTo: got %d, %v; want 0, nil", n, err)
|
t.Errorf("WriteTo: got %d, %v; want 0, nil", n, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -326,6 +326,18 @@ func compareAPI(w io.Writer, features, required, optional, exception []string, a
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// aliasReplacer applies type aliases to earlier API files,
|
||||||
|
// to avoid misleading negative results.
|
||||||
|
// This makes all the references to os.FileInfo in go1.txt
|
||||||
|
// be read as if they said fs.FileInfo, since os.FileInfo is now an alias.
|
||||||
|
// If there are many of these, we could do a more general solution,
|
||||||
|
// but for now the replacer is fine.
|
||||||
|
var aliasReplacer = strings.NewReplacer(
|
||||||
|
"os.FileInfo", "fs.FileInfo",
|
||||||
|
"os.FileMode", "fs.FileMode",
|
||||||
|
"os.PathError", "fs.PathError",
|
||||||
|
)
|
||||||
|
|
||||||
func fileFeatures(filename string) []string {
|
func fileFeatures(filename string) []string {
|
||||||
if filename == "" {
|
if filename == "" {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -334,7 +346,9 @@ func fileFeatures(filename string) []string {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error reading file %s: %v", filename, err)
|
log.Fatalf("Error reading file %s: %v", filename, err)
|
||||||
}
|
}
|
||||||
lines := strings.Split(string(bs), "\n")
|
s := string(bs)
|
||||||
|
s = aliasReplacer.Replace(s)
|
||||||
|
lines := strings.Split(s, "\n")
|
||||||
var nonblank []string
|
var nonblank []string
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
line = strings.TrimSpace(line)
|
line = strings.TrimSpace(line)
|
||||||
|
|
@ -856,6 +870,10 @@ func (w *Walker) emitObj(obj types.Object) {
|
||||||
func (w *Walker) emitType(obj *types.TypeName) {
|
func (w *Walker) emitType(obj *types.TypeName) {
|
||||||
name := obj.Name()
|
name := obj.Name()
|
||||||
typ := obj.Type()
|
typ := obj.Type()
|
||||||
|
if obj.IsAlias() {
|
||||||
|
w.emitf("type %s = %s", name, w.typeString(typ))
|
||||||
|
return
|
||||||
|
}
|
||||||
switch typ := typ.Underlying().(type) {
|
switch typ := typ.Underlying().(type) {
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
w.emitStructType(name, typ)
|
w.emitStructType(name, typ)
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ func (p *Parser) asmText(operands [][]lex.Token) {
|
||||||
// Argsize set below.
|
// Argsize set below.
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
nameAddr.Sym.Func.Text = prog
|
nameAddr.Sym.Func().Text = prog
|
||||||
prog.To.Val = int32(argSize)
|
prog.To.Val = int32(argSize)
|
||||||
p.append(prog, "", true)
|
p.append(prog, "", true)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ func testEndToEnd(t *testing.T, goarch, file string) {
|
||||||
architecture, ctxt := setArch(goarch)
|
architecture, ctxt := setArch(goarch)
|
||||||
architecture.Init(ctxt)
|
architecture.Init(ctxt)
|
||||||
lexer := lex.NewLexer(input)
|
lexer := lex.NewLexer(input)
|
||||||
parser := NewParser(ctxt, architecture, lexer)
|
parser := NewParser(ctxt, architecture, lexer, false)
|
||||||
pList := new(obj.Plist)
|
pList := new(obj.Plist)
|
||||||
var ok bool
|
var ok bool
|
||||||
testOut = new(bytes.Buffer) // The assembler writes test output to this buffer.
|
testOut = new(bytes.Buffer) // The assembler writes test output to this buffer.
|
||||||
|
|
@ -257,11 +257,11 @@ func isHexes(s string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// It would be nice if the error messages began with
|
// It would be nice if the error messages always began with
|
||||||
// the standard file:line: prefix,
|
// the standard file:line: prefix,
|
||||||
// but that's not where we are today.
|
// but that's not where we are today.
|
||||||
// It might be at the beginning but it might be in the middle of the printed instruction.
|
// It might be at the beginning but it might be in the middle of the printed instruction.
|
||||||
var fileLineRE = regexp.MustCompile(`(?:^|\()(testdata[/\\][0-9a-z]+\.s:[0-9]+)(?:$|\))`)
|
var fileLineRE = regexp.MustCompile(`(?:^|\()(testdata[/\\][0-9a-z]+\.s:[0-9]+)(?:$|\)|:)`)
|
||||||
|
|
||||||
// Same as in test/run.go
|
// Same as in test/run.go
|
||||||
var (
|
var (
|
||||||
|
|
@ -273,7 +273,7 @@ func testErrors(t *testing.T, goarch, file string) {
|
||||||
input := filepath.Join("testdata", file+".s")
|
input := filepath.Join("testdata", file+".s")
|
||||||
architecture, ctxt := setArch(goarch)
|
architecture, ctxt := setArch(goarch)
|
||||||
lexer := lex.NewLexer(input)
|
lexer := lex.NewLexer(input)
|
||||||
parser := NewParser(ctxt, architecture, lexer)
|
parser := NewParser(ctxt, architecture, lexer, false)
|
||||||
pList := new(obj.Plist)
|
pList := new(obj.Plist)
|
||||||
var ok bool
|
var ok bool
|
||||||
testOut = new(bytes.Buffer) // The assembler writes test output to this buffer.
|
testOut = new(bytes.Buffer) // The assembler writes test output to this buffer.
|
||||||
|
|
@ -281,6 +281,7 @@ func testErrors(t *testing.T, goarch, file string) {
|
||||||
defer ctxt.Bso.Flush()
|
defer ctxt.Bso.Flush()
|
||||||
failed := false
|
failed := false
|
||||||
var errBuf bytes.Buffer
|
var errBuf bytes.Buffer
|
||||||
|
parser.errorWriter = &errBuf
|
||||||
ctxt.DiagFunc = func(format string, args ...interface{}) {
|
ctxt.DiagFunc = func(format string, args ...interface{}) {
|
||||||
failed = true
|
failed = true
|
||||||
s := fmt.Sprintf(format, args...)
|
s := fmt.Sprintf(format, args...)
|
||||||
|
|
@ -292,7 +293,7 @@ func testErrors(t *testing.T, goarch, file string) {
|
||||||
pList.Firstpc, ok = parser.Parse()
|
pList.Firstpc, ok = parser.Parse()
|
||||||
obj.Flushplist(ctxt, pList, nil, "")
|
obj.Flushplist(ctxt, pList, nil, "")
|
||||||
if ok && !failed {
|
if ok && !failed {
|
||||||
t.Errorf("asm: %s had no errors", goarch)
|
t.Errorf("asm: %s had no errors", file)
|
||||||
}
|
}
|
||||||
|
|
||||||
errors := map[string]string{}
|
errors := map[string]string{}
|
||||||
|
|
@ -368,6 +369,10 @@ func TestARMEndToEnd(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGoBuildErrors(t *testing.T) {
|
||||||
|
testErrors(t, "amd64", "buildtagerror")
|
||||||
|
}
|
||||||
|
|
||||||
func TestARMErrors(t *testing.T) {
|
func TestARMErrors(t *testing.T) {
|
||||||
testErrors(t, "arm", "armerror")
|
testErrors(t, "arm", "armerror")
|
||||||
}
|
}
|
||||||
|
|
@ -437,10 +442,6 @@ func TestPPC64EndToEnd(t *testing.T) {
|
||||||
testEndToEnd(t, "ppc64", "ppc64")
|
testEndToEnd(t, "ppc64", "ppc64")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPPC64Encoder(t *testing.T) {
|
|
||||||
testEndToEnd(t, "ppc64", "ppc64enc")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRISCVEncoder(t *testing.T) {
|
func TestRISCVEncoder(t *testing.T) {
|
||||||
testEndToEnd(t, "riscv64", "riscvenc")
|
testEndToEnd(t, "riscv64", "riscvenc")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ var exprTests = []exprTest{
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExpr(t *testing.T) {
|
func TestExpr(t *testing.T) {
|
||||||
p := NewParser(nil, nil, nil) // Expression evaluation uses none of these fields of the parser.
|
p := NewParser(nil, nil, nil, false) // Expression evaluation uses none of these fields of the parser.
|
||||||
for i, test := range exprTests {
|
for i, test := range exprTests {
|
||||||
p.start(lex.Tokenize(test.input))
|
p.start(lex.Tokenize(test.input))
|
||||||
result := int64(p.expr())
|
result := int64(p.expr())
|
||||||
|
|
@ -113,7 +113,7 @@ func TestBadExpr(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func runBadTest(i int, test badExprTest, t *testing.T) (err error) {
|
func runBadTest(i int, test badExprTest, t *testing.T) (err error) {
|
||||||
p := NewParser(nil, nil, nil) // Expression evaluation uses none of these fields of the parser.
|
p := NewParser(nil, nil, nil, false) // Expression evaluation uses none of these fields of the parser.
|
||||||
p.start(lex.Tokenize(test.input))
|
p.start(lex.Tokenize(test.input))
|
||||||
return tryParse(t, func() {
|
return tryParse(t, func() {
|
||||||
p.expr()
|
p.expr()
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ func testBadInstParser(t *testing.T, goarch string, tests []badInstTest) {
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
arch, ctxt := setArch(goarch)
|
arch, ctxt := setArch(goarch)
|
||||||
tokenizer := lex.NewTokenizer("", strings.NewReader(test.input+"\n"), nil)
|
tokenizer := lex.NewTokenizer("", strings.NewReader(test.input+"\n"), nil)
|
||||||
parser := NewParser(ctxt, arch, tokenizer)
|
parser := NewParser(ctxt, arch, tokenizer, false)
|
||||||
|
|
||||||
err := tryParse(t, func() {
|
err := tryParse(t, func() {
|
||||||
parser.Parse()
|
parser.Parse()
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ func setArch(goarch string) (*arch.Arch, *obj.Link) {
|
||||||
|
|
||||||
func newParser(goarch string) *Parser {
|
func newParser(goarch string) *Parser {
|
||||||
architecture, ctxt := setArch(goarch)
|
architecture, ctxt := setArch(goarch)
|
||||||
return NewParser(ctxt, architecture, nil)
|
return NewParser(ctxt, architecture, nil, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// tryParse executes parse func in panicOnError=true context.
|
// tryParse executes parse func in panicOnError=true context.
|
||||||
|
|
@ -75,7 +75,12 @@ func testOperandParser(t *testing.T, parser *Parser, tests []operandTest) {
|
||||||
parser.start(lex.Tokenize(test.input))
|
parser.start(lex.Tokenize(test.input))
|
||||||
addr := obj.Addr{}
|
addr := obj.Addr{}
|
||||||
parser.operand(&addr)
|
parser.operand(&addr)
|
||||||
result := obj.Dconv(&emptyProg, &addr)
|
var result string
|
||||||
|
if parser.compilingRuntime {
|
||||||
|
result = obj.DconvWithABIDetail(&emptyProg, &addr)
|
||||||
|
} else {
|
||||||
|
result = obj.Dconv(&emptyProg, &addr)
|
||||||
|
}
|
||||||
if result != test.output {
|
if result != test.output {
|
||||||
t.Errorf("fail at %s: got %s; expected %s\n", test.input, result, test.output)
|
t.Errorf("fail at %s: got %s; expected %s\n", test.input, result, test.output)
|
||||||
}
|
}
|
||||||
|
|
@ -86,6 +91,9 @@ func TestAMD64OperandParser(t *testing.T) {
|
||||||
parser := newParser("amd64")
|
parser := newParser("amd64")
|
||||||
testOperandParser(t, parser, amd64OperandTests)
|
testOperandParser(t, parser, amd64OperandTests)
|
||||||
testBadOperandParser(t, parser, amd64BadOperandTests)
|
testBadOperandParser(t, parser, amd64BadOperandTests)
|
||||||
|
parser.compilingRuntime = true
|
||||||
|
testOperandParser(t, parser, amd64RuntimeOperandTests)
|
||||||
|
testBadOperandParser(t, parser, amd64BadOperandRuntimeTests)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test386OperandParser(t *testing.T) {
|
func Test386OperandParser(t *testing.T) {
|
||||||
|
|
@ -141,7 +149,7 @@ func TestFuncAddress(t *testing.T) {
|
||||||
parser := newParser(sub.arch)
|
parser := newParser(sub.arch)
|
||||||
for _, test := range sub.tests {
|
for _, test := range sub.tests {
|
||||||
parser.start(lex.Tokenize(test.input))
|
parser.start(lex.Tokenize(test.input))
|
||||||
name, ok := parser.funcAddress()
|
name, _, ok := parser.funcAddress()
|
||||||
|
|
||||||
isFuncSym := strings.HasSuffix(test.input, "(SB)") &&
|
isFuncSym := strings.HasSuffix(test.input, "(SB)") &&
|
||||||
// Ignore static symbols.
|
// Ignore static symbols.
|
||||||
|
|
@ -298,6 +306,11 @@ var amd64OperandTests = []operandTest{
|
||||||
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
|
{"[):[o-FP", ""}, // Issue 12469 - asm hung parsing the o-FP range on non ARM platforms.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var amd64RuntimeOperandTests = []operandTest{
|
||||||
|
{"$bar<ABI0>(SB)", "$bar<ABI0>(SB)"},
|
||||||
|
{"$foo<ABIInternal>(SB)", "$foo<ABIInternal>(SB)"},
|
||||||
|
}
|
||||||
|
|
||||||
var amd64BadOperandTests = []badOperandTest{
|
var amd64BadOperandTests = []badOperandTest{
|
||||||
{"[", "register list: expected ']', found EOF"},
|
{"[", "register list: expected ']', found EOF"},
|
||||||
{"[4", "register list: bad low register in `[4`"},
|
{"[4", "register list: bad low register in `[4`"},
|
||||||
|
|
@ -311,6 +324,11 @@ var amd64BadOperandTests = []badOperandTest{
|
||||||
{"[X0-X1-X2]", "register list: expected ']' after `[X0-X1`, found '-'"},
|
{"[X0-X1-X2]", "register list: expected ']' after `[X0-X1`, found '-'"},
|
||||||
{"[X0,X3]", "register list: expected '-' after `[X0`, found ','"},
|
{"[X0,X3]", "register list: expected '-' after `[X0`, found ','"},
|
||||||
{"[X0,X1,X2,X3]", "register list: expected '-' after `[X0`, found ','"},
|
{"[X0,X1,X2,X3]", "register list: expected '-' after `[X0`, found ','"},
|
||||||
|
{"$foo<ABI0>", "ABI selector only permitted when compiling runtime, reference was to \"foo\""},
|
||||||
|
}
|
||||||
|
|
||||||
|
var amd64BadOperandRuntimeTests = []badOperandTest{
|
||||||
|
{"$foo<bletch>", "malformed ABI selector \"bletch\" in reference to \"foo\""},
|
||||||
}
|
}
|
||||||
|
|
||||||
var x86OperandTests = []operandTest{
|
var x86OperandTests = []operandTest{
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ type Parser struct {
|
||||||
lineNum int // Line number in source file.
|
lineNum int // Line number in source file.
|
||||||
errorLine int // Line number of last error.
|
errorLine int // Line number of last error.
|
||||||
errorCount int // Number of errors.
|
errorCount int // Number of errors.
|
||||||
|
sawCode bool // saw code in this file (as opposed to comments and blank lines)
|
||||||
pc int64 // virtual PC; count of Progs; doesn't advance for GLOBL or DATA.
|
pc int64 // virtual PC; count of Progs; doesn't advance for GLOBL or DATA.
|
||||||
input []lex.Token
|
input []lex.Token
|
||||||
inputPos int
|
inputPos int
|
||||||
|
|
@ -42,6 +43,7 @@ type Parser struct {
|
||||||
lastProg *obj.Prog
|
lastProg *obj.Prog
|
||||||
dataAddr map[string]int64 // Most recent address for DATA for this symbol.
|
dataAddr map[string]int64 // Most recent address for DATA for this symbol.
|
||||||
isJump bool // Instruction being assembled is a jump.
|
isJump bool // Instruction being assembled is a jump.
|
||||||
|
compilingRuntime bool
|
||||||
errorWriter io.Writer
|
errorWriter io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,7 +52,7 @@ type Patch struct {
|
||||||
label string
|
label string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader) *Parser {
|
func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader, compilingRuntime bool) *Parser {
|
||||||
return &Parser{
|
return &Parser{
|
||||||
ctxt: ctxt,
|
ctxt: ctxt,
|
||||||
arch: ar,
|
arch: ar,
|
||||||
|
|
@ -58,6 +60,7 @@ func NewParser(ctxt *obj.Link, ar *arch.Arch, lexer lex.TokenReader) *Parser {
|
||||||
labels: make(map[string]*obj.Prog),
|
labels: make(map[string]*obj.Prog),
|
||||||
dataAddr: make(map[string]int64),
|
dataAddr: make(map[string]int64),
|
||||||
errorWriter: os.Stderr,
|
errorWriter: os.Stderr,
|
||||||
|
compilingRuntime: compilingRuntime,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -132,6 +135,30 @@ func (p *Parser) ParseSymABIs(w io.Writer) bool {
|
||||||
return p.errorCount == 0
|
return p.errorCount == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nextToken returns the next non-build-comment token from the lexer.
|
||||||
|
// It reports misplaced //go:build comments but otherwise discards them.
|
||||||
|
func (p *Parser) nextToken() lex.ScanToken {
|
||||||
|
for {
|
||||||
|
tok := p.lex.Next()
|
||||||
|
if tok == lex.BuildComment {
|
||||||
|
if p.sawCode {
|
||||||
|
p.errorf("misplaced //go:build comment")
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if tok != '\n' {
|
||||||
|
p.sawCode = true
|
||||||
|
}
|
||||||
|
if tok == '#' {
|
||||||
|
// A leftover wisp of a #include/#define/etc,
|
||||||
|
// to let us know that p.sawCode should be true now.
|
||||||
|
// Otherwise ignored.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return tok
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// line consumes a single assembly line from p.lex of the form
|
// line consumes a single assembly line from p.lex of the form
|
||||||
//
|
//
|
||||||
// {label:} WORD[.cond] [ arg {, arg} ] (';' | '\n')
|
// {label:} WORD[.cond] [ arg {, arg} ] (';' | '\n')
|
||||||
|
|
@ -146,7 +173,7 @@ next:
|
||||||
// Skip newlines.
|
// Skip newlines.
|
||||||
var tok lex.ScanToken
|
var tok lex.ScanToken
|
||||||
for {
|
for {
|
||||||
tok = p.lex.Next()
|
tok = p.nextToken()
|
||||||
// We save the line number here so error messages from this instruction
|
// We save the line number here so error messages from this instruction
|
||||||
// are labeled with this line. Otherwise we complain after we've absorbed
|
// are labeled with this line. Otherwise we complain after we've absorbed
|
||||||
// the terminating newline and the line numbers are off by one in errors.
|
// the terminating newline and the line numbers are off by one in errors.
|
||||||
|
|
@ -179,11 +206,11 @@ next:
|
||||||
items = make([]lex.Token, 0, 3)
|
items = make([]lex.Token, 0, 3)
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
tok = p.lex.Next()
|
tok = p.nextToken()
|
||||||
if len(operands) == 0 && len(items) == 0 {
|
if len(operands) == 0 && len(items) == 0 {
|
||||||
if p.arch.InFamily(sys.ARM, sys.ARM64, sys.AMD64, sys.I386) && tok == '.' {
|
if p.arch.InFamily(sys.ARM, sys.ARM64, sys.AMD64, sys.I386) && tok == '.' {
|
||||||
// Suffixes: ARM conditionals or x86 modifiers.
|
// Suffixes: ARM conditionals or x86 modifiers.
|
||||||
tok = p.lex.Next()
|
tok = p.nextToken()
|
||||||
str := p.lex.Text()
|
str := p.lex.Text()
|
||||||
if tok != scanner.Ident {
|
if tok != scanner.Ident {
|
||||||
p.errorf("instruction suffix expected identifier, found %s", str)
|
p.errorf("instruction suffix expected identifier, found %s", str)
|
||||||
|
|
@ -285,8 +312,8 @@ func (p *Parser) symDefRef(w io.Writer, word string, operands [][]lex.Token) {
|
||||||
// Defines text symbol in operands[0].
|
// Defines text symbol in operands[0].
|
||||||
if len(operands) > 0 {
|
if len(operands) > 0 {
|
||||||
p.start(operands[0])
|
p.start(operands[0])
|
||||||
if name, ok := p.funcAddress(); ok {
|
if name, abi, ok := p.funcAddress(); ok {
|
||||||
fmt.Fprintf(w, "def %s ABI0\n", name)
|
fmt.Fprintf(w, "def %s %s\n", name, abi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
@ -304,8 +331,8 @@ func (p *Parser) symDefRef(w io.Writer, word string, operands [][]lex.Token) {
|
||||||
// Search for symbol references.
|
// Search for symbol references.
|
||||||
for _, op := range operands {
|
for _, op := range operands {
|
||||||
p.start(op)
|
p.start(op)
|
||||||
if name, ok := p.funcAddress(); ok {
|
if name, abi, ok := p.funcAddress(); ok {
|
||||||
fmt.Fprintf(w, "ref %s ABI0\n", name)
|
fmt.Fprintf(w, "ref %s %s\n", name, abi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -740,20 +767,19 @@ func (p *Parser) symbolReference(a *obj.Addr, name string, prefix rune) {
|
||||||
case '*':
|
case '*':
|
||||||
a.Type = obj.TYPE_INDIR
|
a.Type = obj.TYPE_INDIR
|
||||||
}
|
}
|
||||||
// Weirdness with statics: Might now have "<>".
|
|
||||||
isStatic := false
|
// Parse optional <> (indicates a static symbol) or
|
||||||
if p.peek() == '<' {
|
// <ABIxxx> (selecting text symbol with specific ABI).
|
||||||
isStatic = true
|
doIssueError := true
|
||||||
p.next()
|
isStatic, abi := p.symRefAttrs(name, doIssueError)
|
||||||
p.get('>')
|
|
||||||
}
|
|
||||||
if p.peek() == '+' || p.peek() == '-' {
|
if p.peek() == '+' || p.peek() == '-' {
|
||||||
a.Offset = int64(p.expr())
|
a.Offset = int64(p.expr())
|
||||||
}
|
}
|
||||||
if isStatic {
|
if isStatic {
|
||||||
a.Sym = p.ctxt.LookupStatic(name)
|
a.Sym = p.ctxt.LookupStatic(name)
|
||||||
} else {
|
} else {
|
||||||
a.Sym = p.ctxt.Lookup(name)
|
a.Sym = p.ctxt.LookupABI(name, abi)
|
||||||
}
|
}
|
||||||
if p.peek() == scanner.EOF {
|
if p.peek() == scanner.EOF {
|
||||||
if prefix == 0 && p.isJump {
|
if prefix == 0 && p.isJump {
|
||||||
|
|
@ -798,12 +824,60 @@ func (p *Parser) setPseudoRegister(addr *obj.Addr, reg string, isStatic bool, pr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// symRefAttrs parses an optional function symbol attribute clause for
|
||||||
|
// the function symbol 'name', logging an error for a malformed
|
||||||
|
// attribute clause if 'issueError' is true. The return value is a
|
||||||
|
// (boolean, ABI) pair indicating that the named symbol is either
|
||||||
|
// static or a particular ABI specification.
|
||||||
|
//
|
||||||
|
// The expected form of the attribute clause is:
|
||||||
|
//
|
||||||
|
// empty, yielding (false, obj.ABI0)
|
||||||
|
// "<>", yielding (true, obj.ABI0)
|
||||||
|
// "<ABI0>" yielding (false, obj.ABI0)
|
||||||
|
// "<ABIInternal>" yielding (false, obj.ABIInternal)
|
||||||
|
//
|
||||||
|
// Anything else beginning with "<" logs an error if issueError is
|
||||||
|
// true, otherwise returns (false, obj.ABI0).
|
||||||
|
//
|
||||||
|
func (p *Parser) symRefAttrs(name string, issueError bool) (bool, obj.ABI) {
|
||||||
|
abi := obj.ABI0
|
||||||
|
isStatic := false
|
||||||
|
if p.peek() != '<' {
|
||||||
|
return isStatic, abi
|
||||||
|
}
|
||||||
|
p.next()
|
||||||
|
tok := p.peek()
|
||||||
|
if tok == '>' {
|
||||||
|
isStatic = true
|
||||||
|
} else if tok == scanner.Ident {
|
||||||
|
abistr := p.get(scanner.Ident).String()
|
||||||
|
if !p.compilingRuntime {
|
||||||
|
if issueError {
|
||||||
|
p.errorf("ABI selector only permitted when compiling runtime, reference was to %q", name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
theabi, valid := obj.ParseABI(abistr)
|
||||||
|
if !valid {
|
||||||
|
if issueError {
|
||||||
|
p.errorf("malformed ABI selector %q in reference to %q",
|
||||||
|
abistr, name)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
abi = theabi
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.get('>')
|
||||||
|
return isStatic, abi
|
||||||
|
}
|
||||||
|
|
||||||
// funcAddress parses an external function address. This is a
|
// funcAddress parses an external function address. This is a
|
||||||
// constrained form of the operand syntax that's always SB-based,
|
// constrained form of the operand syntax that's always SB-based,
|
||||||
// non-static, and has at most a simple integer offset:
|
// non-static, and has at most a simple integer offset:
|
||||||
//
|
//
|
||||||
// [$|*]sym[+Int](SB)
|
// [$|*]sym[<abi>][+Int](SB)
|
||||||
func (p *Parser) funcAddress() (string, bool) {
|
func (p *Parser) funcAddress() (string, obj.ABI, bool) {
|
||||||
switch p.peek() {
|
switch p.peek() {
|
||||||
case '$', '*':
|
case '$', '*':
|
||||||
// Skip prefix.
|
// Skip prefix.
|
||||||
|
|
@ -813,25 +887,32 @@ func (p *Parser) funcAddress() (string, bool) {
|
||||||
tok := p.next()
|
tok := p.next()
|
||||||
name := tok.String()
|
name := tok.String()
|
||||||
if tok.ScanToken != scanner.Ident || p.atStartOfRegister(name) {
|
if tok.ScanToken != scanner.Ident || p.atStartOfRegister(name) {
|
||||||
return "", false
|
return "", obj.ABI0, false
|
||||||
|
}
|
||||||
|
// Parse optional <> (indicates a static symbol) or
|
||||||
|
// <ABIxxx> (selecting text symbol with specific ABI).
|
||||||
|
noErrMsg := false
|
||||||
|
isStatic, abi := p.symRefAttrs(name, noErrMsg)
|
||||||
|
if isStatic {
|
||||||
|
return "", obj.ABI0, false // This function rejects static symbols.
|
||||||
}
|
}
|
||||||
tok = p.next()
|
tok = p.next()
|
||||||
if tok.ScanToken == '+' {
|
if tok.ScanToken == '+' {
|
||||||
if p.next().ScanToken != scanner.Int {
|
if p.next().ScanToken != scanner.Int {
|
||||||
return "", false
|
return "", obj.ABI0, false
|
||||||
}
|
}
|
||||||
tok = p.next()
|
tok = p.next()
|
||||||
}
|
}
|
||||||
if tok.ScanToken != '(' {
|
if tok.ScanToken != '(' {
|
||||||
return "", false
|
return "", obj.ABI0, false
|
||||||
}
|
}
|
||||||
if reg := p.next(); reg.ScanToken != scanner.Ident || reg.String() != "SB" {
|
if reg := p.next(); reg.ScanToken != scanner.Ident || reg.String() != "SB" {
|
||||||
return "", false
|
return "", obj.ABI0, false
|
||||||
}
|
}
|
||||||
if p.next().ScanToken != ')' || p.peek() != scanner.EOF {
|
if p.next().ScanToken != ')' || p.peek() != scanner.EOF {
|
||||||
return "", false
|
return "", obj.ABI0, false
|
||||||
}
|
}
|
||||||
return name, true
|
return name, abi, true
|
||||||
}
|
}
|
||||||
|
|
||||||
// registerIndirect parses the general form of a register indirection.
|
// registerIndirect parses the general form of a register indirection.
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ func TestErroneous(t *testing.T) {
|
||||||
{"TEXT", "$0É:0, 0, $1", "expected end of operand, found É"}, // Issue #12467.
|
{"TEXT", "$0É:0, 0, $1", "expected end of operand, found É"}, // Issue #12467.
|
||||||
{"TEXT", "$:0:(SB, 0, $1", "expected '(', found 0"}, // Issue 12468.
|
{"TEXT", "$:0:(SB, 0, $1", "expected '(', found 0"}, // Issue 12468.
|
||||||
{"TEXT", "@B(SB),0,$0", "expected '(', found B"}, // Issue 23580.
|
{"TEXT", "@B(SB),0,$0", "expected '(', found B"}, // Issue 23580.
|
||||||
|
{"TEXT", "foo<ABIInternal>(SB),0", "ABI selector only permitted when compiling runtime, reference was to \"foo\""},
|
||||||
{"FUNCDATA", "", "expect two operands for FUNCDATA"},
|
{"FUNCDATA", "", "expect two operands for FUNCDATA"},
|
||||||
{"FUNCDATA", "(SB ", "expect two operands for FUNCDATA"},
|
{"FUNCDATA", "(SB ", "expect two operands for FUNCDATA"},
|
||||||
{"DATA", "", "expect two operands for DATA"},
|
{"DATA", "", "expect two operands for DATA"},
|
||||||
|
|
|
||||||
8
src/cmd/asm/internal/asm/testdata/buildtagerror.s
vendored
Normal file
8
src/cmd/asm/internal/asm/testdata/buildtagerror.s
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
// Copyright 2020 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#define X 1
|
||||||
|
|
||||||
|
//go:build x // ERROR "misplaced //go:build comment"
|
||||||
|
|
||||||
2002
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
2002
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
File diff suppressed because it is too large
Load diff
642
src/cmd/asm/internal/asm/testdata/ppc64enc.s
vendored
642
src/cmd/asm/internal/asm/testdata/ppc64enc.s
vendored
|
|
@ -1,642 +0,0 @@
|
||||||
// Copyright 2018 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.
|
|
||||||
|
|
||||||
// Initial set of opcode combinations based on
|
|
||||||
// improvements to processing of constant
|
|
||||||
// operands.
|
|
||||||
|
|
||||||
// Full set will be added at a later date.
|
|
||||||
|
|
||||||
#include "../../../../../runtime/textflag.h"
|
|
||||||
|
|
||||||
TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
|
||||||
// move constants
|
|
||||||
MOVD $1, R3 // 38600001
|
|
||||||
MOVD $-1, R4 // 3880ffff
|
|
||||||
MOVD $65535, R5 // 6005ffff
|
|
||||||
MOVD $65536, R6 // 64060001
|
|
||||||
MOVD $-32767, R5 // 38a08001
|
|
||||||
MOVD $-32768, R6 // 38c08000
|
|
||||||
MOVD $1234567, R5 // 6405001260a5d687
|
|
||||||
MOVW $1, R3 // 38600001
|
|
||||||
MOVW $-1, R4 // 3880ffff
|
|
||||||
MOVW $65535, R5 // 6005ffff
|
|
||||||
MOVW $65536, R6 // 64060001
|
|
||||||
MOVW $-32767, R5 // 38a08001
|
|
||||||
MOVW $-32768, R6 // 38c08000
|
|
||||||
MOVW $1234567, R5 // 6405001260a5d687
|
|
||||||
MOVD 8(R3), R4 // e8830008
|
|
||||||
MOVD (R3)(R4), R5 // 7ca4182a
|
|
||||||
MOVW 4(R3), R4 // e8830006
|
|
||||||
MOVW (R3)(R4), R5 // 7ca41aaa
|
|
||||||
MOVWZ 4(R3), R4 // 80830004
|
|
||||||
MOVWZ (R3)(R4), R5 // 7ca4182e
|
|
||||||
MOVH 4(R3), R4 // a8830004
|
|
||||||
MOVH (R3)(R4), R5 // 7ca41aae
|
|
||||||
MOVHZ 2(R3), R4 // a0830002
|
|
||||||
MOVHZ (R3)(R4), R5 // 7ca41a2e
|
|
||||||
MOVB 1(R3), R4 // 888300017c840774
|
|
||||||
MOVB (R3)(R4), R5 // 7ca418ae7ca50774
|
|
||||||
MOVBZ 1(R3), R4 // 88830001
|
|
||||||
MOVBZ (R3)(R4), R5 // 7ca418ae
|
|
||||||
MOVDBR (R3)(R4), R5 // 7ca41c28
|
|
||||||
MOVWBR (R3)(R4), R5 // 7ca41c2c
|
|
||||||
MOVHBR (R3)(R4), R5 // 7ca41e2c
|
|
||||||
|
|
||||||
MOVDU 8(R3), R4 // e8830009
|
|
||||||
MOVDU (R3)(R4), R5 // 7ca4186a
|
|
||||||
MOVWU (R3)(R4), R5 // 7ca41aea
|
|
||||||
MOVWZU 4(R3), R4 // 84830004
|
|
||||||
MOVWZU (R3)(R4), R5 // 7ca4186e
|
|
||||||
MOVHU 2(R3), R4 // ac830002
|
|
||||||
MOVHU (R3)(R4), R5 // 7ca41aee
|
|
||||||
MOVHZU 2(R3), R4 // a4830002
|
|
||||||
MOVHZU (R3)(R4), R5 // 7ca41a6e
|
|
||||||
MOVBU 1(R3), R4 // 8c8300017c840774
|
|
||||||
MOVBU (R3)(R4), R5 // 7ca418ee7ca50774
|
|
||||||
MOVBZU 1(R3), R4 // 8c830001
|
|
||||||
MOVBZU (R3)(R4), R5 // 7ca418ee
|
|
||||||
|
|
||||||
MOVD R4, 8(R3) // f8830008
|
|
||||||
MOVD R5, (R3)(R4) // 7ca4192a
|
|
||||||
MOVW R4, 4(R3) // 90830004
|
|
||||||
MOVW R5, (R3)(R4) // 7ca4192e
|
|
||||||
MOVH R4, 2(R3) // b0830002
|
|
||||||
MOVH R5, (R3)(R4) // 7ca41b2e
|
|
||||||
MOVB R4, 1(R3) // 98830001
|
|
||||||
MOVB R5, (R3)(R4) // 7ca419ae
|
|
||||||
MOVDBR R5, (R3)(R4) // 7ca41d28
|
|
||||||
MOVWBR R5, (R3)(R4) // 7ca41d2c
|
|
||||||
MOVHBR R5, (R3)(R4) // 7ca41f2c
|
|
||||||
|
|
||||||
MOVDU R4, 8(R3) // f8830009
|
|
||||||
MOVDU R5, (R3)(R4) // 7ca4196a
|
|
||||||
MOVWU R4, 4(R3) // 94830004
|
|
||||||
MOVWU R5, (R3)(R4) // 7ca4196e
|
|
||||||
MOVHU R4, 2(R3) // b4830002
|
|
||||||
MOVHU R5, (R3)(R4) // 7ca41b6e
|
|
||||||
MOVBU R4, 1(R3) // 9c830001
|
|
||||||
MOVBU R5, (R3)(R4) // 7ca419ee
|
|
||||||
|
|
||||||
ADD $1, R3 // 38630001
|
|
||||||
ADD $1, R3, R4 // 38830001
|
|
||||||
ADD $-1, R4 // 3884ffff
|
|
||||||
ADD $-1, R4, R5 // 38a4ffff
|
|
||||||
ADD $65535, R5 // 601fffff7cbf2a14
|
|
||||||
ADD $65535, R5, R6 // 601fffff7cdf2a14
|
|
||||||
ADD $65536, R6 // 3cc60001
|
|
||||||
ADD $65536, R6, R7 // 3ce60001
|
|
||||||
ADD $-32767, R5 // 38a58001
|
|
||||||
ADD $-32767, R5, R4 // 38858001
|
|
||||||
ADD $-32768, R6 // 38c68000
|
|
||||||
ADD $-32768, R6, R5 // 38a68000
|
|
||||||
ADD $1234567, R5 // 641f001263ffd6877cbf2a14
|
|
||||||
ADD $1234567, R5, R6 // 641f001263ffd6877cdf2a14
|
|
||||||
ADDIS $8, R3 // 3c630008
|
|
||||||
ADDIS $1000, R3, R4 // 3c8303e8
|
|
||||||
|
|
||||||
ANDCC $1, R3 // 70630001
|
|
||||||
ANDCC $1, R3, R4 // 70640001
|
|
||||||
ANDCC $-1, R4 // 3be0ffff7fe42039
|
|
||||||
ANDCC $-1, R4, R5 // 3be0ffff7fe52039
|
|
||||||
ANDCC $65535, R5 // 70a5ffff
|
|
||||||
ANDCC $65535, R5, R6 // 70a6ffff
|
|
||||||
ANDCC $65536, R6 // 74c60001
|
|
||||||
ANDCC $65536, R6, R7 // 74c70001
|
|
||||||
ANDCC $-32767, R5 // 3be080017fe52839
|
|
||||||
ANDCC $-32767, R5, R4 // 3be080017fe42839
|
|
||||||
ANDCC $-32768, R6 // 3be080007fe63039
|
|
||||||
ANDCC $-32768, R5, R6 // 3be080007fe62839
|
|
||||||
ANDCC $1234567, R5 // 641f001263ffd6877fe52839
|
|
||||||
ANDCC $1234567, R5, R6 // 641f001263ffd6877fe62839
|
|
||||||
ANDISCC $1, R3 // 74630001
|
|
||||||
ANDISCC $1000, R3, R4 // 746403e8
|
|
||||||
|
|
||||||
OR $1, R3 // 60630001
|
|
||||||
OR $1, R3, R4 // 60640001
|
|
||||||
OR $-1, R4 // 3be0ffff7fe42378
|
|
||||||
OR $-1, R4, R5 // 3be0ffff7fe52378
|
|
||||||
OR $65535, R5 // 60a5ffff
|
|
||||||
OR $65535, R5, R6 // 60a6ffff
|
|
||||||
OR $65536, R6 // 64c60001
|
|
||||||
OR $65536, R6, R7 // 64c70001
|
|
||||||
OR $-32767, R5 // 3be080017fe52b78
|
|
||||||
OR $-32767, R5, R6 // 3be080017fe62b78
|
|
||||||
OR $-32768, R6 // 3be080007fe63378
|
|
||||||
OR $-32768, R6, R7 // 3be080007fe73378
|
|
||||||
OR $1234567, R5 // 641f001263ffd6877fe52b78
|
|
||||||
OR $1234567, R5, R3 // 641f001263ffd6877fe32b78
|
|
||||||
|
|
||||||
XOR $1, R3 // 68630001
|
|
||||||
XOR $1, R3, R4 // 68640001
|
|
||||||
XOR $-1, R4 // 3be0ffff7fe42278
|
|
||||||
XOR $-1, R4, R5 // 3be0ffff7fe52278
|
|
||||||
XOR $65535, R5 // 68a5ffff
|
|
||||||
XOR $65535, R5, R6 // 68a6ffff
|
|
||||||
XOR $65536, R6 // 6cc60001
|
|
||||||
XOR $65536, R6, R7 // 6cc70001
|
|
||||||
XOR $-32767, R5 // 3be080017fe52a78
|
|
||||||
XOR $-32767, R5, R6 // 3be080017fe62a78
|
|
||||||
XOR $-32768, R6 // 3be080007fe63278
|
|
||||||
XOR $-32768, R6, R7 // 3be080007fe73278
|
|
||||||
XOR $1234567, R5 // 641f001263ffd6877fe52a78
|
|
||||||
XOR $1234567, R5, R3 // 641f001263ffd6877fe32a78
|
|
||||||
|
|
||||||
// TODO: the order of CR operands don't match
|
|
||||||
CMP R3, R4 // 7c232000
|
|
||||||
CMPU R3, R4 // 7c232040
|
|
||||||
CMPW R3, R4 // 7c032000
|
|
||||||
CMPWU R3, R4 // 7c032040
|
|
||||||
|
|
||||||
// TODO: constants for ADDC?
|
|
||||||
ADD R3, R4 // 7c841a14
|
|
||||||
ADD R3, R4, R5 // 7ca41a14
|
|
||||||
ADDC R3, R4 // 7c841814
|
|
||||||
ADDC R3, R4, R5 // 7ca41814
|
|
||||||
ADDE R3, R4 // 7c841914
|
|
||||||
ADDECC R3, R4 // 7c841915
|
|
||||||
ADDEV R3, R4 // 7c841d14
|
|
||||||
ADDEVCC R3, R4 // 7c841d15
|
|
||||||
ADDV R3, R4 // 7c841e14
|
|
||||||
ADDVCC R3, R4 // 7c841e15
|
|
||||||
ADDCCC R3, R4, R5 // 7ca41815
|
|
||||||
ADDME R3, R4 // 7c8301d4
|
|
||||||
ADDMECC R3, R4 // 7c8301d5
|
|
||||||
ADDMEV R3, R4 // 7c8305d4
|
|
||||||
ADDMEVCC R3, R4 // 7c8305d5
|
|
||||||
ADDCV R3, R4 // 7c841c14
|
|
||||||
ADDCVCC R3, R4 // 7c841c15
|
|
||||||
ADDZE R3, R4 // 7c830194
|
|
||||||
ADDZECC R3, R4 // 7c830195
|
|
||||||
ADDZEV R3, R4 // 7c830594
|
|
||||||
ADDZEVCC R3, R4 // 7c830595
|
|
||||||
SUBME R3, R4 // 7c8301d0
|
|
||||||
SUBMECC R3, R4 // 7c8301d1
|
|
||||||
SUBMEV R3, R4 // 7c8305d0
|
|
||||||
SUBZE R3, R4 // 7c830190
|
|
||||||
SUBZECC R3, R4 // 7c830191
|
|
||||||
SUBZEV R3, R4 // 7c830590
|
|
||||||
SUBZEVCC R3, R4 // 7c830591
|
|
||||||
|
|
||||||
AND R3, R4 // 7c841838
|
|
||||||
AND R3, R4, R5 // 7c851838
|
|
||||||
ANDN R3, R4, R5 // 7c851878
|
|
||||||
ANDCC R3, R4, R5 // 7c851839
|
|
||||||
OR R3, R4 // 7c841b78
|
|
||||||
OR R3, R4, R5 // 7c851b78
|
|
||||||
ORN R3, R4, R5 // 7c851b38
|
|
||||||
ORCC R3, R4, R5 // 7c851b79
|
|
||||||
XOR R3, R4 // 7c841a78
|
|
||||||
XOR R3, R4, R5 // 7c851a78
|
|
||||||
XORCC R3, R4, R5 // 7c851a79
|
|
||||||
NAND R3, R4, R5 // 7c851bb8
|
|
||||||
NANDCC R3, R4, R5 // 7c851bb9
|
|
||||||
EQV R3, R4, R5 // 7c851a38
|
|
||||||
EQVCC R3, R4, R5 // 7c851a39
|
|
||||||
NOR R3, R4, R5 // 7c8518f8
|
|
||||||
NORCC R3, R4, R5 // 7c8518f9
|
|
||||||
|
|
||||||
SUB R3, R4 // 7c832050
|
|
||||||
SUB R3, R4, R5 // 7ca32050
|
|
||||||
SUBC R3, R4 // 7c832010
|
|
||||||
SUBC R3, R4, R5 // 7ca32010
|
|
||||||
|
|
||||||
MULLW R3, R4 // 7c8419d6
|
|
||||||
MULLW R3, R4, R5 // 7ca419d6
|
|
||||||
MULLW $10, R3 // 1c63000a
|
|
||||||
MULLW $10000000, R3 // 641f009863ff96807c7f19d6
|
|
||||||
MULLWCC R3, R4, R5 // 7ca419d7
|
|
||||||
MULHW R3, R4, R5 // 7ca41896
|
|
||||||
|
|
||||||
MULHWU R3, R4, R5 // 7ca41816
|
|
||||||
MULLD R3, R4 // 7c8419d2
|
|
||||||
MULLD R4, R4, R5 // 7ca421d2
|
|
||||||
MULLD $20, R4 // 1c840014
|
|
||||||
MULLD $200000000, R4 // 641f0beb63ffc2007c9f21d2
|
|
||||||
MULLDCC R3, R4, R5 // 7ca419d3
|
|
||||||
MULHD R3, R4, R5 // 7ca41892
|
|
||||||
MULHDCC R3, R4, R5 // 7ca41893
|
|
||||||
|
|
||||||
MULLWV R3, R4 // 7c841dd6
|
|
||||||
MULLWV R3, R4, R5 // 7ca41dd6
|
|
||||||
MULLWVCC R3, R4, R5 // 7ca41dd7
|
|
||||||
MULHWUCC R3, R4, R5 // 7ca41817
|
|
||||||
MULLDV R3, R4, R5 // 7ca41dd2
|
|
||||||
MULLDVCC R3, R4, R5 // 7ca41dd3
|
|
||||||
|
|
||||||
DIVD R3,R4 // 7c841bd2
|
|
||||||
DIVD R3, R4, R5 // 7ca41bd2
|
|
||||||
DIVDCC R3,R4, R5 // 7ca41bd3
|
|
||||||
DIVDU R3, R4, R5 // 7ca41b92
|
|
||||||
DIVDV R3, R4, R5 // 7ca41fd2
|
|
||||||
DIVDUCC R3, R4, R5 // 7ca41b93
|
|
||||||
DIVDVCC R3, R4, R5 // 7ca41fd3
|
|
||||||
DIVDUV R3, R4, R5 // 7ca41f92
|
|
||||||
DIVDUVCC R3, R4, R5 // 7ca41f93
|
|
||||||
DIVDE R3, R4, R5 // 7ca41b52
|
|
||||||
DIVDECC R3, R4, R5 // 7ca41b53
|
|
||||||
DIVDEU R3, R4, R5 // 7ca41b12
|
|
||||||
DIVDEUCC R3, R4, R5 // 7ca41b13
|
|
||||||
|
|
||||||
REM R3, R4, R5 // 7fe41bd67fff19d67cbf2050
|
|
||||||
REMU R3, R4, R5 // 7fe41b967fff19d67bff00287cbf2050
|
|
||||||
REMD R3, R4, R5 // 7fe41bd27fff19d27cbf2050
|
|
||||||
REMDU R3, R4, R5 // 7fe41b927fff19d27cbf2050
|
|
||||||
|
|
||||||
MODUD R3, R4, R5 // 7ca41a12
|
|
||||||
MODUW R3, R4, R5 // 7ca41a16
|
|
||||||
MODSD R3, R4, R5 // 7ca41e12
|
|
||||||
MODSW R3, R4, R5 // 7ca41e16
|
|
||||||
|
|
||||||
SLW $8, R3, R4 // 5464402e
|
|
||||||
SLW R3, R4, R5 // 7c851830
|
|
||||||
SLWCC R3, R4 // 7c841831
|
|
||||||
SLD $16, R3, R4 // 786483e4
|
|
||||||
SLD R3, R4, R5 // 7c851836
|
|
||||||
SLDCC R3, R4 // 7c841837
|
|
||||||
|
|
||||||
SRW $8, R3, R4 // 5464c23e
|
|
||||||
SRW R3, R4, R5 // 7c851c30
|
|
||||||
SRWCC R3, R4 // 7c841c31
|
|
||||||
SRAW $8, R3, R4 // 7c644670
|
|
||||||
SRAW R3, R4, R5 // 7c851e30
|
|
||||||
SRAWCC R3, R4 // 7c841e31
|
|
||||||
SRD $16, R3, R4 // 78648402
|
|
||||||
SRD R3, R4, R5 // 7c851c36
|
|
||||||
SRDCC R3, R4 // 7c841c37
|
|
||||||
SRAD $16, R3, R4 // 7c648674
|
|
||||||
SRAD R3, R4, R5 // 7c851e34
|
|
||||||
SRDCC R3, R4 // 7c841c37
|
|
||||||
ROTLW $16, R3, R4 // 5464803e
|
|
||||||
ROTLW R3, R4, R5 // 5c85183e
|
|
||||||
EXTSWSLI $3, R4, R5 // 7c851ef4
|
|
||||||
RLWMI $7, R3, $65535, R6 // 50663c3e
|
|
||||||
RLWMICC $7, R3, $65535, R6 // 50663c3f
|
|
||||||
RLWNM $3, R4, $7, R6 // 54861f7e
|
|
||||||
RLWNMCC $3, R4, $7, R6 // 54861f7f
|
|
||||||
RLDMI $0, R4, $7, R6 // 7886076c
|
|
||||||
RLDMICC $0, R4, $7, R6 // 7886076d
|
|
||||||
RLDIMI $0, R4, $7, R6 // 788601cc
|
|
||||||
RLDIMICC $0, R4, $7, R6 // 788601cd
|
|
||||||
RLDC $0, R4, $15, R6 // 78860728
|
|
||||||
RLDCCC $0, R4, $15, R6 // 78860729
|
|
||||||
RLDCL $0, R4, $7, R6 // 78860770
|
|
||||||
RLDCLCC $0, R4, $15, R6 // 78860721
|
|
||||||
RLDCR $0, R4, $-16, R6 // 788606f2
|
|
||||||
RLDCRCC $0, R4, $-16, R6 // 788606f3
|
|
||||||
RLDICL $0, R4, $15, R6 // 788603c0
|
|
||||||
RLDICLCC $0, R4, $15, R6 // 788603c1
|
|
||||||
RLDICR $0, R4, $15, R6 // 788603c4
|
|
||||||
RLDICRCC $0, R4, $15, R6 // 788603c5
|
|
||||||
RLDIC $0, R4, $15, R6 // 788603c8
|
|
||||||
RLDICCC $0, R4, $15, R6 // 788603c9
|
|
||||||
CLRLSLWI $8, R5, $6, R4 // 54a430b2
|
|
||||||
CLRLSLDI $24, R4, $4, R3 // 78832508
|
|
||||||
|
|
||||||
BEQ 0(PC) // 41820000
|
|
||||||
BGE 0(PC) // 40800000
|
|
||||||
BGT 4(PC) // 41810030
|
|
||||||
BLE 0(PC) // 40810000
|
|
||||||
BLT 0(PC) // 41800000
|
|
||||||
BNE 0(PC) // 40820000
|
|
||||||
JMP 8(PC) // 48000020
|
|
||||||
|
|
||||||
CRAND CR1, CR2, CR3 // 4c620a02
|
|
||||||
CRANDN CR1, CR2, CR3 // 4c620902
|
|
||||||
CREQV CR1, CR2, CR3 // 4c620a42
|
|
||||||
CRNAND CR1, CR2, CR3 // 4c6209c2
|
|
||||||
CRNOR CR1, CR2, CR3 // 4c620842
|
|
||||||
CROR CR1, CR2, CR3 // 4c620b82
|
|
||||||
CRORN CR1, CR2, CR3 // 4c620b42
|
|
||||||
CRXOR CR1, CR2, CR3 // 4c620982
|
|
||||||
|
|
||||||
ISEL $1, R3, R4, R5 // 7ca3205e
|
|
||||||
ISEL $0, R3, R4, R5 // 7ca3201e
|
|
||||||
ISEL $2, R3, R4, R5 // 7ca3209e
|
|
||||||
ISEL $3, R3, R4, R5 // 7ca320de
|
|
||||||
ISEL $4, R3, R4, R5 // 7ca3211e
|
|
||||||
POPCNTB R3, R4 // 7c6400f4
|
|
||||||
POPCNTW R3, R4 // 7c6402f4
|
|
||||||
POPCNTD R3, R4 // 7c6403f4
|
|
||||||
|
|
||||||
PASTECC R3, R4 // 7c23270d
|
|
||||||
COPY R3, R4 // 7c23260c
|
|
||||||
|
|
||||||
// load-and-reserve
|
|
||||||
LBAR (R4)(R3*1),$1,R5 // 7ca32069
|
|
||||||
LBAR (R4),$0,R5 // 7ca02068
|
|
||||||
LBAR (R3),R5 // 7ca01868
|
|
||||||
LHAR (R4)(R3*1),$1,R5 // 7ca320e9
|
|
||||||
LHAR (R4),$0,R5 // 7ca020e8
|
|
||||||
LHAR (R3),R5 // 7ca018e8
|
|
||||||
LWAR (R4)(R3*1),$1,R5 // 7ca32029
|
|
||||||
LWAR (R4),$0,R5 // 7ca02028
|
|
||||||
LWAR (R3),R5 // 7ca01828
|
|
||||||
LDAR (R4)(R3*1),$1,R5 // 7ca320a9
|
|
||||||
LDAR (R4),$0,R5 // 7ca020a8
|
|
||||||
LDAR (R3),R5 // 7ca018a8
|
|
||||||
|
|
||||||
STBCCC R3, (R4)(R5) // 7c65256d
|
|
||||||
STWCCC R3, (R4)(R5) // 7c65212d
|
|
||||||
STDCCC R3, (R4)(R5) // 7c6521ad
|
|
||||||
STHCCC R3, (R4)(R5)
|
|
||||||
|
|
||||||
SYNC // 7c0004ac
|
|
||||||
ISYNC // 4c00012c
|
|
||||||
LWSYNC // 7c2004ac
|
|
||||||
|
|
||||||
DCBF (R3)(R4) // 7c0418ac
|
|
||||||
DCBI (R3)(R4) // 7c041bac
|
|
||||||
DCBST (R3)(R4) // 7c04186c
|
|
||||||
DCBZ (R3)(R4) // 7c041fec
|
|
||||||
DCBT (R3)(R4) // 7c041a2c
|
|
||||||
ICBI (R3)(R4) // 7c041fac
|
|
||||||
|
|
||||||
// float constants
|
|
||||||
FMOVD $(0.0), F1 // f0210cd0
|
|
||||||
FMOVD $(-0.0), F1 // f0210cd0fc200850
|
|
||||||
|
|
||||||
FMOVD 8(R3), F1 // c8230008
|
|
||||||
FMOVD (R3)(R4), F1 // 7c241cae
|
|
||||||
FMOVDU 8(R3), F1 // cc230008
|
|
||||||
FMOVDU (R3)(R4), F1 // 7c241cee
|
|
||||||
FMOVS 4(R3), F1 // c0230004
|
|
||||||
FMOVS (R3)(R4), F1 // 7c241c2e
|
|
||||||
FMOVSU 4(R3), F1 // c4230004
|
|
||||||
FMOVSU (R3)(R4), F1 // 7c241c6e
|
|
||||||
|
|
||||||
FMOVD F1, 8(R3) // d8230008
|
|
||||||
FMOVD F1, (R3)(R4) // 7c241dae
|
|
||||||
FMOVDU F1, 8(R3) // dc230008
|
|
||||||
FMOVDU F1, (R3)(R4) // 7c241dee
|
|
||||||
FMOVS F1, 4(R3) // d0230004
|
|
||||||
FMOVS F1, (R3)(R4) // 7c241d2e
|
|
||||||
FMOVSU F1, 4(R3) // d4230004
|
|
||||||
FMOVSU F1, (R3)(R4) // 7c241d6e
|
|
||||||
FADD F1, F2 // fc42082a
|
|
||||||
FADD F1, F2, F3 // fc62082a
|
|
||||||
FADDCC F1, F2, F3 // fc62082b
|
|
||||||
FADDS F1, F2 // ec42082a
|
|
||||||
FADDS F1, F2, F3 // ec62082a
|
|
||||||
FADDSCC F1, F2, F3 // ec62082b
|
|
||||||
FSUB F1, F2 // fc420828
|
|
||||||
FSUB F1, F2, F3 // fc620828
|
|
||||||
FSUBCC F1, F2, F3 // fc620829
|
|
||||||
FSUBS F1, F2 // ec420828
|
|
||||||
FSUBS F1, F2, F3 // ec620828
|
|
||||||
FSUBCC F1, F2, F3 // fc620829
|
|
||||||
FMUL F1, F2 // fc420072
|
|
||||||
FMUL F1, F2, F3 // fc620072
|
|
||||||
FMULCC F1, F2, F3 // fc620073
|
|
||||||
FMULS F1, F2 // ec420072
|
|
||||||
FMULS F1, F2, F3 // ec620072
|
|
||||||
FMULSCC F1, F2, F3 // ec620073
|
|
||||||
FDIV F1, F2 // fc420824
|
|
||||||
FDIV F1, F2, F3 // fc620824
|
|
||||||
FDIVCC F1, F2, F3 // fc620825
|
|
||||||
FDIVS F1, F2 // ec420824
|
|
||||||
FDIVS F1, F2, F3 // ec620824
|
|
||||||
FDIVSCC F1, F2, F3 // ec620825
|
|
||||||
FMADD F1, F2, F3, F4 // fc8110fa
|
|
||||||
FMADDCC F1, F2, F3, F4 // fc8110fb
|
|
||||||
FMADDS F1, F2, F3, F4 // ec8110fa
|
|
||||||
FMADDSCC F1, F2, F3, F4 // ec8110fb
|
|
||||||
FMSUB F1, F2, F3, F4 // fc8110f8
|
|
||||||
FMSUBCC F1, F2, F3, F4 // fc8110f9
|
|
||||||
FMSUBS F1, F2, F3, F4 // ec8110f8
|
|
||||||
FMSUBSCC F1, F2, F3, F4 // ec8110f9
|
|
||||||
FNMADD F1, F2, F3, F4 // fc8110fe
|
|
||||||
FNMADDCC F1, F2, F3, F4 // fc8110ff
|
|
||||||
FNMADDS F1, F2, F3, F4 // ec8110fe
|
|
||||||
FNMADDSCC F1, F2, F3, F4 // ec8110ff
|
|
||||||
FNMSUB F1, F2, F3, F4 // fc8110fc
|
|
||||||
FNMSUBCC F1, F2, F3, F4 // fc8110fd
|
|
||||||
FNMSUBS F1, F2, F3, F4 // ec8110fc
|
|
||||||
FNMSUBSCC F1, F2, F3, F4 // ec8110fd
|
|
||||||
FSEL F1, F2, F3, F4 // fc8110ee
|
|
||||||
FSELCC F1, F2, F3, F4 // fc8110ef
|
|
||||||
FABS F1, F2 // fc400a10
|
|
||||||
FABSCC F1, F2 // fc400a11
|
|
||||||
FNEG F1, F2 // fc400850
|
|
||||||
FABSCC F1, F2 // fc400a11
|
|
||||||
FRSP F1, F2 // fc400818
|
|
||||||
FRSPCC F1, F2 // fc400819
|
|
||||||
FCTIW F1, F2 // fc40081c
|
|
||||||
FCTIWCC F1, F2 // fc40081d
|
|
||||||
FCTIWZ F1, F2 // fc40081e
|
|
||||||
FCTIWZCC F1, F2 // fc40081f
|
|
||||||
FCTID F1, F2 // fc400e5c
|
|
||||||
FCTIDCC F1, F2 // fc400e5d
|
|
||||||
FCTIDZ F1, F2 // fc400e5e
|
|
||||||
FCTIDZCC F1, F2 // fc400e5f
|
|
||||||
FCFID F1, F2 // fc400e9c
|
|
||||||
FCFIDCC F1, F2 // fc400e9d
|
|
||||||
FCFIDU F1, F2 // fc400f9c
|
|
||||||
FCFIDUCC F1, F2 // fc400f9d
|
|
||||||
FCFIDS F1, F2 // ec400e9c
|
|
||||||
FCFIDSCC F1, F2 // ec400e9d
|
|
||||||
FRES F1, F2 // ec400830
|
|
||||||
FRESCC F1, F2 // ec400831
|
|
||||||
FRIM F1, F2 // fc400bd0
|
|
||||||
FRIMCC F1, F2 // fc400bd1
|
|
||||||
FRIP F1, F2 // fc400b90
|
|
||||||
FRIPCC F1, F2 // fc400b91
|
|
||||||
FRIZ F1, F2 // fc400b50
|
|
||||||
FRIZCC F1, F2 // fc400b51
|
|
||||||
FRIN F1, F2 // fc400b10
|
|
||||||
FRINCC F1, F2 // fc400b11
|
|
||||||
FRSQRTE F1, F2 // fc400834
|
|
||||||
FRSQRTECC F1, F2 // fc400835
|
|
||||||
FSQRT F1, F2 // fc40082c
|
|
||||||
FSQRTCC F1, F2 // fc40082d
|
|
||||||
FSQRTS F1, F2 // ec40082c
|
|
||||||
FSQRTSCC F1, F2 // ec40082d
|
|
||||||
FCPSGN F1, F2 // fc420810
|
|
||||||
FCPSGNCC F1, F2 // fc420811
|
|
||||||
FCMPO F1, F2 // fc011040
|
|
||||||
FCMPU F1, F2 // fc011000
|
|
||||||
LVX (R3)(R4), V1 // 7c2418ce
|
|
||||||
LVXL (R3)(R4), V1 // 7c241ace
|
|
||||||
LVSL (R3)(R4), V1 // 7c24180c
|
|
||||||
LVSR (R3)(R4), V1 // 7c24184c
|
|
||||||
LVEBX (R3)(R4), V1 // 7c24180e
|
|
||||||
LVEHX (R3)(R4), V1 // 7c24184e
|
|
||||||
LVEWX (R3)(R4), V1 // 7c24188e
|
|
||||||
STVX V1, (R3)(R4) // 7c2419ce
|
|
||||||
STVXL V1, (R3)(R4) // 7c241bce
|
|
||||||
STVEBX V1, (R3)(R4) // 7c24190e
|
|
||||||
STVEHX V1, (R3)(R4) // 7c24194e
|
|
||||||
STVEWX V1, (R3)(R4) // 7c24198e
|
|
||||||
|
|
||||||
VAND V1, V2, V3 // 10611404
|
|
||||||
VANDC V1, V2, V3 // 10611444
|
|
||||||
VNAND V1, V2, V3 // 10611584
|
|
||||||
VOR V1, V2, V3 // 10611484
|
|
||||||
VORC V1, V2, V3 // 10611544
|
|
||||||
VXOR V1, V2, V3 // 106114c4
|
|
||||||
VNOR V1, V2, V3 // 10611504
|
|
||||||
VEQV V1, V2, V3 // 10611684
|
|
||||||
VADDUBM V1, V2, V3 // 10611000
|
|
||||||
VADDUHM V1, V2, V3 // 10611040
|
|
||||||
VADDUWM V1, V2, V3 // 10611080
|
|
||||||
VADDUDM V1, V2, V3 // 106110c0
|
|
||||||
VADDUQM V1, V2, V3 // 10611100
|
|
||||||
VADDCUQ V1, V2, V3 // 10611140
|
|
||||||
VADDCUW V1, V2, V3 // 10611180
|
|
||||||
VADDUBS V1, V2, V3 // 10611200
|
|
||||||
VADDUHS V1, V2, V3 // 10611240
|
|
||||||
VADDUWS V1, V2, V3 // 10611280
|
|
||||||
VSUBUBM V1, V2, V3 // 10611400
|
|
||||||
VSUBUHM V1, V2, V3 // 10611440
|
|
||||||
VSUBUWM V1, V2, V3 // 10611480
|
|
||||||
VSUBUDM V1, V2, V3 // 106114c0
|
|
||||||
VSUBUQM V1, V2, V3 // 10611500
|
|
||||||
VSUBCUQ V1, V2, V3 // 10611540
|
|
||||||
VSUBCUW V1, V2, V3 // 10611580
|
|
||||||
VSUBUBS V1, V2, V3 // 10611600
|
|
||||||
VSUBUHS V1, V2, V3 // 10611640
|
|
||||||
VSUBUWS V1, V2, V3 // 10611680
|
|
||||||
VSUBSBS V1, V2, V3 // 10611700
|
|
||||||
VSUBSHS V1, V2, V3 // 10611740
|
|
||||||
VSUBSWS V1, V2, V3 // 10611780
|
|
||||||
VSUBEUQM V1, V2, V3, V4 // 108110fe
|
|
||||||
VSUBECUQ V1, V2, V3, V4 // 108110ff
|
|
||||||
VMULESB V1, V2, V3 // 10611308
|
|
||||||
VMULOSB V1, V2, V3 // 10611108
|
|
||||||
VMULEUB V1, V2, V3 // 10611208
|
|
||||||
VMULOUB V1, V2, V3 // 10611008
|
|
||||||
VMULESH V1, V2, V3 // 10611348
|
|
||||||
VMULOSH V1, V2, V3 // 10611148
|
|
||||||
VMULEUH V1, V2, V3 // 10611248
|
|
||||||
VMULOUH V1, V2, V3 // 10611048
|
|
||||||
VMULESH V1, V2, V3 // 10611348
|
|
||||||
VMULOSW V1, V2, V3 // 10611188
|
|
||||||
VMULEUW V1, V2, V3 // 10611288
|
|
||||||
VMULOUW V1, V2, V3 // 10611088
|
|
||||||
VMULUWM V1, V2, V3 // 10611089
|
|
||||||
VPMSUMB V1, V2, V3 // 10611408
|
|
||||||
VPMSUMH V1, V2, V3 // 10611448
|
|
||||||
VPMSUMW V1, V2, V3 // 10611488
|
|
||||||
VPMSUMD V1, V2, V3 // 106114c8
|
|
||||||
VMSUMUDM V1, V2, V3, V4 // 108110e3
|
|
||||||
VRLB V1, V2, V3 // 10611004
|
|
||||||
VRLH V1, V2, V3 // 10611044
|
|
||||||
VRLW V1, V2, V3 // 10611084
|
|
||||||
VRLD V1, V2, V3 // 106110c4
|
|
||||||
VSLB V1, V2, V3 // 10611104
|
|
||||||
VSLH V1, V2, V3 // 10611144
|
|
||||||
VSLW V1, V2, V3 // 10611184
|
|
||||||
VSL V1, V2, V3 // 106111c4
|
|
||||||
VSLO V1, V2, V3 // 1061140c
|
|
||||||
VSRB V1, V2, V3 // 10611204
|
|
||||||
VSRH V1, V2, V3 // 10611244
|
|
||||||
VSRW V1, V2, V3 // 10611284
|
|
||||||
VSR V1, V2, V3 // 106112c4
|
|
||||||
VSRO V1, V2, V3 // 1061144c
|
|
||||||
VSLD V1, V2, V3 // 106115c4
|
|
||||||
VSRAB V1, V2, V3 // 10611304
|
|
||||||
VSRAH V1, V2, V3 // 10611344
|
|
||||||
VSRAW V1, V2, V3 // 10611384
|
|
||||||
VSRAD V1, V2, V3 // 106113c4
|
|
||||||
VSLDOI $3, V1, V2, V3 // 106110ec
|
|
||||||
VCLZB V1, V2 // 10400f02
|
|
||||||
VCLZH V1, V2 // 10400f42
|
|
||||||
VCLZW V1, V2 // 10400f82
|
|
||||||
VCLZD V1, V2 // 10400fc2
|
|
||||||
VPOPCNTB V1, V2 // 10400f03
|
|
||||||
VPOPCNTH V1, V2 // 10400f43
|
|
||||||
VPOPCNTW V1, V2 // 10400f83
|
|
||||||
VPOPCNTD V1, V2 // 10400fc3
|
|
||||||
VCMPEQUB V1, V2, V3 // 10611006
|
|
||||||
VCMPEQUBCC V1, V2, V3 // 10611406
|
|
||||||
VCMPEQUH V1, V2, V3 // 10611046
|
|
||||||
VCMPEQUHCC V1, V2, V3 // 10611446
|
|
||||||
VCMPEQUW V1, V2, V3 // 10611086
|
|
||||||
VCMPEQUWCC V1, V2, V3 // 10611486
|
|
||||||
VCMPEQUD V1, V2, V3 // 106110c7
|
|
||||||
VCMPEQUDCC V1, V2, V3 // 106114c7
|
|
||||||
VCMPGTUB V1, V2, V3 // 10611206
|
|
||||||
VCMPGTUBCC V1, V2, V3 // 10611606
|
|
||||||
VCMPGTUH V1, V2, V3 // 10611246
|
|
||||||
VCMPGTUHCC V1, V2, V3 // 10611646
|
|
||||||
VCMPGTUW V1, V2, V3 // 10611286
|
|
||||||
VCMPGTUWCC V1, V2, V3 // 10611686
|
|
||||||
VCMPGTUD V1, V2, V3 // 106112c7
|
|
||||||
VCMPGTUDCC V1, V2, V3 // 106116c7
|
|
||||||
VCMPGTSB V1, V2, V3 // 10611306
|
|
||||||
VCMPGTSBCC V1, V2, V3 // 10611706
|
|
||||||
VCMPGTSH V1, V2, V3 // 10611346
|
|
||||||
VCMPGTSHCC V1, V2, V3 // 10611746
|
|
||||||
VCMPGTSW V1, V2, V3 // 10611386
|
|
||||||
VCMPGTSWCC V1, V2, V3 // 10611786
|
|
||||||
VCMPGTSD V1, V2, V3 // 106113c7
|
|
||||||
VCMPGTSDCC V1, V2, V3 // 106117c7
|
|
||||||
VCMPNEZB V1, V2, V3 // 10611107
|
|
||||||
VCMPNEZBCC V1, V2, V3 // 10611507
|
|
||||||
VCMPNEB V1, V2, V3 // 10611007
|
|
||||||
VCMPNEBCC V1, V2, V3 // 10611407
|
|
||||||
VCMPNEH V1, V2, V3 // 10611047
|
|
||||||
VCMPNEHCC V1, V2, V3 // 10611447
|
|
||||||
VCMPNEW V1, V2, V3 // 10611087
|
|
||||||
VCMPNEWCC V1, V2, V3 // 10611487
|
|
||||||
VPERM V1, V2, V3, V4 // 108110eb
|
|
||||||
VPERMR V1, V2, V3, V4 // 108110fb
|
|
||||||
VPERMXOR V1, V2, V3, V4 // 108110ed
|
|
||||||
VBPERMQ V1, V2, V3 // 1061154c
|
|
||||||
VBPERMD V1, V2, V3 // 106115cc
|
|
||||||
VSEL V1, V2, V3, V4 // 108110ea
|
|
||||||
VSPLTB $1, V1, V2 // 10410a0c
|
|
||||||
VSPLTH $1, V1, V2 // 10410a4c
|
|
||||||
VSPLTW $1, V1, V2 // 10410a8c
|
|
||||||
VSPLTISB $1, V1 // 1021030c
|
|
||||||
VSPLTISW $1, V1 // 1021038c
|
|
||||||
VSPLTISH $1, V1 // 1021034c
|
|
||||||
VCIPHER V1, V2, V3 // 10611508
|
|
||||||
VCIPHERLAST V1, V2, V3 // 10611509
|
|
||||||
VNCIPHER V1, V2, V3 // 10611548
|
|
||||||
VNCIPHERLAST V1, V2, V3 // 10611549
|
|
||||||
VSBOX V1, V2 // 104105c8
|
|
||||||
VSHASIGMAW $1, V1, $15, V2 // 10418e82
|
|
||||||
VSHASIGMAD $2, V1, $15, V2 // 104196c2
|
|
||||||
|
|
||||||
LXVD2X (R3)(R4), VS1 // 7c241e98
|
|
||||||
LXV 16(R3), VS1 // f4230011
|
|
||||||
LXVL R3, R4, VS1 // 7c23221a
|
|
||||||
LXVLL R3, R4, VS1 // 7c23225a
|
|
||||||
LXVX R3, R4, VS1 // 7c232218
|
|
||||||
LXSDX (R3)(R4), VS1 // 7c241c98
|
|
||||||
STXVD2X VS1, (R3)(R4) // 7c241f98
|
|
||||||
STXV VS1,16(R3) // f4230015
|
|
||||||
STXVL VS1, R3, R4 // 7c23231a
|
|
||||||
STXVLL VS1, R3, R4 // 7c23235a
|
|
||||||
STXVX VS1, R3, R4 // 7c232318
|
|
||||||
STXSDX VS1, (R3)(R4) // 7c241d98
|
|
||||||
LXSIWAX (R3)(R4), VS1 // 7c241898
|
|
||||||
STXSIWX VS1, (R3)(R4) // 7c241918
|
|
||||||
MFVSRD VS1, R3 // 7c230066
|
|
||||||
MTVSRD R3, VS1 // 7c230166
|
|
||||||
XXLAND VS1, VS2, VS3 // f0611410
|
|
||||||
XXLOR VS1, VS2, VS3 // f0611490
|
|
||||||
XXLORC VS1, VS2, VS3 // f0611550
|
|
||||||
XXLXOR VS1, VS2, VS3 // f06114d0
|
|
||||||
XXSEL VS1, VS2, VS3, VS4 // f08110f0
|
|
||||||
XXMRGHW VS1, VS2, VS3 // f0611090
|
|
||||||
XXSPLTW VS1, $1, VS2 // f0410a90
|
|
||||||
XXPERM VS1, VS2, VS3 // f06110d0
|
|
||||||
XXSLDWI VS1, VS2, $1, VS3 // f0611110
|
|
||||||
XSCVDPSP VS1, VS2 // f0400c24
|
|
||||||
XVCVDPSP VS1, VS2 // f0400e24
|
|
||||||
XSCVSXDDP VS1, VS2 // f0400de0
|
|
||||||
XVCVDPSXDS VS1, VS2 // f0400f60
|
|
||||||
XVCVSXDDP VS1, VS2 // f0400fe0
|
|
||||||
|
|
||||||
MOVD R3, LR // 7c6803a6
|
|
||||||
MOVD R3, CTR // 7c6903a6
|
|
||||||
MOVD R3, XER // 7c6103a6
|
|
||||||
MOVD LR, R3 // 7c6802a6
|
|
||||||
MOVD CTR, R3 // 7c6902a6
|
|
||||||
MOVD XER, R3 // 7c6102a6
|
|
||||||
MOVFL CR3, CR1 // 4c8c0000
|
|
||||||
|
|
||||||
RET
|
|
||||||
|
|
@ -24,6 +24,7 @@ var (
|
||||||
SymABIs = flag.Bool("gensymabis", false, "write symbol ABI information to output file, don't assemble")
|
SymABIs = flag.Bool("gensymabis", false, "write symbol ABI information to output file, don't assemble")
|
||||||
Importpath = flag.String("p", "", "set expected package import to path")
|
Importpath = flag.String("p", "", "set expected package import to path")
|
||||||
Spectre = flag.String("spectre", "", "enable spectre mitigations in `list` (all, ret)")
|
Spectre = flag.String("spectre", "", "enable spectre mitigations in `list` (all, ret)")
|
||||||
|
CompilingRuntime = flag.Bool("compiling-runtime", false, "source to be compiled is part of the Go runtime")
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,9 @@ func (in *Input) Next() ScanToken {
|
||||||
in.Error("'#' must be first item on line")
|
in.Error("'#' must be first item on line")
|
||||||
}
|
}
|
||||||
in.beginningOfLine = in.hash()
|
in.beginningOfLine = in.hash()
|
||||||
|
in.text = "#"
|
||||||
|
return '#'
|
||||||
|
|
||||||
case scanner.Ident:
|
case scanner.Ident:
|
||||||
// Is it a macro name?
|
// Is it a macro name?
|
||||||
name := in.Stack.Text()
|
name := in.Stack.Text()
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ const (
|
||||||
RSH // >> Logical right shift.
|
RSH // >> Logical right shift.
|
||||||
ARR // -> Used on ARM for shift type 3, arithmetic right shift.
|
ARR // -> Used on ARM for shift type 3, arithmetic right shift.
|
||||||
ROT // @> Used on ARM for shift type 4, rotate right.
|
ROT // @> Used on ARM for shift type 4, rotate right.
|
||||||
|
Include // included file started here
|
||||||
|
BuildComment // //go:build or +build comment
|
||||||
macroName // name of macro that should not be expanded
|
macroName // name of macro that should not be expanded
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -281,6 +281,9 @@ func drain(input *Input) string {
|
||||||
if tok == scanner.EOF {
|
if tok == scanner.EOF {
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
if tok == '#' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if buf.Len() > 0 {
|
if buf.Len() > 0 {
|
||||||
buf.WriteByte('.')
|
buf.WriteByte('.')
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,10 +107,13 @@ func (t *Tokenizer) Next() ScanToken {
|
||||||
if t.tok != scanner.Comment {
|
if t.tok != scanner.Comment {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
length := strings.Count(s.TokenText(), "\n")
|
text := s.TokenText()
|
||||||
t.line += length
|
t.line += strings.Count(text, "\n")
|
||||||
// TODO: If we ever have //go: comments in assembly, will need to keep them here.
|
// TODO: Use constraint.IsGoBuild once it exists.
|
||||||
// For now, just discard all comments.
|
if strings.HasPrefix(text, "//go:build") {
|
||||||
|
t.tok = BuildComment
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch t.tok {
|
switch t.tok {
|
||||||
case '\n':
|
case '\n':
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,8 @@ func main() {
|
||||||
var failedFile string
|
var failedFile string
|
||||||
for _, f := range flag.Args() {
|
for _, f := range flag.Args() {
|
||||||
lexer := lex.NewLexer(f)
|
lexer := lex.NewLexer(f)
|
||||||
parser := asm.NewParser(ctxt, architecture, lexer)
|
parser := asm.NewParser(ctxt, architecture, lexer,
|
||||||
|
*flags.CompilingRuntime)
|
||||||
ctxt.DiagFunc = func(format string, args ...interface{}) {
|
ctxt.DiagFunc = func(format string, args ...interface{}) {
|
||||||
diag = true
|
diag = true
|
||||||
log.Printf(format, args...)
|
log.Printf(format, args...)
|
||||||
|
|
|
||||||
|
|
@ -282,7 +282,7 @@ func genhash(t *types.Type) *obj.LSym {
|
||||||
}
|
}
|
||||||
|
|
||||||
sym := typesymprefix(".hash", t)
|
sym := typesymprefix(".hash", t)
|
||||||
if Debug['r'] != 0 {
|
if Debug.r != 0 {
|
||||||
fmt.Printf("genhash %v %v %v\n", closure, sym, t)
|
fmt.Printf("genhash %v %v %v\n", closure, sym, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -374,7 +374,7 @@ func genhash(t *types.Type) *obj.LSym {
|
||||||
r.List.Append(nh)
|
r.List.Append(nh)
|
||||||
fn.Nbody.Append(r)
|
fn.Nbody.Append(r)
|
||||||
|
|
||||||
if Debug['r'] != 0 {
|
if Debug.r != 0 {
|
||||||
dumplist("genhash body", fn.Nbody)
|
dumplist("genhash body", fn.Nbody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -509,7 +509,7 @@ func geneq(t *types.Type) *obj.LSym {
|
||||||
return closure
|
return closure
|
||||||
}
|
}
|
||||||
sym := typesymprefix(".eq", t)
|
sym := typesymprefix(".eq", t)
|
||||||
if Debug['r'] != 0 {
|
if Debug.r != 0 {
|
||||||
fmt.Printf("geneq %v\n", t)
|
fmt.Printf("geneq %v\n", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -732,7 +732,7 @@ func geneq(t *types.Type) *obj.LSym {
|
||||||
fn.Nbody.Append(ret)
|
fn.Nbody.Append(ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug['r'] != 0 {
|
if Debug.r != 0 {
|
||||||
dumplist("geneq body", fn.Nbody)
|
dumplist("geneq body", fn.Nbody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ func expandiface(t *types.Type) {
|
||||||
sort.Sort(methcmp(methods))
|
sort.Sort(methcmp(methods))
|
||||||
|
|
||||||
if int64(len(methods)) >= thearch.MAXWIDTH/int64(Widthptr) {
|
if int64(len(methods)) >= thearch.MAXWIDTH/int64(Widthptr) {
|
||||||
yyerror("interface too large")
|
yyerrorl(typePos(t), "interface too large")
|
||||||
}
|
}
|
||||||
for i, m := range methods {
|
for i, m := range methods {
|
||||||
m.Offset = int64(i) * int64(Widthptr)
|
m.Offset = int64(i) * int64(Widthptr)
|
||||||
|
|
@ -150,7 +150,7 @@ func widstruct(errtype *types.Type, t *types.Type, o int64, flag int) int64 {
|
||||||
maxwidth = 1<<31 - 1
|
maxwidth = 1<<31 - 1
|
||||||
}
|
}
|
||||||
if o >= maxwidth {
|
if o >= maxwidth {
|
||||||
yyerror("type %L too large", errtype)
|
yyerrorl(typePos(errtype), "type %L too large", errtype)
|
||||||
o = 8 // small but nonzero
|
o = 8 // small but nonzero
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -199,7 +199,7 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
*path = append(*path, t)
|
*path = append(*path, t)
|
||||||
if findTypeLoop(asNode(t.Nod).Name.Param.Ntype.Type, path) {
|
if p := asNode(t.Nod).Name.Param; p != nil && findTypeLoop(p.Ntype.Type, path) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
*path = (*path)[:len(*path)-1]
|
*path = (*path)[:len(*path)-1]
|
||||||
|
|
@ -381,7 +381,7 @@ func dowidth(t *types.Type) {
|
||||||
t1 := t.ChanArgs()
|
t1 := t.ChanArgs()
|
||||||
dowidth(t1) // just in case
|
dowidth(t1) // just in case
|
||||||
if t1.Elem().Width >= 1<<16 {
|
if t1.Elem().Width >= 1<<16 {
|
||||||
yyerror("channel element type too large (>64kB)")
|
yyerrorl(typePos(t1), "channel element type too large (>64kB)")
|
||||||
}
|
}
|
||||||
w = 1 // anything will do
|
w = 1 // anything will do
|
||||||
|
|
||||||
|
|
@ -414,7 +414,7 @@ func dowidth(t *types.Type) {
|
||||||
if t.Elem().Width != 0 {
|
if t.Elem().Width != 0 {
|
||||||
cap := (uint64(thearch.MAXWIDTH) - 1) / uint64(t.Elem().Width)
|
cap := (uint64(thearch.MAXWIDTH) - 1) / uint64(t.Elem().Width)
|
||||||
if uint64(t.NumElem()) > cap {
|
if uint64(t.NumElem()) > cap {
|
||||||
yyerror("type %L larger than address space", t)
|
yyerrorl(typePos(t), "type %L larger than address space", t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w = t.NumElem() * t.Elem().Width
|
w = t.NumElem() * t.Elem().Width
|
||||||
|
|
@ -456,7 +456,7 @@ func dowidth(t *types.Type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if Widthptr == 4 && w != int64(int32(w)) {
|
if Widthptr == 4 && w != int64(int32(w)) {
|
||||||
yyerror("type %v too large", t)
|
yyerrorl(typePos(t), "type %v too large", t)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Width = w
|
t.Width = w
|
||||||
|
|
|
||||||
|
|
@ -81,11 +81,6 @@ func (p *exporter) markType(t *types.Type) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// deltaNewFile is a magic line delta offset indicating a new file.
|
|
||||||
// We use -64 because it is rare; see issue 20080 and CL 41619.
|
|
||||||
// -64 is the smallest int that fits in a single byte as a varint.
|
|
||||||
const deltaNewFile = -64
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Export format
|
// Export format
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ func capturevars(xfunc *Node) {
|
||||||
outer = nod(OADDR, outer, nil)
|
outer = nod(OADDR, outer, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug['m'] > 1 {
|
if Debug.m > 1 {
|
||||||
var name *types.Sym
|
var name *types.Sym
|
||||||
if v.Name.Curfn != nil && v.Name.Curfn.Func.Nname != nil {
|
if v.Name.Curfn != nil && v.Name.Curfn.Func.Nname != nil {
|
||||||
name = v.Name.Curfn.Func.Nname.Sym
|
name = v.Name.Curfn.Func.Nname.Sym
|
||||||
|
|
@ -434,6 +434,8 @@ func typecheckpartialcall(fn *Node, sym *types.Sym) {
|
||||||
fn.Type = xfunc.Type
|
fn.Type = xfunc.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// makepartialcall returns a DCLFUNC node representing the wrapper function (*-fm) needed
|
||||||
|
// for partial calls.
|
||||||
func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node {
|
func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node {
|
||||||
rcvrtype := fn.Left.Type
|
rcvrtype := fn.Left.Type
|
||||||
sym := methodSymSuffix(rcvrtype, meth, "-fm")
|
sym := methodSymSuffix(rcvrtype, meth, "-fm")
|
||||||
|
|
@ -500,6 +502,10 @@ func makepartialcall(fn *Node, t0 *types.Type, meth *types.Sym) *Node {
|
||||||
funcbody()
|
funcbody()
|
||||||
|
|
||||||
xfunc = typecheck(xfunc, ctxStmt)
|
xfunc = typecheck(xfunc, ctxStmt)
|
||||||
|
// Need to typecheck the body of the just-generated wrapper.
|
||||||
|
// typecheckslice() requires that Curfn is set when processing an ORETURN.
|
||||||
|
Curfn = xfunc
|
||||||
|
typecheckslice(xfunc.Nbody.Slice(), ctxStmt)
|
||||||
sym.Def = asTypesNode(xfunc)
|
sym.Def = asTypesNode(xfunc)
|
||||||
xtop = append(xtop, xfunc)
|
xtop = append(xtop, xfunc)
|
||||||
Curfn = savecurfn
|
Curfn = savecurfn
|
||||||
|
|
|
||||||
|
|
@ -114,16 +114,16 @@ func (v Val) Interface() interface{} {
|
||||||
|
|
||||||
type NilVal struct{}
|
type NilVal struct{}
|
||||||
|
|
||||||
// Int64 returns n as an int64.
|
// Int64Val returns n as an int64.
|
||||||
// n must be an integer or rune constant.
|
// n must be an integer or rune constant.
|
||||||
func (n *Node) Int64() int64 {
|
func (n *Node) Int64Val() int64 {
|
||||||
if !Isconst(n, CTINT) {
|
if !Isconst(n, CTINT) {
|
||||||
Fatalf("Int64(%v)", n)
|
Fatalf("Int64Val(%v)", n)
|
||||||
}
|
}
|
||||||
return n.Val().U.(*Mpint).Int64()
|
return n.Val().U.(*Mpint).Int64()
|
||||||
}
|
}
|
||||||
|
|
||||||
// CanInt64 reports whether it is safe to call Int64() on n.
|
// CanInt64 reports whether it is safe to call Int64Val() on n.
|
||||||
func (n *Node) CanInt64() bool {
|
func (n *Node) CanInt64() bool {
|
||||||
if !Isconst(n, CTINT) {
|
if !Isconst(n, CTINT) {
|
||||||
return false
|
return false
|
||||||
|
|
@ -131,18 +131,27 @@ func (n *Node) CanInt64() bool {
|
||||||
|
|
||||||
// if the value inside n cannot be represented as an int64, the
|
// if the value inside n cannot be represented as an int64, the
|
||||||
// return value of Int64 is undefined
|
// return value of Int64 is undefined
|
||||||
return n.Val().U.(*Mpint).CmpInt64(n.Int64()) == 0
|
return n.Val().U.(*Mpint).CmpInt64(n.Int64Val()) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bool returns n as a bool.
|
// BoolVal returns n as a bool.
|
||||||
// n must be a boolean constant.
|
// n must be a boolean constant.
|
||||||
func (n *Node) Bool() bool {
|
func (n *Node) BoolVal() bool {
|
||||||
if !Isconst(n, CTBOOL) {
|
if !Isconst(n, CTBOOL) {
|
||||||
Fatalf("Bool(%v)", n)
|
Fatalf("BoolVal(%v)", n)
|
||||||
}
|
}
|
||||||
return n.Val().U.(bool)
|
return n.Val().U.(bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StringVal returns the value of a literal string Node as a string.
|
||||||
|
// n must be a string constant.
|
||||||
|
func (n *Node) StringVal() string {
|
||||||
|
if !Isconst(n, CTSTR) {
|
||||||
|
Fatalf("StringVal(%v)", n)
|
||||||
|
}
|
||||||
|
return n.Val().U.(string)
|
||||||
|
}
|
||||||
|
|
||||||
// truncate float literal fv to 32-bit or 64-bit precision
|
// truncate float literal fv to 32-bit or 64-bit precision
|
||||||
// according to type; return truncated value.
|
// according to type; return truncated value.
|
||||||
func truncfltlit(oldv *Mpflt, t *types.Type) *Mpflt {
|
func truncfltlit(oldv *Mpflt, t *types.Type) *Mpflt {
|
||||||
|
|
@ -612,7 +621,7 @@ func evconst(n *Node) {
|
||||||
var strs []string
|
var strs []string
|
||||||
i2 := i1
|
i2 := i1
|
||||||
for i2 < len(s) && Isconst(s[i2], CTSTR) {
|
for i2 < len(s) && Isconst(s[i2], CTSTR) {
|
||||||
strs = append(strs, strlit(s[i2]))
|
strs = append(strs, s[i2].StringVal())
|
||||||
i2++
|
i2++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -635,7 +644,7 @@ func evconst(n *Node) {
|
||||||
switch nl.Type.Etype {
|
switch nl.Type.Etype {
|
||||||
case TSTRING:
|
case TSTRING:
|
||||||
if Isconst(nl, CTSTR) {
|
if Isconst(nl, CTSTR) {
|
||||||
setintconst(n, int64(len(strlit(nl))))
|
setintconst(n, int64(len(nl.StringVal())))
|
||||||
}
|
}
|
||||||
case TARRAY:
|
case TARRAY:
|
||||||
if !hascallchan(nl) {
|
if !hascallchan(nl) {
|
||||||
|
|
@ -1129,11 +1138,6 @@ func defaultType(t *types.Type) *types.Type {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// strlit returns the value of a literal string Node as a string.
|
|
||||||
func strlit(n *Node) string {
|
|
||||||
return n.Val().U.(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
func smallintconst(n *Node) bool {
|
func smallintconst(n *Node) bool {
|
||||||
if n.Op == OLITERAL && Isconst(n, CTINT) && n.Type != nil {
|
if n.Op == OLITERAL && Isconst(n, CTINT) && n.Type != nil {
|
||||||
switch simtype[n.Type.Etype] {
|
switch simtype[n.Type.Etype] {
|
||||||
|
|
|
||||||
|
|
@ -283,7 +283,7 @@ func oldname(s *types.Sym) *Node {
|
||||||
c.Name.Defn = n
|
c.Name.Defn = n
|
||||||
|
|
||||||
// Link into list of active closure variables.
|
// Link into list of active closure variables.
|
||||||
// Popped from list in func closurebody.
|
// Popped from list in func funcLit.
|
||||||
c.Name.Param.Outer = n.Name.Param.Innermost
|
c.Name.Param.Outer = n.Name.Param.Innermost
|
||||||
n.Name.Param.Innermost = c
|
n.Name.Param.Innermost = c
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ func assembleInlines(fnsym *obj.LSym, dwVars []*dwarf.Var) dwarf.InlCalls {
|
||||||
|
|
||||||
// Walk progs to build up the InlCalls data structure
|
// Walk progs to build up the InlCalls data structure
|
||||||
var prevpos src.XPos
|
var prevpos src.XPos
|
||||||
for p := fnsym.Func.Text; p != nil; p = p.Link {
|
for p := fnsym.Func().Text; p != nil; p = p.Link {
|
||||||
if p.Pos == prevpos {
|
if p.Pos == prevpos {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -150,7 +150,7 @@ func assembleInlines(fnsym *obj.LSym, dwVars []*dwarf.Var) dwarf.InlCalls {
|
||||||
start := int64(-1)
|
start := int64(-1)
|
||||||
curii := -1
|
curii := -1
|
||||||
var prevp *obj.Prog
|
var prevp *obj.Prog
|
||||||
for p := fnsym.Func.Text; p != nil; prevp, p = p, p.Link {
|
for p := fnsym.Func().Text; p != nil; prevp, p = p, p.Link {
|
||||||
if prevp != nil && p.Pos == prevp.Pos {
|
if prevp != nil && p.Pos == prevp.Pos {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -204,7 +204,7 @@ func heapAllocReason(n *Node) string {
|
||||||
if !smallintconst(r) {
|
if !smallintconst(r) {
|
||||||
return "non-constant size"
|
return "non-constant size"
|
||||||
}
|
}
|
||||||
if t := n.Type; t.Elem().Width != 0 && r.Int64() >= maxImplicitStackVarSize/t.Elem().Width {
|
if t := n.Type; t.Elem().Width != 0 && r.Int64Val() >= maxImplicitStackVarSize/t.Elem().Width {
|
||||||
return "too large for stack"
|
return "too large for stack"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -282,7 +282,7 @@ func addrescapes(n *Node) {
|
||||||
|
|
||||||
// moveToHeap records the parameter or local variable n as moved to the heap.
|
// moveToHeap records the parameter or local variable n as moved to the heap.
|
||||||
func moveToHeap(n *Node) {
|
func moveToHeap(n *Node) {
|
||||||
if Debug['r'] != 0 {
|
if Debug.r != 0 {
|
||||||
Dump("MOVE", n)
|
Dump("MOVE", n)
|
||||||
}
|
}
|
||||||
if compiling_runtime {
|
if compiling_runtime {
|
||||||
|
|
@ -359,7 +359,7 @@ func moveToHeap(n *Node) {
|
||||||
n.Xoffset = 0
|
n.Xoffset = 0
|
||||||
n.Name.Param.Heapaddr = heapaddr
|
n.Name.Param.Heapaddr = heapaddr
|
||||||
n.Esc = EscHeap
|
n.Esc = EscHeap
|
||||||
if Debug['m'] != 0 {
|
if Debug.m != 0 {
|
||||||
Warnl(n.Pos, "moved to heap: %v", n)
|
Warnl(n.Pos, "moved to heap: %v", n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -389,7 +389,7 @@ func (e *Escape) paramTag(fn *Node, narg int, f *types.Field) string {
|
||||||
// but we are reusing the ability to annotate an individual function
|
// but we are reusing the ability to annotate an individual function
|
||||||
// argument and pass those annotations along to importing code.
|
// argument and pass those annotations along to importing code.
|
||||||
if f.Type.IsUintptr() {
|
if f.Type.IsUintptr() {
|
||||||
if Debug['m'] != 0 {
|
if Debug.m != 0 {
|
||||||
Warnl(f.Pos, "assuming %v is unsafe uintptr", name())
|
Warnl(f.Pos, "assuming %v is unsafe uintptr", name())
|
||||||
}
|
}
|
||||||
return unsafeUintptrTag
|
return unsafeUintptrTag
|
||||||
|
|
@ -404,11 +404,11 @@ func (e *Escape) paramTag(fn *Node, narg int, f *types.Field) string {
|
||||||
// External functions are assumed unsafe, unless
|
// External functions are assumed unsafe, unless
|
||||||
// //go:noescape is given before the declaration.
|
// //go:noescape is given before the declaration.
|
||||||
if fn.Func.Pragma&Noescape != 0 {
|
if fn.Func.Pragma&Noescape != 0 {
|
||||||
if Debug['m'] != 0 && f.Sym != nil {
|
if Debug.m != 0 && f.Sym != nil {
|
||||||
Warnl(f.Pos, "%v does not escape", name())
|
Warnl(f.Pos, "%v does not escape", name())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if Debug['m'] != 0 && f.Sym != nil {
|
if Debug.m != 0 && f.Sym != nil {
|
||||||
Warnl(f.Pos, "leaking param: %v", name())
|
Warnl(f.Pos, "leaking param: %v", name())
|
||||||
}
|
}
|
||||||
esc.AddHeap(0)
|
esc.AddHeap(0)
|
||||||
|
|
@ -419,14 +419,14 @@ func (e *Escape) paramTag(fn *Node, narg int, f *types.Field) string {
|
||||||
|
|
||||||
if fn.Func.Pragma&UintptrEscapes != 0 {
|
if fn.Func.Pragma&UintptrEscapes != 0 {
|
||||||
if f.Type.IsUintptr() {
|
if f.Type.IsUintptr() {
|
||||||
if Debug['m'] != 0 {
|
if Debug.m != 0 {
|
||||||
Warnl(f.Pos, "marking %v as escaping uintptr", name())
|
Warnl(f.Pos, "marking %v as escaping uintptr", name())
|
||||||
}
|
}
|
||||||
return uintptrEscapesTag
|
return uintptrEscapesTag
|
||||||
}
|
}
|
||||||
if f.IsDDD() && f.Type.Elem().IsUintptr() {
|
if f.IsDDD() && f.Type.Elem().IsUintptr() {
|
||||||
// final argument is ...uintptr.
|
// final argument is ...uintptr.
|
||||||
if Debug['m'] != 0 {
|
if Debug.m != 0 {
|
||||||
Warnl(f.Pos, "marking %v as escaping ...uintptr", name())
|
Warnl(f.Pos, "marking %v as escaping ...uintptr", name())
|
||||||
}
|
}
|
||||||
return uintptrEscapesTag
|
return uintptrEscapesTag
|
||||||
|
|
@ -448,7 +448,7 @@ func (e *Escape) paramTag(fn *Node, narg int, f *types.Field) string {
|
||||||
esc := loc.paramEsc
|
esc := loc.paramEsc
|
||||||
esc.Optimize()
|
esc.Optimize()
|
||||||
|
|
||||||
if Debug['m'] != 0 && !loc.escapes {
|
if Debug.m != 0 && !loc.escapes {
|
||||||
if esc.Empty() {
|
if esc.Empty() {
|
||||||
Warnl(f.Pos, "%v does not escape", name())
|
Warnl(f.Pos, "%v does not escape", name())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ func (e *Escape) initFunc(fn *Node) {
|
||||||
Fatalf("unexpected node: %v", fn)
|
Fatalf("unexpected node: %v", fn)
|
||||||
}
|
}
|
||||||
fn.Esc = EscFuncPlanned
|
fn.Esc = EscFuncPlanned
|
||||||
if Debug['m'] > 3 {
|
if Debug.m > 3 {
|
||||||
Dump("escAnalyze", fn)
|
Dump("escAnalyze", fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -247,7 +247,7 @@ func (e *Escape) stmt(n *Node) {
|
||||||
lineno = lno
|
lineno = lno
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if Debug['m'] > 2 {
|
if Debug.m > 2 {
|
||||||
fmt.Printf("%v:[%d] %v stmt: %v\n", linestr(lineno), e.loopDepth, funcSym(e.curfn), n)
|
fmt.Printf("%v:[%d] %v stmt: %v\n", linestr(lineno), e.loopDepth, funcSym(e.curfn), n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -275,11 +275,11 @@ func (e *Escape) stmt(n *Node) {
|
||||||
case OLABEL:
|
case OLABEL:
|
||||||
switch asNode(n.Sym.Label) {
|
switch asNode(n.Sym.Label) {
|
||||||
case &nonlooping:
|
case &nonlooping:
|
||||||
if Debug['m'] > 2 {
|
if Debug.m > 2 {
|
||||||
fmt.Printf("%v:%v non-looping label\n", linestr(lineno), n)
|
fmt.Printf("%v:%v non-looping label\n", linestr(lineno), n)
|
||||||
}
|
}
|
||||||
case &looping:
|
case &looping:
|
||||||
if Debug['m'] > 2 {
|
if Debug.m > 2 {
|
||||||
fmt.Printf("%v: %v looping label\n", linestr(lineno), n)
|
fmt.Printf("%v: %v looping label\n", linestr(lineno), n)
|
||||||
}
|
}
|
||||||
e.loopDepth++
|
e.loopDepth++
|
||||||
|
|
@ -717,7 +717,7 @@ func (e *Escape) addrs(l Nodes) []EscHole {
|
||||||
func (e *Escape) assign(dst, src *Node, why string, where *Node) {
|
func (e *Escape) assign(dst, src *Node, why string, where *Node) {
|
||||||
// Filter out some no-op assignments for escape analysis.
|
// Filter out some no-op assignments for escape analysis.
|
||||||
ignore := dst != nil && src != nil && isSelfAssign(dst, src)
|
ignore := dst != nil && src != nil && isSelfAssign(dst, src)
|
||||||
if ignore && Debug['m'] != 0 {
|
if ignore && Debug.m != 0 {
|
||||||
Warnl(where.Pos, "%v ignoring self-assignment in %S", funcSym(e.curfn), where)
|
Warnl(where.Pos, "%v ignoring self-assignment in %S", funcSym(e.curfn), where)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -771,10 +771,11 @@ func (e *Escape) call(ks []EscHole, call, where *Node) {
|
||||||
var fn *Node
|
var fn *Node
|
||||||
switch call.Op {
|
switch call.Op {
|
||||||
case OCALLFUNC:
|
case OCALLFUNC:
|
||||||
if call.Left.Op == ONAME && call.Left.Class() == PFUNC {
|
switch v := staticValue(call.Left); {
|
||||||
fn = call.Left
|
case v.Op == ONAME && v.Class() == PFUNC:
|
||||||
} else if call.Left.Op == OCLOSURE {
|
fn = v
|
||||||
fn = call.Left.Func.Closure.Func.Nname
|
case v.Op == OCLOSURE:
|
||||||
|
fn = v.Func.Closure.Func.Nname
|
||||||
}
|
}
|
||||||
case OCALLMETH:
|
case OCALLMETH:
|
||||||
fn = asNode(call.Left.Type.FuncType().Nname)
|
fn = asNode(call.Left.Type.FuncType().Nname)
|
||||||
|
|
@ -930,7 +931,7 @@ func (k EscHole) note(where *Node, why string) EscHole {
|
||||||
if where == nil || why == "" {
|
if where == nil || why == "" {
|
||||||
Fatalf("note: missing where/why")
|
Fatalf("note: missing where/why")
|
||||||
}
|
}
|
||||||
if Debug['m'] >= 2 || logopt.Enabled() {
|
if Debug.m >= 2 || logopt.Enabled() {
|
||||||
k.notes = &EscNote{
|
k.notes = &EscNote{
|
||||||
next: k.notes,
|
next: k.notes,
|
||||||
where: where,
|
where: where,
|
||||||
|
|
@ -1076,9 +1077,9 @@ func (e *Escape) flow(k EscHole, src *EscLocation) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if dst.escapes && k.derefs < 0 { // dst = &src
|
if dst.escapes && k.derefs < 0 { // dst = &src
|
||||||
if Debug['m'] >= 2 || logopt.Enabled() {
|
if Debug.m >= 2 || logopt.Enabled() {
|
||||||
pos := linestr(src.n.Pos)
|
pos := linestr(src.n.Pos)
|
||||||
if Debug['m'] >= 2 {
|
if Debug.m >= 2 {
|
||||||
fmt.Printf("%s: %v escapes to heap:\n", pos, src.n)
|
fmt.Printf("%s: %v escapes to heap:\n", pos, src.n)
|
||||||
}
|
}
|
||||||
explanation := e.explainFlow(pos, dst, src, k.derefs, k.notes, []*logopt.LoggedOpt{})
|
explanation := e.explainFlow(pos, dst, src, k.derefs, k.notes, []*logopt.LoggedOpt{})
|
||||||
|
|
@ -1178,8 +1179,8 @@ func (e *Escape) walkOne(root *EscLocation, walkgen uint32, enqueue func(*EscLoc
|
||||||
// that value flow for tagging the function
|
// that value flow for tagging the function
|
||||||
// later.
|
// later.
|
||||||
if l.isName(PPARAM) {
|
if l.isName(PPARAM) {
|
||||||
if (logopt.Enabled() || Debug['m'] >= 2) && !l.escapes {
|
if (logopt.Enabled() || Debug.m >= 2) && !l.escapes {
|
||||||
if Debug['m'] >= 2 {
|
if Debug.m >= 2 {
|
||||||
fmt.Printf("%s: parameter %v leaks to %s with derefs=%d:\n", linestr(l.n.Pos), l.n, e.explainLoc(root), base)
|
fmt.Printf("%s: parameter %v leaks to %s with derefs=%d:\n", linestr(l.n.Pos), l.n, e.explainLoc(root), base)
|
||||||
}
|
}
|
||||||
explanation := e.explainPath(root, l)
|
explanation := e.explainPath(root, l)
|
||||||
|
|
@ -1195,8 +1196,8 @@ func (e *Escape) walkOne(root *EscLocation, walkgen uint32, enqueue func(*EscLoc
|
||||||
// outlives it, then l needs to be heap
|
// outlives it, then l needs to be heap
|
||||||
// allocated.
|
// allocated.
|
||||||
if addressOf && !l.escapes {
|
if addressOf && !l.escapes {
|
||||||
if logopt.Enabled() || Debug['m'] >= 2 {
|
if logopt.Enabled() || Debug.m >= 2 {
|
||||||
if Debug['m'] >= 2 {
|
if Debug.m >= 2 {
|
||||||
fmt.Printf("%s: %v escapes to heap:\n", linestr(l.n.Pos), l.n)
|
fmt.Printf("%s: %v escapes to heap:\n", linestr(l.n.Pos), l.n)
|
||||||
}
|
}
|
||||||
explanation := e.explainPath(root, l)
|
explanation := e.explainPath(root, l)
|
||||||
|
|
@ -1234,7 +1235,7 @@ func (e *Escape) explainPath(root, src *EscLocation) []*logopt.LoggedOpt {
|
||||||
for {
|
for {
|
||||||
// Prevent infinite loop.
|
// Prevent infinite loop.
|
||||||
if visited[src] {
|
if visited[src] {
|
||||||
if Debug['m'] >= 2 {
|
if Debug.m >= 2 {
|
||||||
fmt.Printf("%s: warning: truncated explanation due to assignment cycle; see golang.org/issue/35518\n", pos)
|
fmt.Printf("%s: warning: truncated explanation due to assignment cycle; see golang.org/issue/35518\n", pos)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
@ -1262,7 +1263,7 @@ func (e *Escape) explainFlow(pos string, dst, srcloc *EscLocation, derefs int, n
|
||||||
if derefs >= 0 {
|
if derefs >= 0 {
|
||||||
ops = strings.Repeat("*", derefs)
|
ops = strings.Repeat("*", derefs)
|
||||||
}
|
}
|
||||||
print := Debug['m'] >= 2
|
print := Debug.m >= 2
|
||||||
|
|
||||||
flow := fmt.Sprintf(" flow: %s = %s%v:", e.explainLoc(dst), ops, e.explainLoc(srcloc))
|
flow := fmt.Sprintf(" flow: %s = %s%v:", e.explainLoc(dst), ops, e.explainLoc(srcloc))
|
||||||
if print {
|
if print {
|
||||||
|
|
@ -1416,7 +1417,7 @@ func (e *Escape) finish(fns []*Node) {
|
||||||
|
|
||||||
if loc.escapes {
|
if loc.escapes {
|
||||||
if n.Op != ONAME {
|
if n.Op != ONAME {
|
||||||
if Debug['m'] != 0 {
|
if Debug.m != 0 {
|
||||||
Warnl(n.Pos, "%S escapes to heap", n)
|
Warnl(n.Pos, "%S escapes to heap", n)
|
||||||
}
|
}
|
||||||
if logopt.Enabled() {
|
if logopt.Enabled() {
|
||||||
|
|
@ -1426,7 +1427,7 @@ func (e *Escape) finish(fns []*Node) {
|
||||||
n.Esc = EscHeap
|
n.Esc = EscHeap
|
||||||
addrescapes(n)
|
addrescapes(n)
|
||||||
} else {
|
} else {
|
||||||
if Debug['m'] != 0 && n.Op != ONAME {
|
if Debug.m != 0 && n.Op != ONAME {
|
||||||
Warnl(n.Pos, "%S does not escape", n)
|
Warnl(n.Pos, "%S does not escape", n)
|
||||||
}
|
}
|
||||||
n.Esc = EscNone
|
n.Esc = EscNone
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ func exportsym(n *Node) {
|
||||||
}
|
}
|
||||||
n.Sym.SetOnExportList(true)
|
n.Sym.SetOnExportList(true)
|
||||||
|
|
||||||
if Debug['E'] != 0 {
|
if Debug.E != 0 {
|
||||||
fmt.Printf("export symbol %v\n", n.Sym)
|
fmt.Printf("export symbol %v\n", n.Sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -150,7 +150,7 @@ func importconst(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type, val
|
||||||
|
|
||||||
n.SetVal(val)
|
n.SetVal(val)
|
||||||
|
|
||||||
if Debug['E'] != 0 {
|
if Debug.E != 0 {
|
||||||
fmt.Printf("import const %v %L = %v\n", s, t, val)
|
fmt.Printf("import const %v %L = %v\n", s, t, val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +166,7 @@ func importfunc(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
|
||||||
n.Func = new(Func)
|
n.Func = new(Func)
|
||||||
t.SetNname(asTypesNode(n))
|
t.SetNname(asTypesNode(n))
|
||||||
|
|
||||||
if Debug['E'] != 0 {
|
if Debug.E != 0 {
|
||||||
fmt.Printf("import func %v%S\n", s, t)
|
fmt.Printf("import func %v%S\n", s, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +179,7 @@ func importvar(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug['E'] != 0 {
|
if Debug.E != 0 {
|
||||||
fmt.Printf("import var %v %L\n", s, t)
|
fmt.Printf("import var %v %L\n", s, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -192,7 +192,7 @@ func importalias(ipkg *types.Pkg, pos src.XPos, s *types.Sym, t *types.Type) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug['E'] != 0 {
|
if Debug.E != 0 {
|
||||||
fmt.Printf("import type %v = %L\n", s, t)
|
fmt.Printf("import type %v = %L\n", s, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -792,6 +792,13 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if mode == FDbg {
|
||||||
|
b.WriteString(t.Etype.String())
|
||||||
|
b.WriteByte('-')
|
||||||
|
tconv2(b, t, flag, FErr, visited)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// At this point, we might call tconv2 recursively. Add the current type to the visited list so we don't
|
// At this point, we might call tconv2 recursively. Add the current type to the visited list so we don't
|
||||||
// try to print it recursively.
|
// try to print it recursively.
|
||||||
// We record the offset in the result buffer where the type's text starts. This offset serves as a reference
|
// We record the offset in the result buffer where the type's text starts. This offset serves as a reference
|
||||||
|
|
@ -805,12 +812,6 @@ func tconv2(b *bytes.Buffer, t *types.Type, flag FmtFlag, mode fmtMode, visited
|
||||||
visited[t] = b.Len()
|
visited[t] = b.Len()
|
||||||
defer delete(visited, t)
|
defer delete(visited, t)
|
||||||
|
|
||||||
if mode == FDbg {
|
|
||||||
b.WriteString(t.Etype.String())
|
|
||||||
b.WriteByte('-')
|
|
||||||
tconv2(b, t, flag, FErr, visited)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
switch t.Etype {
|
switch t.Etype {
|
||||||
case TPTR:
|
case TPTR:
|
||||||
b.WriteByte('*')
|
b.WriteByte('*')
|
||||||
|
|
@ -1333,7 +1334,7 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
|
||||||
n.Orig.exprfmt(s, prec, mode)
|
n.Orig.exprfmt(s, prec, mode)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if n.Type != nil && n.Type.Etype != TIDEAL && n.Type.Etype != TNIL && n.Type != types.UntypedBool && n.Type != types.UntypedString {
|
if n.Type != nil && !n.Type.IsUntyped() {
|
||||||
// Need parens when type begins with what might
|
// Need parens when type begins with what might
|
||||||
// be misinterpreted as a unary operator: * or <-.
|
// be misinterpreted as a unary operator: * or <-.
|
||||||
if n.Type.IsPtr() || (n.Type.IsChan() && n.Type.ChanDir() == types.Crecv) {
|
if n.Type.IsPtr() || (n.Type.IsChan() && n.Type.ChanDir() == types.Crecv) {
|
||||||
|
|
|
||||||
|
|
@ -61,12 +61,12 @@ type Class uint8
|
||||||
//go:generate stringer -type=Class
|
//go:generate stringer -type=Class
|
||||||
const (
|
const (
|
||||||
Pxxx Class = iota // no class; used during ssa conversion to indicate pseudo-variables
|
Pxxx Class = iota // no class; used during ssa conversion to indicate pseudo-variables
|
||||||
PEXTERN // global variable
|
PEXTERN // global variables
|
||||||
PAUTO // local variables
|
PAUTO // local variables
|
||||||
PAUTOHEAP // local variable or parameter moved to heap
|
PAUTOHEAP // local variables or parameters moved to heap
|
||||||
PPARAM // input arguments
|
PPARAM // input arguments
|
||||||
PPARAMOUT // output results
|
PPARAMOUT // output results
|
||||||
PFUNC // global function
|
PFUNC // global functions
|
||||||
|
|
||||||
// Careful: Class is stored in three bits in Node.flags.
|
// Careful: Class is stored in three bits in Node.flags.
|
||||||
_ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3)
|
_ = uint((1 << 3) - iota) // static assert for iota <= (1 << 3)
|
||||||
|
|
@ -116,7 +116,15 @@ var decldepth int32
|
||||||
|
|
||||||
var nolocalimports bool
|
var nolocalimports bool
|
||||||
|
|
||||||
var Debug [256]int
|
// gc debug flags
|
||||||
|
type DebugFlags struct {
|
||||||
|
P, B, C, E, G,
|
||||||
|
K, L, N, S,
|
||||||
|
W, e, h, j,
|
||||||
|
l, m, r, w int
|
||||||
|
}
|
||||||
|
|
||||||
|
var Debug DebugFlags
|
||||||
|
|
||||||
var debugstr string
|
var debugstr string
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,7 @@ func (pp *Progs) Prog(as obj.As) *obj.Prog {
|
||||||
pp.clearp(pp.next)
|
pp.clearp(pp.next)
|
||||||
p.Link = pp.next
|
p.Link = pp.next
|
||||||
|
|
||||||
if !pp.pos.IsKnown() && Debug['K'] != 0 {
|
if !pp.pos.IsKnown() && Debug.K != 0 {
|
||||||
Warn("prog: unknown position (line 0)")
|
Warn("prog: unknown position (line 0)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -199,7 +199,7 @@ func (pp *Progs) settext(fn *Node) {
|
||||||
ptxt := pp.Prog(obj.ATEXT)
|
ptxt := pp.Prog(obj.ATEXT)
|
||||||
pp.Text = ptxt
|
pp.Text = ptxt
|
||||||
|
|
||||||
fn.Func.lsym.Func.Text = ptxt
|
fn.Func.lsym.Func().Text = ptxt
|
||||||
ptxt.From.Type = obj.TYPE_MEM
|
ptxt.From.Type = obj.TYPE_MEM
|
||||||
ptxt.From.Name = obj.NAME_EXTERN
|
ptxt.From.Name = obj.NAME_EXTERN
|
||||||
ptxt.From.Sym = fn.Func.lsym
|
ptxt.From.Sym = fn.Func.lsym
|
||||||
|
|
|
||||||
|
|
@ -1266,8 +1266,13 @@ func (w *exportWriter) expr(n *Node) {
|
||||||
// case OSTRUCTKEY:
|
// case OSTRUCTKEY:
|
||||||
// unreachable - handled in case OSTRUCTLIT by elemList
|
// unreachable - handled in case OSTRUCTLIT by elemList
|
||||||
|
|
||||||
// case OCALLPART:
|
case OCALLPART:
|
||||||
// unimplemented - handled by default case
|
// An OCALLPART is an OXDOT before type checking.
|
||||||
|
w.op(OXDOT)
|
||||||
|
w.pos(n.Pos)
|
||||||
|
w.expr(n.Left)
|
||||||
|
// Right node should be ONAME
|
||||||
|
w.selector(n.Right.Sym)
|
||||||
|
|
||||||
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
|
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
|
||||||
w.op(OXDOT)
|
w.op(OXDOT)
|
||||||
|
|
|
||||||
|
|
@ -742,8 +742,8 @@ func (r *importReader) doInline(n *Node) {
|
||||||
|
|
||||||
importlist = append(importlist, n)
|
importlist = append(importlist, n)
|
||||||
|
|
||||||
if Debug['E'] > 0 && Debug['m'] > 2 {
|
if Debug.E > 0 && Debug.m > 2 {
|
||||||
if Debug['m'] > 3 {
|
if Debug.m > 3 {
|
||||||
fmt.Printf("inl body for %v %#v: %+v\n", n, n.Type, asNodes(n.Func.Inl.Body))
|
fmt.Printf("inl body for %v %#v: %+v\n", n, n.Type, asNodes(n.Func.Inl.Body))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("inl body for %v %#v: %v\n", n, n.Type, asNodes(n.Func.Inl.Body))
|
fmt.Printf("inl body for %v %#v: %v\n", n, n.Type, asNodes(n.Func.Inl.Body))
|
||||||
|
|
@ -866,7 +866,7 @@ func (r *importReader) node() *Node {
|
||||||
// unreachable - handled in case OSTRUCTLIT by elemList
|
// unreachable - handled in case OSTRUCTLIT by elemList
|
||||||
|
|
||||||
// case OCALLPART:
|
// case OCALLPART:
|
||||||
// unimplemented
|
// unreachable - mapped to case OXDOT below by exporter
|
||||||
|
|
||||||
// case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
|
// case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
|
||||||
// unreachable - mapped to case OXDOT below by exporter
|
// unreachable - mapped to case OXDOT below by exporter
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
// saves a copy of the body. Then inlcalls walks each function body to
|
// saves a copy of the body. Then inlcalls walks each function body to
|
||||||
// expand calls to inlinable functions.
|
// expand calls to inlinable functions.
|
||||||
//
|
//
|
||||||
// The debug['l'] flag controls the aggressiveness. Note that main() swaps level 0 and 1,
|
// The Debug.l flag controls the aggressiveness. Note that main() swaps level 0 and 1,
|
||||||
// making 1 the default and -l disable. Additional levels (beyond -l) may be buggy and
|
// making 1 the default and -l disable. Additional levels (beyond -l) may be buggy and
|
||||||
// are not supported.
|
// are not supported.
|
||||||
// 0: disabled
|
// 0: disabled
|
||||||
|
|
@ -21,7 +21,7 @@
|
||||||
// The -d typcheckinl flag enables early typechecking of all imported bodies,
|
// The -d typcheckinl flag enables early typechecking of all imported bodies,
|
||||||
// which is useful to flush out bugs.
|
// which is useful to flush out bugs.
|
||||||
//
|
//
|
||||||
// The debug['m'] flag enables diagnostic output. a single -m is useful for verifying
|
// The Debug.m flag enables diagnostic output. a single -m is useful for verifying
|
||||||
// which calls get inlined or not, more is for debugging, and may go away at any point.
|
// which calls get inlined or not, more is for debugging, and may go away at any point.
|
||||||
|
|
||||||
package gc
|
package gc
|
||||||
|
|
@ -85,7 +85,7 @@ func typecheckinl(fn *Node) {
|
||||||
return // typecheckinl on local function
|
return // typecheckinl on local function
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug['m'] > 2 || Debug_export != 0 {
|
if Debug.m > 2 || Debug_export != 0 {
|
||||||
fmt.Printf("typecheck import [%v] %L { %#v }\n", fn.Sym, fn, asNodes(fn.Func.Inl.Body))
|
fmt.Printf("typecheck import [%v] %L { %#v }\n", fn.Sym, fn, asNodes(fn.Func.Inl.Body))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,10 +116,10 @@ func caninl(fn *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var reason string // reason, if any, that the function was not inlined
|
var reason string // reason, if any, that the function was not inlined
|
||||||
if Debug['m'] > 1 || logopt.Enabled() {
|
if Debug.m > 1 || logopt.Enabled() {
|
||||||
defer func() {
|
defer func() {
|
||||||
if reason != "" {
|
if reason != "" {
|
||||||
if Debug['m'] > 1 {
|
if Debug.m > 1 {
|
||||||
fmt.Printf("%v: cannot inline %v: %s\n", fn.Line(), fn.Func.Nname, reason)
|
fmt.Printf("%v: cannot inline %v: %s\n", fn.Line(), fn.Func.Nname, reason)
|
||||||
}
|
}
|
||||||
if logopt.Enabled() {
|
if logopt.Enabled() {
|
||||||
|
|
@ -187,7 +187,7 @@ func caninl(fn *Node) {
|
||||||
defer n.Func.SetInlinabilityChecked(true)
|
defer n.Func.SetInlinabilityChecked(true)
|
||||||
|
|
||||||
cc := int32(inlineExtraCallCost)
|
cc := int32(inlineExtraCallCost)
|
||||||
if Debug['l'] == 4 {
|
if Debug.l == 4 {
|
||||||
cc = 1 // this appears to yield better performance than 0.
|
cc = 1 // this appears to yield better performance than 0.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -224,9 +224,9 @@ func caninl(fn *Node) {
|
||||||
// this is so export can find the body of a method
|
// this is so export can find the body of a method
|
||||||
fn.Type.FuncType().Nname = asTypesNode(n)
|
fn.Type.FuncType().Nname = asTypesNode(n)
|
||||||
|
|
||||||
if Debug['m'] > 1 {
|
if Debug.m > 1 {
|
||||||
fmt.Printf("%v: can inline %#v with cost %d as: %#v { %#v }\n", fn.Line(), n, inlineMaxBudget-visitor.budget, fn.Type, asNodes(n.Func.Inl.Body))
|
fmt.Printf("%v: can inline %#v with cost %d as: %#v { %#v }\n", fn.Line(), n, inlineMaxBudget-visitor.budget, fn.Type, asNodes(n.Func.Inl.Body))
|
||||||
} else if Debug['m'] != 0 {
|
} else if Debug.m != 0 {
|
||||||
fmt.Printf("%v: can inline %v\n", fn.Line(), n)
|
fmt.Printf("%v: can inline %v\n", fn.Line(), n)
|
||||||
}
|
}
|
||||||
if logopt.Enabled() {
|
if logopt.Enabled() {
|
||||||
|
|
@ -325,18 +325,10 @@ func (v *hairyVisitor) visit(n *Node) bool {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if fn := n.Left.Func; fn != nil && fn.Inl != nil {
|
if fn := inlCallee(n.Left); fn != nil && fn.Func.Inl != nil {
|
||||||
v.budget -= fn.Inl.Cost
|
v.budget -= fn.Func.Inl.Cost
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if n.Left.isMethodExpression() {
|
|
||||||
if d := asNode(n.Left.Sym.Def); d != nil && d.Func.Inl != nil {
|
|
||||||
v.budget -= d.Func.Inl.Cost
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO(mdempsky): Budget for OCLOSURE calls if we
|
|
||||||
// ever allow that. See #15561 and #23093.
|
|
||||||
|
|
||||||
// Call cost for non-leaf inlining.
|
// Call cost for non-leaf inlining.
|
||||||
v.budget -= v.extraCallCost
|
v.budget -= v.extraCallCost
|
||||||
|
|
@ -382,17 +374,16 @@ func (v *hairyVisitor) visit(n *Node) bool {
|
||||||
v.reason = "call to recover"
|
v.reason = "call to recover"
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
case OCALLPART:
|
||||||
|
// OCALLPART is inlineable, but no extra cost to the budget
|
||||||
|
|
||||||
case OCLOSURE,
|
case OCLOSURE,
|
||||||
OCALLPART,
|
|
||||||
ORANGE,
|
ORANGE,
|
||||||
OFOR,
|
|
||||||
OFORUNTIL,
|
|
||||||
OSELECT,
|
OSELECT,
|
||||||
OTYPESW,
|
OTYPESW,
|
||||||
OGO,
|
OGO,
|
||||||
ODEFER,
|
ODEFER,
|
||||||
ODCLTYPE, // can't print yet
|
ODCLTYPE, // can't print yet
|
||||||
OBREAK,
|
|
||||||
ORETJMP:
|
ORETJMP:
|
||||||
v.reason = "unhandled op " + n.Op.String()
|
v.reason = "unhandled op " + n.Op.String()
|
||||||
return true
|
return true
|
||||||
|
|
@ -400,10 +391,23 @@ func (v *hairyVisitor) visit(n *Node) bool {
|
||||||
case OAPPEND:
|
case OAPPEND:
|
||||||
v.budget -= inlineExtraAppendCost
|
v.budget -= inlineExtraAppendCost
|
||||||
|
|
||||||
case ODCLCONST, OEMPTY, OFALL, OLABEL:
|
case ODCLCONST, OEMPTY, OFALL:
|
||||||
// These nodes don't produce code; omit from inlining budget.
|
// These nodes don't produce code; omit from inlining budget.
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
case OLABEL:
|
||||||
|
// TODO(mdempsky): Add support for inlining labeled control statements.
|
||||||
|
if n.labeledControl() != nil {
|
||||||
|
v.reason = "labeled control"
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
case OBREAK, OCONTINUE:
|
||||||
|
if n.Sym != nil {
|
||||||
|
// Should have short-circuited due to labeledControl above.
|
||||||
|
Fatalf("unexpected labeled break/continue: %v", n)
|
||||||
|
}
|
||||||
|
|
||||||
case OIF:
|
case OIF:
|
||||||
if Isconst(n.Left, CTBOOL) {
|
if Isconst(n.Left, CTBOOL) {
|
||||||
// This if and the condition cost nothing.
|
// This if and the condition cost nothing.
|
||||||
|
|
@ -421,7 +425,7 @@ func (v *hairyVisitor) visit(n *Node) bool {
|
||||||
v.budget--
|
v.budget--
|
||||||
|
|
||||||
// When debugging, don't stop early, to get full cost of inlining this function
|
// When debugging, don't stop early, to get full cost of inlining this function
|
||||||
if v.budget < 0 && Debug['m'] < 2 && !logopt.Enabled() {
|
if v.budget < 0 && Debug.m < 2 && !logopt.Enabled() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -452,7 +456,7 @@ func inlcopy(n *Node) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
m := n.copy()
|
m := n.copy()
|
||||||
if m.Func != nil {
|
if n.Op != OCALLPART && m.Func != nil {
|
||||||
Fatalf("unexpected Func: %v", m)
|
Fatalf("unexpected Func: %v", m)
|
||||||
}
|
}
|
||||||
m.Left = inlcopy(n.Left)
|
m.Left = inlcopy(n.Left)
|
||||||
|
|
@ -666,60 +670,18 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
|
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case OCALLFUNC:
|
case OCALLFUNC:
|
||||||
if Debug['m'] > 3 {
|
if Debug.m > 3 {
|
||||||
fmt.Printf("%v:call to func %+v\n", n.Line(), n.Left)
|
fmt.Printf("%v:call to func %+v\n", n.Line(), n.Left)
|
||||||
}
|
}
|
||||||
if n.Left.Func != nil && n.Left.Func.Inl != nil && !isIntrinsicCall(n) { // normal case
|
if isIntrinsicCall(n) {
|
||||||
n = mkinlcall(n, n.Left, maxCost, inlMap)
|
|
||||||
} else if n.Left.isMethodExpression() && asNode(n.Left.Sym.Def) != nil {
|
|
||||||
n = mkinlcall(n, asNode(n.Left.Sym.Def), maxCost, inlMap)
|
|
||||||
} else if n.Left.Op == OCLOSURE {
|
|
||||||
if f := inlinableClosure(n.Left); f != nil {
|
|
||||||
n = mkinlcall(n, f, maxCost, inlMap)
|
|
||||||
}
|
|
||||||
} else if n.Left.Op == ONAME && n.Left.Name != nil && n.Left.Name.Defn != nil {
|
|
||||||
if d := n.Left.Name.Defn; d.Op == OAS && d.Right.Op == OCLOSURE {
|
|
||||||
if f := inlinableClosure(d.Right); f != nil {
|
|
||||||
// NB: this check is necessary to prevent indirect re-assignment of the variable
|
|
||||||
// having the address taken after the invocation or only used for reads is actually fine
|
|
||||||
// but we have no easy way to distinguish the safe cases
|
|
||||||
if d.Left.Name.Addrtaken() {
|
|
||||||
if Debug['m'] > 1 {
|
|
||||||
fmt.Printf("%v: cannot inline escaping closure variable %v\n", n.Line(), n.Left)
|
|
||||||
}
|
|
||||||
if logopt.Enabled() {
|
|
||||||
logopt.LogOpt(n.Pos, "cannotInlineCall", "inline", Curfn.funcname(),
|
|
||||||
fmt.Sprintf("%v cannot be inlined (escaping closure variable)", n.Left))
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if fn := inlCallee(n.Left); fn != nil && fn.Func.Inl != nil {
|
||||||
// ensure the variable is never re-assigned
|
n = mkinlcall(n, fn, maxCost, inlMap)
|
||||||
if unsafe, a := reassigned(n.Left); unsafe {
|
|
||||||
if Debug['m'] > 1 {
|
|
||||||
if a != nil {
|
|
||||||
fmt.Printf("%v: cannot inline re-assigned closure variable at %v: %v\n", n.Line(), a.Line(), a)
|
|
||||||
if logopt.Enabled() {
|
|
||||||
logopt.LogOpt(n.Pos, "cannotInlineCall", "inline", Curfn.funcname(),
|
|
||||||
fmt.Sprintf("%v cannot be inlined (re-assigned closure variable)", a))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fmt.Printf("%v: cannot inline global closure variable %v\n", n.Line(), n.Left)
|
|
||||||
if logopt.Enabled() {
|
|
||||||
logopt.LogOpt(n.Pos, "cannotInlineCall", "inline", Curfn.funcname(),
|
|
||||||
fmt.Sprintf("%v cannot be inlined (global closure variable)", n.Left))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
n = mkinlcall(n, f, maxCost, inlMap)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case OCALLMETH:
|
case OCALLMETH:
|
||||||
if Debug['m'] > 3 {
|
if Debug.m > 3 {
|
||||||
fmt.Printf("%v:call to meth %L\n", n.Line(), n.Left.Right)
|
fmt.Printf("%v:call to meth %L\n", n.Line(), n.Left.Right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -739,16 +701,73 @@ func inlnode(n *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// inlinableClosure takes an OCLOSURE node and follows linkage to the matching ONAME with
|
// inlCallee takes a function-typed expression and returns the underlying function ONAME
|
||||||
// the inlinable body. Returns nil if the function is not inlinable.
|
// that it refers to if statically known. Otherwise, it returns nil.
|
||||||
func inlinableClosure(n *Node) *Node {
|
func inlCallee(fn *Node) *Node {
|
||||||
c := n.Func.Closure
|
fn = staticValue(fn)
|
||||||
|
switch {
|
||||||
|
case fn.Op == ONAME && fn.Class() == PFUNC:
|
||||||
|
if fn.isMethodExpression() {
|
||||||
|
return asNode(fn.Sym.Def)
|
||||||
|
}
|
||||||
|
return fn
|
||||||
|
case fn.Op == OCLOSURE:
|
||||||
|
c := fn.Func.Closure
|
||||||
caninl(c)
|
caninl(c)
|
||||||
f := c.Func.Nname
|
return c.Func.Nname
|
||||||
if f == nil || f.Func.Inl == nil {
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func staticValue(n *Node) *Node {
|
||||||
|
for {
|
||||||
|
n1 := staticValue1(n)
|
||||||
|
if n1 == nil {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
n = n1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// staticValue1 implements a simple SSA-like optimization. If n is a local variable
|
||||||
|
// that is initialized and never reassigned, staticValue1 returns the initializer
|
||||||
|
// expression. Otherwise, it returns nil.
|
||||||
|
func staticValue1(n *Node) *Node {
|
||||||
|
if n.Op != ONAME || n.Class() != PAUTO || n.Name.Addrtaken() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return f
|
|
||||||
|
defn := n.Name.Defn
|
||||||
|
if defn == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var rhs *Node
|
||||||
|
FindRHS:
|
||||||
|
switch defn.Op {
|
||||||
|
case OAS:
|
||||||
|
rhs = defn.Right
|
||||||
|
case OAS2:
|
||||||
|
for i, lhs := range defn.List.Slice() {
|
||||||
|
if lhs == n {
|
||||||
|
rhs = defn.Rlist.Index(i)
|
||||||
|
break FindRHS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fatalf("%v missing from LHS of %v", n, defn)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if rhs == nil {
|
||||||
|
Fatalf("RHS is nil: %v", defn)
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe, _ := reassigned(n)
|
||||||
|
if unsafe {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return rhs
|
||||||
}
|
}
|
||||||
|
|
||||||
// reassigned takes an ONAME node, walks the function in which it is defined, and returns a boolean
|
// reassigned takes an ONAME node, walks the function in which it is defined, and returns a boolean
|
||||||
|
|
@ -831,16 +850,19 @@ func (v *reassignVisitor) visitList(l Nodes) *Node {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func tinlvar(t *types.Field, inlvars map[*Node]*Node) *Node {
|
func inlParam(t *types.Field, as *Node, inlvars map[*Node]*Node) *Node {
|
||||||
if n := asNode(t.Nname); n != nil && !n.isBlank() {
|
n := asNode(t.Nname)
|
||||||
inlvar := inlvars[n]
|
if n == nil || n.isBlank() {
|
||||||
if inlvar == nil {
|
return nblank
|
||||||
Fatalf("missing inlvar for %v\n", n)
|
|
||||||
}
|
|
||||||
return inlvar
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return typecheck(nblank, ctxExpr|ctxAssign)
|
inlvar := inlvars[n]
|
||||||
|
if inlvar == nil {
|
||||||
|
Fatalf("missing inlvar for %v", n)
|
||||||
|
}
|
||||||
|
as.Ninit.Append(nod(ODCL, inlvar, nil))
|
||||||
|
inlvar.Name.Defn = as
|
||||||
|
return inlvar
|
||||||
}
|
}
|
||||||
|
|
||||||
var inlgen int
|
var inlgen int
|
||||||
|
|
@ -889,7 +911,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
if inlMap[fn] {
|
if inlMap[fn] {
|
||||||
if Debug['m'] > 1 {
|
if Debug.m > 1 {
|
||||||
fmt.Printf("%v: cannot inline %v into %v: repeated recursive cycle\n", n.Line(), fn, Curfn.funcname())
|
fmt.Printf("%v: cannot inline %v into %v: repeated recursive cycle\n", n.Line(), fn, Curfn.funcname())
|
||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
|
|
@ -903,12 +925,12 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have a function node, and it has an inlineable body.
|
// We have a function node, and it has an inlineable body.
|
||||||
if Debug['m'] > 1 {
|
if Debug.m > 1 {
|
||||||
fmt.Printf("%v: inlining call to %v %#v { %#v }\n", n.Line(), fn.Sym, fn.Type, asNodes(fn.Func.Inl.Body))
|
fmt.Printf("%v: inlining call to %v %#v { %#v }\n", n.Line(), fn.Sym, fn.Type, asNodes(fn.Func.Inl.Body))
|
||||||
} else if Debug['m'] != 0 {
|
} else if Debug.m != 0 {
|
||||||
fmt.Printf("%v: inlining call to %v\n", n.Line(), fn)
|
fmt.Printf("%v: inlining call to %v\n", n.Line(), fn)
|
||||||
}
|
}
|
||||||
if Debug['m'] > 2 {
|
if Debug.m > 2 {
|
||||||
fmt.Printf("%v: Before inlining: %+v\n", n.Line(), n)
|
fmt.Printf("%v: Before inlining: %+v\n", n.Line(), n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -970,14 +992,15 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ln.isParamStackCopy() { // ignore the on-stack copy of a parameter that moved to the heap
|
if ln.isParamStackCopy() { // ignore the on-stack copy of a parameter that moved to the heap
|
||||||
continue
|
// TODO(mdempsky): Remove once I'm confident
|
||||||
}
|
// this never actually happens. We currently
|
||||||
inlvars[ln] = typecheck(inlvar(ln), ctxExpr)
|
// perform inlining before escape analysis, so
|
||||||
if ln.Class() == PPARAM || ln.Name.Param.Stackcopy != nil && ln.Name.Param.Stackcopy.Class() == PPARAM {
|
// nothing should have moved to the heap yet.
|
||||||
ninit.Append(nod(ODCL, inlvars[ln], nil))
|
Fatalf("impossible: %v", ln)
|
||||||
}
|
}
|
||||||
|
inlf := typecheck(inlvar(ln), ctxExpr)
|
||||||
|
inlvars[ln] = inlf
|
||||||
if genDwarfInline > 0 {
|
if genDwarfInline > 0 {
|
||||||
inlf := inlvars[ln]
|
|
||||||
if ln.Class() == PPARAM {
|
if ln.Class() == PPARAM {
|
||||||
inlf.Name.SetInlFormal(true)
|
inlf.Name.SetInlFormal(true)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1019,56 +1042,42 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
|
|
||||||
// Assign arguments to the parameters' temp names.
|
// Assign arguments to the parameters' temp names.
|
||||||
as := nod(OAS2, nil, nil)
|
as := nod(OAS2, nil, nil)
|
||||||
as.Rlist.Set(n.List.Slice())
|
as.SetColas(true)
|
||||||
|
if n.Op == OCALLMETH {
|
||||||
|
if n.Left.Left == nil {
|
||||||
|
Fatalf("method call without receiver: %+v", n)
|
||||||
|
}
|
||||||
|
as.Rlist.Append(n.Left.Left)
|
||||||
|
}
|
||||||
|
as.Rlist.Append(n.List.Slice()...)
|
||||||
|
|
||||||
// For non-dotted calls to variadic functions, we assign the
|
// For non-dotted calls to variadic functions, we assign the
|
||||||
// variadic parameter's temp name separately.
|
// variadic parameter's temp name separately.
|
||||||
var vas *Node
|
var vas *Node
|
||||||
|
|
||||||
if fn.IsMethod() {
|
if recv := fn.Type.Recv(); recv != nil {
|
||||||
rcv := fn.Type.Recv()
|
as.List.Append(inlParam(recv, as, inlvars))
|
||||||
|
|
||||||
if n.Left.Op == ODOTMETH {
|
|
||||||
// For x.M(...), assign x directly to the
|
|
||||||
// receiver parameter.
|
|
||||||
if n.Left.Left == nil {
|
|
||||||
Fatalf("method call without receiver: %+v", n)
|
|
||||||
}
|
}
|
||||||
ras := nod(OAS, tinlvar(rcv, inlvars), n.Left.Left)
|
|
||||||
ras = typecheck(ras, ctxStmt)
|
|
||||||
ninit.Append(ras)
|
|
||||||
} else {
|
|
||||||
// For T.M(...), add the receiver parameter to
|
|
||||||
// as.List, so it's assigned by the normal
|
|
||||||
// arguments.
|
|
||||||
if as.Rlist.Len() == 0 {
|
|
||||||
Fatalf("non-method call to method without first arg: %+v", n)
|
|
||||||
}
|
|
||||||
as.List.Append(tinlvar(rcv, inlvars))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, param := range fn.Type.Params().Fields().Slice() {
|
for _, param := range fn.Type.Params().Fields().Slice() {
|
||||||
// For ordinary parameters or variadic parameters in
|
// For ordinary parameters or variadic parameters in
|
||||||
// dotted calls, just add the variable to the
|
// dotted calls, just add the variable to the
|
||||||
// assignment list, and we're done.
|
// assignment list, and we're done.
|
||||||
if !param.IsDDD() || n.IsDDD() {
|
if !param.IsDDD() || n.IsDDD() {
|
||||||
as.List.Append(tinlvar(param, inlvars))
|
as.List.Append(inlParam(param, as, inlvars))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, we need to collect the remaining values
|
// Otherwise, we need to collect the remaining values
|
||||||
// to pass as a slice.
|
// to pass as a slice.
|
||||||
|
|
||||||
numvals := n.List.Len()
|
|
||||||
|
|
||||||
x := as.List.Len()
|
x := as.List.Len()
|
||||||
for as.List.Len() < numvals {
|
for as.List.Len() < as.Rlist.Len() {
|
||||||
as.List.Append(argvar(param.Type, as.List.Len()))
|
as.List.Append(argvar(param.Type, as.List.Len()))
|
||||||
}
|
}
|
||||||
varargs := as.List.Slice()[x:]
|
varargs := as.List.Slice()[x:]
|
||||||
|
|
||||||
vas = nod(OAS, tinlvar(param, inlvars), nil)
|
vas = nod(OAS, nil, nil)
|
||||||
|
vas.Left = inlParam(param, vas, inlvars)
|
||||||
if len(varargs) == 0 {
|
if len(varargs) == 0 {
|
||||||
vas.Right = nodnil()
|
vas.Right = nodnil()
|
||||||
vas.Right.Type = param.Type
|
vas.Right.Type = param.Type
|
||||||
|
|
@ -1165,7 +1174,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug['m'] > 2 {
|
if Debug.m > 2 {
|
||||||
fmt.Printf("%v: After inlining %+v\n\n", call.Line(), call)
|
fmt.Printf("%v: After inlining %+v\n\n", call.Line(), call)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1176,7 +1185,7 @@ func mkinlcall(n, fn *Node, maxCost int32, inlMap map[*Node]bool) *Node {
|
||||||
// PAUTO's in the calling functions, and link them off of the
|
// PAUTO's in the calling functions, and link them off of the
|
||||||
// PPARAM's, PAUTOS and PPARAMOUTs of the called function.
|
// PPARAM's, PAUTOS and PPARAMOUTs of the called function.
|
||||||
func inlvar(var_ *Node) *Node {
|
func inlvar(var_ *Node) *Node {
|
||||||
if Debug['m'] > 3 {
|
if Debug.m > 3 {
|
||||||
fmt.Printf("inlvar %+v\n", var_)
|
fmt.Printf("inlvar %+v\n", var_)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1255,13 +1264,13 @@ func (subst *inlsubst) node(n *Node) *Node {
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case ONAME:
|
case ONAME:
|
||||||
if inlvar := subst.inlvars[n]; inlvar != nil { // These will be set during inlnode
|
if inlvar := subst.inlvars[n]; inlvar != nil { // These will be set during inlnode
|
||||||
if Debug['m'] > 2 {
|
if Debug.m > 2 {
|
||||||
fmt.Printf("substituting name %+v -> %+v\n", n, inlvar)
|
fmt.Printf("substituting name %+v -> %+v\n", n, inlvar)
|
||||||
}
|
}
|
||||||
return inlvar
|
return inlvar
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug['m'] > 2 {
|
if Debug.m > 2 {
|
||||||
fmt.Printf("not substituting name %+v\n", n)
|
fmt.Printf("not substituting name %+v\n", n)
|
||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ func TestIntendedInlining(t *testing.T) {
|
||||||
"puintptr.ptr",
|
"puintptr.ptr",
|
||||||
"spanOf",
|
"spanOf",
|
||||||
"spanOfUnchecked",
|
"spanOfUnchecked",
|
||||||
//"(*gcWork).putFast", // TODO(austin): For debugging #27993
|
"(*gcWork).putFast",
|
||||||
"(*gcWork).tryGetFast",
|
"(*gcWork).tryGetFast",
|
||||||
"(*guintptr).set",
|
"(*guintptr).set",
|
||||||
"(*markBits).advance",
|
"(*markBits).advance",
|
||||||
|
|
@ -115,6 +115,7 @@ func TestIntendedInlining(t *testing.T) {
|
||||||
"byLiteral.Len",
|
"byLiteral.Len",
|
||||||
"byLiteral.Less",
|
"byLiteral.Less",
|
||||||
"byLiteral.Swap",
|
"byLiteral.Swap",
|
||||||
|
"(*dictDecoder).tryWriteCopy",
|
||||||
},
|
},
|
||||||
"encoding/base64": {
|
"encoding/base64": {
|
||||||
"assemble32",
|
"assemble32",
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,9 @@ const (
|
||||||
|
|
||||||
// Runtime and cgo type pragmas
|
// Runtime and cgo type pragmas
|
||||||
NotInHeap // values of this type must not be heap allocated
|
NotInHeap // values of this type must not be heap allocated
|
||||||
|
|
||||||
|
// Go command pragmas
|
||||||
|
GoBuildPragma
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -71,6 +74,8 @@ const (
|
||||||
|
|
||||||
func pragmaFlag(verb string) PragmaFlag {
|
func pragmaFlag(verb string) PragmaFlag {
|
||||||
switch verb {
|
switch verb {
|
||||||
|
case "go:build":
|
||||||
|
return GoBuildPragma
|
||||||
case "go:nointerface":
|
case "go:nointerface":
|
||||||
if objabi.Fieldtrack_enabled != 0 {
|
if objabi.Fieldtrack_enabled != 0 {
|
||||||
return Nointerface
|
return Nointerface
|
||||||
|
|
|
||||||
|
|
@ -211,19 +211,28 @@ func Main(archInit func(*Arch)) {
|
||||||
|
|
||||||
flag.BoolVar(&compiling_runtime, "+", false, "compiling runtime")
|
flag.BoolVar(&compiling_runtime, "+", false, "compiling runtime")
|
||||||
flag.BoolVar(&compiling_std, "std", false, "compiling standard library")
|
flag.BoolVar(&compiling_std, "std", false, "compiling standard library")
|
||||||
objabi.Flagcount("%", "debug non-static initializers", &Debug['%'])
|
|
||||||
objabi.Flagcount("B", "disable bounds checking", &Debug['B'])
|
|
||||||
objabi.Flagcount("C", "disable printing of columns in error messages", &Debug['C']) // TODO(gri) remove eventually
|
|
||||||
flag.StringVar(&localimport, "D", "", "set relative `path` for local imports")
|
flag.StringVar(&localimport, "D", "", "set relative `path` for local imports")
|
||||||
objabi.Flagcount("E", "debug symbol export", &Debug['E'])
|
|
||||||
objabi.Flagcount("G", "accept generic code", &Debug['G'])
|
objabi.Flagcount("%", "debug non-static initializers", &Debug.P)
|
||||||
|
objabi.Flagcount("B", "disable bounds checking", &Debug.B)
|
||||||
|
objabi.Flagcount("C", "disable printing of columns in error messages", &Debug.C)
|
||||||
|
objabi.Flagcount("E", "debug symbol export", &Debug.E)
|
||||||
|
objabi.Flagcount("G", "accept generic code", &Debug.G)
|
||||||
|
objabi.Flagcount("K", "debug missing line numbers", &Debug.K)
|
||||||
|
objabi.Flagcount("L", "show full file names in error messages", &Debug.L)
|
||||||
|
objabi.Flagcount("N", "disable optimizations", &Debug.N)
|
||||||
|
objabi.Flagcount("S", "print assembly listing", &Debug.S)
|
||||||
|
objabi.Flagcount("W", "debug parse tree after type checking", &Debug.W)
|
||||||
|
objabi.Flagcount("e", "no limit on number of errors reported", &Debug.e)
|
||||||
|
objabi.Flagcount("h", "halt on error", &Debug.h)
|
||||||
|
objabi.Flagcount("j", "debug runtime-initialized variables", &Debug.j)
|
||||||
|
objabi.Flagcount("l", "disable inlining", &Debug.l)
|
||||||
|
objabi.Flagcount("m", "print optimization decisions", &Debug.m)
|
||||||
|
objabi.Flagcount("r", "debug generated wrappers", &Debug.r)
|
||||||
|
objabi.Flagcount("w", "debug type checking", &Debug.w)
|
||||||
|
|
||||||
objabi.Flagfn1("I", "add `directory` to import search path", addidir)
|
objabi.Flagfn1("I", "add `directory` to import search path", addidir)
|
||||||
objabi.Flagcount("K", "debug missing line numbers", &Debug['K'])
|
|
||||||
objabi.Flagcount("L", "show full file names in error messages", &Debug['L'])
|
|
||||||
objabi.Flagcount("N", "disable optimizations", &Debug['N'])
|
|
||||||
objabi.Flagcount("S", "print assembly listing", &Debug['S'])
|
|
||||||
objabi.AddVersionFlag() // -V
|
objabi.AddVersionFlag() // -V
|
||||||
objabi.Flagcount("W", "debug parse tree after type checking", &Debug['W'])
|
|
||||||
flag.StringVar(&asmhdr, "asmhdr", "", "write assembly header to `file`")
|
flag.StringVar(&asmhdr, "asmhdr", "", "write assembly header to `file`")
|
||||||
flag.StringVar(&buildid, "buildid", "", "record `id` as the build id in the export metadata")
|
flag.StringVar(&buildid, "buildid", "", "record `id` as the build id in the export metadata")
|
||||||
flag.IntVar(&nBackendWorkers, "c", 1, "concurrency during compilation, 1 means no concurrency")
|
flag.IntVar(&nBackendWorkers, "c", 1, "concurrency during compilation, 1 means no concurrency")
|
||||||
|
|
@ -232,17 +241,12 @@ func Main(archInit func(*Arch)) {
|
||||||
flag.BoolVar(&flagDWARF, "dwarf", !Wasm, "generate DWARF symbols")
|
flag.BoolVar(&flagDWARF, "dwarf", !Wasm, "generate DWARF symbols")
|
||||||
flag.BoolVar(&Ctxt.Flag_locationlists, "dwarflocationlists", true, "add location lists to DWARF in optimized mode")
|
flag.BoolVar(&Ctxt.Flag_locationlists, "dwarflocationlists", true, "add location lists to DWARF in optimized mode")
|
||||||
flag.IntVar(&genDwarfInline, "gendwarfinl", 2, "generate DWARF inline info records")
|
flag.IntVar(&genDwarfInline, "gendwarfinl", 2, "generate DWARF inline info records")
|
||||||
objabi.Flagcount("e", "no limit on number of errors reported", &Debug['e'])
|
|
||||||
objabi.Flagcount("h", "halt on error", &Debug['h'])
|
|
||||||
objabi.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap)
|
objabi.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap)
|
||||||
objabi.Flagfn1("importcfg", "read import configuration from `file`", readImportCfg)
|
objabi.Flagfn1("importcfg", "read import configuration from `file`", readImportCfg)
|
||||||
flag.StringVar(&flag_installsuffix, "installsuffix", "", "set pkg directory `suffix`")
|
flag.StringVar(&flag_installsuffix, "installsuffix", "", "set pkg directory `suffix`")
|
||||||
objabi.Flagcount("j", "debug runtime-initialized variables", &Debug['j'])
|
|
||||||
objabi.Flagcount("l", "disable inlining", &Debug['l'])
|
|
||||||
flag.StringVar(&flag_lang, "lang", "", "release to compile for")
|
flag.StringVar(&flag_lang, "lang", "", "release to compile for")
|
||||||
flag.StringVar(&linkobj, "linkobj", "", "write linker-specific object to `file`")
|
flag.StringVar(&linkobj, "linkobj", "", "write linker-specific object to `file`")
|
||||||
objabi.Flagcount("live", "debug liveness analysis", &debuglive)
|
objabi.Flagcount("live", "debug liveness analysis", &debuglive)
|
||||||
objabi.Flagcount("m", "print optimization decisions", &Debug['m'])
|
|
||||||
if sys.MSanSupported(objabi.GOOS, objabi.GOARCH) {
|
if sys.MSanSupported(objabi.GOOS, objabi.GOARCH) {
|
||||||
flag.BoolVar(&flag_msan, "msan", false, "build code compatible with C/C++ memory sanitizer")
|
flag.BoolVar(&flag_msan, "msan", false, "build code compatible with C/C++ memory sanitizer")
|
||||||
}
|
}
|
||||||
|
|
@ -250,7 +254,6 @@ func Main(archInit func(*Arch)) {
|
||||||
flag.StringVar(&outfile, "o", "", "write output to `file`")
|
flag.StringVar(&outfile, "o", "", "write output to `file`")
|
||||||
flag.StringVar(&myimportpath, "p", "", "set expected package import `path`")
|
flag.StringVar(&myimportpath, "p", "", "set expected package import `path`")
|
||||||
flag.BoolVar(&writearchive, "pack", false, "write to file.a instead of file.o")
|
flag.BoolVar(&writearchive, "pack", false, "write to file.a instead of file.o")
|
||||||
objabi.Flagcount("r", "debug generated wrappers", &Debug['r'])
|
|
||||||
if sys.RaceDetectorSupported(objabi.GOOS, objabi.GOARCH) {
|
if sys.RaceDetectorSupported(objabi.GOOS, objabi.GOARCH) {
|
||||||
flag.BoolVar(&flag_race, "race", false, "enable race detector")
|
flag.BoolVar(&flag_race, "race", false, "enable race detector")
|
||||||
}
|
}
|
||||||
|
|
@ -260,7 +263,6 @@ func Main(archInit func(*Arch)) {
|
||||||
}
|
}
|
||||||
flag.StringVar(&pathPrefix, "trimpath", "", "remove `prefix` from recorded source file paths")
|
flag.StringVar(&pathPrefix, "trimpath", "", "remove `prefix` from recorded source file paths")
|
||||||
flag.BoolVar(&Debug_vlog, "v", false, "increase debug verbosity")
|
flag.BoolVar(&Debug_vlog, "v", false, "increase debug verbosity")
|
||||||
objabi.Flagcount("w", "debug type checking", &Debug['w'])
|
|
||||||
flag.BoolVar(&use_writebarrier, "wb", true, "enable write barrier")
|
flag.BoolVar(&use_writebarrier, "wb", true, "enable write barrier")
|
||||||
var flag_shared bool
|
var flag_shared bool
|
||||||
var flag_dynlink bool
|
var flag_dynlink bool
|
||||||
|
|
@ -326,9 +328,9 @@ func Main(archInit func(*Arch)) {
|
||||||
|
|
||||||
Ctxt.Flag_shared = flag_dynlink || flag_shared
|
Ctxt.Flag_shared = flag_dynlink || flag_shared
|
||||||
Ctxt.Flag_dynlink = flag_dynlink
|
Ctxt.Flag_dynlink = flag_dynlink
|
||||||
Ctxt.Flag_optimize = Debug['N'] == 0
|
Ctxt.Flag_optimize = Debug.N == 0
|
||||||
|
|
||||||
Ctxt.Debugasm = Debug['S']
|
Ctxt.Debugasm = Debug.S
|
||||||
Ctxt.Debugvlog = Debug_vlog
|
Ctxt.Debugvlog = Debug_vlog
|
||||||
if flagDWARF {
|
if flagDWARF {
|
||||||
Ctxt.DebugInfo = debuginfo
|
Ctxt.DebugInfo = debuginfo
|
||||||
|
|
@ -400,7 +402,7 @@ func Main(archInit func(*Arch)) {
|
||||||
instrumenting = true
|
instrumenting = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if compiling_runtime && Debug['N'] != 0 {
|
if compiling_runtime && Debug.N != 0 {
|
||||||
log.Fatal("cannot disable optimizations while compiling runtime")
|
log.Fatal("cannot disable optimizations while compiling runtime")
|
||||||
}
|
}
|
||||||
if nBackendWorkers < 1 {
|
if nBackendWorkers < 1 {
|
||||||
|
|
@ -505,11 +507,11 @@ func Main(archInit func(*Arch)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// enable inlining. for now:
|
// enable inlining. for now:
|
||||||
// default: inlining on. (debug['l'] == 1)
|
// default: inlining on. (Debug.l == 1)
|
||||||
// -l: inlining off (debug['l'] == 0)
|
// -l: inlining off (Debug.l == 0)
|
||||||
// -l=2, -l=3: inlining on again, with extra debugging (debug['l'] > 1)
|
// -l=2, -l=3: inlining on again, with extra debugging (Debug.l > 1)
|
||||||
if Debug['l'] <= 1 {
|
if Debug.l <= 1 {
|
||||||
Debug['l'] = 1 - Debug['l']
|
Debug.l = 1 - Debug.l
|
||||||
}
|
}
|
||||||
|
|
||||||
if jsonLogOpt != "" { // parse version,destination from json logging optimization.
|
if jsonLogOpt != "" { // parse version,destination from json logging optimization.
|
||||||
|
|
@ -572,10 +574,10 @@ func Main(archInit func(*Arch)) {
|
||||||
loadsys()
|
loadsys()
|
||||||
|
|
||||||
timings.Start("fe", "parse")
|
timings.Start("fe", "parse")
|
||||||
lines := parseFiles(flag.Args(), Debug['G'] != 0)
|
lines := parseFiles(flag.Args(), Debug.G != 0)
|
||||||
timings.Stop()
|
timings.Stop()
|
||||||
timings.AddEvent(int64(lines), "lines")
|
timings.AddEvent(int64(lines), "lines")
|
||||||
if Debug['G'] != 0 {
|
if Debug.G != 0 {
|
||||||
// can only parse generic code for now
|
// can only parse generic code for now
|
||||||
if nerrors+nsavederrors != 0 {
|
if nerrors+nsavederrors != 0 {
|
||||||
errorexit()
|
errorexit()
|
||||||
|
|
@ -674,7 +676,7 @@ func Main(archInit func(*Arch)) {
|
||||||
// Phase 5: Inlining
|
// Phase 5: Inlining
|
||||||
timings.Start("fe", "inlining")
|
timings.Start("fe", "inlining")
|
||||||
if Debug_typecheckinl != 0 {
|
if Debug_typecheckinl != 0 {
|
||||||
// Typecheck imported function bodies if debug['l'] > 1,
|
// Typecheck imported function bodies if Debug.l > 1,
|
||||||
// otherwise lazily when used or re-exported.
|
// otherwise lazily when used or re-exported.
|
||||||
for _, n := range importlist {
|
for _, n := range importlist {
|
||||||
if n.Func.Inl != nil {
|
if n.Func.Inl != nil {
|
||||||
|
|
@ -688,7 +690,7 @@ func Main(archInit func(*Arch)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if Debug['l'] != 0 {
|
if Debug.l != 0 {
|
||||||
// Find functions that can be inlined and clone them before walk expands them.
|
// Find functions that can be inlined and clone them before walk expands them.
|
||||||
visitBottomUp(xtop, func(list []*Node, recursive bool) {
|
visitBottomUp(xtop, func(list []*Node, recursive bool) {
|
||||||
numfns := numNonClosures(list)
|
numfns := numNonClosures(list)
|
||||||
|
|
@ -699,7 +701,7 @@ func Main(archInit func(*Arch)) {
|
||||||
// across more than one function.
|
// across more than one function.
|
||||||
caninl(n)
|
caninl(n)
|
||||||
} else {
|
} else {
|
||||||
if Debug['m'] > 1 {
|
if Debug.m > 1 {
|
||||||
fmt.Printf("%v: cannot inline %v: recursive\n", n.Line(), n.Func.Nname)
|
fmt.Printf("%v: cannot inline %v: recursive\n", n.Line(), n.Func.Nname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -976,9 +978,10 @@ func readSymABIs(file, myimportpath string) {
|
||||||
if len(parts) != 3 {
|
if len(parts) != 3 {
|
||||||
log.Fatalf(`%s:%d: invalid symabi: syntax is "%s sym abi"`, file, lineNum, parts[0])
|
log.Fatalf(`%s:%d: invalid symabi: syntax is "%s sym abi"`, file, lineNum, parts[0])
|
||||||
}
|
}
|
||||||
sym, abi := parts[1], parts[2]
|
sym, abistr := parts[1], parts[2]
|
||||||
if abi != "ABI0" { // Only supported external ABI right now
|
abi, valid := obj.ParseABI(abistr)
|
||||||
log.Fatalf(`%s:%d: invalid symabi: unknown abi "%s"`, file, lineNum, abi)
|
if !valid {
|
||||||
|
log.Fatalf(`%s:%d: invalid symabi: unknown abi "%s"`, file, lineNum, abistr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the symbol is already prefixed with
|
// If the symbol is already prefixed with
|
||||||
|
|
@ -991,9 +994,9 @@ func readSymABIs(file, myimportpath string) {
|
||||||
|
|
||||||
// Record for later.
|
// Record for later.
|
||||||
if parts[0] == "def" {
|
if parts[0] == "def" {
|
||||||
symabiDefs[sym] = obj.ABI0
|
symabiDefs[sym] = abi
|
||||||
} else {
|
} else {
|
||||||
symabiRefs[sym] = obj.ABI0
|
symabiRefs[sym] = abi
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
log.Fatalf(`%s:%d: invalid symabi type "%s"`, file, lineNum, parts[0])
|
log.Fatalf(`%s:%d: invalid symabi type "%s"`, file, lineNum, parts[0])
|
||||||
|
|
@ -1415,29 +1418,34 @@ func IsAlias(sym *types.Sym) bool {
|
||||||
return sym.Def != nil && asNode(sym.Def).Sym != sym
|
return sym.Def != nil && asNode(sym.Def).Sym != sym
|
||||||
}
|
}
|
||||||
|
|
||||||
// By default, assume any debug flags are incompatible with concurrent compilation.
|
// By default, assume any debug flags are incompatible with concurrent
|
||||||
// A few are safe and potentially in common use for normal compiles, though; mark them as such here.
|
// compilation. A few are safe and potentially in common use for
|
||||||
var concurrentFlagOK = [256]bool{
|
// normal compiles, though; return true for those.
|
||||||
'B': true, // disabled bounds checking
|
func concurrentFlagOk() bool {
|
||||||
'C': true, // disable printing of columns in error messages
|
// Report whether any debug flag that would prevent concurrent
|
||||||
'e': true, // no limit on errors; errors all come from non-concurrent code
|
// compilation is set, by zeroing out the allowed ones and then
|
||||||
'I': true, // add `directory` to import search path
|
// checking if the resulting struct is zero.
|
||||||
'N': true, // disable optimizations
|
d := Debug
|
||||||
'l': true, // disable inlining
|
d.B = 0 // disable bounds checking
|
||||||
'w': true, // all printing happens before compilation
|
d.C = 0 // disable printing of columns in error messages
|
||||||
'W': true, // all printing happens before compilation
|
d.e = 0 // no limit on errors; errors all come from non-concurrent code
|
||||||
'S': true, // printing disassembly happens at the end (but see concurrentBackendAllowed below)
|
d.N = 0 // disable optimizations
|
||||||
|
d.l = 0 // disable inlining
|
||||||
|
d.w = 0 // all printing happens before compilation
|
||||||
|
d.W = 0 // all printing happens before compilation
|
||||||
|
d.S = 0 // printing disassembly happens at the end (but see concurrentBackendAllowed below)
|
||||||
|
|
||||||
|
return d == DebugFlags{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func concurrentBackendAllowed() bool {
|
func concurrentBackendAllowed() bool {
|
||||||
for i, x := range &Debug {
|
if !concurrentFlagOk() {
|
||||||
if x != 0 && !concurrentFlagOK[i] {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Debug['S'] by itself is ok, because all printing occurs
|
// Debug.S by itself is ok, because all printing occurs
|
||||||
// while writing the object file, and that is non-concurrent.
|
// while writing the object file, and that is non-concurrent.
|
||||||
// Adding Debug_vlog, however, causes Debug['S'] to also print
|
// Adding Debug_vlog, however, causes Debug.S to also print
|
||||||
// while flushing the plist, which happens concurrently.
|
// while flushing the plist, which happens concurrently.
|
||||||
if Debug_vlog || debugstr != "" || debuglive > 0 {
|
if Debug_vlog || debugstr != "" || debuglive > 0 {
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -249,6 +249,7 @@ func (p *noder) node() {
|
||||||
mkpackage(p.file.PkgName.Value)
|
mkpackage(p.file.PkgName.Value)
|
||||||
|
|
||||||
if pragma, ok := p.file.Pragma.(*Pragma); ok {
|
if pragma, ok := p.file.Pragma.(*Pragma); ok {
|
||||||
|
pragma.Flag &^= GoBuildPragma
|
||||||
p.checkUnused(pragma)
|
p.checkUnused(pragma)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -780,7 +781,7 @@ func (p *noder) sum(x syntax.Expr) *Node {
|
||||||
n := p.expr(x)
|
n := p.expr(x)
|
||||||
if Isconst(n, CTSTR) && n.Sym == nil {
|
if Isconst(n, CTSTR) && n.Sym == nil {
|
||||||
nstr = n
|
nstr = n
|
||||||
chunks = append(chunks, strlit(nstr))
|
chunks = append(chunks, nstr.StringVal())
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := len(adds) - 1; i >= 0; i-- {
|
for i := len(adds) - 1; i >= 0; i-- {
|
||||||
|
|
@ -790,12 +791,12 @@ func (p *noder) sum(x syntax.Expr) *Node {
|
||||||
if Isconst(r, CTSTR) && r.Sym == nil {
|
if Isconst(r, CTSTR) && r.Sym == nil {
|
||||||
if nstr != nil {
|
if nstr != nil {
|
||||||
// Collapse r into nstr instead of adding to n.
|
// Collapse r into nstr instead of adding to n.
|
||||||
chunks = append(chunks, strlit(r))
|
chunks = append(chunks, r.StringVal())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
nstr = r
|
nstr = r
|
||||||
chunks = append(chunks, strlit(nstr))
|
chunks = append(chunks, nstr.StringVal())
|
||||||
} else {
|
} else {
|
||||||
if len(chunks) > 1 {
|
if len(chunks) > 1 {
|
||||||
nstr.SetVal(Val{U: strings.Join(chunks, "")})
|
nstr.SetVal(Val{U: strings.Join(chunks, "")})
|
||||||
|
|
@ -1444,11 +1445,6 @@ func (p *noder) mkname(name *syntax.Name) *Node {
|
||||||
return mkname(p.name(name))
|
return mkname(p.name(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) newname(name *syntax.Name) *Node {
|
|
||||||
// TODO(mdempsky): Set line number?
|
|
||||||
return newname(p.name(name))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *noder) wrapname(n syntax.Node, x *Node) *Node {
|
func (p *noder) wrapname(n syntax.Node, x *Node) *Node {
|
||||||
// These nodes do not carry line numbers.
|
// These nodes do not carry line numbers.
|
||||||
// Introduce a wrapper node to give them the correct line.
|
// Introduce a wrapper node to give them the correct line.
|
||||||
|
|
|
||||||
|
|
@ -272,7 +272,7 @@ func dumpGlobalConst(n *Node) {
|
||||||
default:
|
default:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
Ctxt.DwarfIntConst(myimportpath, n.Sym.Name, typesymname(t), n.Int64())
|
Ctxt.DwarfIntConst(myimportpath, n.Sym.Name, typesymname(t), n.Int64Val())
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpglobls() {
|
func dumpglobls() {
|
||||||
|
|
@ -305,20 +305,21 @@ func dumpglobls() {
|
||||||
// global symbols can't be declared during parallel compilation.
|
// global symbols can't be declared during parallel compilation.
|
||||||
func addGCLocals() {
|
func addGCLocals() {
|
||||||
for _, s := range Ctxt.Text {
|
for _, s := range Ctxt.Text {
|
||||||
if s.Func == nil {
|
fn := s.Func()
|
||||||
|
if fn == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, gcsym := range []*obj.LSym{s.Func.GCArgs, s.Func.GCLocals, s.Func.GCRegs} {
|
for _, gcsym := range []*obj.LSym{fn.GCArgs, fn.GCLocals, fn.GCRegs} {
|
||||||
if gcsym != nil && !gcsym.OnList() {
|
if gcsym != nil && !gcsym.OnList() {
|
||||||
ggloblsym(gcsym, int32(len(gcsym.P)), obj.RODATA|obj.DUPOK)
|
ggloblsym(gcsym, int32(len(gcsym.P)), obj.RODATA|obj.DUPOK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if x := s.Func.StackObjects; x != nil {
|
if x := fn.StackObjects; x != nil {
|
||||||
attr := int16(obj.RODATA)
|
attr := int16(obj.RODATA)
|
||||||
ggloblsym(x, int32(len(x.P)), attr)
|
ggloblsym(x, int32(len(x.P)), attr)
|
||||||
x.Set(obj.AttrStatic, true)
|
x.Set(obj.AttrStatic, true)
|
||||||
}
|
}
|
||||||
if x := s.Func.OpenCodedDeferInfo; x != nil {
|
if x := fn.OpenCodedDeferInfo; x != nil {
|
||||||
ggloblsym(x, int32(len(x.P)), obj.RODATA|obj.DUPOK)
|
ggloblsym(x, int32(len(x.P)), obj.RODATA|obj.DUPOK)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ type Order struct {
|
||||||
// Order rewrites fn.Nbody to apply the ordering constraints
|
// Order rewrites fn.Nbody to apply the ordering constraints
|
||||||
// described in the comment at the top of the file.
|
// described in the comment at the top of the file.
|
||||||
func order(fn *Node) {
|
func order(fn *Node) {
|
||||||
if Debug['W'] > 1 {
|
if Debug.W > 1 {
|
||||||
s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym)
|
s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym)
|
||||||
dumplist(s, fn.Nbody)
|
dumplist(s, fn.Nbody)
|
||||||
}
|
}
|
||||||
|
|
@ -323,12 +323,7 @@ func (o *Order) stmtList(l Nodes) {
|
||||||
// and rewrites it to:
|
// and rewrites it to:
|
||||||
// m = OMAKESLICECOPY([]T, x, s); nil
|
// m = OMAKESLICECOPY([]T, x, s); nil
|
||||||
func orderMakeSliceCopy(s []*Node) {
|
func orderMakeSliceCopy(s []*Node) {
|
||||||
const go115makeslicecopy = true
|
if Debug.N != 0 || instrumenting {
|
||||||
if !go115makeslicecopy {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if Debug['N'] != 0 || instrumenting {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1102,7 +1097,7 @@ func (o *Order) expr(n, lhs *Node) *Node {
|
||||||
haslit := false
|
haslit := false
|
||||||
for _, n1 := range n.List.Slice() {
|
for _, n1 := range n.List.Slice() {
|
||||||
hasbyte = hasbyte || n1.Op == OBYTES2STR
|
hasbyte = hasbyte || n1.Op == OBYTES2STR
|
||||||
haslit = haslit || n1.Op == OLITERAL && len(strlit(n1)) != 0
|
haslit = haslit || n1.Op == OLITERAL && len(n1.StringVal()) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
if haslit && hasbyte {
|
if haslit && hasbyte {
|
||||||
|
|
@ -1274,7 +1269,7 @@ func (o *Order) expr(n, lhs *Node) *Node {
|
||||||
var t *types.Type
|
var t *types.Type
|
||||||
switch n.Op {
|
switch n.Op {
|
||||||
case OSLICELIT:
|
case OSLICELIT:
|
||||||
t = types.NewArray(n.Type.Elem(), n.Right.Int64())
|
t = types.NewArray(n.Type.Elem(), n.Right.Int64Val())
|
||||||
case OCALLPART:
|
case OCALLPART:
|
||||||
t = partialCallType(n)
|
t = partialCallType(n)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -266,8 +266,8 @@ func compile(fn *Node) {
|
||||||
dtypesym(n.Type)
|
dtypesym(n.Type)
|
||||||
// Also make sure we allocate a linker symbol
|
// Also make sure we allocate a linker symbol
|
||||||
// for the stack object data, for the same reason.
|
// for the stack object data, for the same reason.
|
||||||
if fn.Func.lsym.Func.StackObjects == nil {
|
if fn.Func.lsym.Func().StackObjects == nil {
|
||||||
fn.Func.lsym.Func.StackObjects = Ctxt.Lookup(fn.Func.lsym.Name + ".stkobj")
|
fn.Func.lsym.Func().StackObjects = Ctxt.Lookup(fn.Func.lsym.Name + ".stkobj")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -415,7 +415,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S
|
||||||
case PAUTO:
|
case PAUTO:
|
||||||
if !n.Name.Used() {
|
if !n.Name.Used() {
|
||||||
// Text == nil -> generating abstract function
|
// Text == nil -> generating abstract function
|
||||||
if fnsym.Func.Text != nil {
|
if fnsym.Func().Text != nil {
|
||||||
Fatalf("debuginfo unused node (AllocFrame should truncate fn.Func.Dcl)")
|
Fatalf("debuginfo unused node (AllocFrame should truncate fn.Func.Dcl)")
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
|
@ -425,7 +425,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
apdecls = append(apdecls, n)
|
apdecls = append(apdecls, n)
|
||||||
fnsym.Func.RecordAutoType(ngotype(n).Linksym())
|
fnsym.Func().RecordAutoType(ngotype(n).Linksym())
|
||||||
}
|
}
|
||||||
|
|
||||||
decls, dwarfVars := createDwarfVars(fnsym, fn.Func, apdecls)
|
decls, dwarfVars := createDwarfVars(fnsym, fn.Func, apdecls)
|
||||||
|
|
@ -435,7 +435,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S
|
||||||
// the function symbol to insure that the type included in DWARF
|
// the function symbol to insure that the type included in DWARF
|
||||||
// processing during linking.
|
// processing during linking.
|
||||||
typesyms := []*obj.LSym{}
|
typesyms := []*obj.LSym{}
|
||||||
for t, _ := range fnsym.Func.Autot {
|
for t, _ := range fnsym.Func().Autot {
|
||||||
typesyms = append(typesyms, t)
|
typesyms = append(typesyms, t)
|
||||||
}
|
}
|
||||||
sort.Sort(obj.BySymName(typesyms))
|
sort.Sort(obj.BySymName(typesyms))
|
||||||
|
|
@ -444,7 +444,7 @@ func debuginfo(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.S
|
||||||
r.Sym = sym
|
r.Sym = sym
|
||||||
r.Type = objabi.R_USETYPE
|
r.Type = objabi.R_USETYPE
|
||||||
}
|
}
|
||||||
fnsym.Func.Autot = nil
|
fnsym.Func().Autot = nil
|
||||||
|
|
||||||
var varScopes []ScopeID
|
var varScopes []ScopeID
|
||||||
for _, decl := range decls {
|
for _, decl := range decls {
|
||||||
|
|
@ -522,7 +522,7 @@ func createSimpleVar(fnsym *obj.LSym, n *Node) *dwarf.Var {
|
||||||
}
|
}
|
||||||
|
|
||||||
typename := dwarf.InfoPrefix + typesymname(n.Type)
|
typename := dwarf.InfoPrefix + typesymname(n.Type)
|
||||||
delete(fnsym.Func.Autot, ngotype(n).Linksym())
|
delete(fnsym.Func().Autot, ngotype(n).Linksym())
|
||||||
inlIndex := 0
|
inlIndex := 0
|
||||||
if genDwarfInline > 1 {
|
if genDwarfInline > 1 {
|
||||||
if n.Name.InlFormal() || n.Name.InlLocal() {
|
if n.Name.InlFormal() || n.Name.InlLocal() {
|
||||||
|
|
@ -667,7 +667,7 @@ func createDwarfVars(fnsym *obj.LSym, fn *Func, apDecls []*Node) ([]*Node, []*dw
|
||||||
ChildIndex: -1,
|
ChildIndex: -1,
|
||||||
})
|
})
|
||||||
// Record go type of to insure that it gets emitted by the linker.
|
// Record go type of to insure that it gets emitted by the linker.
|
||||||
fnsym.Func.RecordAutoType(ngotype(n).Linksym())
|
fnsym.Func().RecordAutoType(ngotype(n).Linksym())
|
||||||
}
|
}
|
||||||
|
|
||||||
return decls, vars
|
return decls, vars
|
||||||
|
|
@ -731,7 +731,7 @@ func createComplexVar(fnsym *obj.LSym, fn *Func, varID ssa.VarID) *dwarf.Var {
|
||||||
}
|
}
|
||||||
|
|
||||||
gotype := ngotype(n).Linksym()
|
gotype := ngotype(n).Linksym()
|
||||||
delete(fnsym.Func.Autot, gotype)
|
delete(fnsym.Func().Autot, gotype)
|
||||||
typename := dwarf.InfoPrefix + gotype.Name[len("type."):]
|
typename := dwarf.InfoPrefix + gotype.Name[len("type."):]
|
||||||
inlIndex := 0
|
inlIndex := 0
|
||||||
if genDwarfInline > 1 {
|
if genDwarfInline > 1 {
|
||||||
|
|
|
||||||
|
|
@ -1552,26 +1552,27 @@ func liveness(e *ssafn, f *ssa.Func, pp *Progs) LivenessMap {
|
||||||
|
|
||||||
// Emit the live pointer map data structures
|
// Emit the live pointer map data structures
|
||||||
ls := e.curfn.Func.lsym
|
ls := e.curfn.Func.lsym
|
||||||
ls.Func.GCArgs, ls.Func.GCLocals, ls.Func.GCRegs = lv.emit()
|
fninfo := ls.Func()
|
||||||
|
fninfo.GCArgs, fninfo.GCLocals, fninfo.GCRegs = lv.emit()
|
||||||
|
|
||||||
p := pp.Prog(obj.AFUNCDATA)
|
p := pp.Prog(obj.AFUNCDATA)
|
||||||
Addrconst(&p.From, objabi.FUNCDATA_ArgsPointerMaps)
|
Addrconst(&p.From, objabi.FUNCDATA_ArgsPointerMaps)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Name = obj.NAME_EXTERN
|
p.To.Name = obj.NAME_EXTERN
|
||||||
p.To.Sym = ls.Func.GCArgs
|
p.To.Sym = fninfo.GCArgs
|
||||||
|
|
||||||
p = pp.Prog(obj.AFUNCDATA)
|
p = pp.Prog(obj.AFUNCDATA)
|
||||||
Addrconst(&p.From, objabi.FUNCDATA_LocalsPointerMaps)
|
Addrconst(&p.From, objabi.FUNCDATA_LocalsPointerMaps)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Name = obj.NAME_EXTERN
|
p.To.Name = obj.NAME_EXTERN
|
||||||
p.To.Sym = ls.Func.GCLocals
|
p.To.Sym = fninfo.GCLocals
|
||||||
|
|
||||||
if !go115ReduceLiveness {
|
if !go115ReduceLiveness {
|
||||||
p = pp.Prog(obj.AFUNCDATA)
|
p = pp.Prog(obj.AFUNCDATA)
|
||||||
Addrconst(&p.From, objabi.FUNCDATA_RegPointerMaps)
|
Addrconst(&p.From, objabi.FUNCDATA_RegPointerMaps)
|
||||||
p.To.Type = obj.TYPE_MEM
|
p.To.Type = obj.TYPE_MEM
|
||||||
p.To.Name = obj.NAME_EXTERN
|
p.To.Name = obj.NAME_EXTERN
|
||||||
p.To.Sym = ls.Func.GCRegs
|
p.To.Sym = fninfo.GCRegs
|
||||||
}
|
}
|
||||||
|
|
||||||
return lv.livenessMap
|
return lv.livenessMap
|
||||||
|
|
|
||||||
|
|
@ -112,22 +112,25 @@ func typecheckrangeExpr(n *Node) {
|
||||||
v2 = nil
|
v2 = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var why string
|
|
||||||
if v1 != nil {
|
if v1 != nil {
|
||||||
if v1.Name != nil && v1.Name.Defn == n {
|
if v1.Name != nil && v1.Name.Defn == n {
|
||||||
v1.Type = t1
|
v1.Type = t1
|
||||||
} else if v1.Type != nil && assignop(t1, v1.Type, &why) == 0 {
|
} else if v1.Type != nil {
|
||||||
|
if op, why := assignop(t1, v1.Type); op == OXXX {
|
||||||
yyerrorl(n.Pos, "cannot assign type %v to %L in range%s", t1, v1, why)
|
yyerrorl(n.Pos, "cannot assign type %v to %L in range%s", t1, v1, why)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
checkassign(n, v1)
|
checkassign(n, v1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if v2 != nil {
|
if v2 != nil {
|
||||||
if v2.Name != nil && v2.Name.Defn == n {
|
if v2.Name != nil && v2.Name.Defn == n {
|
||||||
v2.Type = t2
|
v2.Type = t2
|
||||||
} else if v2.Type != nil && assignop(t2, v2.Type, &why) == 0 {
|
} else if v2.Type != nil {
|
||||||
|
if op, why := assignop(t2, v2.Type); op == OXXX {
|
||||||
yyerrorl(n.Pos, "cannot assign type %v to %L in range%s", t2, v2, why)
|
yyerrorl(n.Pos, "cannot assign type %v to %L in range%s", t2, v2, why)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
checkassign(n, v2)
|
checkassign(n, v2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -463,7 +466,7 @@ func walkrange(n *Node) *Node {
|
||||||
//
|
//
|
||||||
// where == for keys of map m is reflexive.
|
// where == for keys of map m is reflexive.
|
||||||
func isMapClear(n *Node) bool {
|
func isMapClear(n *Node) bool {
|
||||||
if Debug['N'] != 0 || instrumenting {
|
if Debug.N != 0 || instrumenting {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -530,7 +533,7 @@ func mapClear(m *Node) *Node {
|
||||||
//
|
//
|
||||||
// Parameters are as in walkrange: "for v1, v2 = range a".
|
// Parameters are as in walkrange: "for v1, v2 = range a".
|
||||||
func arrayClear(n, v1, v2, a *Node) bool {
|
func arrayClear(n, v1, v2, a *Node) bool {
|
||||||
if Debug['N'] != 0 || instrumenting {
|
if Debug.N != 0 || instrumenting {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,9 @@ func scopePCs(fnsym *obj.LSym, marks []Mark, dwarfScopes []dwarf.Scope) {
|
||||||
if len(marks) == 0 {
|
if len(marks) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p0 := fnsym.Func.Text
|
p0 := fnsym.Func().Text
|
||||||
scope := findScope(marks, p0.Pos)
|
scope := findScope(marks, p0.Pos)
|
||||||
for p := fnsym.Func.Text; p != nil; p = p.Link {
|
for p := p0; p != nil; p = p.Link {
|
||||||
if p.Pos == p0.Pos {
|
if p.Pos == p0.Pos {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ func (s *InitSchedule) append(n *Node) {
|
||||||
// staticInit adds an initialization statement n to the schedule.
|
// staticInit adds an initialization statement n to the schedule.
|
||||||
func (s *InitSchedule) staticInit(n *Node) {
|
func (s *InitSchedule) staticInit(n *Node) {
|
||||||
if !s.tryStaticInit(n) {
|
if !s.tryStaticInit(n) {
|
||||||
if Debug['%'] != 0 {
|
if Debug.P != 0 {
|
||||||
Dump("nonstatic", n)
|
Dump("nonstatic", n)
|
||||||
}
|
}
|
||||||
s.append(n)
|
s.append(n)
|
||||||
|
|
@ -128,7 +128,7 @@ func (s *InitSchedule) staticcopy(l *Node, r *Node) bool {
|
||||||
case OSLICELIT:
|
case OSLICELIT:
|
||||||
// copy slice
|
// copy slice
|
||||||
a := s.inittemps[r]
|
a := s.inittemps[r]
|
||||||
slicesym(l, a, r.Right.Int64())
|
slicesym(l, a, r.Right.Int64Val())
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case OARRAYLIT, OSTRUCTLIT:
|
case OARRAYLIT, OSTRUCTLIT:
|
||||||
|
|
@ -205,7 +205,7 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool {
|
||||||
|
|
||||||
case OSTR2BYTES:
|
case OSTR2BYTES:
|
||||||
if l.Class() == PEXTERN && r.Left.Op == OLITERAL {
|
if l.Class() == PEXTERN && r.Left.Op == OLITERAL {
|
||||||
sval := strlit(r.Left)
|
sval := r.Left.StringVal()
|
||||||
slicebytes(l, sval)
|
slicebytes(l, sval)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -213,7 +213,7 @@ func (s *InitSchedule) staticassign(l *Node, r *Node) bool {
|
||||||
case OSLICELIT:
|
case OSLICELIT:
|
||||||
s.initplan(r)
|
s.initplan(r)
|
||||||
// Init slice.
|
// Init slice.
|
||||||
bound := r.Right.Int64()
|
bound := r.Right.Int64Val()
|
||||||
ta := types.NewArray(r.Type.Elem(), bound)
|
ta := types.NewArray(r.Type.Elem(), bound)
|
||||||
ta.SetNoalg(true)
|
ta.SetNoalg(true)
|
||||||
a := staticname(ta)
|
a := staticname(ta)
|
||||||
|
|
@ -413,7 +413,7 @@ func getdyn(n *Node, top bool) initGenType {
|
||||||
if !top {
|
if !top {
|
||||||
return initDynamic
|
return initDynamic
|
||||||
}
|
}
|
||||||
if n.Right.Int64()/4 > int64(n.List.Len()) {
|
if n.Right.Int64Val()/4 > int64(n.List.Len()) {
|
||||||
// <25% of entries have explicit values.
|
// <25% of entries have explicit values.
|
||||||
// Very rough estimation, it takes 4 bytes of instructions
|
// Very rough estimation, it takes 4 bytes of instructions
|
||||||
// to initialize 1 byte of result. So don't use a static
|
// to initialize 1 byte of result. So don't use a static
|
||||||
|
|
@ -589,12 +589,12 @@ func isSmallSliceLit(n *Node) bool {
|
||||||
|
|
||||||
r := n.Right
|
r := n.Right
|
||||||
|
|
||||||
return smallintconst(r) && (n.Type.Elem().Width == 0 || r.Int64() <= smallArrayBytes/n.Type.Elem().Width)
|
return smallintconst(r) && (n.Type.Elem().Width == 0 || r.Int64Val() <= smallArrayBytes/n.Type.Elem().Width)
|
||||||
}
|
}
|
||||||
|
|
||||||
func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) {
|
func slicelit(ctxt initContext, n *Node, var_ *Node, init *Nodes) {
|
||||||
// make an array type corresponding the number of elements we have
|
// make an array type corresponding the number of elements we have
|
||||||
t := types.NewArray(n.Type.Elem(), n.Right.Int64())
|
t := types.NewArray(n.Type.Elem(), n.Right.Int64Val())
|
||||||
dowidth(t)
|
dowidth(t)
|
||||||
|
|
||||||
if ctxt == inNonInitFunction {
|
if ctxt == inNonInitFunction {
|
||||||
|
|
@ -993,7 +993,7 @@ func oaslit(n *Node, init *Nodes) bool {
|
||||||
|
|
||||||
func getlit(lit *Node) int {
|
func getlit(lit *Node) int {
|
||||||
if smallintconst(lit) {
|
if smallintconst(lit) {
|
||||||
return int(lit.Int64())
|
return int(lit.Int64Val())
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ func initssaconfig() {
|
||||||
_ = types.NewPtr(types.Types[TINT64]) // *int64
|
_ = types.NewPtr(types.Types[TINT64]) // *int64
|
||||||
_ = types.NewPtr(types.Errortype) // *error
|
_ = types.NewPtr(types.Errortype) // *error
|
||||||
types.NewPtrCacheEnabled = false
|
types.NewPtrCacheEnabled = false
|
||||||
ssaConfig = ssa.NewConfig(thearch.LinkArch.Name, *types_, Ctxt, Debug['N'] == 0)
|
ssaConfig = ssa.NewConfig(thearch.LinkArch.Name, *types_, Ctxt, Debug.N == 0)
|
||||||
ssaConfig.SoftFloat = thearch.SoftFloat
|
ssaConfig.SoftFloat = thearch.SoftFloat
|
||||||
ssaConfig.Race = flag_race
|
ssaConfig.Race = flag_race
|
||||||
ssaCaches = make([]ssa.Cache, nBackendWorkers)
|
ssaCaches = make([]ssa.Cache, nBackendWorkers)
|
||||||
|
|
@ -240,7 +240,7 @@ func dvarint(x *obj.LSym, off int, v int64) int {
|
||||||
// - Offset of where argument should be placed in the args frame when making call
|
// - Offset of where argument should be placed in the args frame when making call
|
||||||
func (s *state) emitOpenDeferInfo() {
|
func (s *state) emitOpenDeferInfo() {
|
||||||
x := Ctxt.Lookup(s.curfn.Func.lsym.Name + ".opendefer")
|
x := Ctxt.Lookup(s.curfn.Func.lsym.Name + ".opendefer")
|
||||||
s.curfn.Func.lsym.Func.OpenCodedDeferInfo = x
|
s.curfn.Func.lsym.Func().OpenCodedDeferInfo = x
|
||||||
off := 0
|
off := 0
|
||||||
|
|
||||||
// Compute maxargsize (max size of arguments for all defers)
|
// Compute maxargsize (max size of arguments for all defers)
|
||||||
|
|
@ -357,7 +357,7 @@ func buildssa(fn *Node, worker int) *ssa.Func {
|
||||||
s.fwdVars = map[*Node]*ssa.Value{}
|
s.fwdVars = map[*Node]*ssa.Value{}
|
||||||
s.startmem = s.entryNewValue0(ssa.OpInitMem, types.TypeMem)
|
s.startmem = s.entryNewValue0(ssa.OpInitMem, types.TypeMem)
|
||||||
|
|
||||||
s.hasOpenDefers = Debug['N'] == 0 && s.hasdefer && !s.curfn.Func.OpenCodedDeferDisallowed()
|
s.hasOpenDefers = Debug.N == 0 && s.hasdefer && !s.curfn.Func.OpenCodedDeferDisallowed()
|
||||||
switch {
|
switch {
|
||||||
case s.hasOpenDefers && (Ctxt.Flag_shared || Ctxt.Flag_dynlink) && thearch.LinkArch.Name == "386":
|
case s.hasOpenDefers && (Ctxt.Flag_shared || Ctxt.Flag_dynlink) && thearch.LinkArch.Name == "386":
|
||||||
// Don't support open-coded defers for 386 ONLY when using shared
|
// Don't support open-coded defers for 386 ONLY when using shared
|
||||||
|
|
@ -741,7 +741,7 @@ func (s *state) pushLine(line src.XPos) {
|
||||||
// the frontend may emit node with line number missing,
|
// the frontend may emit node with line number missing,
|
||||||
// use the parent line number in this case.
|
// use the parent line number in this case.
|
||||||
line = s.peekPos()
|
line = s.peekPos()
|
||||||
if Debug['K'] != 0 {
|
if Debug.K != 0 {
|
||||||
Warn("buildssa: unknown position (line 0)")
|
Warn("buildssa: unknown position (line 0)")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1214,7 +1214,7 @@ func (s *state) stmt(n *Node) {
|
||||||
// Check whether we're writing the result of an append back to the same slice.
|
// Check whether we're writing the result of an append back to the same slice.
|
||||||
// If so, we handle it specially to avoid write barriers on the fast
|
// If so, we handle it specially to avoid write barriers on the fast
|
||||||
// (non-growth) path.
|
// (non-growth) path.
|
||||||
if !samesafeexpr(n.Left, rhs.List.First()) || Debug['N'] != 0 {
|
if !samesafeexpr(n.Left, rhs.List.First()) || Debug.N != 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// If the slice can be SSA'd, it'll be on the stack,
|
// If the slice can be SSA'd, it'll be on the stack,
|
||||||
|
|
@ -1271,7 +1271,7 @@ func (s *state) stmt(n *Node) {
|
||||||
// We're assigning a slicing operation back to its source.
|
// We're assigning a slicing operation back to its source.
|
||||||
// Don't write back fields we aren't changing. See issue #14855.
|
// Don't write back fields we aren't changing. See issue #14855.
|
||||||
i, j, k := rhs.SliceBounds()
|
i, j, k := rhs.SliceBounds()
|
||||||
if i != nil && (i.Op == OLITERAL && i.Val().Ctype() == CTINT && i.Int64() == 0) {
|
if i != nil && (i.Op == OLITERAL && i.Val().Ctype() == CTINT && i.Int64Val() == 0) {
|
||||||
// [0:...] is the same as [:...]
|
// [0:...] is the same as [:...]
|
||||||
i = nil
|
i = nil
|
||||||
}
|
}
|
||||||
|
|
@ -1301,7 +1301,7 @@ func (s *state) stmt(n *Node) {
|
||||||
case OIF:
|
case OIF:
|
||||||
if Isconst(n.Left, CTBOOL) {
|
if Isconst(n.Left, CTBOOL) {
|
||||||
s.stmtList(n.Left.Ninit)
|
s.stmtList(n.Left.Ninit)
|
||||||
if n.Left.Bool() {
|
if n.Left.BoolVal() {
|
||||||
s.stmtList(n.Nbody)
|
s.stmtList(n.Nbody)
|
||||||
} else {
|
} else {
|
||||||
s.stmtList(n.Rlist)
|
s.stmtList(n.Rlist)
|
||||||
|
|
@ -2610,7 +2610,7 @@ func (s *state) expr(n *Node) *ssa.Value {
|
||||||
// Replace "abc"[1] with 'b'.
|
// Replace "abc"[1] with 'b'.
|
||||||
// Delayed until now because "abc"[1] is not an ideal constant.
|
// Delayed until now because "abc"[1] is not an ideal constant.
|
||||||
// See test/fixedbugs/issue11370.go.
|
// See test/fixedbugs/issue11370.go.
|
||||||
return s.newValue0I(ssa.OpConst8, types.Types[TUINT8], int64(int8(strlit(n.Left)[n.Right.Int64()])))
|
return s.newValue0I(ssa.OpConst8, types.Types[TUINT8], int64(int8(n.Left.StringVal()[n.Right.Int64Val()])))
|
||||||
}
|
}
|
||||||
a := s.expr(n.Left)
|
a := s.expr(n.Left)
|
||||||
i := s.expr(n.Right)
|
i := s.expr(n.Right)
|
||||||
|
|
@ -2619,7 +2619,7 @@ func (s *state) expr(n *Node) *ssa.Value {
|
||||||
ptrtyp := s.f.Config.Types.BytePtr
|
ptrtyp := s.f.Config.Types.BytePtr
|
||||||
ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a)
|
ptr := s.newValue1(ssa.OpStringPtr, ptrtyp, a)
|
||||||
if Isconst(n.Right, CTINT) {
|
if Isconst(n.Right, CTINT) {
|
||||||
ptr = s.newValue1I(ssa.OpOffPtr, ptrtyp, n.Right.Int64(), ptr)
|
ptr = s.newValue1I(ssa.OpOffPtr, ptrtyp, n.Right.Int64Val(), ptr)
|
||||||
} else {
|
} else {
|
||||||
ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i)
|
ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i)
|
||||||
}
|
}
|
||||||
|
|
@ -3389,6 +3389,13 @@ func init() {
|
||||||
return s.newValue1(ssa.OpSelect0, types.Types[TUINT32], v)
|
return s.newValue1(ssa.OpSelect0, types.Types[TUINT32], v)
|
||||||
},
|
},
|
||||||
sys.PPC64, sys.S390X)
|
sys.PPC64, sys.S390X)
|
||||||
|
addF("runtime/internal/atomic", "LoadAcq64",
|
||||||
|
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
||||||
|
v := s.newValue2(ssa.OpAtomicLoadAcq64, types.NewTuple(types.Types[TUINT64], types.TypeMem), args[0], s.mem())
|
||||||
|
s.vars[&memVar] = s.newValue1(ssa.OpSelect1, types.TypeMem, v)
|
||||||
|
return s.newValue1(ssa.OpSelect0, types.Types[TUINT64], v)
|
||||||
|
},
|
||||||
|
sys.PPC64)
|
||||||
addF("runtime/internal/atomic", "Loadp",
|
addF("runtime/internal/atomic", "Loadp",
|
||||||
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
||||||
v := s.newValue2(ssa.OpAtomicLoadPtr, types.NewTuple(s.f.Config.Types.BytePtr, types.TypeMem), args[0], s.mem())
|
v := s.newValue2(ssa.OpAtomicLoadPtr, types.NewTuple(s.f.Config.Types.BytePtr, types.TypeMem), args[0], s.mem())
|
||||||
|
|
@ -3427,6 +3434,12 @@ func init() {
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
sys.PPC64, sys.S390X)
|
sys.PPC64, sys.S390X)
|
||||||
|
addF("runtime/internal/atomic", "StoreRel64",
|
||||||
|
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
||||||
|
s.vars[&memVar] = s.newValue3(ssa.OpAtomicStoreRel64, types.TypeMem, args[0], args[1], s.mem())
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
sys.PPC64)
|
||||||
|
|
||||||
addF("runtime/internal/atomic", "Xchg",
|
addF("runtime/internal/atomic", "Xchg",
|
||||||
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
func(s *state, n *Node, args []*ssa.Value) *ssa.Value {
|
||||||
|
|
@ -3542,9 +3555,15 @@ func init() {
|
||||||
alias("runtime/internal/atomic", "Loaduintptr", "runtime/internal/atomic", "Load", p4...)
|
alias("runtime/internal/atomic", "Loaduintptr", "runtime/internal/atomic", "Load", p4...)
|
||||||
alias("runtime/internal/atomic", "Loaduintptr", "runtime/internal/atomic", "Load64", p8...)
|
alias("runtime/internal/atomic", "Loaduintptr", "runtime/internal/atomic", "Load64", p8...)
|
||||||
alias("runtime/internal/atomic", "LoadAcq", "runtime/internal/atomic", "Load", lwatomics...)
|
alias("runtime/internal/atomic", "LoadAcq", "runtime/internal/atomic", "Load", lwatomics...)
|
||||||
|
alias("runtime/internal/atomic", "LoadAcq64", "runtime/internal/atomic", "Load64", lwatomics...)
|
||||||
|
alias("runtime/internal/atomic", "LoadAcquintptr", "runtime/internal/atomic", "LoadAcq", p4...)
|
||||||
|
alias("runtime/internal/atomic", "LoadAcquintptr", "runtime/internal/atomic", "LoadAcq64", p8...)
|
||||||
alias("runtime/internal/atomic", "Storeuintptr", "runtime/internal/atomic", "Store", p4...)
|
alias("runtime/internal/atomic", "Storeuintptr", "runtime/internal/atomic", "Store", p4...)
|
||||||
alias("runtime/internal/atomic", "Storeuintptr", "runtime/internal/atomic", "Store64", p8...)
|
alias("runtime/internal/atomic", "Storeuintptr", "runtime/internal/atomic", "Store64", p8...)
|
||||||
alias("runtime/internal/atomic", "StoreRel", "runtime/internal/atomic", "Store", lwatomics...)
|
alias("runtime/internal/atomic", "StoreRel", "runtime/internal/atomic", "Store", lwatomics...)
|
||||||
|
alias("runtime/internal/atomic", "StoreRel64", "runtime/internal/atomic", "Store64", lwatomics...)
|
||||||
|
alias("runtime/internal/atomic", "StoreReluintptr", "runtime/internal/atomic", "StoreRel", p4...)
|
||||||
|
alias("runtime/internal/atomic", "StoreReluintptr", "runtime/internal/atomic", "StoreRel64", p8...)
|
||||||
alias("runtime/internal/atomic", "Xchguintptr", "runtime/internal/atomic", "Xchg", p4...)
|
alias("runtime/internal/atomic", "Xchguintptr", "runtime/internal/atomic", "Xchg", p4...)
|
||||||
alias("runtime/internal/atomic", "Xchguintptr", "runtime/internal/atomic", "Xchg64", p8...)
|
alias("runtime/internal/atomic", "Xchguintptr", "runtime/internal/atomic", "Xchg64", p8...)
|
||||||
alias("runtime/internal/atomic", "Xadduintptr", "runtime/internal/atomic", "Xadd", p4...)
|
alias("runtime/internal/atomic", "Xadduintptr", "runtime/internal/atomic", "Xadd", p4...)
|
||||||
|
|
@ -4830,7 +4849,7 @@ func (s *state) addr(n *Node) *ssa.Value {
|
||||||
// canSSA reports whether n is SSA-able.
|
// canSSA reports whether n is SSA-able.
|
||||||
// n must be an ONAME (or an ODOT sequence with an ONAME base).
|
// n must be an ONAME (or an ODOT sequence with an ONAME base).
|
||||||
func (s *state) canSSA(n *Node) bool {
|
func (s *state) canSSA(n *Node) bool {
|
||||||
if Debug['N'] != 0 {
|
if Debug.N != 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for n.Op == ODOT || (n.Op == OINDEX && n.Left.Type.IsArray()) {
|
for n.Op == ODOT || (n.Op == OINDEX && n.Left.Type.IsArray()) {
|
||||||
|
|
@ -4941,7 +4960,7 @@ func (s *state) nilCheck(ptr *ssa.Value) {
|
||||||
func (s *state) boundsCheck(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bool) *ssa.Value {
|
func (s *state) boundsCheck(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bool) *ssa.Value {
|
||||||
idx = s.extendIndex(idx, len, kind, bounded)
|
idx = s.extendIndex(idx, len, kind, bounded)
|
||||||
|
|
||||||
if bounded || Debug['B'] != 0 {
|
if bounded || Debug.B != 0 {
|
||||||
// If bounded or bounds checking is flag-disabled, then no check necessary,
|
// If bounded or bounds checking is flag-disabled, then no check necessary,
|
||||||
// just return the extended index.
|
// just return the extended index.
|
||||||
//
|
//
|
||||||
|
|
@ -6108,7 +6127,7 @@ func emitStackObjects(e *ssafn, pp *Progs) {
|
||||||
|
|
||||||
// Populate the stack object data.
|
// Populate the stack object data.
|
||||||
// Format must match runtime/stack.go:stackObjectRecord.
|
// Format must match runtime/stack.go:stackObjectRecord.
|
||||||
x := e.curfn.Func.lsym.Func.StackObjects
|
x := e.curfn.Func.lsym.Func().StackObjects
|
||||||
off := 0
|
off := 0
|
||||||
off = duintptr(x, off, uint64(len(vars)))
|
off = duintptr(x, off, uint64(len(vars)))
|
||||||
for _, v := range vars {
|
for _, v := range vars {
|
||||||
|
|
@ -6145,7 +6164,7 @@ func genssa(f *ssa.Func, pp *Progs) {
|
||||||
s.livenessMap = liveness(e, f, pp)
|
s.livenessMap = liveness(e, f, pp)
|
||||||
emitStackObjects(e, pp)
|
emitStackObjects(e, pp)
|
||||||
|
|
||||||
openDeferInfo := e.curfn.Func.lsym.Func.OpenCodedDeferInfo
|
openDeferInfo := e.curfn.Func.lsym.Func().OpenCodedDeferInfo
|
||||||
if openDeferInfo != nil {
|
if openDeferInfo != nil {
|
||||||
// This function uses open-coded defers -- write out the funcdata
|
// This function uses open-coded defers -- write out the funcdata
|
||||||
// info that we computed at the end of genssa.
|
// info that we computed at the end of genssa.
|
||||||
|
|
@ -6291,7 +6310,7 @@ func genssa(f *ssa.Func, pp *Progs) {
|
||||||
}
|
}
|
||||||
// Emit control flow instructions for block
|
// Emit control flow instructions for block
|
||||||
var next *ssa.Block
|
var next *ssa.Block
|
||||||
if i < len(f.Blocks)-1 && Debug['N'] == 0 {
|
if i < len(f.Blocks)-1 && Debug.N == 0 {
|
||||||
// If -N, leave next==nil so every block with successors
|
// If -N, leave next==nil so every block with successors
|
||||||
// ends in a JMP (except call blocks - plive doesn't like
|
// ends in a JMP (except call blocks - plive doesn't like
|
||||||
// select{send,recv} followed by a JMP call). Helps keep
|
// select{send,recv} followed by a JMP call). Helps keep
|
||||||
|
|
@ -6350,7 +6369,7 @@ func genssa(f *ssa.Func, pp *Progs) {
|
||||||
// some of the inline marks.
|
// some of the inline marks.
|
||||||
// Use this instruction instead.
|
// Use this instruction instead.
|
||||||
p.Pos = p.Pos.WithIsStmt() // promote position to a statement
|
p.Pos = p.Pos.WithIsStmt() // promote position to a statement
|
||||||
pp.curfn.Func.lsym.Func.AddInlMark(p, inlMarks[m])
|
pp.curfn.Func.lsym.Func().AddInlMark(p, inlMarks[m])
|
||||||
// Make the inline mark a real nop, so it doesn't generate any code.
|
// Make the inline mark a real nop, so it doesn't generate any code.
|
||||||
m.As = obj.ANOP
|
m.As = obj.ANOP
|
||||||
m.Pos = src.NoXPos
|
m.Pos = src.NoXPos
|
||||||
|
|
@ -6362,7 +6381,7 @@ func genssa(f *ssa.Func, pp *Progs) {
|
||||||
// Any unmatched inline marks now need to be added to the inlining tree (and will generate a nop instruction).
|
// Any unmatched inline marks now need to be added to the inlining tree (and will generate a nop instruction).
|
||||||
for _, p := range inlMarkList {
|
for _, p := range inlMarkList {
|
||||||
if p.As != obj.ANOP {
|
if p.As != obj.ANOP {
|
||||||
pp.curfn.Func.lsym.Func.AddInlMark(p, inlMarks[p])
|
pp.curfn.Func.lsym.Func().AddInlMark(p, inlMarks[p])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6599,7 +6618,7 @@ func (s *state) extendIndex(idx, len *ssa.Value, kind ssa.BoundsKind, bounded bo
|
||||||
} else {
|
} else {
|
||||||
lo = s.newValue1(ssa.OpInt64Lo, types.Types[TUINT], idx)
|
lo = s.newValue1(ssa.OpInt64Lo, types.Types[TUINT], idx)
|
||||||
}
|
}
|
||||||
if bounded || Debug['B'] != 0 {
|
if bounded || Debug.B != 0 {
|
||||||
return lo
|
return lo
|
||||||
}
|
}
|
||||||
bNext := s.f.NewBlock(ssa.BlockPlain)
|
bNext := s.f.NewBlock(ssa.BlockPlain)
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ func flusherrors() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func hcrash() {
|
func hcrash() {
|
||||||
if Debug['h'] != 0 {
|
if Debug.h != 0 {
|
||||||
flusherrors()
|
flusherrors()
|
||||||
if outfile != "" {
|
if outfile != "" {
|
||||||
os.Remove(outfile)
|
os.Remove(outfile)
|
||||||
|
|
@ -107,7 +107,7 @@ func hcrash() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func linestr(pos src.XPos) string {
|
func linestr(pos src.XPos) string {
|
||||||
return Ctxt.OutermostPos(pos).Format(Debug['C'] == 0, Debug['L'] == 1)
|
return Ctxt.OutermostPos(pos).Format(Debug.C == 0, Debug.L == 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// lasterror keeps track of the most recently issued error.
|
// lasterror keeps track of the most recently issued error.
|
||||||
|
|
@ -153,7 +153,7 @@ func yyerrorl(pos src.XPos, format string, args ...interface{}) {
|
||||||
|
|
||||||
hcrash()
|
hcrash()
|
||||||
nerrors++
|
nerrors++
|
||||||
if nsavederrors+nerrors >= 10 && Debug['e'] == 0 {
|
if nsavederrors+nerrors >= 10 && Debug.e == 0 {
|
||||||
flusherrors()
|
flusherrors()
|
||||||
fmt.Printf("%v: too many errors\n", linestr(pos))
|
fmt.Printf("%v: too many errors\n", linestr(pos))
|
||||||
errorexit()
|
errorexit()
|
||||||
|
|
@ -175,7 +175,7 @@ func Warn(fmt_ string, args ...interface{}) {
|
||||||
|
|
||||||
func Warnl(line src.XPos, fmt_ string, args ...interface{}) {
|
func Warnl(line src.XPos, fmt_ string, args ...interface{}) {
|
||||||
adderr(line, fmt_, args...)
|
adderr(line, fmt_, args...)
|
||||||
if Debug['m'] != 0 {
|
if Debug.m != 0 {
|
||||||
flusherrors()
|
flusherrors()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -222,7 +222,7 @@ func hasUniquePos(n *Node) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !n.Pos.IsKnown() {
|
if !n.Pos.IsKnown() {
|
||||||
if Debug['K'] != 0 {
|
if Debug.K != 0 {
|
||||||
Warn("setlineno: unknown position (line 0)")
|
Warn("setlineno: unknown position (line 0)")
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
@ -348,7 +348,7 @@ func newname(s *types.Sym) *Node {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// newname returns a new ONAME Node associated with symbol s at position pos.
|
// newnamel returns a new ONAME Node associated with symbol s at position pos.
|
||||||
// The caller is responsible for setting n.Name.Curfn.
|
// The caller is responsible for setting n.Name.Curfn.
|
||||||
func newnamel(pos src.XPos, s *types.Sym) *Node {
|
func newnamel(pos src.XPos, s *types.Sym) *Node {
|
||||||
if s == nil {
|
if s == nil {
|
||||||
|
|
@ -546,22 +546,19 @@ func methtype(t *types.Type) *types.Type {
|
||||||
|
|
||||||
// Is type src assignment compatible to type dst?
|
// Is type src assignment compatible to type dst?
|
||||||
// If so, return op code to use in conversion.
|
// If so, return op code to use in conversion.
|
||||||
// If not, return OXXX.
|
// If not, return OXXX. In this case, the string return parameter may
|
||||||
func assignop(src, dst *types.Type, why *string) Op {
|
// hold a reason why. In all other cases, it'll be the empty string.
|
||||||
if why != nil {
|
func assignop(src, dst *types.Type) (Op, string) {
|
||||||
*why = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if src == dst {
|
if src == dst {
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
if src == nil || dst == nil || src.Etype == TFORW || dst.Etype == TFORW || src.Orig == nil || dst.Orig == nil {
|
if src == nil || dst == nil || src.Etype == TFORW || dst.Etype == TFORW || src.Orig == nil || dst.Orig == nil {
|
||||||
return OXXX
|
return OXXX, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. src type is identical to dst.
|
// 1. src type is identical to dst.
|
||||||
if types.Identical(src, dst) {
|
if types.Identical(src, dst) {
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. src and dst have identical underlying types
|
// 2. src and dst have identical underlying types
|
||||||
|
|
@ -575,13 +572,13 @@ func assignop(src, dst *types.Type, why *string) Op {
|
||||||
if src.IsEmptyInterface() {
|
if src.IsEmptyInterface() {
|
||||||
// Conversion between two empty interfaces
|
// Conversion between two empty interfaces
|
||||||
// requires no code.
|
// requires no code.
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
if (src.Sym == nil || dst.Sym == nil) && !src.IsInterface() {
|
if (src.Sym == nil || dst.Sym == nil) && !src.IsInterface() {
|
||||||
// Conversion between two types, at least one unnamed,
|
// Conversion between two types, at least one unnamed,
|
||||||
// needs no conversion. The exception is nonempty interfaces
|
// needs no conversion. The exception is nonempty interfaces
|
||||||
// which need to have their itab updated.
|
// which need to have their itab updated.
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -590,49 +587,47 @@ func assignop(src, dst *types.Type, why *string) Op {
|
||||||
var missing, have *types.Field
|
var missing, have *types.Field
|
||||||
var ptr int
|
var ptr int
|
||||||
if implements(src, dst, &missing, &have, &ptr) {
|
if implements(src, dst, &missing, &have, &ptr) {
|
||||||
return OCONVIFACE
|
return OCONVIFACE, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// we'll have complained about this method anyway, suppress spurious messages.
|
// we'll have complained about this method anyway, suppress spurious messages.
|
||||||
if have != nil && have.Sym == missing.Sym && (have.Type.Broke() || missing.Type.Broke()) {
|
if have != nil && have.Sym == missing.Sym && (have.Type.Broke() || missing.Type.Broke()) {
|
||||||
return OCONVIFACE
|
return OCONVIFACE, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if why != nil {
|
var why string
|
||||||
if isptrto(src, TINTER) {
|
if isptrto(src, TINTER) {
|
||||||
*why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", src)
|
why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", src)
|
||||||
} else if have != nil && have.Sym == missing.Sym && have.Nointerface() {
|
} else if have != nil && have.Sym == missing.Sym && have.Nointerface() {
|
||||||
*why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym)
|
why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym)
|
||||||
} else if have != nil && have.Sym == missing.Sym {
|
} else if have != nil && have.Sym == missing.Sym {
|
||||||
*why = fmt.Sprintf(":\n\t%v does not implement %v (wrong type for %v method)\n"+
|
why = fmt.Sprintf(":\n\t%v does not implement %v (wrong type for %v method)\n"+
|
||||||
"\t\thave %v%0S\n\t\twant %v%0S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
|
"\t\thave %v%0S\n\t\twant %v%0S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
|
||||||
} else if ptr != 0 {
|
} else if ptr != 0 {
|
||||||
*why = fmt.Sprintf(":\n\t%v does not implement %v (%v method has pointer receiver)", src, dst, missing.Sym)
|
why = fmt.Sprintf(":\n\t%v does not implement %v (%v method has pointer receiver)", src, dst, missing.Sym)
|
||||||
} else if have != nil {
|
} else if have != nil {
|
||||||
*why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)\n"+
|
why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)\n"+
|
||||||
"\t\thave %v%0S\n\t\twant %v%0S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
|
"\t\thave %v%0S\n\t\twant %v%0S", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
|
||||||
} else {
|
} else {
|
||||||
*why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym)
|
why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return OXXX
|
return OXXX, why
|
||||||
}
|
}
|
||||||
|
|
||||||
if isptrto(dst, TINTER) {
|
if isptrto(dst, TINTER) {
|
||||||
if why != nil {
|
why := fmt.Sprintf(":\n\t%v is pointer to interface, not interface", dst)
|
||||||
*why = fmt.Sprintf(":\n\t%v is pointer to interface, not interface", dst)
|
return OXXX, why
|
||||||
}
|
|
||||||
return OXXX
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if src.IsInterface() && dst.Etype != TBLANK {
|
if src.IsInterface() && dst.Etype != TBLANK {
|
||||||
var missing, have *types.Field
|
var missing, have *types.Field
|
||||||
var ptr int
|
var ptr int
|
||||||
if why != nil && implements(dst, src, &missing, &have, &ptr) {
|
var why string
|
||||||
*why = ": need type assertion"
|
if implements(dst, src, &missing, &have, &ptr) {
|
||||||
|
why = ": need type assertion"
|
||||||
}
|
}
|
||||||
return OXXX
|
return OXXX, why
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. src is a bidirectional channel value, dst is a channel type,
|
// 4. src is a bidirectional channel value, dst is a channel type,
|
||||||
|
|
@ -640,7 +635,7 @@ func assignop(src, dst *types.Type, why *string) Op {
|
||||||
// either src or dst is not a named type.
|
// either src or dst is not a named type.
|
||||||
if src.IsChan() && src.ChanDir() == types.Cboth && dst.IsChan() {
|
if src.IsChan() && src.ChanDir() == types.Cboth && dst.IsChan() {
|
||||||
if types.Identical(src.Elem(), dst.Elem()) && (src.Sym == nil || dst.Sym == nil) {
|
if types.Identical(src.Elem(), dst.Elem()) && (src.Sym == nil || dst.Sym == nil) {
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -653,7 +648,7 @@ func assignop(src, dst *types.Type, why *string) Op {
|
||||||
TCHAN,
|
TCHAN,
|
||||||
TINTER,
|
TINTER,
|
||||||
TSLICE:
|
TSLICE:
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -661,26 +656,23 @@ func assignop(src, dst *types.Type, why *string) Op {
|
||||||
|
|
||||||
// 7. Any typed value can be assigned to the blank identifier.
|
// 7. Any typed value can be assigned to the blank identifier.
|
||||||
if dst.Etype == TBLANK {
|
if dst.Etype == TBLANK {
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return OXXX
|
return OXXX, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can we convert a value of type src to a value of type dst?
|
// Can we convert a value of type src to a value of type dst?
|
||||||
// If so, return op code to use in conversion (maybe OCONVNOP).
|
// If so, return op code to use in conversion (maybe OCONVNOP).
|
||||||
// If not, return OXXX.
|
// If not, return OXXX. In this case, the string return parameter may
|
||||||
|
// hold a reason why. In all other cases, it'll be the empty string.
|
||||||
// srcConstant indicates whether the value of type src is a constant.
|
// srcConstant indicates whether the value of type src is a constant.
|
||||||
func convertop(srcConstant bool, src, dst *types.Type, why *string) Op {
|
func convertop(srcConstant bool, src, dst *types.Type) (Op, string) {
|
||||||
if why != nil {
|
|
||||||
*why = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if src == dst {
|
if src == dst {
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
if src == nil || dst == nil {
|
if src == nil || dst == nil {
|
||||||
return OXXX
|
return OXXX, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conversions from regular to go:notinheap are not allowed
|
// Conversions from regular to go:notinheap are not allowed
|
||||||
|
|
@ -688,23 +680,19 @@ func convertop(srcConstant bool, src, dst *types.Type, why *string) Op {
|
||||||
// rules.
|
// rules.
|
||||||
// (a) Disallow (*T) to (*U) where T is go:notinheap but U isn't.
|
// (a) Disallow (*T) to (*U) where T is go:notinheap but U isn't.
|
||||||
if src.IsPtr() && dst.IsPtr() && dst.Elem().NotInHeap() && !src.Elem().NotInHeap() {
|
if src.IsPtr() && dst.IsPtr() && dst.Elem().NotInHeap() && !src.Elem().NotInHeap() {
|
||||||
if why != nil {
|
why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable), but %v is not", dst.Elem(), src.Elem())
|
||||||
*why = fmt.Sprintf(":\n\t%v is incomplete (or unallocatable), but %v is not", dst.Elem(), src.Elem())
|
return OXXX, why
|
||||||
}
|
|
||||||
return OXXX
|
|
||||||
}
|
}
|
||||||
// (b) Disallow string to []T where T is go:notinheap.
|
// (b) Disallow string to []T where T is go:notinheap.
|
||||||
if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Etype == types.Bytetype.Etype || dst.Elem().Etype == types.Runetype.Etype) {
|
if src.IsString() && dst.IsSlice() && dst.Elem().NotInHeap() && (dst.Elem().Etype == types.Bytetype.Etype || dst.Elem().Etype == types.Runetype.Etype) {
|
||||||
if why != nil {
|
why := fmt.Sprintf(":\n\t%v is incomplete (or unallocatable)", dst.Elem())
|
||||||
*why = fmt.Sprintf(":\n\t%v is incomplete (or unallocatable)", dst.Elem())
|
return OXXX, why
|
||||||
}
|
|
||||||
return OXXX
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. src can be assigned to dst.
|
// 1. src can be assigned to dst.
|
||||||
op := assignop(src, dst, why)
|
op, why := assignop(src, dst)
|
||||||
if op != OXXX {
|
if op != OXXX {
|
||||||
return op
|
return op, why
|
||||||
}
|
}
|
||||||
|
|
||||||
// The rules for interfaces are no different in conversions
|
// The rules for interfaces are no different in conversions
|
||||||
|
|
@ -712,60 +700,57 @@ func convertop(srcConstant bool, src, dst *types.Type, why *string) Op {
|
||||||
// with the good message from assignop.
|
// with the good message from assignop.
|
||||||
// Otherwise clear the error.
|
// Otherwise clear the error.
|
||||||
if src.IsInterface() || dst.IsInterface() {
|
if src.IsInterface() || dst.IsInterface() {
|
||||||
return OXXX
|
return OXXX, why
|
||||||
}
|
|
||||||
if why != nil {
|
|
||||||
*why = ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Ignoring struct tags, src and dst have identical underlying types.
|
// 2. Ignoring struct tags, src and dst have identical underlying types.
|
||||||
if types.IdenticalIgnoreTags(src.Orig, dst.Orig) {
|
if types.IdenticalIgnoreTags(src.Orig, dst.Orig) {
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. src and dst are unnamed pointer types and, ignoring struct tags,
|
// 3. src and dst are unnamed pointer types and, ignoring struct tags,
|
||||||
// their base types have identical underlying types.
|
// their base types have identical underlying types.
|
||||||
if src.IsPtr() && dst.IsPtr() && src.Sym == nil && dst.Sym == nil {
|
if src.IsPtr() && dst.IsPtr() && src.Sym == nil && dst.Sym == nil {
|
||||||
if types.IdenticalIgnoreTags(src.Elem().Orig, dst.Elem().Orig) {
|
if types.IdenticalIgnoreTags(src.Elem().Orig, dst.Elem().Orig) {
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. src and dst are both integer or floating point types.
|
// 4. src and dst are both integer or floating point types.
|
||||||
if (src.IsInteger() || src.IsFloat()) && (dst.IsInteger() || dst.IsFloat()) {
|
if (src.IsInteger() || src.IsFloat()) && (dst.IsInteger() || dst.IsFloat()) {
|
||||||
if simtype[src.Etype] == simtype[dst.Etype] {
|
if simtype[src.Etype] == simtype[dst.Etype] {
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
return OCONV
|
return OCONV, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. src and dst are both complex types.
|
// 5. src and dst are both complex types.
|
||||||
if src.IsComplex() && dst.IsComplex() {
|
if src.IsComplex() && dst.IsComplex() {
|
||||||
if simtype[src.Etype] == simtype[dst.Etype] {
|
if simtype[src.Etype] == simtype[dst.Etype] {
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
return OCONV
|
return OCONV, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case for constant conversions: any numeric
|
// Special case for constant conversions: any numeric
|
||||||
// conversion is potentially okay. We'll validate further
|
// conversion is potentially okay. We'll validate further
|
||||||
// within evconst. See #38117.
|
// within evconst. See #38117.
|
||||||
if srcConstant && (src.IsInteger() || src.IsFloat() || src.IsComplex()) && (dst.IsInteger() || dst.IsFloat() || dst.IsComplex()) {
|
if srcConstant && (src.IsInteger() || src.IsFloat() || src.IsComplex()) && (dst.IsInteger() || dst.IsFloat() || dst.IsComplex()) {
|
||||||
return OCONV
|
return OCONV, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. src is an integer or has type []byte or []rune
|
// 6. src is an integer or has type []byte or []rune
|
||||||
// and dst is a string type.
|
// and dst is a string type.
|
||||||
if src.IsInteger() && dst.IsString() {
|
if src.IsInteger() && dst.IsString() {
|
||||||
return ORUNESTR
|
return ORUNESTR, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if src.IsSlice() && dst.IsString() {
|
if src.IsSlice() && dst.IsString() {
|
||||||
if src.Elem().Etype == types.Bytetype.Etype {
|
if src.Elem().Etype == types.Bytetype.Etype {
|
||||||
return OBYTES2STR
|
return OBYTES2STR, ""
|
||||||
}
|
}
|
||||||
if src.Elem().Etype == types.Runetype.Etype {
|
if src.Elem().Etype == types.Runetype.Etype {
|
||||||
return ORUNES2STR
|
return ORUNES2STR, ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -773,21 +758,21 @@ func convertop(srcConstant bool, src, dst *types.Type, why *string) Op {
|
||||||
// String to slice.
|
// String to slice.
|
||||||
if src.IsString() && dst.IsSlice() {
|
if src.IsString() && dst.IsSlice() {
|
||||||
if dst.Elem().Etype == types.Bytetype.Etype {
|
if dst.Elem().Etype == types.Bytetype.Etype {
|
||||||
return OSTR2BYTES
|
return OSTR2BYTES, ""
|
||||||
}
|
}
|
||||||
if dst.Elem().Etype == types.Runetype.Etype {
|
if dst.Elem().Etype == types.Runetype.Etype {
|
||||||
return OSTR2RUNES
|
return OSTR2RUNES, ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. src is a pointer or uintptr and dst is unsafe.Pointer.
|
// 8. src is a pointer or uintptr and dst is unsafe.Pointer.
|
||||||
if (src.IsPtr() || src.IsUintptr()) && dst.IsUnsafePtr() {
|
if (src.IsPtr() || src.IsUintptr()) && dst.IsUnsafePtr() {
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// 9. src is unsafe.Pointer and dst is a pointer or uintptr.
|
// 9. src is unsafe.Pointer and dst is a pointer or uintptr.
|
||||||
if src.IsUnsafePtr() && (dst.IsPtr() || dst.IsUintptr()) {
|
if src.IsUnsafePtr() && (dst.IsPtr() || dst.IsUintptr()) {
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// src is map and dst is a pointer to corresponding hmap.
|
// src is map and dst is a pointer to corresponding hmap.
|
||||||
|
|
@ -795,10 +780,10 @@ func convertop(srcConstant bool, src, dst *types.Type, why *string) Op {
|
||||||
// go gc maps are implemented as a pointer to a hmap struct.
|
// go gc maps are implemented as a pointer to a hmap struct.
|
||||||
if src.Etype == TMAP && dst.IsPtr() &&
|
if src.Etype == TMAP && dst.IsPtr() &&
|
||||||
src.MapType().Hmap == dst.Elem() {
|
src.MapType().Hmap == dst.Elem() {
|
||||||
return OCONVNOP
|
return OCONVNOP, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return OXXX
|
return OXXX, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func assignconv(n *Node, t *types.Type, context string) *Node {
|
func assignconv(n *Node, t *types.Type, context string) *Node {
|
||||||
|
|
@ -839,8 +824,7 @@ func assignconvfn(n *Node, t *types.Type, context func() string) *Node {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
var why string
|
op, why := assignop(n.Type, t)
|
||||||
op := assignop(n.Type, t, &why)
|
|
||||||
if op == OXXX {
|
if op == OXXX {
|
||||||
yyerror("cannot use %L as type %v in %s%s", n, t, context(), why)
|
yyerror("cannot use %L as type %v in %s%s", n, t, context(), why)
|
||||||
op = OCONV
|
op = OCONV
|
||||||
|
|
@ -1040,25 +1024,24 @@ func calcHasCall(n *Node) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func badtype(op Op, tl *types.Type, tr *types.Type) {
|
func badtype(op Op, tl, tr *types.Type) {
|
||||||
fmt_ := ""
|
var s string
|
||||||
if tl != nil {
|
if tl != nil {
|
||||||
fmt_ += fmt.Sprintf("\n\t%v", tl)
|
s += fmt.Sprintf("\n\t%v", tl)
|
||||||
}
|
}
|
||||||
if tr != nil {
|
if tr != nil {
|
||||||
fmt_ += fmt.Sprintf("\n\t%v", tr)
|
s += fmt.Sprintf("\n\t%v", tr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// common mistake: *struct and *interface.
|
// common mistake: *struct and *interface.
|
||||||
if tl != nil && tr != nil && tl.IsPtr() && tr.IsPtr() {
|
if tl != nil && tr != nil && tl.IsPtr() && tr.IsPtr() {
|
||||||
if tl.Elem().IsStruct() && tr.Elem().IsInterface() {
|
if tl.Elem().IsStruct() && tr.Elem().IsInterface() {
|
||||||
fmt_ += "\n\t(*struct vs *interface)"
|
s += "\n\t(*struct vs *interface)"
|
||||||
} else if tl.Elem().IsInterface() && tr.Elem().IsStruct() {
|
} else if tl.Elem().IsInterface() && tr.Elem().IsStruct() {
|
||||||
fmt_ += "\n\t(*interface vs *struct)"
|
s += "\n\t(*interface vs *struct)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s := fmt_
|
|
||||||
yyerror("illegal types for operand: %v%s", op, s)
|
yyerror("illegal types for operand: %v%s", op, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1523,7 +1506,7 @@ func structargs(tl *types.Type, mustname bool) []*Node {
|
||||||
// method - M func (t T)(), a TFIELD type struct
|
// method - M func (t T)(), a TFIELD type struct
|
||||||
// newnam - the eventual mangled name of this function
|
// newnam - the eventual mangled name of this function
|
||||||
func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
|
func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
|
||||||
if false && Debug['r'] != 0 {
|
if false && Debug.r != 0 {
|
||||||
fmt.Printf("genwrapper rcvrtype=%v method=%v newnam=%v\n", rcvr, method, newnam)
|
fmt.Printf("genwrapper rcvrtype=%v method=%v newnam=%v\n", rcvr, method, newnam)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1596,7 +1579,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
|
||||||
fn.Nbody.Append(call)
|
fn.Nbody.Append(call)
|
||||||
}
|
}
|
||||||
|
|
||||||
if false && Debug['r'] != 0 {
|
if false && Debug.r != 0 {
|
||||||
dumplist("genwrapper body", fn.Nbody)
|
dumplist("genwrapper body", fn.Nbody)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1737,7 +1720,7 @@ func implements(t, iface *types.Type, m, samename **types.Field, ptr *int) bool
|
||||||
// the method does not exist for value types.
|
// the method does not exist for value types.
|
||||||
rcvr := tm.Type.Recv().Type
|
rcvr := tm.Type.Recv().Type
|
||||||
if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !isifacemethod(tm.Type) {
|
if rcvr.IsPtr() && !t0.IsPtr() && !followptr && !isifacemethod(tm.Type) {
|
||||||
if false && Debug['r'] != 0 {
|
if false && Debug.r != 0 {
|
||||||
yyerror("interface pointer mismatch")
|
yyerror("interface pointer mismatch")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -189,18 +189,21 @@ func typecheckExprSwitch(n *Node) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
if nilonly != "" && !n1.isNil() {
|
||||||
case nilonly != "" && !n1.isNil():
|
|
||||||
yyerrorl(ncase.Pos, "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Left)
|
yyerrorl(ncase.Pos, "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Left)
|
||||||
case t.IsInterface() && !n1.Type.IsInterface() && !IsComparable(n1.Type):
|
} else if t.IsInterface() && !n1.Type.IsInterface() && !IsComparable(n1.Type) {
|
||||||
yyerrorl(ncase.Pos, "invalid case %L in switch (incomparable type)", n1)
|
yyerrorl(ncase.Pos, "invalid case %L in switch (incomparable type)", n1)
|
||||||
case assignop(n1.Type, t, nil) == 0 && assignop(t, n1.Type, nil) == 0:
|
} else {
|
||||||
|
op1, _ := assignop(n1.Type, t)
|
||||||
|
op2, _ := assignop(t, n1.Type)
|
||||||
|
if op1 == OXXX && op2 == OXXX {
|
||||||
if n.Left != nil {
|
if n.Left != nil {
|
||||||
yyerrorl(ncase.Pos, "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Left, n1.Type, t)
|
yyerrorl(ncase.Pos, "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Left, n1.Type, t)
|
||||||
} else {
|
} else {
|
||||||
yyerrorl(ncase.Pos, "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type)
|
yyerrorl(ncase.Pos, "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Don't check for duplicate bools. Although the spec allows it,
|
// Don't check for duplicate bools. Although the spec allows it,
|
||||||
// (1) the compiler hasn't checked it in the past, so compatibility mandates it, and
|
// (1) the compiler hasn't checked it in the past, so compatibility mandates it, and
|
||||||
|
|
@ -358,8 +361,8 @@ func (s *exprSwitch) flush() {
|
||||||
// all we need here is consistency. We respect this
|
// all we need here is consistency. We respect this
|
||||||
// sorting below.
|
// sorting below.
|
||||||
sort.Slice(cc, func(i, j int) bool {
|
sort.Slice(cc, func(i, j int) bool {
|
||||||
si := strlit(cc[i].lo)
|
si := cc[i].lo.StringVal()
|
||||||
sj := strlit(cc[j].lo)
|
sj := cc[j].lo.StringVal()
|
||||||
if len(si) != len(sj) {
|
if len(si) != len(sj) {
|
||||||
return len(si) < len(sj)
|
return len(si) < len(sj)
|
||||||
}
|
}
|
||||||
|
|
@ -368,7 +371,7 @@ func (s *exprSwitch) flush() {
|
||||||
|
|
||||||
// runLen returns the string length associated with a
|
// runLen returns the string length associated with a
|
||||||
// particular run of exprClauses.
|
// particular run of exprClauses.
|
||||||
runLen := func(run []exprClause) int64 { return int64(len(strlit(run[0].lo))) }
|
runLen := func(run []exprClause) int64 { return int64(len(run[0].lo.StringVal())) }
|
||||||
|
|
||||||
// Collapse runs of consecutive strings with the same length.
|
// Collapse runs of consecutive strings with the same length.
|
||||||
var runs [][]exprClause
|
var runs [][]exprClause
|
||||||
|
|
@ -405,7 +408,7 @@ func (s *exprSwitch) flush() {
|
||||||
merged := cc[:1]
|
merged := cc[:1]
|
||||||
for _, c := range cc[1:] {
|
for _, c := range cc[1:] {
|
||||||
last := &merged[len(merged)-1]
|
last := &merged[len(merged)-1]
|
||||||
if last.jmp == c.jmp && last.hi.Int64()+1 == c.lo.Int64() {
|
if last.jmp == c.jmp && last.hi.Int64Val()+1 == c.lo.Int64Val() {
|
||||||
last.hi = c.lo
|
last.hi = c.lo
|
||||||
} else {
|
} else {
|
||||||
merged = append(merged, c)
|
merged = append(merged, c)
|
||||||
|
|
@ -440,7 +443,7 @@ func (c *exprClause) test(exprname *Node) *Node {
|
||||||
|
|
||||||
// Optimize "switch true { ...}" and "switch false { ... }".
|
// Optimize "switch true { ...}" and "switch false { ... }".
|
||||||
if Isconst(exprname, CTBOOL) && !c.lo.Type.IsInterface() {
|
if Isconst(exprname, CTBOOL) && !c.lo.Type.IsInterface() {
|
||||||
if exprname.Bool() {
|
if exprname.BoolVal() {
|
||||||
return c.lo
|
return c.lo
|
||||||
} else {
|
} else {
|
||||||
return nodl(c.pos, ONOT, c.lo, nil)
|
return nodl(c.pos, ONOT, c.lo, nil)
|
||||||
|
|
|
||||||
|
|
@ -247,7 +247,7 @@ func (n *Node) Val() Val {
|
||||||
// SetVal sets the Val for the node, which must not have been used with SetOpt.
|
// SetVal sets the Val for the node, which must not have been used with SetOpt.
|
||||||
func (n *Node) SetVal(v Val) {
|
func (n *Node) SetVal(v Val) {
|
||||||
if n.HasOpt() {
|
if n.HasOpt() {
|
||||||
Debug['h'] = 1
|
Debug.h = 1
|
||||||
Dump("have Opt", n)
|
Dump("have Opt", n)
|
||||||
Fatalf("have Opt")
|
Fatalf("have Opt")
|
||||||
}
|
}
|
||||||
|
|
@ -270,7 +270,7 @@ func (n *Node) SetOpt(x interface{}) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if n.HasVal() {
|
if n.HasVal() {
|
||||||
Debug['h'] = 1
|
Debug.h = 1
|
||||||
Dump("have Val", n)
|
Dump("have Val", n)
|
||||||
Fatalf("have Val")
|
Fatalf("have Val")
|
||||||
}
|
}
|
||||||
|
|
@ -460,14 +460,14 @@ type Param struct {
|
||||||
// x1 := xN.Defn
|
// x1 := xN.Defn
|
||||||
// x1.Innermost = xN.Outer
|
// x1.Innermost = xN.Outer
|
||||||
//
|
//
|
||||||
// We leave xN.Innermost set so that we can still get to the original
|
// We leave x1.Innermost set so that we can still get to the original
|
||||||
// variable quickly. Not shown here, but once we're
|
// variable quickly. Not shown here, but once we're
|
||||||
// done parsing a function and no longer need xN.Outer for the
|
// done parsing a function and no longer need xN.Outer for the
|
||||||
// lexical x reference links as described above, closurebody
|
// lexical x reference links as described above, funcLit
|
||||||
// recomputes xN.Outer as the semantic x reference link tree,
|
// recomputes xN.Outer as the semantic x reference link tree,
|
||||||
// even filling in x in intermediate closures that might not
|
// even filling in x in intermediate closures that might not
|
||||||
// have mentioned it along the way to inner closures that did.
|
// have mentioned it along the way to inner closures that did.
|
||||||
// See closurebody for details.
|
// See funcLit for details.
|
||||||
//
|
//
|
||||||
// During the eventual compilation, then, for closure variables we have:
|
// During the eventual compilation, then, for closure variables we have:
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -674,8 +674,8 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||||
// The conversion allocates, so only do it if the concrete type is huge.
|
// The conversion allocates, so only do it if the concrete type is huge.
|
||||||
converted := false
|
converted := false
|
||||||
if r.Type.Etype != TBLANK {
|
if r.Type.Etype != TBLANK {
|
||||||
aop = assignop(l.Type, r.Type, nil)
|
aop, _ = assignop(l.Type, r.Type)
|
||||||
if aop != 0 {
|
if aop != OXXX {
|
||||||
if r.Type.IsInterface() && !l.Type.IsInterface() && !IsComparable(l.Type) {
|
if r.Type.IsInterface() && !l.Type.IsInterface() && !IsComparable(l.Type) {
|
||||||
yyerror("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(l.Type))
|
yyerror("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(l.Type))
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
|
|
@ -696,8 +696,8 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !converted && l.Type.Etype != TBLANK {
|
if !converted && l.Type.Etype != TBLANK {
|
||||||
aop = assignop(r.Type, l.Type, nil)
|
aop, _ = assignop(r.Type, l.Type)
|
||||||
if aop != 0 {
|
if aop != OXXX {
|
||||||
if l.Type.IsInterface() && !r.Type.IsInterface() && !IsComparable(r.Type) {
|
if l.Type.IsInterface() && !r.Type.IsInterface() && !IsComparable(r.Type) {
|
||||||
yyerror("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(r.Type))
|
yyerror("invalid operation: %v (operator %v not defined on %s)", n, op, typekind(r.Type))
|
||||||
n.Type = nil
|
n.Type = nil
|
||||||
|
|
@ -1046,13 +1046,13 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !n.Bounded() && Isconst(n.Right, CTINT) {
|
if !n.Bounded() && Isconst(n.Right, CTINT) {
|
||||||
x := n.Right.Int64()
|
x := n.Right.Int64Val()
|
||||||
if x < 0 {
|
if x < 0 {
|
||||||
yyerror("invalid %s index %v (index must be non-negative)", why, n.Right)
|
yyerror("invalid %s index %v (index must be non-negative)", why, n.Right)
|
||||||
} else if t.IsArray() && x >= t.NumElem() {
|
} else if t.IsArray() && x >= t.NumElem() {
|
||||||
yyerror("invalid array index %v (out of bounds for %d-element array)", n.Right, t.NumElem())
|
yyerror("invalid array index %v (out of bounds for %d-element array)", n.Right, t.NumElem())
|
||||||
} else if Isconst(n.Left, CTSTR) && x >= int64(len(strlit(n.Left))) {
|
} else if Isconst(n.Left, CTSTR) && x >= int64(len(n.Left.StringVal())) {
|
||||||
yyerror("invalid string index %v (out of bounds for %d-byte string)", n.Right, len(strlit(n.Left)))
|
yyerror("invalid string index %v (out of bounds for %d-byte string)", n.Right, len(n.Left.StringVal()))
|
||||||
} else if n.Right.Val().U.(*Mpint).Cmp(maxintval[TINT]) > 0 {
|
} else if n.Right.Val().U.(*Mpint).Cmp(maxintval[TINT]) > 0 {
|
||||||
yyerror("invalid %s index %v (index too large)", why, n.Right)
|
yyerror("invalid %s index %v (index too large)", why, n.Right)
|
||||||
}
|
}
|
||||||
|
|
@ -1148,11 +1148,11 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||||
l = defaultlit(l, types.Types[TINT])
|
l = defaultlit(l, types.Types[TINT])
|
||||||
c = defaultlit(c, types.Types[TINT])
|
c = defaultlit(c, types.Types[TINT])
|
||||||
|
|
||||||
if Isconst(l, CTINT) && l.Int64() < 0 {
|
if Isconst(l, CTINT) && l.Int64Val() < 0 {
|
||||||
Fatalf("len for OSLICEHEADER must be non-negative")
|
Fatalf("len for OSLICEHEADER must be non-negative")
|
||||||
}
|
}
|
||||||
|
|
||||||
if Isconst(c, CTINT) && c.Int64() < 0 {
|
if Isconst(c, CTINT) && c.Int64Val() < 0 {
|
||||||
Fatalf("cap for OSLICEHEADER must be non-negative")
|
Fatalf("cap for OSLICEHEADER must be non-negative")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1201,7 +1201,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||||
if n.Left.Val().U.(*Mpint).Cmp(maxintval[TINT]) > 0 {
|
if n.Left.Val().U.(*Mpint).Cmp(maxintval[TINT]) > 0 {
|
||||||
Fatalf("len for OMAKESLICECOPY too large")
|
Fatalf("len for OMAKESLICECOPY too large")
|
||||||
}
|
}
|
||||||
if n.Left.Int64() < 0 {
|
if n.Left.Int64Val() < 0 {
|
||||||
Fatalf("len for OMAKESLICECOPY must be non-negative")
|
Fatalf("len for OMAKESLICECOPY must be non-negative")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1691,7 +1691,7 @@ func typecheck1(n *Node, top int) (res *Node) {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
var why string
|
var why string
|
||||||
n.Op = convertop(n.Left.Op == OLITERAL, t, n.Type, &why)
|
n.Op, why = convertop(n.Left.Op == OLITERAL, t, n.Type)
|
||||||
if n.Op == OXXX {
|
if n.Op == OXXX {
|
||||||
if !n.Diag() && !n.Type.Broke() && !n.Left.Diag() {
|
if !n.Diag() && !n.Type.Broke() && !n.Left.Diag() {
|
||||||
yyerror("cannot convert %L to type %v%s", n.Left, n.Type, why)
|
yyerror("cannot convert %L to type %v%s", n.Left, n.Type, why)
|
||||||
|
|
@ -2187,14 +2187,14 @@ func checksliceindex(l *Node, r *Node, tp *types.Type) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.Op == OLITERAL {
|
if r.Op == OLITERAL {
|
||||||
if r.Int64() < 0 {
|
if r.Int64Val() < 0 {
|
||||||
yyerror("invalid slice index %v (index must be non-negative)", r)
|
yyerror("invalid slice index %v (index must be non-negative)", r)
|
||||||
return false
|
return false
|
||||||
} else if tp != nil && tp.NumElem() >= 0 && r.Int64() > tp.NumElem() {
|
} else if tp != nil && tp.NumElem() >= 0 && r.Int64Val() > tp.NumElem() {
|
||||||
yyerror("invalid slice index %v (out of bounds for %d-element array)", r, tp.NumElem())
|
yyerror("invalid slice index %v (out of bounds for %d-element array)", r, tp.NumElem())
|
||||||
return false
|
return false
|
||||||
} else if Isconst(l, CTSTR) && r.Int64() > int64(len(strlit(l))) {
|
} else if Isconst(l, CTSTR) && r.Int64Val() > int64(len(l.StringVal())) {
|
||||||
yyerror("invalid slice index %v (out of bounds for %d-byte string)", r, len(strlit(l)))
|
yyerror("invalid slice index %v (out of bounds for %d-byte string)", r, len(l.StringVal()))
|
||||||
return false
|
return false
|
||||||
} else if r.Val().U.(*Mpint).Cmp(maxintval[TINT]) > 0 {
|
} else if r.Val().U.(*Mpint).Cmp(maxintval[TINT]) > 0 {
|
||||||
yyerror("invalid slice index %v (index too large)", r)
|
yyerror("invalid slice index %v (index too large)", r)
|
||||||
|
|
@ -3267,9 +3267,7 @@ func typecheckas(n *Node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkassignto(src *types.Type, dst *Node) {
|
func checkassignto(src *types.Type, dst *Node) {
|
||||||
var why string
|
if op, why := assignop(src, dst.Type); op == OXXX {
|
||||||
|
|
||||||
if assignop(src, dst.Type, &why) == 0 {
|
|
||||||
yyerror("cannot assign %v to %L in multiple assignment%s", src, dst, why)
|
yyerror("cannot assign %v to %L in multiple assignment%s", src, dst, why)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -3450,9 +3448,8 @@ func stringtoruneslit(n *Node) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
var l []*Node
|
var l []*Node
|
||||||
s := strlit(n.Left)
|
|
||||||
i := 0
|
i := 0
|
||||||
for _, r := range s {
|
for _, r := range n.Left.StringVal() {
|
||||||
l = append(l, nod(OKEY, nodintconst(int64(i)), nodintconst(int64(r))))
|
l = append(l, nod(OKEY, nodintconst(int64(i)), nodintconst(int64(r))))
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
@ -3904,7 +3901,7 @@ func deadcodefn(fn *Node) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case OFOR:
|
case OFOR:
|
||||||
if !Isconst(n.Left, CTBOOL) || n.Left.Bool() {
|
if !Isconst(n.Left, CTBOOL) || n.Left.BoolVal() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
@ -3934,7 +3931,7 @@ func deadcodeslice(nn Nodes) {
|
||||||
n.Left = deadcodeexpr(n.Left)
|
n.Left = deadcodeexpr(n.Left)
|
||||||
if Isconst(n.Left, CTBOOL) {
|
if Isconst(n.Left, CTBOOL) {
|
||||||
var body Nodes
|
var body Nodes
|
||||||
if n.Left.Bool() {
|
if n.Left.BoolVal() {
|
||||||
n.Rlist = Nodes{}
|
n.Rlist = Nodes{}
|
||||||
body = n.Nbody
|
body = n.Nbody
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -3977,7 +3974,7 @@ func deadcodeexpr(n *Node) *Node {
|
||||||
n.Left = deadcodeexpr(n.Left)
|
n.Left = deadcodeexpr(n.Left)
|
||||||
n.Right = deadcodeexpr(n.Right)
|
n.Right = deadcodeexpr(n.Right)
|
||||||
if Isconst(n.Left, CTBOOL) {
|
if Isconst(n.Left, CTBOOL) {
|
||||||
if n.Left.Bool() {
|
if n.Left.BoolVal() {
|
||||||
return n.Right // true && x => x
|
return n.Right // true && x => x
|
||||||
} else {
|
} else {
|
||||||
return n.Left // false && x => false
|
return n.Left // false && x => false
|
||||||
|
|
@ -3987,7 +3984,7 @@ func deadcodeexpr(n *Node) *Node {
|
||||||
n.Left = deadcodeexpr(n.Left)
|
n.Left = deadcodeexpr(n.Left)
|
||||||
n.Right = deadcodeexpr(n.Right)
|
n.Right = deadcodeexpr(n.Right)
|
||||||
if Isconst(n.Left, CTBOOL) {
|
if Isconst(n.Left, CTBOOL) {
|
||||||
if n.Left.Bool() {
|
if n.Left.BoolVal() {
|
||||||
return n.Left // true || x => true
|
return n.Left // true || x => true
|
||||||
} else {
|
} else {
|
||||||
return n.Right // false || x => x
|
return n.Right // false || x => x
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ const zeroValSize = 1024 // must match value of runtime/map.go:maxZero
|
||||||
func walk(fn *Node) {
|
func walk(fn *Node) {
|
||||||
Curfn = fn
|
Curfn = fn
|
||||||
|
|
||||||
if Debug['W'] != 0 {
|
if Debug.W != 0 {
|
||||||
s := fmt.Sprintf("\nbefore walk %v", Curfn.Func.Nname.Sym)
|
s := fmt.Sprintf("\nbefore walk %v", Curfn.Func.Nname.Sym)
|
||||||
dumplist(s, Curfn.Nbody)
|
dumplist(s, Curfn.Nbody)
|
||||||
}
|
}
|
||||||
|
|
@ -63,14 +63,14 @@ func walk(fn *Node) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
walkstmtlist(Curfn.Nbody.Slice())
|
walkstmtlist(Curfn.Nbody.Slice())
|
||||||
if Debug['W'] != 0 {
|
if Debug.W != 0 {
|
||||||
s := fmt.Sprintf("after walk %v", Curfn.Func.Nname.Sym)
|
s := fmt.Sprintf("after walk %v", Curfn.Func.Nname.Sym)
|
||||||
dumplist(s, Curfn.Nbody)
|
dumplist(s, Curfn.Nbody)
|
||||||
}
|
}
|
||||||
|
|
||||||
zeroResults()
|
zeroResults()
|
||||||
heapmoves()
|
heapmoves()
|
||||||
if Debug['W'] != 0 && Curfn.Func.Enter.Len() > 0 {
|
if Debug.W != 0 && Curfn.Func.Enter.Len() > 0 {
|
||||||
s := fmt.Sprintf("enter %v", Curfn.Func.Nname.Sym)
|
s := fmt.Sprintf("enter %v", Curfn.Func.Nname.Sym)
|
||||||
dumplist(s, Curfn.Func.Enter)
|
dumplist(s, Curfn.Func.Enter)
|
||||||
}
|
}
|
||||||
|
|
@ -436,7 +436,7 @@ func walkexpr(n *Node, init *Nodes) *Node {
|
||||||
|
|
||||||
lno := setlineno(n)
|
lno := setlineno(n)
|
||||||
|
|
||||||
if Debug['w'] > 1 {
|
if Debug.w > 1 {
|
||||||
Dump("before walk expr", n)
|
Dump("before walk expr", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1001,7 +1001,7 @@ opswitch:
|
||||||
// The SSA backend will handle those.
|
// The SSA backend will handle those.
|
||||||
switch et {
|
switch et {
|
||||||
case TINT64:
|
case TINT64:
|
||||||
c := n.Right.Int64()
|
c := n.Right.Int64Val()
|
||||||
if c < 0 {
|
if c < 0 {
|
||||||
c = -c
|
c = -c
|
||||||
}
|
}
|
||||||
|
|
@ -1009,7 +1009,7 @@ opswitch:
|
||||||
break opswitch
|
break opswitch
|
||||||
}
|
}
|
||||||
case TUINT64:
|
case TUINT64:
|
||||||
c := uint64(n.Right.Int64())
|
c := uint64(n.Right.Int64Val())
|
||||||
if c != 0 && c&(c-1) == 0 {
|
if c != 0 && c&(c-1) == 0 {
|
||||||
break opswitch
|
break opswitch
|
||||||
}
|
}
|
||||||
|
|
@ -1049,15 +1049,15 @@ opswitch:
|
||||||
}
|
}
|
||||||
if t.IsArray() {
|
if t.IsArray() {
|
||||||
n.SetBounded(bounded(r, t.NumElem()))
|
n.SetBounded(bounded(r, t.NumElem()))
|
||||||
if Debug['m'] != 0 && n.Bounded() && !Isconst(n.Right, CTINT) {
|
if Debug.m != 0 && n.Bounded() && !Isconst(n.Right, CTINT) {
|
||||||
Warn("index bounds check elided")
|
Warn("index bounds check elided")
|
||||||
}
|
}
|
||||||
if smallintconst(n.Right) && !n.Bounded() {
|
if smallintconst(n.Right) && !n.Bounded() {
|
||||||
yyerror("index out of bounds")
|
yyerror("index out of bounds")
|
||||||
}
|
}
|
||||||
} else if Isconst(n.Left, CTSTR) {
|
} else if Isconst(n.Left, CTSTR) {
|
||||||
n.SetBounded(bounded(r, int64(len(strlit(n.Left)))))
|
n.SetBounded(bounded(r, int64(len(n.Left.StringVal()))))
|
||||||
if Debug['m'] != 0 && n.Bounded() && !Isconst(n.Right, CTINT) {
|
if Debug.m != 0 && n.Bounded() && !Isconst(n.Right, CTINT) {
|
||||||
Warn("index bounds check elided")
|
Warn("index bounds check elided")
|
||||||
}
|
}
|
||||||
if smallintconst(n.Right) && !n.Bounded() {
|
if smallintconst(n.Right) && !n.Bounded() {
|
||||||
|
|
@ -1491,7 +1491,7 @@ opswitch:
|
||||||
case OSTR2BYTES:
|
case OSTR2BYTES:
|
||||||
s := n.Left
|
s := n.Left
|
||||||
if Isconst(s, CTSTR) {
|
if Isconst(s, CTSTR) {
|
||||||
sc := strlit(s)
|
sc := s.StringVal()
|
||||||
|
|
||||||
// Allocate a [n]byte of the right size.
|
// Allocate a [n]byte of the right size.
|
||||||
t := types.NewArray(types.Types[TUINT8], int64(len(sc)))
|
t := types.NewArray(types.Types[TUINT8], int64(len(sc)))
|
||||||
|
|
@ -1599,7 +1599,7 @@ opswitch:
|
||||||
|
|
||||||
updateHasCall(n)
|
updateHasCall(n)
|
||||||
|
|
||||||
if Debug['w'] != 0 && n != nil {
|
if Debug.w != 0 && n != nil {
|
||||||
Dump("after walk expr", n)
|
Dump("after walk expr", n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1919,7 +1919,7 @@ func walkprint(nn *Node, init *Nodes) *Node {
|
||||||
for i := 0; i < len(s); {
|
for i := 0; i < len(s); {
|
||||||
var strs []string
|
var strs []string
|
||||||
for i < len(s) && Isconst(s[i], CTSTR) {
|
for i < len(s) && Isconst(s[i], CTSTR) {
|
||||||
strs = append(strs, strlit(s[i]))
|
strs = append(strs, s[i].StringVal())
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
if len(strs) > 0 {
|
if len(strs) > 0 {
|
||||||
|
|
@ -1988,7 +1988,7 @@ func walkprint(nn *Node, init *Nodes) *Node {
|
||||||
case TSTRING:
|
case TSTRING:
|
||||||
cs := ""
|
cs := ""
|
||||||
if Isconst(n, CTSTR) {
|
if Isconst(n, CTSTR) {
|
||||||
cs = strlit(n)
|
cs = n.StringVal()
|
||||||
}
|
}
|
||||||
switch cs {
|
switch cs {
|
||||||
case " ":
|
case " ":
|
||||||
|
|
@ -2157,7 +2157,7 @@ func reorder3(all []*Node) []*Node {
|
||||||
// The result of reorder3save MUST be assigned back to n, e.g.
|
// The result of reorder3save MUST be assigned back to n, e.g.
|
||||||
// n.Left = reorder3save(n.Left, all, i, early)
|
// n.Left = reorder3save(n.Left, all, i, early)
|
||||||
func reorder3save(n *Node, all []*Node, i int, early *[]*Node) *Node {
|
func reorder3save(n *Node, all []*Node, i int, early *[]*Node) *Node {
|
||||||
if !aliased(n, all, i) {
|
if !aliased(n, all[:i]) {
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2189,73 +2189,75 @@ func outervalue(n *Node) *Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it possible that the computation of n might be
|
// Is it possible that the computation of r might be
|
||||||
// affected by writes in as up to but not including the ith element?
|
// affected by assignments in all?
|
||||||
func aliased(n *Node, all []*Node, i int) bool {
|
func aliased(r *Node, all []*Node) bool {
|
||||||
if n == nil {
|
if r == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Treat all fields of a struct as referring to the whole struct.
|
// Treat all fields of a struct as referring to the whole struct.
|
||||||
// We could do better but we would have to keep track of the fields.
|
// We could do better but we would have to keep track of the fields.
|
||||||
for n.Op == ODOT {
|
for r.Op == ODOT {
|
||||||
n = n.Left
|
r = r.Left
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for obvious aliasing: a variable being assigned
|
// Look for obvious aliasing: a variable being assigned
|
||||||
// during the all list and appearing in n.
|
// during the all list and appearing in n.
|
||||||
// Also record whether there are any writes to main memory.
|
// Also record whether there are any writes to addressable
|
||||||
// Also record whether there are any writes to variables
|
// memory (either main memory or variables whose addresses
|
||||||
// whose addresses have been taken.
|
// have been taken).
|
||||||
memwrite := false
|
memwrite := false
|
||||||
varwrite := false
|
for _, as := range all {
|
||||||
for _, an := range all[:i] {
|
// We can ignore assignments to blank.
|
||||||
a := outervalue(an.Left)
|
if as.Left.isBlank() {
|
||||||
|
continue
|
||||||
for a.Op == ODOT {
|
|
||||||
a = a.Left
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if a.Op != ONAME {
|
l := outervalue(as.Left)
|
||||||
|
if l.Op != ONAME {
|
||||||
memwrite = true
|
memwrite = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
switch n.Class() {
|
switch l.Class() {
|
||||||
default:
|
default:
|
||||||
varwrite = true
|
Fatalf("unexpected class: %v, %v", l, l.Class())
|
||||||
|
|
||||||
|
case PAUTOHEAP, PEXTERN:
|
||||||
|
memwrite = true
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case PAUTO, PPARAM, PPARAMOUT:
|
case PAUTO, PPARAM, PPARAMOUT:
|
||||||
if n.Name.Addrtaken() {
|
if l.Name.Addrtaken() {
|
||||||
varwrite = true
|
memwrite = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if vmatch2(a, n) {
|
if vmatch2(l, r) {
|
||||||
// Direct hit.
|
// Direct hit: l appears in r.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The variables being written do not appear in n.
|
// The variables being written do not appear in r.
|
||||||
// However, n might refer to computed addresses
|
// However, r might refer to computed addresses
|
||||||
// that are being written.
|
// that are being written.
|
||||||
|
|
||||||
// If no computed addresses are affected by the writes, no aliasing.
|
// If no computed addresses are affected by the writes, no aliasing.
|
||||||
if !memwrite && !varwrite {
|
if !memwrite {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// If n does not refer to computed addresses
|
// If r does not refer to computed addresses
|
||||||
// (that is, if n only refers to variables whose addresses
|
// (that is, if r only refers to variables whose addresses
|
||||||
// have not been taken), no aliasing.
|
// have not been taken), no aliasing.
|
||||||
if varexpr(n) {
|
if varexpr(r) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, both the writes and n refer to computed memory addresses.
|
// Otherwise, both the writes and r refer to computed memory addresses.
|
||||||
// Assume that they might conflict.
|
// Assume that they might conflict.
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -2643,7 +2645,7 @@ func addstr(n *Node, init *Nodes) *Node {
|
||||||
sz := int64(0)
|
sz := int64(0)
|
||||||
for _, n1 := range n.List.Slice() {
|
for _, n1 := range n.List.Slice() {
|
||||||
if n1.Op == OLITERAL {
|
if n1.Op == OLITERAL {
|
||||||
sz += int64(len(strlit(n1)))
|
sz += int64(len(n1.StringVal()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2817,7 +2819,7 @@ func appendslice(n *Node, init *Nodes) *Node {
|
||||||
// isAppendOfMake reports whether n is of the form append(x , make([]T, y)...).
|
// isAppendOfMake reports whether n is of the form append(x , make([]T, y)...).
|
||||||
// isAppendOfMake assumes n has already been typechecked.
|
// isAppendOfMake assumes n has already been typechecked.
|
||||||
func isAppendOfMake(n *Node) bool {
|
func isAppendOfMake(n *Node) bool {
|
||||||
if Debug['N'] != 0 || instrumenting {
|
if Debug.N != 0 || instrumenting {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3437,7 +3439,7 @@ func walkcompare(n *Node, init *Nodes) *Node {
|
||||||
|
|
||||||
func tracecmpArg(n *Node, t *types.Type, init *Nodes) *Node {
|
func tracecmpArg(n *Node, t *types.Type, init *Nodes) *Node {
|
||||||
// Ugly hack to avoid "constant -1 overflows uintptr" errors, etc.
|
// Ugly hack to avoid "constant -1 overflows uintptr" errors, etc.
|
||||||
if n.Op == OLITERAL && n.Type.IsSigned() && n.Int64() < 0 {
|
if n.Op == OLITERAL && n.Type.IsSigned() && n.Int64Val() < 0 {
|
||||||
n = copyexpr(n, n.Type, init)
|
n = copyexpr(n, n.Type, init)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3507,7 +3509,7 @@ func walkcompareString(n *Node, init *Nodes) *Node {
|
||||||
// Length-only checks are ok, though.
|
// Length-only checks are ok, though.
|
||||||
maxRewriteLen = 0
|
maxRewriteLen = 0
|
||||||
}
|
}
|
||||||
if s := strlit(cs); len(s) <= maxRewriteLen {
|
if s := cs.StringVal(); len(s) <= maxRewriteLen {
|
||||||
if len(s) > 0 {
|
if len(s) > 0 {
|
||||||
ncs = safeexpr(ncs, init)
|
ncs = safeexpr(ncs, init)
|
||||||
}
|
}
|
||||||
|
|
@ -3602,7 +3604,7 @@ func bounded(n *Node, max int64) bool {
|
||||||
bits := int32(8 * n.Type.Width)
|
bits := int32(8 * n.Type.Width)
|
||||||
|
|
||||||
if smallintconst(n) {
|
if smallintconst(n) {
|
||||||
v := n.Int64()
|
v := n.Int64Val()
|
||||||
return 0 <= v && v < max
|
return 0 <= v && v < max
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3610,9 +3612,9 @@ func bounded(n *Node, max int64) bool {
|
||||||
case OAND:
|
case OAND:
|
||||||
v := int64(-1)
|
v := int64(-1)
|
||||||
if smallintconst(n.Left) {
|
if smallintconst(n.Left) {
|
||||||
v = n.Left.Int64()
|
v = n.Left.Int64Val()
|
||||||
} else if smallintconst(n.Right) {
|
} else if smallintconst(n.Right) {
|
||||||
v = n.Right.Int64()
|
v = n.Right.Int64Val()
|
||||||
}
|
}
|
||||||
|
|
||||||
if 0 <= v && v < max {
|
if 0 <= v && v < max {
|
||||||
|
|
@ -3621,7 +3623,7 @@ func bounded(n *Node, max int64) bool {
|
||||||
|
|
||||||
case OMOD:
|
case OMOD:
|
||||||
if !sign && smallintconst(n.Right) {
|
if !sign && smallintconst(n.Right) {
|
||||||
v := n.Right.Int64()
|
v := n.Right.Int64Val()
|
||||||
if 0 <= v && v <= max {
|
if 0 <= v && v <= max {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -3629,7 +3631,7 @@ func bounded(n *Node, max int64) bool {
|
||||||
|
|
||||||
case ODIV:
|
case ODIV:
|
||||||
if !sign && smallintconst(n.Right) {
|
if !sign && smallintconst(n.Right) {
|
||||||
v := n.Right.Int64()
|
v := n.Right.Int64Val()
|
||||||
for bits > 0 && v >= 2 {
|
for bits > 0 && v >= 2 {
|
||||||
bits--
|
bits--
|
||||||
v >>= 1
|
v >>= 1
|
||||||
|
|
@ -3638,7 +3640,7 @@ func bounded(n *Node, max int64) bool {
|
||||||
|
|
||||||
case ORSH:
|
case ORSH:
|
||||||
if !sign && smallintconst(n.Right) {
|
if !sign && smallintconst(n.Right) {
|
||||||
v := n.Right.Int64()
|
v := n.Right.Int64Val()
|
||||||
if v > int64(bits) {
|
if v > int64(bits) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -3879,6 +3881,16 @@ func wrapCall(n *Node, init *Nodes) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
isBuiltinCall := n.Op != OCALLFUNC && n.Op != OCALLMETH && n.Op != OCALLINTER
|
isBuiltinCall := n.Op != OCALLFUNC && n.Op != OCALLMETH && n.Op != OCALLINTER
|
||||||
|
|
||||||
|
// Turn f(a, b, []T{c, d, e}...) back into f(a, b, c, d, e).
|
||||||
|
if !isBuiltinCall && n.IsDDD() {
|
||||||
|
last := n.List.Len() - 1
|
||||||
|
if va := n.List.Index(last); va.Op == OSLICELIT {
|
||||||
|
n.List.Set(append(n.List.Slice()[:last], va.List.Slice()...))
|
||||||
|
n.SetIsDDD(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// origArgs keeps track of what argument is uintptr-unsafe/unsafe-uintptr conversion.
|
// origArgs keeps track of what argument is uintptr-unsafe/unsafe-uintptr conversion.
|
||||||
origArgs := make([]*Node, n.List.Len())
|
origArgs := make([]*Node, n.List.Len())
|
||||||
t := nod(OTFUNC, nil, nil)
|
t := nod(OTFUNC, nil, nil)
|
||||||
|
|
@ -3964,7 +3976,7 @@ func canMergeLoads() bool {
|
||||||
// isRuneCount reports whether n is of the form len([]rune(string)).
|
// isRuneCount reports whether n is of the form len([]rune(string)).
|
||||||
// These are optimized into a call to runtime.countrunes.
|
// These are optimized into a call to runtime.countrunes.
|
||||||
func isRuneCount(n *Node) bool {
|
func isRuneCount(n *Node) bool {
|
||||||
return Debug['N'] == 0 && !instrumenting && n.Op == OLEN && n.Left.Op == OSTR2RUNES
|
return Debug.N == 0 && !instrumenting && n.Op == OLEN && n.Left.Op == OSTR2RUNES
|
||||||
}
|
}
|
||||||
|
|
||||||
func walkCheckPtrAlignment(n *Node, init *Nodes, count *Node) *Node {
|
func walkCheckPtrAlignment(n *Node, init *Nodes, count *Node) *Node {
|
||||||
|
|
|
||||||
|
|
@ -208,12 +208,11 @@ func s15a8(x *[15]int64) [15]int64 {
|
||||||
`"relatedInformation":[{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"}]}`)
|
`"relatedInformation":[{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"}]}`)
|
||||||
want(t, slogged, `{"range":{"start":{"line":11,"character":6},"end":{"line":11,"character":6}},"severity":3,"code":"isInBounds","source":"go compiler","message":""}`)
|
want(t, slogged, `{"range":{"start":{"line":11,"character":6},"end":{"line":11,"character":6}},"severity":3,"code":"isInBounds","source":"go compiler","message":""}`)
|
||||||
want(t, slogged, `{"range":{"start":{"line":7,"character":6},"end":{"line":7,"character":6}},"severity":3,"code":"canInlineFunction","source":"go compiler","message":"cost: 35"}`)
|
want(t, slogged, `{"range":{"start":{"line":7,"character":6},"end":{"line":7,"character":6}},"severity":3,"code":"canInlineFunction","source":"go compiler","message":"cost: 35"}`)
|
||||||
want(t, slogged, `{"range":{"start":{"line":21,"character":21},"end":{"line":21,"character":21}},"severity":3,"code":"cannotInlineCall","source":"go compiler","message":"foo cannot be inlined (escaping closure variable)"}`)
|
|
||||||
// escape analysis explanation
|
// escape analysis explanation
|
||||||
want(t, slogged, `{"range":{"start":{"line":7,"character":13},"end":{"line":7,"character":13}},"severity":3,"code":"leak","source":"go compiler","message":"parameter z leaks to ~r2 with derefs=0",`+
|
want(t, slogged, `{"range":{"start":{"line":7,"character":13},"end":{"line":7,"character":13}},"severity":3,"code":"leak","source":"go compiler","message":"parameter z leaks to ~r2 with derefs=0",`+
|
||||||
`"relatedInformation":[`+
|
`"relatedInformation":[`+
|
||||||
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: y = z:"},`+
|
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: y = z:"},`+
|
||||||
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y = \u003cN\u003e (assign-pair)"},`+
|
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y := z (assign-pair)"},`+
|
||||||
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: ~r1 = y:"},`+
|
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: flow: ~r1 = y:"},`+
|
||||||
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"},`+
|
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"},`+
|
||||||
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y.b (dot of pointer)"},`+
|
`{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}}},"message":"escflow: from y.b (dot of pointer)"},`+
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ func branchelim(f *Func) {
|
||||||
for _, b := range f.Blocks {
|
for _, b := range f.Blocks {
|
||||||
for _, v := range b.Values {
|
for _, v := range b.Values {
|
||||||
switch v.Op {
|
switch v.Op {
|
||||||
case OpLoad, OpAtomicLoad8, OpAtomicLoad32, OpAtomicLoad64, OpAtomicLoadPtr, OpAtomicLoadAcq32:
|
case OpLoad, OpAtomicLoad8, OpAtomicLoad32, OpAtomicLoad64, OpAtomicLoadPtr, OpAtomicLoadAcq32, OpAtomicLoadAcq64:
|
||||||
loadAddr.add(v.Args[0].ID)
|
loadAddr.add(v.Args[0].ID)
|
||||||
case OpMove:
|
case OpMove:
|
||||||
loadAddr.add(v.Args[1].ID)
|
loadAddr.add(v.Args[1].ID)
|
||||||
|
|
|
||||||
|
|
@ -191,11 +191,6 @@ func flagalloc(f *Func) {
|
||||||
b.FlagsLiveAtEnd = end[b.ID] != nil
|
b.FlagsLiveAtEnd = end[b.ID] != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const go115flagallocdeadcode = true
|
|
||||||
if !go115flagallocdeadcode {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove any now-dead values.
|
// Remove any now-dead values.
|
||||||
// The number of values to remove is likely small,
|
// The number of values to remove is likely small,
|
||||||
// and removing them requires processing all values in a block,
|
// and removing them requires processing all values in a block,
|
||||||
|
|
|
||||||
|
|
@ -1052,8 +1052,8 @@
|
||||||
(BICshiftRL x (MOVWconst [c]) [d]) => (BICconst x [int32(uint32(c)>>uint64(d))])
|
(BICshiftRL x (MOVWconst [c]) [d]) => (BICconst x [int32(uint32(c)>>uint64(d))])
|
||||||
(BICshiftRA x (MOVWconst [c]) [d]) => (BICconst x [c>>uint64(d)])
|
(BICshiftRA x (MOVWconst [c]) [d]) => (BICconst x [c>>uint64(d)])
|
||||||
(MVNshiftLL (MOVWconst [c]) [d]) => (MOVWconst [^(c<<uint64(d))])
|
(MVNshiftLL (MOVWconst [c]) [d]) => (MOVWconst [^(c<<uint64(d))])
|
||||||
(MVNshiftRL (MOVWconst [c]) [d]) -> (MOVWconst [^int64(uint32(c)>>uint64(d))])
|
(MVNshiftRL (MOVWconst [c]) [d]) => (MOVWconst [^int32(uint32(c)>>uint64(d))])
|
||||||
(MVNshiftRA (MOVWconst [c]) [d]) -> (MOVWconst [^int64(int32(c)>>uint64(d))])
|
(MVNshiftRA (MOVWconst [c]) [d]) => (MOVWconst [int32(c)>>uint64(d)])
|
||||||
(CMPshiftLL x (MOVWconst [c]) [d]) => (CMPconst x [c<<uint64(d)])
|
(CMPshiftLL x (MOVWconst [c]) [d]) => (CMPconst x [c<<uint64(d)])
|
||||||
(CMPshiftRL x (MOVWconst [c]) [d]) => (CMPconst x [int32(uint32(c)>>uint64(d))])
|
(CMPshiftRL x (MOVWconst [c]) [d]) => (CMPconst x [int32(uint32(c)>>uint64(d))])
|
||||||
(CMPshiftRA x (MOVWconst [c]) [d]) => (CMPconst x [c>>uint64(d)])
|
(CMPshiftRA x (MOVWconst [c]) [d]) => (CMPconst x [c>>uint64(d)])
|
||||||
|
|
@ -1190,12 +1190,12 @@
|
||||||
(MOVWstoreidx ptr (SRAconst idx [c]) val mem) => (MOVWstoreshiftRA ptr idx [c] val mem)
|
(MOVWstoreidx ptr (SRAconst idx [c]) val mem) => (MOVWstoreshiftRA ptr idx [c] val mem)
|
||||||
(MOVWstoreidx (SRAconst idx [c]) ptr val mem) => (MOVWstoreshiftRA ptr idx [c] val mem)
|
(MOVWstoreidx (SRAconst idx [c]) ptr val mem) => (MOVWstoreshiftRA ptr idx [c] val mem)
|
||||||
|
|
||||||
(MOVWloadshiftLL ptr (MOVWconst [c]) [d] mem) -> (MOVWload [int64(uint32(c)<<uint64(d))] ptr mem)
|
(MOVWloadshiftLL ptr (MOVWconst [c]) [d] mem) => (MOVWload [int32(uint32(c)<<uint64(d))] ptr mem)
|
||||||
(MOVWloadshiftRL ptr (MOVWconst [c]) [d] mem) -> (MOVWload [int64(uint32(c)>>uint64(d))] ptr mem)
|
(MOVWloadshiftRL ptr (MOVWconst [c]) [d] mem) => (MOVWload [int32(uint32(c)>>uint64(d))] ptr mem)
|
||||||
(MOVWloadshiftRA ptr (MOVWconst [c]) [d] mem) => (MOVWload [c>>uint64(d)] ptr mem)
|
(MOVWloadshiftRA ptr (MOVWconst [c]) [d] mem) => (MOVWload [c>>uint64(d)] ptr mem)
|
||||||
|
|
||||||
(MOVWstoreshiftLL ptr (MOVWconst [c]) [d] val mem) -> (MOVWstore [int64(uint32(c)<<uint64(d))] ptr val mem)
|
(MOVWstoreshiftLL ptr (MOVWconst [c]) [d] val mem) => (MOVWstore [int32(uint32(c)<<uint64(d))] ptr val mem)
|
||||||
(MOVWstoreshiftRL ptr (MOVWconst [c]) [d] val mem) -> (MOVWstore [int64(uint32(c)>>uint64(d))] ptr val mem)
|
(MOVWstoreshiftRL ptr (MOVWconst [c]) [d] val mem) => (MOVWstore [int32(uint32(c)>>uint64(d))] ptr val mem)
|
||||||
(MOVWstoreshiftRA ptr (MOVWconst [c]) [d] val mem) => (MOVWstore [c>>uint64(d)] ptr val mem)
|
(MOVWstoreshiftRA ptr (MOVWconst [c]) [d] val mem) => (MOVWstore [c>>uint64(d)] ptr val mem)
|
||||||
|
|
||||||
// generic simplifications
|
// generic simplifications
|
||||||
|
|
|
||||||
|
|
@ -967,10 +967,10 @@
|
||||||
|
|
||||||
// atomic intrinsics
|
// atomic intrinsics
|
||||||
(AtomicLoad(8|32|64|Ptr) ptr mem) => (LoweredAtomicLoad(8|32|64|Ptr) [1] ptr mem)
|
(AtomicLoad(8|32|64|Ptr) ptr mem) => (LoweredAtomicLoad(8|32|64|Ptr) [1] ptr mem)
|
||||||
(AtomicLoadAcq32 ptr mem) => (LoweredAtomicLoad32 [0] ptr mem)
|
(AtomicLoadAcq(32|64) ptr mem) => (LoweredAtomicLoad(32|64) [0] ptr mem)
|
||||||
|
|
||||||
(AtomicStore(8|32|64) ptr val mem) => (LoweredAtomicStore(8|32|64) [1] ptr val mem)
|
(AtomicStore(8|32|64) ptr val mem) => (LoweredAtomicStore(8|32|64) [1] ptr val mem)
|
||||||
(AtomicStoreRel32 ptr val mem) => (LoweredAtomicStore32 [0] ptr val mem)
|
(AtomicStoreRel(32|64) ptr val mem) => (LoweredAtomicStore(32|64) [0] ptr val mem)
|
||||||
//(AtomicStorePtrNoWB ptr val mem) => (STLR ptr val mem)
|
//(AtomicStorePtrNoWB ptr val mem) => (STLR ptr val mem)
|
||||||
|
|
||||||
(AtomicExchange(32|64) ...) => (LoweredAtomicExchange(32|64) ...)
|
(AtomicExchange(32|64) ...) => (LoweredAtomicExchange(32|64) ...)
|
||||||
|
|
|
||||||
|
|
@ -24,10 +24,11 @@ import (
|
||||||
// L = 64 bit int, used when the opcode starts with F
|
// L = 64 bit int, used when the opcode starts with F
|
||||||
|
|
||||||
const (
|
const (
|
||||||
riscv64REG_G = 4
|
riscv64REG_G = 27
|
||||||
riscv64REG_CTXT = 20
|
riscv64REG_CTXT = 20
|
||||||
riscv64REG_LR = 1
|
riscv64REG_LR = 1
|
||||||
riscv64REG_SP = 2
|
riscv64REG_SP = 2
|
||||||
|
riscv64REG_TP = 4
|
||||||
riscv64REG_TMP = 31
|
riscv64REG_TMP = 31
|
||||||
riscv64REG_ZERO = 0
|
riscv64REG_ZERO = 0
|
||||||
)
|
)
|
||||||
|
|
@ -78,8 +79,8 @@ func init() {
|
||||||
|
|
||||||
// Add general purpose registers to gpMask.
|
// Add general purpose registers to gpMask.
|
||||||
switch r {
|
switch r {
|
||||||
// ZERO, and TMP are not in any gp mask.
|
// ZERO, TP and TMP are not in any gp mask.
|
||||||
case riscv64REG_ZERO, riscv64REG_TMP:
|
case riscv64REG_ZERO, riscv64REG_TP, riscv64REG_TMP:
|
||||||
case riscv64REG_G:
|
case riscv64REG_G:
|
||||||
gpgMask |= mask
|
gpgMask |= mask
|
||||||
gpspsbgMask |= mask
|
gpspsbgMask |= mask
|
||||||
|
|
|
||||||
|
|
@ -1961,6 +1961,31 @@
|
||||||
&& warnRule(fe.Debug_checknil(), v, "removed nil check")
|
&& warnRule(fe.Debug_checknil(), v, "removed nil check")
|
||||||
=> (Invalid)
|
=> (Invalid)
|
||||||
|
|
||||||
|
// for late-expanded calls
|
||||||
|
(Zero (SelectN [0] call:(StaticLECall _ _)) mem:(SelectN [1] call))
|
||||||
|
&& isSameCall(call.Aux, "runtime.newobject")
|
||||||
|
=> mem
|
||||||
|
|
||||||
|
(Store (SelectN [0] call:(StaticLECall _ _)) x mem:(SelectN [1] call))
|
||||||
|
&& isConstZero(x)
|
||||||
|
&& isSameCall(call.Aux, "runtime.newobject")
|
||||||
|
=> mem
|
||||||
|
|
||||||
|
(Store (OffPtr (SelectN [0] call:(StaticLECall _ _))) x mem:(SelectN [1] call))
|
||||||
|
&& isConstZero(x)
|
||||||
|
&& isSameCall(call.Aux, "runtime.newobject")
|
||||||
|
=> mem
|
||||||
|
|
||||||
|
(NilCheck (SelectN [0] call:(StaticLECall _ _)) (SelectN [1] call))
|
||||||
|
&& isSameCall(call.Aux, "runtime.newobject")
|
||||||
|
&& warnRule(fe.Debug_checknil(), v, "removed nil check")
|
||||||
|
=> (Invalid)
|
||||||
|
|
||||||
|
(NilCheck (OffPtr (SelectN [0] call:(StaticLECall _ _))) (SelectN [1] call))
|
||||||
|
&& isSameCall(call.Aux, "runtime.newobject")
|
||||||
|
&& warnRule(fe.Debug_checknil(), v, "removed nil check")
|
||||||
|
=> (Invalid)
|
||||||
|
|
||||||
// Evaluate constant address comparisons.
|
// Evaluate constant address comparisons.
|
||||||
(EqPtr x x) => (ConstBool [true])
|
(EqPtr x x) => (ConstBool [true])
|
||||||
(NeqPtr x x) => (ConstBool [false])
|
(NeqPtr x x) => (ConstBool [false])
|
||||||
|
|
@ -2017,6 +2042,17 @@
|
||||||
&& clobber(s1, s2, s3)
|
&& clobber(s1, s2, s3)
|
||||||
=> (Move {t.Elem()} [int64(sz)] dst src mem)
|
=> (Move {t.Elem()} [int64(sz)] dst src mem)
|
||||||
|
|
||||||
|
// Inline small or disjoint runtime.memmove calls with constant length.
|
||||||
|
// See the comment in op Move in genericOps.go for discussion of the type.
|
||||||
|
(SelectN [0] call:(StaticLECall {sym} dst src (Const(64|32) [sz]) mem))
|
||||||
|
&& sz >= 0
|
||||||
|
&& call.Uses == 1 // this will exclude all calls with results
|
||||||
|
&& isSameCall(sym, "runtime.memmove")
|
||||||
|
&& dst.Type.IsPtr() // avoids TUINTPTR, see issue 30061
|
||||||
|
&& isInlinableMemmove(dst, src, int64(sz), config)
|
||||||
|
&& clobber(call)
|
||||||
|
=> (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
|
||||||
|
|
||||||
// De-virtualize interface calls into static calls.
|
// De-virtualize interface calls into static calls.
|
||||||
// Note that (ITab (IMake)) doesn't get
|
// Note that (ITab (IMake)) doesn't get
|
||||||
// rewritten until after the first opt pass,
|
// rewritten until after the first opt pass,
|
||||||
|
|
@ -2411,6 +2447,7 @@
|
||||||
(Store {t5} (OffPtr <tt5> [o5] dst) d4
|
(Store {t5} (OffPtr <tt5> [o5] dst) d4
|
||||||
(Zero {t1} [n] dst mem)))))
|
(Zero {t1} [n] dst mem)))))
|
||||||
|
|
||||||
|
// TODO this does not fire before call expansion; is that acceptable?
|
||||||
(StaticCall {sym} x) && needRaceCleanup(sym, v) => x
|
(StaticCall {sym} x) && needRaceCleanup(sym, v) => x
|
||||||
|
|
||||||
// Collapse moving A -> B -> C into just A -> C.
|
// Collapse moving A -> B -> C into just A -> C.
|
||||||
|
|
|
||||||
|
|
@ -550,11 +550,13 @@ var genericOps = []opData{
|
||||||
{name: "AtomicLoad64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
|
{name: "AtomicLoad64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
|
||||||
{name: "AtomicLoadPtr", argLength: 2, typ: "(BytePtr,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
|
{name: "AtomicLoadPtr", argLength: 2, typ: "(BytePtr,Mem)"}, // Load from arg0. arg1=memory. Returns loaded value and new memory.
|
||||||
{name: "AtomicLoadAcq32", argLength: 2, typ: "(UInt32,Mem)"}, // Load from arg0. arg1=memory. Lock acquisition, returns loaded value and new memory.
|
{name: "AtomicLoadAcq32", argLength: 2, typ: "(UInt32,Mem)"}, // Load from arg0. arg1=memory. Lock acquisition, returns loaded value and new memory.
|
||||||
|
{name: "AtomicLoadAcq64", argLength: 2, typ: "(UInt64,Mem)"}, // Load from arg0. arg1=memory. Lock acquisition, returns loaded value and new memory.
|
||||||
{name: "AtomicStore8", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
|
{name: "AtomicStore8", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
|
||||||
{name: "AtomicStore32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
|
{name: "AtomicStore32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
|
||||||
{name: "AtomicStore64", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
|
{name: "AtomicStore64", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
|
||||||
{name: "AtomicStorePtrNoWB", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
|
{name: "AtomicStorePtrNoWB", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns memory.
|
||||||
{name: "AtomicStoreRel32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Lock release, returns memory.
|
{name: "AtomicStoreRel32", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Lock release, returns memory.
|
||||||
|
{name: "AtomicStoreRel64", argLength: 3, typ: "Mem", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Lock release, returns memory.
|
||||||
{name: "AtomicExchange32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
|
{name: "AtomicExchange32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
|
||||||
{name: "AtomicExchange64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
|
{name: "AtomicExchange64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true}, // Store arg1 to *arg0. arg2=memory. Returns old contents of *arg0 and new memory.
|
||||||
{name: "AtomicAdd32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
|
{name: "AtomicAdd32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true}, // Do *arg0 += arg1. arg2=memory. Returns sum and new memory.
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1012,8 +1012,8 @@ func (s *regAllocState) regalloc(f *Func) {
|
||||||
// Copy phi ops into new schedule.
|
// Copy phi ops into new schedule.
|
||||||
b.Values = append(b.Values, phis...)
|
b.Values = append(b.Values, phis...)
|
||||||
|
|
||||||
// Third pass - pick registers for phis whose inputs
|
// Third pass - pick registers for phis whose input
|
||||||
// were not in a register.
|
// was not in a register in the primary predecessor.
|
||||||
for i, v := range phis {
|
for i, v := range phis {
|
||||||
if !s.values[v.ID].needReg {
|
if !s.values[v.ID].needReg {
|
||||||
continue
|
continue
|
||||||
|
|
@ -1022,6 +1022,24 @@ func (s *regAllocState) regalloc(f *Func) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
m := s.compatRegs(v.Type) &^ phiUsed &^ s.used
|
m := s.compatRegs(v.Type) &^ phiUsed &^ s.used
|
||||||
|
// If one of the other inputs of v is in a register, and the register is available,
|
||||||
|
// select this register, which can save some unnecessary copies.
|
||||||
|
for i, pe := range b.Preds {
|
||||||
|
if int32(i) == idx {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ri := noRegister
|
||||||
|
for _, er := range s.endRegs[pe.b.ID] {
|
||||||
|
if er.v == s.orig[v.Args[i].ID] {
|
||||||
|
ri = er.r
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ri != noRegister && m>>ri&1 != 0 {
|
||||||
|
m = regMask(1) << ri
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
if m != 0 {
|
if m != 0 {
|
||||||
r := pickReg(m)
|
r := pickReg(m)
|
||||||
phiRegs[i] = r
|
phiRegs[i] = r
|
||||||
|
|
@ -1118,9 +1136,21 @@ func (s *regAllocState) regalloc(f *Func) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
rp, ok := s.f.getHome(v.ID).(*Register)
|
rp, ok := s.f.getHome(v.ID).(*Register)
|
||||||
|
if !ok {
|
||||||
|
// If v is not assigned a register, pick a register assigned to one of v's inputs.
|
||||||
|
// Hopefully v will get assigned that register later.
|
||||||
|
// If the inputs have allocated register information, add it to desired,
|
||||||
|
// which may reduce spill or copy operations when the register is available.
|
||||||
|
for _, a := range v.Args {
|
||||||
|
rp, ok = s.f.getHome(a.ID).(*Register)
|
||||||
|
if ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
}
|
||||||
desired.add(v.Args[pidx].ID, register(rp.num))
|
desired.add(v.Args[pidx].ID, register(rp.num))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1552,6 +1582,19 @@ func (s *regAllocState) regalloc(f *Func) {
|
||||||
}
|
}
|
||||||
v := s.orig[vid]
|
v := s.orig[vid]
|
||||||
m := s.compatRegs(v.Type) &^ s.used
|
m := s.compatRegs(v.Type) &^ s.used
|
||||||
|
// Used desired register if available.
|
||||||
|
outerloop:
|
||||||
|
for _, e := range desired.entries {
|
||||||
|
if e.ID != v.ID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, r := range e.regs {
|
||||||
|
if r != noRegister && m>>r&1 != 0 {
|
||||||
|
m = regMask(1) << r
|
||||||
|
break outerloop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if m&^desired.avoid != 0 {
|
if m&^desired.avoid != 0 {
|
||||||
m &^= desired.avoid
|
m &^= desired.avoid
|
||||||
}
|
}
|
||||||
|
|
@ -1613,7 +1656,9 @@ func (s *regAllocState) regalloc(f *Func) {
|
||||||
// we'll rematerialize during the merge.
|
// we'll rematerialize during the merge.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
//fmt.Printf("live-at-end spill for %s at %s\n", s.orig[e.ID], b)
|
if s.f.pass.debug > regDebug {
|
||||||
|
fmt.Printf("live-at-end spill for %s at %s\n", s.orig[e.ID], b)
|
||||||
|
}
|
||||||
spill := s.makeSpill(s.orig[e.ID], b)
|
spill := s.makeSpill(s.orig[e.ID], b)
|
||||||
s.spillLive[b.ID] = append(s.spillLive[b.ID], spill.ID)
|
s.spillLive[b.ID] = append(s.spillLive[b.ID], spill.ID)
|
||||||
}
|
}
|
||||||
|
|
@ -2484,7 +2529,7 @@ func (s *regAllocState) computeLive() {
|
||||||
for _, b := range f.Blocks {
|
for _, b := range f.Blocks {
|
||||||
fmt.Printf(" %s:", b)
|
fmt.Printf(" %s:", b)
|
||||||
for _, x := range s.live[b.ID] {
|
for _, x := range s.live[b.ID] {
|
||||||
fmt.Printf(" v%d", x.ID)
|
fmt.Printf(" v%d(%d)", x.ID, x.dist)
|
||||||
for _, e := range s.desired[b.ID].entries {
|
for _, e := range s.desired[b.ID].entries {
|
||||||
if e.ID != x.ID {
|
if e.ID != x.ID {
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -395,7 +395,8 @@ func canMergeLoad(target, load *Value) bool {
|
||||||
|
|
||||||
// isSameCall reports whether sym is the same as the given named symbol
|
// isSameCall reports whether sym is the same as the given named symbol
|
||||||
func isSameCall(sym interface{}, name string) bool {
|
func isSameCall(sym interface{}, name string) bool {
|
||||||
return sym.(*AuxCall).Fn.String() == name
|
fn := sym.(*AuxCall).Fn
|
||||||
|
return fn != nil && fn.String() == name
|
||||||
}
|
}
|
||||||
|
|
||||||
// nlz returns the number of leading zeros.
|
// nlz returns the number of leading zeros.
|
||||||
|
|
|
||||||
|
|
@ -6412,17 +6412,17 @@ func rewriteValueARM_OpARMMOVWloadshiftLL(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVWloadshiftLL ptr (MOVWconst [c]) [d] mem)
|
// match: (MOVWloadshiftLL ptr (MOVWconst [c]) [d] mem)
|
||||||
// result: (MOVWload [int64(uint32(c)<<uint64(d))] ptr mem)
|
// result: (MOVWload [int32(uint32(c)<<uint64(d))] ptr mem)
|
||||||
for {
|
for {
|
||||||
d := v.AuxInt
|
d := auxIntToInt32(v.AuxInt)
|
||||||
ptr := v_0
|
ptr := v_0
|
||||||
if v_1.Op != OpARMMOVWconst {
|
if v_1.Op != OpARMMOVWconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := v_1.AuxInt
|
c := auxIntToInt32(v_1.AuxInt)
|
||||||
mem := v_2
|
mem := v_2
|
||||||
v.reset(OpARMMOVWload)
|
v.reset(OpARMMOVWload)
|
||||||
v.AuxInt = int64(uint32(c) << uint64(d))
|
v.AuxInt = int32ToAuxInt(int32(uint32(c) << uint64(d)))
|
||||||
v.AddArg2(ptr, mem)
|
v.AddArg2(ptr, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -6492,17 +6492,17 @@ func rewriteValueARM_OpARMMOVWloadshiftRL(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
// match: (MOVWloadshiftRL ptr (MOVWconst [c]) [d] mem)
|
// match: (MOVWloadshiftRL ptr (MOVWconst [c]) [d] mem)
|
||||||
// result: (MOVWload [int64(uint32(c)>>uint64(d))] ptr mem)
|
// result: (MOVWload [int32(uint32(c)>>uint64(d))] ptr mem)
|
||||||
for {
|
for {
|
||||||
d := v.AuxInt
|
d := auxIntToInt32(v.AuxInt)
|
||||||
ptr := v_0
|
ptr := v_0
|
||||||
if v_1.Op != OpARMMOVWconst {
|
if v_1.Op != OpARMMOVWconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := v_1.AuxInt
|
c := auxIntToInt32(v_1.AuxInt)
|
||||||
mem := v_2
|
mem := v_2
|
||||||
v.reset(OpARMMOVWload)
|
v.reset(OpARMMOVWload)
|
||||||
v.AuxInt = int64(uint32(c) >> uint64(d))
|
v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
|
||||||
v.AddArg2(ptr, mem)
|
v.AddArg2(ptr, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -6833,18 +6833,18 @@ func rewriteValueARM_OpARMMOVWstoreshiftLL(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (MOVWstoreshiftLL ptr (MOVWconst [c]) [d] val mem)
|
// match: (MOVWstoreshiftLL ptr (MOVWconst [c]) [d] val mem)
|
||||||
// result: (MOVWstore [int64(uint32(c)<<uint64(d))] ptr val mem)
|
// result: (MOVWstore [int32(uint32(c)<<uint64(d))] ptr val mem)
|
||||||
for {
|
for {
|
||||||
d := v.AuxInt
|
d := auxIntToInt32(v.AuxInt)
|
||||||
ptr := v_0
|
ptr := v_0
|
||||||
if v_1.Op != OpARMMOVWconst {
|
if v_1.Op != OpARMMOVWconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := v_1.AuxInt
|
c := auxIntToInt32(v_1.AuxInt)
|
||||||
val := v_2
|
val := v_2
|
||||||
mem := v_3
|
mem := v_3
|
||||||
v.reset(OpARMMOVWstore)
|
v.reset(OpARMMOVWstore)
|
||||||
v.AuxInt = int64(uint32(c) << uint64(d))
|
v.AuxInt = int32ToAuxInt(int32(uint32(c) << uint64(d)))
|
||||||
v.AddArg3(ptr, val, mem)
|
v.AddArg3(ptr, val, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -6879,18 +6879,18 @@ func rewriteValueARM_OpARMMOVWstoreshiftRL(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (MOVWstoreshiftRL ptr (MOVWconst [c]) [d] val mem)
|
// match: (MOVWstoreshiftRL ptr (MOVWconst [c]) [d] val mem)
|
||||||
// result: (MOVWstore [int64(uint32(c)>>uint64(d))] ptr val mem)
|
// result: (MOVWstore [int32(uint32(c)>>uint64(d))] ptr val mem)
|
||||||
for {
|
for {
|
||||||
d := v.AuxInt
|
d := auxIntToInt32(v.AuxInt)
|
||||||
ptr := v_0
|
ptr := v_0
|
||||||
if v_1.Op != OpARMMOVWconst {
|
if v_1.Op != OpARMMOVWconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := v_1.AuxInt
|
c := auxIntToInt32(v_1.AuxInt)
|
||||||
val := v_2
|
val := v_2
|
||||||
mem := v_3
|
mem := v_3
|
||||||
v.reset(OpARMMOVWstore)
|
v.reset(OpARMMOVWstore)
|
||||||
v.AuxInt = int64(uint32(c) >> uint64(d))
|
v.AuxInt = int32ToAuxInt(int32(uint32(c) >> uint64(d)))
|
||||||
v.AddArg3(ptr, val, mem)
|
v.AddArg3(ptr, val, mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -8105,15 +8105,15 @@ func rewriteValueARM_OpARMMVNshiftLLreg(v *Value) bool {
|
||||||
func rewriteValueARM_OpARMMVNshiftRA(v *Value) bool {
|
func rewriteValueARM_OpARMMVNshiftRA(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (MVNshiftRA (MOVWconst [c]) [d])
|
// match: (MVNshiftRA (MOVWconst [c]) [d])
|
||||||
// result: (MOVWconst [^int64(int32(c)>>uint64(d))])
|
// result: (MOVWconst [int32(c)>>uint64(d)])
|
||||||
for {
|
for {
|
||||||
d := v.AuxInt
|
d := auxIntToInt32(v.AuxInt)
|
||||||
if v_0.Op != OpARMMOVWconst {
|
if v_0.Op != OpARMMOVWconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := v_0.AuxInt
|
c := auxIntToInt32(v_0.AuxInt)
|
||||||
v.reset(OpARMMOVWconst)
|
v.reset(OpARMMOVWconst)
|
||||||
v.AuxInt = ^int64(int32(c) >> uint64(d))
|
v.AuxInt = int32ToAuxInt(int32(c) >> uint64(d))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
@ -8139,15 +8139,15 @@ func rewriteValueARM_OpARMMVNshiftRAreg(v *Value) bool {
|
||||||
func rewriteValueARM_OpARMMVNshiftRL(v *Value) bool {
|
func rewriteValueARM_OpARMMVNshiftRL(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (MVNshiftRL (MOVWconst [c]) [d])
|
// match: (MVNshiftRL (MOVWconst [c]) [d])
|
||||||
// result: (MOVWconst [^int64(uint32(c)>>uint64(d))])
|
// result: (MOVWconst [^int32(uint32(c)>>uint64(d))])
|
||||||
for {
|
for {
|
||||||
d := v.AuxInt
|
d := auxIntToInt32(v.AuxInt)
|
||||||
if v_0.Op != OpARMMOVWconst {
|
if v_0.Op != OpARMMOVWconst {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
c := v_0.AuxInt
|
c := auxIntToInt32(v_0.AuxInt)
|
||||||
v.reset(OpARMMOVWconst)
|
v.reset(OpARMMOVWconst)
|
||||||
v.AuxInt = ^int64(uint32(c) >> uint64(d))
|
v.AuxInt = int32ToAuxInt(^int32(uint32(c) >> uint64(d)))
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,8 @@ func rewriteValuePPC64(v *Value) bool {
|
||||||
return rewriteValuePPC64_OpAtomicLoad8(v)
|
return rewriteValuePPC64_OpAtomicLoad8(v)
|
||||||
case OpAtomicLoadAcq32:
|
case OpAtomicLoadAcq32:
|
||||||
return rewriteValuePPC64_OpAtomicLoadAcq32(v)
|
return rewriteValuePPC64_OpAtomicLoadAcq32(v)
|
||||||
|
case OpAtomicLoadAcq64:
|
||||||
|
return rewriteValuePPC64_OpAtomicLoadAcq64(v)
|
||||||
case OpAtomicLoadPtr:
|
case OpAtomicLoadPtr:
|
||||||
return rewriteValuePPC64_OpAtomicLoadPtr(v)
|
return rewriteValuePPC64_OpAtomicLoadPtr(v)
|
||||||
case OpAtomicOr8:
|
case OpAtomicOr8:
|
||||||
|
|
@ -95,6 +97,8 @@ func rewriteValuePPC64(v *Value) bool {
|
||||||
return rewriteValuePPC64_OpAtomicStore8(v)
|
return rewriteValuePPC64_OpAtomicStore8(v)
|
||||||
case OpAtomicStoreRel32:
|
case OpAtomicStoreRel32:
|
||||||
return rewriteValuePPC64_OpAtomicStoreRel32(v)
|
return rewriteValuePPC64_OpAtomicStoreRel32(v)
|
||||||
|
case OpAtomicStoreRel64:
|
||||||
|
return rewriteValuePPC64_OpAtomicStoreRel64(v)
|
||||||
case OpAvg64u:
|
case OpAvg64u:
|
||||||
return rewriteValuePPC64_OpAvg64u(v)
|
return rewriteValuePPC64_OpAvg64u(v)
|
||||||
case OpBitLen32:
|
case OpBitLen32:
|
||||||
|
|
@ -930,6 +934,20 @@ func rewriteValuePPC64_OpAtomicLoadAcq32(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func rewriteValuePPC64_OpAtomicLoadAcq64(v *Value) bool {
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
// match: (AtomicLoadAcq64 ptr mem)
|
||||||
|
// result: (LoweredAtomicLoad64 [0] ptr mem)
|
||||||
|
for {
|
||||||
|
ptr := v_0
|
||||||
|
mem := v_1
|
||||||
|
v.reset(OpPPC64LoweredAtomicLoad64)
|
||||||
|
v.AuxInt = int64ToAuxInt(0)
|
||||||
|
v.AddArg2(ptr, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
func rewriteValuePPC64_OpAtomicLoadPtr(v *Value) bool {
|
func rewriteValuePPC64_OpAtomicLoadPtr(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
|
|
@ -1008,6 +1026,22 @@ func rewriteValuePPC64_OpAtomicStoreRel32(v *Value) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func rewriteValuePPC64_OpAtomicStoreRel64(v *Value) bool {
|
||||||
|
v_2 := v.Args[2]
|
||||||
|
v_1 := v.Args[1]
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
// match: (AtomicStoreRel64 ptr val mem)
|
||||||
|
// result: (LoweredAtomicStore64 [0] ptr val mem)
|
||||||
|
for {
|
||||||
|
ptr := v_0
|
||||||
|
val := v_1
|
||||||
|
mem := v_2
|
||||||
|
v.reset(OpPPC64LoweredAtomicStore64)
|
||||||
|
v.AuxInt = int64ToAuxInt(0)
|
||||||
|
v.AddArg3(ptr, val, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
func rewriteValuePPC64_OpAvg64u(v *Value) bool {
|
func rewriteValuePPC64_OpAvg64u(v *Value) bool {
|
||||||
v_1 := v.Args[1]
|
v_1 := v.Args[1]
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
|
|
|
||||||
|
|
@ -368,6 +368,8 @@ func rewriteValuegeneric(v *Value) bool {
|
||||||
return rewriteValuegeneric_OpSelect0(v)
|
return rewriteValuegeneric_OpSelect0(v)
|
||||||
case OpSelect1:
|
case OpSelect1:
|
||||||
return rewriteValuegeneric_OpSelect1(v)
|
return rewriteValuegeneric_OpSelect1(v)
|
||||||
|
case OpSelectN:
|
||||||
|
return rewriteValuegeneric_OpSelectN(v)
|
||||||
case OpSignExt16to32:
|
case OpSignExt16to32:
|
||||||
return rewriteValuegeneric_OpSignExt16to32(v)
|
return rewriteValuegeneric_OpSignExt16to32(v)
|
||||||
case OpSignExt16to64:
|
case OpSignExt16to64:
|
||||||
|
|
@ -16124,6 +16126,38 @@ func rewriteValuegeneric_OpNilCheck(v *Value) bool {
|
||||||
v.reset(OpInvalid)
|
v.reset(OpInvalid)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (NilCheck (SelectN [0] call:(StaticLECall _ _)) (SelectN [1] call))
|
||||||
|
// cond: isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check")
|
||||||
|
// result: (Invalid)
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpSelectN || auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
call := v_0.Args[0]
|
||||||
|
if call.Op != OpStaticLECall || len(call.Args) != 2 || v_1.Op != OpSelectN || auxIntToInt64(v_1.AuxInt) != 1 || call != v_1.Args[0] || !(isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check")) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpInvalid)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (NilCheck (OffPtr (SelectN [0] call:(StaticLECall _ _))) (SelectN [1] call))
|
||||||
|
// cond: isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check")
|
||||||
|
// result: (Invalid)
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpOffPtr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0_0 := v_0.Args[0]
|
||||||
|
if v_0_0.Op != OpSelectN || auxIntToInt64(v_0_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
call := v_0_0.Args[0]
|
||||||
|
if call.Op != OpStaticLECall || len(call.Args) != 2 || v_1.Op != OpSelectN || auxIntToInt64(v_1.AuxInt) != 1 || call != v_1.Args[0] || !(isSameCall(call.Aux, "runtime.newobject") && warnRule(fe.Debug_checknil(), v, "removed nil check")) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpInvalid)
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
func rewriteValuegeneric_OpNot(v *Value) bool {
|
func rewriteValuegeneric_OpNot(v *Value) bool {
|
||||||
|
|
@ -20669,6 +20703,70 @@ func rewriteValuegeneric_OpSelect1(v *Value) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
func rewriteValuegeneric_OpSelectN(v *Value) bool {
|
||||||
|
v_0 := v.Args[0]
|
||||||
|
b := v.Block
|
||||||
|
config := b.Func.Config
|
||||||
|
// match: (SelectN [0] call:(StaticLECall {sym} dst src (Const64 [sz]) mem))
|
||||||
|
// cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)
|
||||||
|
// result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
|
||||||
|
for {
|
||||||
|
if auxIntToInt64(v.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
call := v_0
|
||||||
|
if call.Op != OpStaticLECall || len(call.Args) != 4 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
sym := auxToCall(call.Aux)
|
||||||
|
mem := call.Args[3]
|
||||||
|
dst := call.Args[0]
|
||||||
|
src := call.Args[1]
|
||||||
|
call_2 := call.Args[2]
|
||||||
|
if call_2.Op != OpConst64 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
sz := auxIntToInt64(call_2.AuxInt)
|
||||||
|
if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpMove)
|
||||||
|
v.AuxInt = int64ToAuxInt(int64(sz))
|
||||||
|
v.Aux = typeToAux(dst.Type.Elem())
|
||||||
|
v.AddArg3(dst, src, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (SelectN [0] call:(StaticLECall {sym} dst src (Const32 [sz]) mem))
|
||||||
|
// cond: sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)
|
||||||
|
// result: (Move {dst.Type.Elem()} [int64(sz)] dst src mem)
|
||||||
|
for {
|
||||||
|
if auxIntToInt64(v.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
call := v_0
|
||||||
|
if call.Op != OpStaticLECall || len(call.Args) != 4 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
sym := auxToCall(call.Aux)
|
||||||
|
mem := call.Args[3]
|
||||||
|
dst := call.Args[0]
|
||||||
|
src := call.Args[1]
|
||||||
|
call_2 := call.Args[2]
|
||||||
|
if call_2.Op != OpConst32 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
sz := auxIntToInt32(call_2.AuxInt)
|
||||||
|
if !(sz >= 0 && call.Uses == 1 && isSameCall(sym, "runtime.memmove") && dst.Type.IsPtr() && isInlinableMemmove(dst, src, int64(sz), config) && clobber(call)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.reset(OpMove)
|
||||||
|
v.AuxInt = int64ToAuxInt(int64(sz))
|
||||||
|
v.Aux = typeToAux(dst.Type.Elem())
|
||||||
|
v.AddArg3(dst, src, mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
func rewriteValuegeneric_OpSignExt16to32(v *Value) bool {
|
func rewriteValuegeneric_OpSignExt16to32(v *Value) bool {
|
||||||
v_0 := v.Args[0]
|
v_0 := v.Args[0]
|
||||||
// match: (SignExt16to32 (Const16 [c]))
|
// match: (SignExt16to32 (Const16 [c]))
|
||||||
|
|
@ -21714,6 +21812,48 @@ func rewriteValuegeneric_OpStore(v *Value) bool {
|
||||||
v.copyOf(mem)
|
v.copyOf(mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (Store (SelectN [0] call:(StaticLECall _ _)) x mem:(SelectN [1] call))
|
||||||
|
// cond: isConstZero(x) && isSameCall(call.Aux, "runtime.newobject")
|
||||||
|
// result: mem
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpSelectN || auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
call := v_0.Args[0]
|
||||||
|
if call.Op != OpStaticLECall || len(call.Args) != 2 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_1
|
||||||
|
mem := v_2
|
||||||
|
if mem.Op != OpSelectN || auxIntToInt64(mem.AuxInt) != 1 || call != mem.Args[0] || !(isConstZero(x) && isSameCall(call.Aux, "runtime.newobject")) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.copyOf(mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// match: (Store (OffPtr (SelectN [0] call:(StaticLECall _ _))) x mem:(SelectN [1] call))
|
||||||
|
// cond: isConstZero(x) && isSameCall(call.Aux, "runtime.newobject")
|
||||||
|
// result: mem
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpOffPtr {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v_0_0 := v_0.Args[0]
|
||||||
|
if v_0_0.Op != OpSelectN || auxIntToInt64(v_0_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
call := v_0_0.Args[0]
|
||||||
|
if call.Op != OpStaticLECall || len(call.Args) != 2 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
x := v_1
|
||||||
|
mem := v_2
|
||||||
|
if mem.Op != OpSelectN || auxIntToInt64(mem.AuxInt) != 1 || call != mem.Args[0] || !(isConstZero(x) && isSameCall(call.Aux, "runtime.newobject")) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.copyOf(mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
// match: (Store {t1} op1:(OffPtr [o1] p1) d1 m2:(Store {t2} op2:(OffPtr [0] p2) d2 m3:(Move [n] p3 _ mem)))
|
// match: (Store {t1} op1:(OffPtr [o1] p1) d1 m2:(Store {t2} op2:(OffPtr [0] p2) d2 m3:(Move [n] p3 _ mem)))
|
||||||
// cond: m2.Uses == 1 && m3.Uses == 1 && o1 == t2.Size() && n == t2.Size() + t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && clobber(m2, m3)
|
// cond: m2.Uses == 1 && m3.Uses == 1 && o1 == t2.Size() && n == t2.Size() + t1.Size() && isSamePtr(p1, p2) && isSamePtr(p2, p3) && clobber(m2, m3)
|
||||||
// result: (Store {t1} op1 d1 (Store {t2} op2 d2 mem))
|
// result: (Store {t1} op1 d1 (Store {t2} op2 d2 mem))
|
||||||
|
|
@ -24411,6 +24551,24 @@ func rewriteValuegeneric_OpZero(v *Value) bool {
|
||||||
v.copyOf(mem)
|
v.copyOf(mem)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
// match: (Zero (SelectN [0] call:(StaticLECall _ _)) mem:(SelectN [1] call))
|
||||||
|
// cond: isSameCall(call.Aux, "runtime.newobject")
|
||||||
|
// result: mem
|
||||||
|
for {
|
||||||
|
if v_0.Op != OpSelectN || auxIntToInt64(v_0.AuxInt) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
call := v_0.Args[0]
|
||||||
|
if call.Op != OpStaticLECall || len(call.Args) != 2 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
mem := v_1
|
||||||
|
if mem.Op != OpSelectN || auxIntToInt64(mem.AuxInt) != 1 || call != mem.Args[0] || !(isSameCall(call.Aux, "runtime.newobject")) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
v.copyOf(mem)
|
||||||
|
return true
|
||||||
|
}
|
||||||
// match: (Zero {t1} [n] p1 store:(Store {t2} (OffPtr [o2] p2) _ mem))
|
// match: (Zero {t1} [n] p1 store:(Store {t2} (OffPtr [o2] p2) _ mem))
|
||||||
// cond: isSamePtr(p1, p2) && store.Uses == 1 && n >= o2 + t2.Size() && clobber(store)
|
// cond: isSamePtr(p1, p2) && store.Uses == 1 && n >= o2 + t2.Size() && clobber(store)
|
||||||
// result: (Zero {t1} [n] p1 mem)
|
// result: (Zero {t1} [n] p1 mem)
|
||||||
|
|
|
||||||
|
|
@ -261,11 +261,6 @@ func shortcircuitBlock(b *Block) bool {
|
||||||
// and the CFG modifications must not proceed.
|
// and the CFG modifications must not proceed.
|
||||||
// The returned function assumes that shortcircuitBlock has completed its CFG modifications.
|
// The returned function assumes that shortcircuitBlock has completed its CFG modifications.
|
||||||
func shortcircuitPhiPlan(b *Block, ctl *Value, cidx int, ti int64) func(*Value, int) {
|
func shortcircuitPhiPlan(b *Block, ctl *Value, cidx int, ti int64) func(*Value, int) {
|
||||||
const go115shortcircuitPhis = true
|
|
||||||
if !go115shortcircuitPhis {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// t is the "taken" branch: the successor we always go to when coming in from p.
|
// t is the "taken" branch: the successor we always go to when coming in from p.
|
||||||
t := b.Succs[ti].b
|
t := b.Succs[ti].b
|
||||||
// u is the "untaken" branch: the successor we never go to when coming in from p.
|
// u is the "untaken" branch: the successor we never go to when coming in from p.
|
||||||
|
|
|
||||||
|
|
@ -188,6 +188,8 @@ func TestStdFixed(t *testing.T) {
|
||||||
"issue20780.go", // go/types does not have constraints on stack size
|
"issue20780.go", // go/types does not have constraints on stack size
|
||||||
"issue31747.go", // go/types does not have constraints on language level (-lang=go1.12) (see #31793)
|
"issue31747.go", // go/types does not have constraints on language level (-lang=go1.12) (see #31793)
|
||||||
"issue34329.go", // go/types does not have constraints on language level (-lang=go1.13) (see #31793)
|
"issue34329.go", // go/types does not have constraints on language level (-lang=go1.13) (see #31793)
|
||||||
|
"issue42058a.go", // go/types does not have constraints on channel element size
|
||||||
|
"issue42058b.go", // go/types does not have constraints on channel element size
|
||||||
"bug251.go", // issue #34333 which was exposed with fix for #34151
|
"bug251.go", // issue #34333 which was exposed with fix for #34151
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
40
src/cmd/dist/build.go
vendored
40
src/cmd/dist/build.go
vendored
|
|
@ -832,6 +832,21 @@ func runInstall(pkg string, ch chan struct{}) {
|
||||||
asmArgs = append(asmArgs, "-D", "GOMIPS64_"+gomips64)
|
asmArgs = append(asmArgs, "-D", "GOMIPS64_"+gomips64)
|
||||||
}
|
}
|
||||||
goasmh := pathf("%s/go_asm.h", workdir)
|
goasmh := pathf("%s/go_asm.h", workdir)
|
||||||
|
if IsRuntimePackagePath(pkg) {
|
||||||
|
asmArgs = append(asmArgs, "-compiling-runtime")
|
||||||
|
if os.Getenv("GOEXPERIMENT") == "regabi" {
|
||||||
|
// In order to make it easier to port runtime assembly
|
||||||
|
// to the register ABI, we introduce a macro
|
||||||
|
// indicating the experiment is enabled.
|
||||||
|
//
|
||||||
|
// Note: a similar change also appears in
|
||||||
|
// cmd/go/internal/work/gc.go.
|
||||||
|
//
|
||||||
|
// TODO(austin): Remove this once we commit to the
|
||||||
|
// register ABI (#40724).
|
||||||
|
asmArgs = append(asmArgs, "-D=GOEXPERIMENT_REGABI=1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Collect symabis from assembly code.
|
// Collect symabis from assembly code.
|
||||||
var symabis string
|
var symabis string
|
||||||
|
|
@ -1462,8 +1477,8 @@ func wrapperPathFor(goos, goarch string) string {
|
||||||
if gohostos != "android" {
|
if gohostos != "android" {
|
||||||
return pathf("%s/misc/android/go_android_exec.go", goroot)
|
return pathf("%s/misc/android/go_android_exec.go", goroot)
|
||||||
}
|
}
|
||||||
case (goos == "darwin" || goos == "ios") && goarch == "arm64":
|
case goos == "ios":
|
||||||
if gohostos != "darwin" || gohostarch != "arm64" {
|
if gohostos != "ios" {
|
||||||
return pathf("%s/misc/ios/go_ios_exec.go", goroot)
|
return pathf("%s/misc/ios/go_ios_exec.go", goroot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1542,6 +1557,7 @@ var cgoEnabled = map[string]bool{
|
||||||
"android/arm": true,
|
"android/arm": true,
|
||||||
"android/arm64": true,
|
"android/arm64": true,
|
||||||
"ios/arm64": true,
|
"ios/arm64": true,
|
||||||
|
"ios/amd64": true,
|
||||||
"js/wasm": false,
|
"js/wasm": false,
|
||||||
"netbsd/386": true,
|
"netbsd/386": true,
|
||||||
"netbsd/amd64": true,
|
"netbsd/amd64": true,
|
||||||
|
|
@ -1733,3 +1749,23 @@ func cmdlist() {
|
||||||
fatalf("write failed: %v", err)
|
fatalf("write failed: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsRuntimePackagePath examines 'pkgpath' and returns TRUE if it
|
||||||
|
// belongs to the collection of "runtime-related" packages, including
|
||||||
|
// "runtime" itself, "reflect", "syscall", and the
|
||||||
|
// "runtime/internal/*" packages. See also the function of the same
|
||||||
|
// name in cmd/internal/objabi/path.go.
|
||||||
|
func IsRuntimePackagePath(pkgpath string) bool {
|
||||||
|
rval := false
|
||||||
|
switch pkgpath {
|
||||||
|
case "runtime":
|
||||||
|
rval = true
|
||||||
|
case "reflect":
|
||||||
|
rval = true
|
||||||
|
case "syscall":
|
||||||
|
rval = true
|
||||||
|
default:
|
||||||
|
rval = strings.HasPrefix(pkgpath, "runtime/internal")
|
||||||
|
}
|
||||||
|
return rval
|
||||||
|
}
|
||||||
|
|
|
||||||
4
src/cmd/dist/main.go
vendored
4
src/cmd/dist/main.go
vendored
|
|
@ -133,6 +133,10 @@ func main() {
|
||||||
if strings.Contains(run("", CheckExit, "uname", "-v"), "RELEASE_ARM64_") {
|
if strings.Contains(run("", CheckExit, "uname", "-v"), "RELEASE_ARM64_") {
|
||||||
gohostarch = "arm64"
|
gohostarch = "arm64"
|
||||||
}
|
}
|
||||||
|
case gohostos == "openbsd":
|
||||||
|
if strings.Contains(run("", CheckExit, "uname", "-p"), "mips64") {
|
||||||
|
gohostarch = "mips64"
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
fatalf("unknown architecture: %s", out)
|
fatalf("unknown architecture: %s", out)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
24
src/cmd/dist/test.go
vendored
24
src/cmd/dist/test.go
vendored
|
|
@ -921,7 +921,7 @@ func (t *tester) extLink() bool {
|
||||||
"darwin-amd64", "darwin-arm64",
|
"darwin-amd64", "darwin-arm64",
|
||||||
"dragonfly-amd64",
|
"dragonfly-amd64",
|
||||||
"freebsd-386", "freebsd-amd64", "freebsd-arm",
|
"freebsd-386", "freebsd-amd64", "freebsd-arm",
|
||||||
"linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-mips64", "linux-mips64le", "linux-mips", "linux-mipsle", "linux-s390x",
|
"linux-386", "linux-amd64", "linux-arm", "linux-arm64", "linux-ppc64le", "linux-mips64", "linux-mips64le", "linux-mips", "linux-mipsle", "linux-riscv64", "linux-s390x",
|
||||||
"netbsd-386", "netbsd-amd64",
|
"netbsd-386", "netbsd-amd64",
|
||||||
"openbsd-386", "openbsd-amd64",
|
"openbsd-386", "openbsd-amd64",
|
||||||
"windows-386", "windows-amd64":
|
"windows-386", "windows-amd64":
|
||||||
|
|
@ -946,9 +946,6 @@ func (t *tester) internalLink() bool {
|
||||||
if goos == "ios" {
|
if goos == "ios" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if goos == "darwin" && goarch == "arm64" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// Internally linking cgo is incomplete on some architectures.
|
// Internally linking cgo is incomplete on some architectures.
|
||||||
// https://golang.org/issue/10373
|
// https://golang.org/issue/10373
|
||||||
// https://golang.org/issue/14449
|
// https://golang.org/issue/14449
|
||||||
|
|
@ -964,10 +961,10 @@ func (t *tester) internalLink() bool {
|
||||||
|
|
||||||
func (t *tester) internalLinkPIE() bool {
|
func (t *tester) internalLinkPIE() bool {
|
||||||
switch goos + "-" + goarch {
|
switch goos + "-" + goarch {
|
||||||
case "linux-amd64", "linux-arm64",
|
case "darwin-amd64", "darwin-arm64",
|
||||||
"android-arm64":
|
"linux-amd64", "linux-arm64",
|
||||||
return true
|
"android-arm64",
|
||||||
case "windows-amd64", "windows-386", "windows-arm":
|
"windows-amd64", "windows-386", "windows-arm":
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
@ -1088,7 +1085,7 @@ func (t *tester) cgoTest(dt *distTest) error {
|
||||||
|
|
||||||
pair := gohostos + "-" + goarch
|
pair := gohostos + "-" + goarch
|
||||||
switch pair {
|
switch pair {
|
||||||
case "darwin-amd64",
|
case "darwin-amd64", "darwin-arm64",
|
||||||
"openbsd-386", "openbsd-amd64",
|
"openbsd-386", "openbsd-amd64",
|
||||||
"windows-386", "windows-amd64":
|
"windows-386", "windows-amd64":
|
||||||
// test linkmode=external, but __thread not supported, so skip testtls.
|
// test linkmode=external, but __thread not supported, so skip testtls.
|
||||||
|
|
@ -1100,6 +1097,13 @@ func (t *tester) cgoTest(dt *distTest) error {
|
||||||
|
|
||||||
cmd = t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s")
|
cmd = t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s")
|
||||||
|
|
||||||
|
if t.supportedBuildmode("pie") {
|
||||||
|
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie")
|
||||||
|
if t.internalLink() && t.internalLinkPIE() {
|
||||||
|
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case "aix-ppc64",
|
case "aix-ppc64",
|
||||||
"android-arm", "android-arm64",
|
"android-arm", "android-arm64",
|
||||||
"dragonfly-amd64",
|
"dragonfly-amd64",
|
||||||
|
|
@ -1151,7 +1155,7 @@ func (t *tester) cgoTest(dt *distTest) error {
|
||||||
if t.supportedBuildmode("pie") {
|
if t.supportedBuildmode("pie") {
|
||||||
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie")
|
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie")
|
||||||
if t.internalLink() && t.internalLinkPIE() {
|
if t.internalLink() && t.internalLinkPIE() {
|
||||||
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal")
|
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie")
|
||||||
}
|
}
|
||||||
t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-buildmode=pie")
|
t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-buildmode=pie")
|
||||||
t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-buildmode=pie")
|
t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-buildmode=pie")
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ import (
|
||||||
"go/printer"
|
"go/printer"
|
||||||
"go/token"
|
"go/token"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
@ -129,11 +129,10 @@ func (pkg *Package) Fatalf(format string, args ...interface{}) {
|
||||||
// parsePackage turns the build package we found into a parsed package
|
// parsePackage turns the build package we found into a parsed package
|
||||||
// we can then use to generate documentation.
|
// we can then use to generate documentation.
|
||||||
func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Package {
|
func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Package {
|
||||||
fs := token.NewFileSet()
|
|
||||||
// include tells parser.ParseDir which files to include.
|
// include tells parser.ParseDir which files to include.
|
||||||
// That means the file must be in the build package's GoFiles or CgoFiles
|
// That means the file must be in the build package's GoFiles or CgoFiles
|
||||||
// list only (no tag-ignored files, tests, swig or other non-Go files).
|
// list only (no tag-ignored files, tests, swig or other non-Go files).
|
||||||
include := func(info os.FileInfo) bool {
|
include := func(info fs.FileInfo) bool {
|
||||||
for _, name := range pkg.GoFiles {
|
for _, name := range pkg.GoFiles {
|
||||||
if name == info.Name() {
|
if name == info.Name() {
|
||||||
return true
|
return true
|
||||||
|
|
@ -146,7 +145,8 @@ func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Packag
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
pkgs, err := parser.ParseDir(fs, pkg.Dir, include, parser.ParseComments)
|
fset := token.NewFileSet()
|
||||||
|
pkgs, err := parser.ParseDir(fset, pkg.Dir, include, parser.ParseComments)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -203,7 +203,7 @@ func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Packag
|
||||||
typedValue: typedValue,
|
typedValue: typedValue,
|
||||||
constructor: constructor,
|
constructor: constructor,
|
||||||
build: pkg,
|
build: pkg,
|
||||||
fs: fs,
|
fs: fset,
|
||||||
}
|
}
|
||||||
p.buf.pkg = p
|
p.buf.pkg = p
|
||||||
return p
|
return p
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ import (
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/scanner"
|
"go/scanner"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -127,7 +129,7 @@ func processFile(filename string, useStdin bool) error {
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
src, err := ioutil.ReadAll(f)
|
src, err := io.ReadAll(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -235,7 +237,7 @@ func walkDir(path string) {
|
||||||
filepath.Walk(path, visitFile)
|
filepath.Walk(path, visitFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
func visitFile(path string, f os.FileInfo, err error) error {
|
func visitFile(path string, f fs.FileInfo, err error) error {
|
||||||
if err == nil && isGoFile(f) {
|
if err == nil && isGoFile(f) {
|
||||||
err = processFile(path, false)
|
err = processFile(path, false)
|
||||||
}
|
}
|
||||||
|
|
@ -245,7 +247,7 @@ func visitFile(path string, f os.FileInfo, err error) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func isGoFile(f os.FileInfo) bool {
|
func isGoFile(f fs.FileInfo) bool {
|
||||||
// ignore non-Go files
|
// ignore non-Go files
|
||||||
name := f.Name()
|
name := f.Name()
|
||||||
return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
|
return !f.IsDir() && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go")
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ go 1.16
|
||||||
require (
|
require (
|
||||||
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99
|
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340 // indirect
|
github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340 // indirect
|
||||||
golang.org/x/arch v0.0.0-20200826200359-b19915210f00
|
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff
|
||||||
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
|
||||||
golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449
|
golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449
|
||||||
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d // indirect
|
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d // indirect
|
||||||
golang.org/x/tools v0.0.0-20200918232735-d647fc253266
|
golang.org/x/tools v0.0.0-20201014170642-d1624618ad65
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340 h1:S1+yTUaFPXuDZnPDbO+TrDFIjPzQraYH8/CwSlu9Fac=
|
github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340 h1:S1+yTUaFPXuDZnPDbO+TrDFIjPzQraYH8/CwSlu9Fac=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20200414190113-039b1ae3a340/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
golang.org/x/arch v0.0.0-20200826200359-b19915210f00 h1:cfd5G6xu8iZTFmjBYVemyBmE/sTf0A3vpE3BmoOuLCI=
|
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff h1:XmKBi9R6duxOB3lfc72wyrwiOY7X2Jl1wuI+RFOyMDE=
|
||||||
golang.org/x/arch v0.0.0-20200826200359-b19915210f00/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
golang.org/x/arch v0.0.0-20201008161808-52c3e6f60cff/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
|
@ -30,8 +30,8 @@ golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d h1:L/IKR6COd7ubZrs2oTnTi73Ih
|
||||||
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200918232735-d647fc253266 h1:k7tVuG0g1JwmD3Jh8oAl1vQ1C3jb4Hi/dUl1wWDBJpQ=
|
golang.org/x/tools v0.0.0-20201014170642-d1624618ad65 h1:q80OtYaeeySe8Kqg0vjXehHwj5fUTqe3xOvnbi5w3Gg=
|
||||||
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
golang.org/x/tools v0.0.0-20201014170642-d1624618ad65/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
|
|
|
||||||
|
|
@ -796,6 +796,7 @@
|
||||||
// BinaryOnly bool // binary-only package (no longer supported)
|
// BinaryOnly bool // binary-only package (no longer supported)
|
||||||
// ForTest string // package is only for use in named test
|
// ForTest string // package is only for use in named test
|
||||||
// Export string // file containing export data (when using -export)
|
// Export string // file containing export data (when using -export)
|
||||||
|
// BuildID string // build ID of the export data (when using -export)
|
||||||
// Module *Module // info about package's containing module, if any (can be nil)
|
// Module *Module // info about package's containing module, if any (can be nil)
|
||||||
// Match []string // command-line patterns matching this package
|
// Match []string // command-line patterns matching this package
|
||||||
// DepOnly bool // package is only a dependency, not explicitly listed
|
// DepOnly bool // package is only a dependency, not explicitly listed
|
||||||
|
|
@ -805,6 +806,7 @@
|
||||||
// CgoFiles []string // .go source files that import "C"
|
// CgoFiles []string // .go source files that import "C"
|
||||||
// CompiledGoFiles []string // .go files presented to compiler (when using -compiled)
|
// CompiledGoFiles []string // .go files presented to compiler (when using -compiled)
|
||||||
// IgnoredGoFiles []string // .go source files ignored due to build constraints
|
// IgnoredGoFiles []string // .go source files ignored due to build constraints
|
||||||
|
// IgnoredOtherFiles []string // non-.go source files ignored due to build constraints
|
||||||
// CFiles []string // .c source files
|
// CFiles []string // .c source files
|
||||||
// CXXFiles []string // .cc, .cxx and .cpp source files
|
// CXXFiles []string // .cc, .cxx and .cpp source files
|
||||||
// MFiles []string // .m source files
|
// MFiles []string // .m source files
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"internal/race"
|
"internal/race"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -813,7 +814,7 @@ func (tg *testgoData) cleanup() {
|
||||||
func removeAll(dir string) error {
|
func removeAll(dir string) error {
|
||||||
// module cache has 0444 directories;
|
// module cache has 0444 directories;
|
||||||
// make them writable in order to remove content.
|
// make them writable in order to remove content.
|
||||||
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
filepath.Walk(dir, func(path string, info fs.FileInfo, err error) error {
|
||||||
// chmod not only directories, but also things that we couldn't even stat
|
// chmod not only directories, but also things that we couldn't even stat
|
||||||
// due to permission errors: they may also be unreadable directories.
|
// due to permission errors: they may also be unreadable directories.
|
||||||
if err != nil || info.IsDir() {
|
if err != nil || info.IsDir() {
|
||||||
|
|
@ -860,7 +861,7 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
|
||||||
srcdir := filepath.Join(testGOROOT, copydir)
|
srcdir := filepath.Join(testGOROOT, copydir)
|
||||||
tg.tempDir(filepath.Join("goroot", copydir))
|
tg.tempDir(filepath.Join("goroot", copydir))
|
||||||
err := filepath.Walk(srcdir,
|
err := filepath.Walk(srcdir,
|
||||||
func(path string, info os.FileInfo, err error) error {
|
func(path string, info fs.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -1236,6 +1237,18 @@ func TestGoListExport(t *testing.T) {
|
||||||
if _, err := os.Stat(file); err != nil {
|
if _, err := os.Stat(file); err != nil {
|
||||||
t.Fatalf("cannot find .Export result %s: %v", file, err)
|
t.Fatalf("cannot find .Export result %s: %v", file, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tg.run("list", "-export", "-f", "{{.BuildID}}", "strings")
|
||||||
|
buildID := strings.TrimSpace(tg.stdout.String())
|
||||||
|
if buildID == "" {
|
||||||
|
t.Fatalf(".BuildID with -export was empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
tg.run("tool", "buildid", file)
|
||||||
|
toolBuildID := strings.TrimSpace(tg.stdout.String())
|
||||||
|
if buildID != toolBuildID {
|
||||||
|
t.Fatalf(".BuildID with -export %q disagrees with 'go tool buildid' %q", buildID, toolBuildID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue 4096. Validate the output of unsuccessful go install foo/quxx.
|
// Issue 4096. Validate the output of unsuccessful go install foo/quxx.
|
||||||
|
|
@ -2018,7 +2031,7 @@ func main() {
|
||||||
tg.run("build", "-o", exe, "p")
|
tg.run("build", "-o", exe, "p")
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyFile(src, dst string, perm os.FileMode) error {
|
func copyFile(src, dst string, perm fs.FileMode) error {
|
||||||
sf, err := os.Open(src)
|
sf, err := os.Open(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,11 @@ func SetFromGOFLAGS(flags *flag.FlagSet) {
|
||||||
}
|
}
|
||||||
for _, goflag := range goflags {
|
for _, goflag := range goflags {
|
||||||
name, value, hasValue := goflag, "", false
|
name, value, hasValue := goflag, "", false
|
||||||
if i := strings.Index(goflag, "="); i >= 0 {
|
// Ignore invalid flags like '=' or '=value'.
|
||||||
|
// If it is not reported in InitGOFlags it means we don't want to report it.
|
||||||
|
if i := strings.Index(goflag, "="); i == 0 {
|
||||||
|
continue
|
||||||
|
} else if i > 0 {
|
||||||
name, value, hasValue = goflag[:i], goflag[i+1:], true
|
name, value, hasValue = goflag[:i], goflag[i+1:], true
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(name, "--") {
|
if strings.HasPrefix(name, "--") {
|
||||||
|
|
|
||||||
3
src/cmd/go/internal/cache/cache.go
vendored
3
src/cmd/go/internal/cache/cache.go
vendored
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -54,7 +55,7 @@ func Open(dir string) (*Cache, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !info.IsDir() {
|
if !info.IsDir() {
|
||||||
return nil, &os.PathError{Op: "open", Path: dir, Err: fmt.Errorf("not a directory")}
|
return nil, &fs.PathError{Op: "open", Path: dir, Err: fmt.Errorf("not a directory")}
|
||||||
}
|
}
|
||||||
for i := 0; i < 256; i++ {
|
for i := 0; i < 256; i++ {
|
||||||
name := filepath.Join(dir, fmt.Sprintf("%02x", i))
|
name := filepath.Join(dir, fmt.Sprintf("%02x", i))
|
||||||
|
|
|
||||||
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