mirror of
https://github.com/golang/go.git
synced 2026-02-09 03:10:15 +00:00
[dev.fuzz] all: merge master into dev.fuzz
Change-Id: I5d8c8329ccc9d747bd81ade6b1cb7cb8ae2e94b2
This commit is contained in:
commit
0345ede87e
2192 changed files with 121081 additions and 62689 deletions
230
api/except.txt
230
api/except.txt
|
|
@ -2,12 +2,56 @@ pkg encoding/json, method (*RawMessage) MarshalJSON() ([]uint8, error)
|
|||
pkg math/big, const MaxBase = 36
|
||||
pkg math/big, type Word uintptr
|
||||
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 = 2399666176
|
||||
pkg os (linux-arm), const O_SYNC = 4096
|
||||
pkg os (linux-arm-cgo), const O_SYNC = 4096
|
||||
pkg os (linux-arm), const O_SYNC = 1052672
|
||||
pkg os (linux-arm-cgo), const O_SYNC = 1052672
|
||||
pkg os, const ModeType FileMode
|
||||
pkg os, func Chmod(string, FileMode) error
|
||||
pkg os, func Lstat(string) (FileInfo, error)
|
||||
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), func Fchflags(string, int) error
|
||||
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 O_CLOEXEC = 0
|
||||
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 DLT_MATCHING_MAX = 242
|
||||
pkg syscall (freebsd-386-cgo), const ELAST = 94
|
||||
pkg syscall (freebsd-386-cgo), const ImplementsGetwd = false
|
||||
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 DLT_MATCHING_MAX = 242
|
||||
pkg syscall (freebsd-amd64), const ELAST = 94
|
||||
pkg syscall (freebsd-amd64), const ImplementsGetwd = false
|
||||
pkg syscall (freebsd-amd64), const O_CLOEXEC = 0
|
||||
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 DLT_MATCHING_MAX = 242
|
||||
pkg syscall (freebsd-amd64-cgo), const ELAST = 94
|
||||
pkg syscall (freebsd-amd64-cgo), const ImplementsGetwd = false
|
||||
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 BIOCGRTIMEOUT = 1074545262
|
||||
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 TIOCTIMESTAMP = 1074558041
|
||||
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 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 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, 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 BIOCGRTIMEOUT = 1074545262
|
||||
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 TIOCTIMESTAMP = 1074558041
|
||||
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 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 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, 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-cgo), 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-cgo), 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), func Fchflags(string, int) error
|
||||
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), func Fchflags(string, int) error
|
||||
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_GETTIMEOFDAY = 116
|
||||
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_NANOSLEEP = 240
|
||||
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_GETTIMEOFDAY = 116
|
||||
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_NANOSLEEP = 240
|
||||
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_GETTIMEOFDAY = 116
|
||||
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_NANOSLEEP = 240
|
||||
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_GETTIMEOFDAY = 116
|
||||
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_NANOSLEEP = 240
|
||||
pkg syscall (openbsd-amd64-cgo), const SYS_SELECT = 93
|
||||
|
|
@ -348,20 +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 Timespec struct, Pad_cgo_0 [4]uint8
|
||||
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 testing, func MainStart(testDeps, []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), type AddrinfoW struct, Addr uintptr
|
||||
pkg syscall (windows-386), type CertChainPolicyPara struct, ExtraPolicyPara uintptr
|
||||
|
|
@ -380,81 +488,17 @@ pkg syscall (windows-amd64), type CertRevocationInfo struct, CrlInfo uintptr
|
|||
pkg syscall (windows-amd64), type CertRevocationInfo struct, OidSpecificInfo uintptr
|
||||
pkg syscall (windows-amd64), type CertSimpleChain struct, TrustListInfo uintptr
|
||||
pkg syscall (windows-amd64), type RawSockaddrAny struct, Pad [96]int8
|
||||
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), 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 testing, func MainStart(func(string, string) (bool, error), []InternalTest, []InternalBenchmark, []InternalExample) *M
|
||||
pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalExample) *M
|
||||
pkg testing, func RegisterCover(Cover)
|
||||
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 = "11.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"
|
||||
|
|
|
|||
473
api/next.txt
473
api/next.txt
|
|
@ -1,22 +1,420 @@
|
|||
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
|
||||
pkg text/template/parse, const NodeComment = 20
|
||||
pkg text/template/parse, const NodeComment NodeType
|
||||
pkg text/template/parse, const ParseComments = 1
|
||||
pkg text/template/parse, const ParseComments Mode
|
||||
pkg text/template/parse, method (*CommentNode) Copy() Node
|
||||
pkg text/template/parse, method (*CommentNode) String() string
|
||||
pkg text/template/parse, method (CommentNode) Position() Pos
|
||||
pkg text/template/parse, method (CommentNode) Type() NodeType
|
||||
pkg text/template/parse, type CommentNode struct
|
||||
pkg text/template/parse, type CommentNode struct, Text string
|
||||
pkg text/template/parse, type CommentNode struct, embedded NodeType
|
||||
pkg text/template/parse, type CommentNode struct, embedded Pos
|
||||
pkg text/template/parse, type Mode uint
|
||||
pkg text/template/parse, type Tree struct, Mode Mode
|
||||
pkg archive/zip, method (*ReadCloser) Open(string) (fs.File, error)
|
||||
pkg archive/zip, method (*Reader) Open(string) (fs.File, error)
|
||||
pkg debug/elf, const DT_ADDRRNGHI = 1879047935
|
||||
pkg debug/elf, const DT_ADDRRNGHI DynTag
|
||||
pkg debug/elf, const DT_ADDRRNGLO = 1879047680
|
||||
pkg debug/elf, const DT_ADDRRNGLO DynTag
|
||||
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 embed, method (FS) Open(string) (fs.File, error)
|
||||
pkg embed, method (FS) ReadDir(string) ([]fs.DirEntry, error)
|
||||
pkg embed, method (FS) ReadFile(string) ([]uint8, error)
|
||||
pkg embed, type FS struct
|
||||
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, EmbedPatterns []string
|
||||
pkg go/build, type Package struct, IgnoredOtherFiles []string
|
||||
pkg go/build, type Package struct, TestEmbedPatterns []string
|
||||
pkg go/build, type Package struct, XTestEmbedPatterns []string
|
||||
pkg html/template, func ParseFS(fs.FS, ...string) (*Template, error)
|
||||
pkg html/template, method (*Template) ParseFS(fs.FS, ...string) (*Template, error)
|
||||
pkg io, func NopCloser(Reader) ReadCloser
|
||||
pkg io, func ReadAll(Reader) ([]uint8, error)
|
||||
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, var Discard Writer
|
||||
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, func Glob(FS, string) ([]string, error)
|
||||
pkg io/fs, func ReadDir(FS, string) ([]DirEntry, error)
|
||||
pkg io/fs, func ReadFile(FS, string) ([]uint8, error)
|
||||
pkg io/fs, func Stat(FS, string) (FileInfo, error)
|
||||
pkg io/fs, func ValidPath(string) bool
|
||||
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 DirEntry interface { Info, IsDir, Name, Type }
|
||||
pkg io/fs, type DirEntry interface, Info() (FileInfo, error)
|
||||
pkg io/fs, type DirEntry interface, IsDir() bool
|
||||
pkg io/fs, type DirEntry interface, Name() string
|
||||
pkg io/fs, type DirEntry interface, Type() FileMode
|
||||
pkg io/fs, type FS interface { Open }
|
||||
pkg io/fs, type FS interface, Open(string) (File, error)
|
||||
pkg io/fs, type File interface { Close, Read, Stat }
|
||||
pkg io/fs, type File interface, Close() error
|
||||
pkg io/fs, type File interface, Read([]uint8) (int, error)
|
||||
pkg io/fs, type File interface, Stat() (FileInfo, error)
|
||||
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 GlobFS interface { Glob, Open }
|
||||
pkg io/fs, type GlobFS interface, Glob(string) ([]string, error)
|
||||
pkg io/fs, type GlobFS interface, Open(string) (File, error)
|
||||
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, type ReadDirFS interface { Open, ReadDir }
|
||||
pkg io/fs, type ReadDirFS interface, Open(string) (File, error)
|
||||
pkg io/fs, type ReadDirFS interface, ReadDir(string) ([]DirEntry, error)
|
||||
pkg io/fs, type ReadDirFile interface { Close, Read, ReadDir, Stat }
|
||||
pkg io/fs, type ReadDirFile interface, Close() error
|
||||
pkg io/fs, type ReadDirFile interface, Read([]uint8) (int, error)
|
||||
pkg io/fs, type ReadDirFile interface, ReadDir(int) ([]DirEntry, error)
|
||||
pkg io/fs, type ReadDirFile interface, Stat() (FileInfo, error)
|
||||
pkg io/fs, type ReadFileFS interface { Open, ReadFile }
|
||||
pkg io/fs, type ReadFileFS interface, Open(string) (File, error)
|
||||
pkg io/fs, type ReadFileFS interface, ReadFile(string) ([]uint8, error)
|
||||
pkg io/fs, type StatFS interface { Open, Stat }
|
||||
pkg io/fs, type StatFS interface, Open(string) (File, error)
|
||||
pkg io/fs, type StatFS interface, Stat(string) (FileInfo, error)
|
||||
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 log, func Default() *Logger
|
||||
pkg net, var ErrClosed error
|
||||
pkg net/http, func FS(fs.FS) FileSystem
|
||||
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 DirFS(string) fs.FS
|
||||
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) ([]fs.DirEntry, error)
|
||||
pkg os, method (*File) Readdir(int) ([]fs.FileInfo, error)
|
||||
pkg os, method (*File) Stat() (fs.FileInfo, error)
|
||||
pkg os, type DirEntry = fs.DirEntry
|
||||
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 runtime/metrics, const KindBad = 0
|
||||
pkg runtime/metrics, const KindBad ValueKind
|
||||
pkg runtime/metrics, const KindFloat64 = 2
|
||||
pkg runtime/metrics, const KindFloat64 ValueKind
|
||||
pkg runtime/metrics, const KindFloat64Histogram = 3
|
||||
pkg runtime/metrics, const KindFloat64Histogram ValueKind
|
||||
pkg runtime/metrics, const KindUint64 = 1
|
||||
pkg runtime/metrics, const KindUint64 ValueKind
|
||||
pkg runtime/metrics, func All() []Description
|
||||
pkg runtime/metrics, func Read([]Sample)
|
||||
pkg runtime/metrics, method (Value) Float64() float64
|
||||
pkg runtime/metrics, method (Value) Float64Histogram() *Float64Histogram
|
||||
pkg runtime/metrics, method (Value) Kind() ValueKind
|
||||
pkg runtime/metrics, method (Value) Uint64() uint64
|
||||
pkg runtime/metrics, type Description struct
|
||||
pkg runtime/metrics, type Description struct, Cumulative bool
|
||||
pkg runtime/metrics, type Description struct, Description string
|
||||
pkg runtime/metrics, type Description struct, Kind ValueKind
|
||||
pkg runtime/metrics, type Description struct, Name string
|
||||
pkg runtime/metrics, type Description struct, StopTheWorld bool
|
||||
pkg runtime/metrics, type Float64Histogram struct
|
||||
pkg runtime/metrics, type Float64Histogram struct, Buckets []float64
|
||||
pkg runtime/metrics, type Float64Histogram struct, Counts []uint64
|
||||
pkg runtime/metrics, type Sample struct
|
||||
pkg runtime/metrics, type Sample struct, Name string
|
||||
pkg runtime/metrics, type Sample struct, Value Value
|
||||
pkg runtime/metrics, type Value struct
|
||||
pkg runtime/metrics, type ValueKind int
|
||||
pkg syscall (linux-386), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
|
||||
pkg syscall (linux-386), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
|
||||
pkg syscall (linux-386), func Setegid(int) error
|
||||
pkg syscall (linux-386), func Seteuid(int) error
|
||||
pkg syscall (linux-386-cgo), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
|
||||
pkg syscall (linux-386-cgo), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
|
||||
pkg syscall (linux-386-cgo), func Setegid(int) error
|
||||
pkg syscall (linux-386-cgo), func Seteuid(int) error
|
||||
pkg syscall (linux-amd64), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
|
||||
pkg syscall (linux-amd64), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
|
||||
pkg syscall (linux-amd64), func Setegid(int) error
|
||||
pkg syscall (linux-amd64), func Seteuid(int) error
|
||||
pkg syscall (linux-amd64-cgo), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
|
||||
pkg syscall (linux-amd64-cgo), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
|
||||
pkg syscall (linux-amd64-cgo), func Setegid(int) error
|
||||
pkg syscall (linux-amd64-cgo), func Seteuid(int) error
|
||||
pkg syscall (linux-arm), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
|
||||
pkg syscall (linux-arm), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
|
||||
pkg syscall (linux-arm), func Setegid(int) error
|
||||
pkg syscall (linux-arm), func Seteuid(int) error
|
||||
pkg syscall (linux-arm-cgo), func AllThreadsSyscall(uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
|
||||
pkg syscall (linux-arm-cgo), func AllThreadsSyscall6(uintptr, uintptr, uintptr, uintptr, uintptr, uintptr, uintptr) (uintptr, uintptr, Errno)
|
||||
pkg syscall (linux-arm-cgo), func Setegid(int) error
|
||||
pkg syscall (linux-arm-cgo), func Seteuid(int) error
|
||||
pkg syscall (windows-386), func RtlGenRandom(*uint8, uint32) error
|
||||
pkg syscall (windows-amd64), func RtlGenRandom(*uint8, uint32) error
|
||||
pkg testing, func Fuzz(func(*F)) FuzzResult
|
||||
pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalFuzzTarget, []InternalExample) *M
|
||||
pkg testing, func RunFuzzTargets(func(string, string) (bool, error), []InternalFuzzTarget) bool
|
||||
|
|
@ -49,4 +447,39 @@ pkg testing, type FuzzResult struct, N int
|
|||
pkg testing, type FuzzResult struct, T time.Duration
|
||||
pkg testing, type InternalFuzzTarget struct
|
||||
pkg testing, type InternalFuzzTarget struct, Fn func(*F)
|
||||
pkg testing, type InternalFuzzTarget struct, Name string
|
||||
pkg testing, type InternalFuzzTarget struct, Name string
|
||||
pkg testing/fstest, func TestFS(fs.FS, ...string) error
|
||||
pkg testing/fstest, method (MapFS) Glob(string) ([]string, error)
|
||||
pkg testing/fstest, method (MapFS) Open(string) (fs.File, error)
|
||||
pkg testing/fstest, method (MapFS) ReadDir(string) ([]fs.DirEntry, error)
|
||||
pkg testing/fstest, method (MapFS) ReadFile(string) ([]uint8, error)
|
||||
pkg testing/fstest, method (MapFS) Stat(string) (fs.FileInfo, error)
|
||||
pkg testing/fstest, type MapFS map[string]*MapFile
|
||||
pkg testing/fstest, type MapFile struct
|
||||
pkg testing/fstest, type MapFile struct, Data []uint8
|
||||
pkg testing/fstest, type MapFile struct, ModTime time.Time
|
||||
pkg testing/fstest, type MapFile struct, Mode fs.FileMode
|
||||
pkg testing/fstest, type MapFile struct, Sys interface{}
|
||||
pkg testing/iotest, func ErrReader(error) io.Reader
|
||||
pkg testing/iotest, func TestReader(io.Reader, []uint8) error
|
||||
pkg text/template, func ParseFS(fs.FS, ...string) (*Template, error)
|
||||
pkg text/template, method (*Template) ParseFS(fs.FS, ...string) (*Template, error)
|
||||
pkg text/template/parse, const NodeComment = 20
|
||||
pkg text/template/parse, const NodeComment NodeType
|
||||
pkg text/template/parse, const ParseComments = 1
|
||||
pkg text/template/parse, const ParseComments Mode
|
||||
pkg text/template/parse, method (*CommentNode) Copy() Node
|
||||
pkg text/template/parse, method (*CommentNode) String() string
|
||||
pkg text/template/parse, method (CommentNode) Position() Pos
|
||||
pkg text/template/parse, method (CommentNode) Type() NodeType
|
||||
pkg text/template/parse, type CommentNode struct
|
||||
pkg text/template/parse, type CommentNode struct, Text string
|
||||
pkg text/template/parse, type CommentNode struct, embedded NodeType
|
||||
pkg text/template/parse, type CommentNode struct, embedded Pos
|
||||
pkg text/template/parse, type Mode uint
|
||||
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
|
||||
|
|
|
|||
|
|
@ -418,7 +418,7 @@ close(c)
|
|||
<code>linux/amd64</code>, <code>linux/ppc64le</code>,
|
||||
<code>linux/arm64</code>, <code>freebsd/amd64</code>,
|
||||
<code>netbsd/amd64</code>, <code>darwin/amd64</code>,
|
||||
and <code>windows/amd64</code>.
|
||||
<code>darwin/arm64</code>, and <code>windows/amd64</code>.
|
||||
</p>
|
||||
|
||||
<h2 id="Runtime_Overheads">Runtime Overhead</h2>
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ CLA (Contributor License Agreement).
|
|||
</li>
|
||||
<li>
|
||||
<b>Step 2</b>: Configure authentication credentials for the Go Git repository.
|
||||
Visit <a href="https://go.googlesource.com/">go.googlesource.com</a>, click
|
||||
on the gear icon (top right), then on "Obtain password", and follow the
|
||||
Visit <a href="https://go.googlesource.com">go.googlesource.com</a>, click
|
||||
"Generate Password" in the page's top right menu bar, and follow the
|
||||
instructions.
|
||||
</li>
|
||||
<li>
|
||||
|
|
@ -806,10 +806,9 @@ tracker will automatically mark the issue as fixed.
|
|||
|
||||
<p>
|
||||
If the change is a partial step towards the resolution of the issue,
|
||||
uses the notation "Updates #12345".
|
||||
This will leave a comment in the issue
|
||||
linking back to the change in Gerrit, but it will not close the issue
|
||||
when the change is applied.
|
||||
write "Updates #12345" instead.
|
||||
This will leave a comment in the issue linking back to the change in
|
||||
Gerrit, but it will not close the issue when the change is applied.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
@ -948,10 +947,18 @@ The Gerrit voting system involves an integer in the range -2 to +2:
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
At least two maintainers must approve of the change, and at least one
|
||||
of those maintainers must +2 the change.
|
||||
The second maintainer may cast a vote of Trust+1, meaning that the
|
||||
change looks basically OK, but that the maintainer hasn't done the
|
||||
detailed review required for a +2 vote.
|
||||
</p>
|
||||
|
||||
<h3 id="submit">Submitting an approved change</h3>
|
||||
|
||||
<p>
|
||||
After the code has been +2'ed, an approver will
|
||||
After the code has been +2'ed and Trust+1'ed, an approver will
|
||||
apply it to the master branch using the Gerrit user interface.
|
||||
This is called "submitting the change".
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -454,6 +454,8 @@ environmental variable is set accordingly.</p>
|
|||
<li>GODEBUG=gctrace=1 prints garbage collector events at
|
||||
each collection, summarizing the amount of memory collected
|
||||
and the length of the pause.</li>
|
||||
<li>GODEBUG=inittrace=1 prints a summary of execution time and memory allocation
|
||||
information for completed package initialization work.</li>
|
||||
<li>GODEBUG=schedtrace=X prints scheduling events every X milliseconds.</li>
|
||||
</ul>
|
||||
|
||||
|
|
|
|||
894
doc/go1.16.html
894
doc/go1.16.html
|
|
@ -26,61 +26,395 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<h2 id="language">Changes to the language</h2>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
There are no changes to the language.
|
||||
</p>
|
||||
|
||||
<h2 id="ports">Ports</h2>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
<h3 id="darwin">Darwin and iOS</h3>
|
||||
|
||||
<p><!-- golang.org/issue/38485, golang.org/issue/41385, CL 266373, more CLs -->
|
||||
Go 1.16 adds support of 64-bit ARM architecture on macOS (also known as
|
||||
Apple Silicon) with <code>GOOS=darwin</code>, <code>GOARCH=arm64</code>.
|
||||
Like the <code>darwin/amd64</code> port, the <code>darwin/arm64</code>
|
||||
port supports cgo, internal and external linking, <code>c-archive</code>,
|
||||
<code>c-shared</code>, and <code>pie</code> build modes, and the race
|
||||
detector.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 254740 -->
|
||||
The iOS port, which was previously <code>darwin/arm64</code>, has
|
||||
been renamed to <code>ios/arm64</code>. <code>GOOS=ios</code>
|
||||
implies the
|
||||
<code>darwin</code> build tag, just as <code>GOOS=android</code>
|
||||
implies the <code>linux</code> build tag. This change should be
|
||||
transparent to anyone using gomobile to build iOS apps.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/42100, CL 263798 -->
|
||||
Go 1.16 adds an <code>ios/amd64</code> port, which targets the iOS
|
||||
simulator running on AMD64-based macOS. Previously this was
|
||||
unofficially supported through <code>darwin/amd64</code> with
|
||||
the <code>ios</code> build tag set.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/23011 -->
|
||||
Go 1.16 is the last release that will run on macOS 10.12 Sierra.
|
||||
Go 1.17 will require macOS 10.13 High Sierra or later.
|
||||
</p>
|
||||
|
||||
<h3 id="netbsd">NetBSD</h3>
|
||||
|
||||
<p><!-- golang.org/issue/30824 -->
|
||||
Go now supports the 64-bit ARM architecture on NetBSD (the
|
||||
<code>netbsd/arm64</code> port).
|
||||
</p>
|
||||
|
||||
<h3 id="openbsd">OpenBSD</h3>
|
||||
|
||||
<p><!-- golang.org/issue/40995 -->
|
||||
Go now supports the MIPS64 architecture on OpenBSD
|
||||
(the <code>openbsd/mips64</code> port). This port does not yet
|
||||
support cgo.
|
||||
</p>
|
||||
|
||||
<h3 id="386">386</h3>
|
||||
|
||||
<p><!-- golang.org/issue/40255, golang.org/issue/41848, CL 258957, and CL 260017 -->
|
||||
As <a href="go1.15#386">announced</a> in the Go 1.15 release notes,
|
||||
Go 1.16 drops support for x87 mode compilation (<code>GO386=387</code>).
|
||||
Support for non-SSE2 processors is now available using soft float
|
||||
mode (<code>GO386=softfloat</code>).
|
||||
Users running on non-SSE2 processors should replace <code>GO386=387</code>
|
||||
with <code>GO386=softfloat</code>.
|
||||
</p>
|
||||
|
||||
<h3 id="riscv">RISC-V</h3>
|
||||
|
||||
<p><!-- golang.org/issue/36641, CL 267317 -->
|
||||
The <code>linux/riscv64</code> port now supports cgo and
|
||||
<code>-buildmode=pie</code>. This release also includes performance
|
||||
optimizations and code generation improvements for RISC-V.
|
||||
</p>
|
||||
|
||||
<h2 id="tools">Tools</h2>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
<h3 id="go-command">Go command</h3>
|
||||
|
||||
<h4 id="modules">Modules</h4>
|
||||
|
||||
<p><!-- golang.org/issue/41330 -->
|
||||
Module-aware mode is enabled by default, regardless of whether a
|
||||
<code>go.mod</code> file is present in the current working directory or a
|
||||
parent directory. More precisely, the <code>GO111MODULE</code> environment
|
||||
variable now defaults to <code>on</code>. To switch to the previous behavior,
|
||||
set <code>GO111MODULE</code> to <code>auto</code>.
|
||||
</p>
|
||||
|
||||
<h3 id="go-command">Go command</h3>
|
||||
<p><!-- golang.org/issue/40728 -->
|
||||
Build commands like <code>go</code> <code>build</code> and <code>go</code>
|
||||
<code>test</code> no longer modify <code>go.mod</code> and <code>go.sum</code>
|
||||
by default. Instead, they report an error if a module requirement or checksum
|
||||
needs to be added or updated (as if the <code>-mod=readonly</code> flag were
|
||||
used). Module requirements and sums may be adjusted with <code>go</code>
|
||||
<code>mod</code> <code>tidy</code> or <code>go</code> <code>get</code>.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/40276 -->
|
||||
<code>go</code> <code>install</code> now accepts arguments with
|
||||
version suffixes (for example, <code>go</code> <code>install</code>
|
||||
<code>example.com/cmd@v1.0.0</code>). This causes <code>go</code>
|
||||
<code>install</code> to build and install packages in module-aware mode,
|
||||
ignoring the <code>go.mod</code> file in the current directory or any parent
|
||||
directory, if there is one. This is useful for installing executables without
|
||||
affecting the dependencies of the main module.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/40276 -->
|
||||
<code>go</code> <code>install</code>, with or without a version suffix (as
|
||||
described above), is now the recommended way to build and install packages in
|
||||
module mode. <code>go</code> <code>get</code> should be used with the
|
||||
<code>-d</code> flag to adjust the current module's dependencies without
|
||||
building packages, and use of <code>go</code> <code>get</code> to build and
|
||||
install packages is deprecated. In a future release, the <code>-d</code> flag
|
||||
will always be enabled.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/24031 -->
|
||||
<code>retract</code> directives may now be used in a <code>go.mod</code> file
|
||||
to indicate that certain published versions of the module should not be used
|
||||
by other modules. A module author may retract a version after a severe problem
|
||||
is discovered or if the version was published unintentionally.<br>
|
||||
TODO: write and link to section in golang.org/ref/mod<br>
|
||||
TODO: write and link to tutorial or blog post
|
||||
</p>
|
||||
|
||||
<p><!-= golang.org/issue/29062 -->
|
||||
When using <code>go test</code>, a test that
|
||||
<p><!-- golang.org/issue/26603 -->
|
||||
The <code>go</code> <code>mod</code> <code>vendor</code>
|
||||
and <code>go</code> <code>mod</code> <code>tidy</code> subcommands now accept
|
||||
the <code>-e</code> flag, which instructs them to proceed despite errors in
|
||||
resolving missing packages.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/36465 -->
|
||||
The <code>go</code> command now ignores requirements on module versions
|
||||
excluded by <code>exclude</code> directives in the main module. Previously,
|
||||
the <code>go</code> command used the next version higher than an excluded
|
||||
version, but that version could change over time, resulting in
|
||||
non-reproducible builds.
|
||||
</p>
|
||||
|
||||
<h4 id="embed">Embedding Files</h4>
|
||||
|
||||
<p>
|
||||
The <code>go</code> command now supports including
|
||||
static files and file trees as part of the final executable,
|
||||
using the new <code>//go:embed</code> directive.
|
||||
See the documentation for the new
|
||||
<a href="/pkg/embed/"><code>embed</code></a>
|
||||
package for details.
|
||||
</p>
|
||||
|
||||
<h4 id="go-test"><code>go</code> <code>test</code></h4>
|
||||
|
||||
<p><!-- golang.org/issue/29062 -->
|
||||
When using <code>go</code> <code>test</code>, a test that
|
||||
calls <code>os.Exit(0)</code> during execution of a test function
|
||||
will now be considered to fail.
|
||||
This will help catch cases in which a test calls code that calls
|
||||
os.Exit(0) and thereby stops running all future tests.
|
||||
<code>os.Exit(0)</code> and thereby stops running all future tests.
|
||||
If a <code>TestMain</code> function calls <code>os.Exit(0)</code>
|
||||
that is still considered to be a passing test.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/39484 -->
|
||||
<code>go</code> <code>test</code> reports an error when the <code>-c</code>
|
||||
or <code>-i</code> flags are used together with unknown flags. Normally,
|
||||
unknown flags are passed to tests, but when <code>-c</code> or <code>-i</code>
|
||||
are used, tests are not run.
|
||||
</p>
|
||||
|
||||
<h4 id="go-get"><code>go</code> <code>get</code></h4>
|
||||
|
||||
<p><!-- golang.org/issue/37519 -->
|
||||
The <code>go</code> <code>get</code> <code>-insecure</code> flag is
|
||||
deprecated and will be removed in a future version. This flag permits
|
||||
fetching from repositories and resolving custom domains using insecure
|
||||
schemes such as HTTP, and also bypasses module sum validation using the
|
||||
checksum database. To permit the use of insecure schemes, use the
|
||||
<code>GOINSECURE</code> environment variable instead. To bypass module
|
||||
sum validation, use <code>GOPRIVATE</code> or <code>GONOSUMDB</code>.
|
||||
See <code>go</code> <code>help</code> <code>environment</code> for details.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/cl/263267 -->
|
||||
<code>go</code> <code>get</code> <code>example.com/mod@patch</code> now
|
||||
requires that some version of <code>example.com/mod</code> already be
|
||||
required by the main module.
|
||||
(However, <code>go</code> <code>get</code> <code>-u=patch</code> continues
|
||||
to patch even newly-added dependencies.)
|
||||
</p>
|
||||
|
||||
<h4 id="govcs"><code>GOVCS</code> environment variable</h4>
|
||||
|
||||
<p><!-- golang.org/issue/266420 -->
|
||||
<code>GOVCS</code> is a new environment variable that limits which version
|
||||
control tools the <code>go</code> command may use to download source code.
|
||||
This mitigates security issues with tools that are typically used in trusted,
|
||||
authenticated environments. By default, <code>git</code> and <code>hg</code>
|
||||
may be used to download code from any repository. <code>svn</code>,
|
||||
<code>bzr</code>, and <code>fossil</code> may only be used to download code
|
||||
from repositories with module paths or package paths matching patterns in
|
||||
the <code>GOPRIVATE</code> environment variable. See
|
||||
<a href="/cmd/go/#hdr-Controlling_version_control_with_GOVCS"><code>go</code>
|
||||
<code>help</code> <code>vcs</code></a> for details.
|
||||
</p>
|
||||
|
||||
<h4 id="all-pattern">The <code>all</code> pattern</h4>
|
||||
|
||||
<p><!-- golang.org/cl/240623 -->
|
||||
When the main module's <code>go.mod</code> file
|
||||
declares <code>go</code> <code>1.16</code> or higher, the <code>all</code>
|
||||
package pattern now matches only those packages that are transitively imported
|
||||
by a package or test found in the main module. (Packages imported by <em>tests
|
||||
of</em> packages imported by the main module are no longer included.) This is
|
||||
the same set of packages retained
|
||||
by <code>go</code> <code>mod</code> <code>vendor</code> since Go 1.11.
|
||||
</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>
|
||||
|
||||
<h4 id="i-flag">The <code>-i</code> build flag</h4>
|
||||
|
||||
<p><!-- golang.org/issue/41696 -->
|
||||
The <code>-i</code> flag accepted by <code>go</code> <code>build</code>,
|
||||
<code>go</code> <code>install</code>, and <code>go</code> <code>test</code> is
|
||||
now deprecated. The <code>-i</code> flag instructs the <code>go</code> command
|
||||
to install packages imported by packages named on the command line. Since
|
||||
the build cache was introduced in Go 1.10, the <code>-i</code> flag no longer
|
||||
has a significant effect on build times, and it causes errors when the install
|
||||
directory is not writable.
|
||||
</p>
|
||||
|
||||
<h4 id="list-buildid">The <code>list</code> command</h4>
|
||||
|
||||
<p><!-- golang.org/cl/263542 -->
|
||||
When the <code>-export</code> flag is specified, the <code>BuildID</code>
|
||||
field is now set to the build ID of the compiled package. This is equivalent
|
||||
to running <code>go</code> <code>tool</code> <code>buildid</code> on
|
||||
<code>go</code> <code>list</code> <code>-exported</code> <code>-f</code> <code>{{.Export}</code>,
|
||||
but without the extra step.
|
||||
</p>
|
||||
|
||||
<h4 id="overlay-flag">The <code>-overlay</code> flag</h4>
|
||||
|
||||
<p><!-- golang.org/issue/39958 -->
|
||||
The <code>-overlay</code> flag specifies a JSON configuration file containing
|
||||
a set of file path replacements. The <code>-overlay</code> flag may be used
|
||||
with all build commands and <code>go</code> <code>mod</code> subcommands.
|
||||
It is primarily intended to be used by editor tooling such as gopls to
|
||||
understand the effects of unsaved changes to source files. The config file
|
||||
maps actual file paths to replacement file paths and the <code>go</code>
|
||||
command and its builds will run as if the actual file paths exist with the
|
||||
contents given by the replacement file paths, or don't exist if the replacement
|
||||
file paths are empty.
|
||||
</p>
|
||||
|
||||
<h3 id="cgo">Cgo</h3>
|
||||
|
||||
<p><!-- CL 252378 -->
|
||||
The <a href="/cmd/cgo">cgo</a> tool will no longer try to translate
|
||||
C struct bitfields into Go struct fields, even if their size can be
|
||||
represented in Go. The order in which C bitfields appear in memory
|
||||
is implementation dependent, so in some cases the cgo tool produced
|
||||
results that were silently incorrect.
|
||||
</p>
|
||||
|
||||
<h3 id="vet">Vet</h3>
|
||||
|
||||
<h4 id="vet-string-int">New warning for invalid testing.T use in
|
||||
goroutines</h4>
|
||||
|
||||
<p><!-- CL 235677 -->
|
||||
The vet tool now warns about invalid calls to the <code>testing.T</code>
|
||||
method <code>Fatal</code> from within a goroutine created during the test.
|
||||
This also warns on calls to <code>Fatalf</code>, <code>FailNow</code>, and
|
||||
<code>Skip{,f,Now}</code> methods on <code>testing.T</code> tests or
|
||||
<code>testing.B</code> benchmarks.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
Calls to these methods stop the execution of the created goroutine and not
|
||||
the <code>Test*</code> or <code>Benchmark*</code> function. So these are
|
||||
<a href="/pkg/testing/#T.FailNow">required</a> to be called by the goroutine
|
||||
running the test or benchmark function. For example:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func TestFoo(t *testing.T) {
|
||||
go func() {
|
||||
if condition() {
|
||||
t.Fatal("oops") // This exits the inner func instead of TestFoo.
|
||||
}
|
||||
...
|
||||
}()
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Code calling <code>t.Fatal</code> (or a similar method) from a created
|
||||
goroutine should be rewritten to signal the test failure using
|
||||
<code>t.Error</code> and exit the goroutine early using an alternative
|
||||
method, such as using a <code>return</code> statement. The previous example
|
||||
could be rewritten as:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
func TestFoo(t *testing.T) {
|
||||
go func() {
|
||||
if condition() {
|
||||
t.Error("oops")
|
||||
return
|
||||
}
|
||||
...
|
||||
}()
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p><!-- CL 248686, CL 276372 -->
|
||||
The vet tool now warns about amd64 assembly that clobbers the BP
|
||||
register (the frame pointer) without saving and restoring it,
|
||||
contrary to the calling convention. Code that doesn't preserve the
|
||||
BP register must be modified to either not use BP at all or preserve
|
||||
BP by saving and restoring it. An easy way to preserve BP is to set
|
||||
the frame size to a nonzero value, which causes the generated
|
||||
prologue and epilogue to preserve the BP register for you.
|
||||
See <a href="https://golang.org/cl/248260">CL 248260</a> for example
|
||||
fixes.
|
||||
</p>
|
||||
|
||||
<h2 id="runtime">Runtime</h2>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
The new <a href="/pkg/runtime/metrics/"><code>runtime/metrics</code></a> package
|
||||
introduces a stable interface for reading
|
||||
implementation-defined metrics from the Go runtime.
|
||||
It supersedes existing functions like
|
||||
<a href="/pkg/runtime/#ReadMemStats"><code>runtime.ReadMemStats</code></a>
|
||||
and
|
||||
<a href="/pkg/runtime/debug/#GCStats"><code>debug.GCStats</code></a>
|
||||
and is significantly more general and efficient.
|
||||
See the package documentation for more details.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 254659 -->
|
||||
Setting the <code>GODEBUG</code> environment variable
|
||||
to <code>inittrace=1</code> now causes the runtime to emit a single
|
||||
line to standard error for each package <code>init</code>,
|
||||
summarizing its execution time and memory allocation. This trace can
|
||||
be used to find bottlenecks or regressions in Go startup
|
||||
performance.
|
||||
The <a href="/pkg/runtime/#hdr-Environment_Variables"><code>GODEBUG</code><
|
||||
documentation</a> describes the format.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 267100 -->
|
||||
On Linux, the runtime now defaults to releasing memory to the
|
||||
operating system promptly (using <code>MADV_DONTNEED</code>), rather
|
||||
than lazily when the operating system is under memory pressure
|
||||
(using <code>MADV_FREE</code>). This means process-level memory
|
||||
statistics like RSS will more accurately reflect the amount of
|
||||
physical memory being used by Go processes. Systems that are
|
||||
currently using <code>GODEBUG=madvdontneed=1</code> to improve
|
||||
memory monitoring behavior no longer need to set this environment
|
||||
variable.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 220419, CL 271987 -->
|
||||
Go 1.16 fixes a discrepancy between the race detector and
|
||||
the <a href="/ref/mem">Go memory model</a>. The race detector now
|
||||
more precisely follows the channel synchronization rules of the
|
||||
memory model. As a result, the detector may now report races it
|
||||
previously missed.
|
||||
</p>
|
||||
|
||||
<h2 id="compiler">Compiler</h2>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
<p><!-- CL 256459, CL 264837, CL 266203, CL 256460 -->
|
||||
The compiler can now inline functions with
|
||||
non-labeled <code>for</code> loops, method values, and type
|
||||
switches. The inliner can also detect more indirect calls where
|
||||
inlining is possible.
|
||||
</p>
|
||||
|
||||
<h2 id="linker">Linker</h2>
|
||||
|
||||
<p>
|
||||
<p><!-- CL 248197 -->
|
||||
This release includes additional improvements to the Go linker,
|
||||
reducing linker resource usage (both time and memory) and improving
|
||||
code robustness/maintainability. These changes form the second half
|
||||
|
|
@ -94,54 +428,74 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
supported architecture/OS combinations (the 1.15 performance improvements
|
||||
were primarily focused on <code>ELF</code>-based OSes and
|
||||
<code>amd64</code> architectures). For a representative set of
|
||||
large Go programs, linking is 20-35% faster than 1.15 and requires
|
||||
large Go programs, linking is 20-25% faster than 1.15 and requires
|
||||
5-15% less memory on average for <code>linux/amd64</code>, with larger
|
||||
improvements for other architectures and OSes.
|
||||
improvements for other architectures and OSes. Most binaries are
|
||||
also smaller as a result of more aggressive symbol pruning.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
TODO: update with final numbers later in the release.
|
||||
<p><!-- CL 255259 -->
|
||||
On Windows, <code>go build -buildmode=c-shared</code> now generates Windows
|
||||
ASLR DLLs by default. ASLR can be disabled with <code>--ldflags=-aslr=false</code>.
|
||||
</p>
|
||||
|
||||
<h2 id="library">Core library</h2>
|
||||
|
||||
<h3 id="library-embed">Embedded Files</h3>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
The new <a href="/pkg/embed/"><code>embed</code></a> package
|
||||
provides access to files embedded in the program during compilation
|
||||
using the new <a href="#embed"><code>//go:embed</code> directive</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="net"><a href="/pkg/net/">net</a></h3>
|
||||
<h3 id="fs">File Systems</h3>
|
||||
|
||||
<p><!-- CL 250357 -->
|
||||
The case of I/O on a closed network connection, or I/O on a network
|
||||
connection that is closed before any of the I/O completes, can now
|
||||
be detected using the new <a href="/pkg/net/#ErrClosed">ErrClosed</a> error.
|
||||
A typical use would be <code>errors.Is(err, net.ErrClosed)</code>.
|
||||
In earlier releases the only way to reliably detect this case was to
|
||||
match the string returned by the <code>Error</code> method
|
||||
with <code>"use of closed network connection"</code>.
|
||||
<p>
|
||||
The new <a href="/pkg/io/fs/"><code>io/fs</code></a> package
|
||||
defines an abstraction for read-only trees of files,
|
||||
the <a href="/pkg/io/fs/#FS"><code>fs.FS</code></a> interface,
|
||||
and the standard library packages have
|
||||
been adapted to make use of the interface as appropriate.
|
||||
</p>
|
||||
|
||||
|
||||
<h3 id="text/template/parse"><a href="/pkg/text/template/parse/">text/template/parse</a></h3>
|
||||
|
||||
<p><!-- CL 229398, golang.org/issue/34652 -->
|
||||
A new <a href="/pkg/text/template/parse/#CommentNode"><code>CommentNode</code></a>
|
||||
was added to the parse tree. The <a href="/pkg/text/template/parse/#Mode"><code>Mode</code></a>
|
||||
field in the <code>parse.Tree</code> enables access to it.
|
||||
<p>
|
||||
On the producer side of the interface,
|
||||
the new <a href="/pkg/embed/#FS">embed.FS</code></a> type
|
||||
implements <code>fs.FS</code>, as does
|
||||
<a href="/pkg/archive/zip/#Reader"><code>zip.Reader</code></a>.
|
||||
The new <a href="/pkg/os/#DirFS"><code>os.DirFS</code></a> function
|
||||
provides an implementation of <code>fs.FS</code> backed by a tree
|
||||
of operating system files.
|
||||
</p>
|
||||
<!-- text/template/parse -->
|
||||
|
||||
<h3 id="unicode"><a href="/pkg/unicode/">unicode</a></h3>
|
||||
|
||||
<p><!-- CL 248765 -->
|
||||
The <a href="/pkg/unicode/"><code>unicode</code></a> package and associated
|
||||
support throughout the system has been upgraded from Unicode 12.0.0 to
|
||||
<a href="https://www.unicode.org/versions/Unicode13.0.0/">Unicode 13.0.0</a>,
|
||||
which adds 5,930 new characters, including four new scripts, and 55 new emoji.
|
||||
Unicode 13.0.0 also designates plane 3 (U+30000-U+3FFFF) as the tertiary
|
||||
ideographic plane.
|
||||
<p>
|
||||
On the consumer side,
|
||||
the new <a href="/pkg/net/http/#FS"><code>http.FS</code></a>
|
||||
function converts an <code>fs.FS</code> to an
|
||||
<a href="/pkg/net/http/#Handler"><code>http.Handler</code></a>.
|
||||
Also, the <a href="/pkg/html/template/"><code>html/template</code></a>
|
||||
and <a href="/pkg/text/template/"><code>text/template</code></a>
|
||||
packages’ <a href="/pkg/html/template/#ParseFS"><code>ParseFS</code></a>
|
||||
functions and methods read templates from an <code>fs.FS</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For testing code that implements <code>fs.FS</code>,
|
||||
the new <a href="/pkg/testing/fstest/"><code>testing/fstest</code></a>
|
||||
package provides a <a href="/pkg/testing/fstest/#TestFS"><code>TestFS</code></a>
|
||||
function that checks for and reports common mistakes.
|
||||
It also provides a simple in-memory file system implementation,
|
||||
<a href="/pkg/testing/fstest/#MapFS"><code>MapFS</code></a>,
|
||||
which can be useful for testing code that accepts <code>fs.FS</code>
|
||||
implementations.
|
||||
</p>
|
||||
|
||||
<!-- okay-after-beta1
|
||||
TODO: decide if any additional changes are worth factoring out from
|
||||
"Minor changes to the library" and highlighting in "Core library"
|
||||
-->
|
||||
|
||||
<h3 id="minor_library_changes">Minor changes to the library</h3>
|
||||
|
||||
<p>
|
||||
|
|
@ -150,9 +504,244 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
in mind.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
</p>
|
||||
<dl id="crypto/dsa"><dt><a href="/pkg/crypto/dsa/">crypto/dsa</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 257939 -->
|
||||
The <a href="/pkg/crypto/dsa/"><code>crypto/dsa</code></a> package is now deprecated.
|
||||
See <a href="https://golang.org/issue/40337">issue #40337</a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- crypto/dsa -->
|
||||
|
||||
<dl id="crypto/hmac"><dt><a href="/pkg/crypto/hmac/">crypto/hmac</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 261960 -->
|
||||
<a href="/pkg/crypto/hmac/#New"><code>New</code></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>
|
||||
</dd>
|
||||
</dl><!-- crypto/hmac -->
|
||||
|
||||
<dl id="crypto/tls"><dt><a href="/pkg/crypto/tls/">crypto/tls</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 256897 -->
|
||||
I/O operations on closing or closed TLS connections can now be detected
|
||||
using the new <a href="/pkg/net/#ErrClosed"><code>net.ErrClosed</code></a>
|
||||
error. A typical use would be <code>errors.Is(err, net.ErrClosed)</code>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 266037 -->
|
||||
A default write deadline is now set in
|
||||
<a href="/pkg/crypto/tls/#Conn.Close"><code>Conn.Close</code></a>
|
||||
before sending the "close notify" alert, in order to prevent blocking
|
||||
indefinitely.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 246338 -->
|
||||
The new <a href="/pkg/crypto/tls#Conn.HandshakeContext"><code>Conn.HandshakeContext</code></a>
|
||||
method allows cancellation of an in-progress handshake. The provided
|
||||
context is accessible through the new
|
||||
<a href="/pkg/crypto/tls#ClientHelloInfo.Context"><code>ClientHelloInfo.Context</code></a>
|
||||
and <a href="/pkg/crypto/tls#CertificateRequestInfo.Context">
|
||||
<code>CertificateRequestInfo.Context</code></a> methods. Canceling the
|
||||
context after the handshake has finished has no effect.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 239748 -->
|
||||
Clients now return a handshake error if the server selects
|
||||
<a href="/pkg/crypto/tls/#ConnectionState.NegotiatedProtocol">
|
||||
an ALPN protocol</a> that was not in
|
||||
<a href="/pkg/crypto/tls/#Config.NextProtos">
|
||||
the list advertised by the client</a>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 262857 -->
|
||||
Servers will now prefer other available AEAD cipher suites (such as ChaCha20Poly1305)
|
||||
over AES-GCM cipher suites if either the client or server doesn't have AES hardware
|
||||
support, unless both <a href="/pkg/crypto/tls/#Config.PreferServerCipherSuites">
|
||||
<code>Config.PreferServerCipherSuites</code></a>
|
||||
and <a href="/pkg/crypto/tls/#Config.CipherSuites"><code>Config.CipherSuites</code></a>
|
||||
are set. The client is assumed not to have AES hardware support if it does
|
||||
not signal a preference for AES-GCM cipher suites.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 246637 -->
|
||||
<a href="/pkg/crypto/tls/#Config.Clone"><code>Config.Clone</code></a> now
|
||||
returns nil if the receiver is nil, rather than panicking.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- crypto/tls -->
|
||||
|
||||
<dl id="crypto/x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt>
|
||||
<dd>
|
||||
<p>
|
||||
The <code>GODEBUG=x509ignoreCN=0</code> flag will be removed in Go 1.17.
|
||||
It enables the legacy behavior of treating the <code>CommonName</code>
|
||||
field on X.509 certificates as a host name when no Subject Alternative
|
||||
Names are present.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 235078 -->
|
||||
<a href="/pkg/crypto/x509/#ParseCertificate"><code>ParseCertificate</code></a> and
|
||||
<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
|
||||
now enforce string encoding restrictions for the <code>DNSNames</code>,
|
||||
<code>EmailAddresses</code>, and <code>URIs</code> fields. These fields
|
||||
can only contain strings with characters within the ASCII range.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 259697 -->
|
||||
<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></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>
|
||||
|
||||
<p><!-- CL 233163 -->
|
||||
A number of additional fields have been added to the
|
||||
<a href="/pkg/crypto/x509/#CertificateRequest"><code>CertificateRequest</code></a> type.
|
||||
These fields are now parsed in <a href="/pkg/crypto/x509/#ParseCertificateRequest">
|
||||
<code>ParseCertificateRequest</code></a> and marshalled in
|
||||
<a href="/pkg/crypto/x509/#CreateCertificateRequest"><code>CreateCertificateRequest</code></a>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 257939 -->
|
||||
DSA signature verification is no longer supported. Note that DSA signature
|
||||
generation was never supported.
|
||||
See <a href="https://golang.org/issue/40337">issue #40337</a>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 257257 -->
|
||||
On Windows, <a href="/pkg/crypto/x509/#Certificate.Verify"><code>Certificate.Verify</code></a>
|
||||
will now return all certificate chains that are built by the platform
|
||||
certificate verifier, instead of just the highest ranked chain.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 262343 -->
|
||||
The new <a href="/pkg/crypto/x509/#SystemRootsError.Unwrap"><code>SystemRootsError.Unwrap</code></a>
|
||||
method allows accessing the <a href="/pkg/crypto/x509/#SystemRootsError.Err"><code>Err</code></a>
|
||||
field through the <a href="/pkg/errors"><code>errors</code></a> package functions.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- crypto/x509 -->
|
||||
|
||||
<dl id="encoding/asn1"><dt><a href="/pkg/encoding/asn1">encoding/asn1</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 255881 -->
|
||||
<a href="/pkg/encoding/asn1/#Unmarshal"><code>Unmarshal</code></a> and
|
||||
<a href="/pkg/encoding/asn1/#UnmarshalWithParams"><code>UnmarshalWithParams</code></a>
|
||||
now return an error instead of panicking when the argument is not
|
||||
a pointer or is nil. This change matches the behavior of other
|
||||
encoding packages such as <a href="/pkg/encoding/json"><code>encoding/json</code></a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<dl id="encoding/json"><dt><a href="/pkg/encoding/json/">encoding/json</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 234818 -->
|
||||
The <code>json</code> struct field tags understood by
|
||||
<a href="/pkg/encoding/json/#Marshal"><code>Marshal</code></a>,
|
||||
<a href="/pkg/encoding/json/#Unmarshal"><code>Unmarshal</code></a>,
|
||||
and related functionality now permit semicolon characters within
|
||||
a JSON object name for a Go struct field.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- encoding/json -->
|
||||
|
||||
<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="flag"><dt><a href="/pkg/flag/">flag</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 240014 -->
|
||||
The new <a href="/pkg/flag/#Func"><code>Func</code></a> function
|
||||
allows registering a flag implemented by calling a function,
|
||||
as a lighter-weight alternative to implementing the
|
||||
<a href="/pkg/flag/#Value"><code>Value</code></a> interface.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- flag -->
|
||||
|
||||
<dl id="io"><dt><a href="/pkg/io/">io</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 261577 -->
|
||||
The package now defines a
|
||||
<a href="/pkg/io/#ReadSeekCloser"><code>ReadSeekCloser</code></a> interface.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- io -->
|
||||
|
||||
<dl id="log"><dt><a href="/pkg/log/">log</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 264460 -->
|
||||
The new <a href="/pkg/log/#Default"><code>Default</code></a> function
|
||||
provides access to the default <a href="/pkg/log/#Logger"><code>Logger</code></a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- log -->
|
||||
|
||||
<dl id="log/syslog"><dt><a href="/pkg/log/syslog/">log/syslog</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 264297 -->
|
||||
The <a href="/pkg/log/syslog/#Writer"><code>Writer</code></a>
|
||||
now uses the local message format
|
||||
(omitting the host name and using a shorter time stamp)
|
||||
when logging to custom Unix domain sockets,
|
||||
matching the format already used for the default log socket.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- log/syslog -->
|
||||
|
||||
<dl id="mime/multipart"><dt><a href="/pkg/mime/multipart/">mime/multipart</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 247477 -->
|
||||
The <a href="/pkg/mime/multipart/#Reader"><code>Reader</code></a>'s
|
||||
<a href="/pkg/mime/multipart/#Reader.ReadForm"><code>ReadForm</code></a>
|
||||
method no longer rejects form data
|
||||
when passed the maximum int64 value as a limit.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- mime/multipart -->
|
||||
|
||||
<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 250357 -->
|
||||
The case of I/O on a closed network connection, or I/O on a network
|
||||
connection that is closed before any of the I/O completes, can now
|
||||
be detected using the new <a href="/pkg/net/#ErrClosed">ErrClosed</a> error.
|
||||
A typical use would be <code>errors.Is(err, net.ErrClosed)</code>.
|
||||
In earlier releases the only way to reliably detect this case was to
|
||||
match the string returned by the <code>Error</code> method
|
||||
with <code>"use of closed network connection"</code>.
|
||||
</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>
|
||||
|
||||
<p><!-- CL 238629 -->
|
||||
On Linux, host name lookups no longer use DNS before checking
|
||||
<code>/etc/hosts</code> when <code>/etc/nsswitch.conf</code>
|
||||
is missing; this is common on musl-based systems and makes
|
||||
Go programs match the behavior of C programs on those systems.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- net -->
|
||||
|
||||
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
|
||||
<dd>
|
||||
|
|
@ -171,9 +760,208 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
</p>
|
||||
|
||||
<p><!-- CL 252497 -->
|
||||
The <a href="/pkg/net/http/"><code>net/http</code></a> package now rejects HTTP range requests
|
||||
of the form <code>"Range": "bytes=--N"</code> where <code>"-N"</code> is a negative suffix length, for
|
||||
example <code>"Range": "bytes=--2"</code>. It now replies with a <code>416 "Range Not Satisfiable"</code> response.
|
||||
The <a href="/pkg/net/http/"><code>net/http</code></a> package now rejects HTTP range requests
|
||||
of the form <code>"Range": "bytes=--N"</code> where <code>"-N"</code> is a negative suffix length, for
|
||||
example <code>"Range": "bytes=--2"</code>. It now replies with a <code>416 "Range Not Satisfiable"</code> response.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 256498, golang.org/issue/36990 -->
|
||||
Cookies set with <a href="/pkg/net/http/#SameSiteDefaultMode"><code>SameSiteDefaultMode</code></a>
|
||||
now behave according to the current spec (no attribute is set) instead of
|
||||
generating a SameSite key without a value.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 246338 -->
|
||||
The <a href="/pkg/net/http/"><code>net/http</code></a> package now passes the
|
||||
<a href="/pkg/net/http/#Request.Context"><code>Request</code> context</a> to
|
||||
<a href="/pkg/crypto/tls#Conn.HandshakeContext"><code>tls.Conn.HandshakeContext</code></a>
|
||||
when performing TLS handshakes.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 250039 -->
|
||||
The <a href="/pkg/net/http/#Client">Client</a> now sends
|
||||
an explicit <code>Content-Length:</code> <code>0</code>
|
||||
header in <code>PATCH</code> requests with empty bodies,
|
||||
matching the existing behavior of <code>POST</code> and <code>PUT</code>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 249440 -->
|
||||
The <a href="/pkg/net/http/#ProxyFromEnvironment">ProxyFromEnvironment</a> function
|
||||
no longer returns the setting of the <code>HTTP_PROXY</code> environment
|
||||
variable for <code>https://</code> URLs when <code>HTTPS_PROXY</code> is unset.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- net/http -->
|
||||
|
||||
<dl id="net/http/httputil"><dt><a href="/pkg/net/http/httputil/">net/http/httputil</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 260637 -->
|
||||
The <a href="/pkg/net/http/httputil/#ReverseProxy">ReverseProxy</a>
|
||||
now flushes buffered data more aggressively when proxying
|
||||
streamed responses with unknown body lengths.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- net/http/httputil -->
|
||||
|
||||
<dl id="net/smtp"><dt><a href="/pkg/net/smtp/">net/smtp</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 247257 -->
|
||||
The <a href="/pkg/net/smtp/#Client">Client</a>'s
|
||||
<a href="/pkg/net/smtp/#Client.Mail"><code>Mail</code></a>
|
||||
method now sends the <code>SMTPUTF8</code> directive to
|
||||
servers that support it, signaling that addresses are encoded in UTF-8.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- net/smtp -->
|
||||
|
||||
<dl id="os"><dt><a href="/pkg/os/">os</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 242998 -->
|
||||
<a href="/pkg/os/#Process.Signal"><code>Process.Signal</code></a> now
|
||||
returns <a href="/pkg/os/#ErrProcessDone"><code>ErrProcessDone</code></a>
|
||||
instead of the unexported <code>errFinished</code> when the process has
|
||||
already finished.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- os -->
|
||||
|
||||
<dl id="os/signal"><dt><a href="/pkg/os/signal/">os/signal</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 219640 -->
|
||||
The new
|
||||
<a href="/pkg/os/signal/#NotifyContext"><code>NotifyContext</code></a>
|
||||
function allows creating contexts that are canceled upon arrival of
|
||||
specific signals.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- os/signal -->
|
||||
|
||||
<dl id="path"><dt><a href="/pkg/path/">path</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 264397, golang.org/issues/28614 -->
|
||||
The <code>Match</code> and <code>Glob</code> functions now
|
||||
return an error if the unmatched part of the pattern has a
|
||||
syntax error. Previously, the functions returned early on a failed
|
||||
match, and thus did not report any later syntax error in the
|
||||
pattern.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- path -->
|
||||
|
||||
<dl id="path/filepath"><dt><a href="/pkg/path/filepath/">path/filepath</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 264397, golang.org/issues/28614 -->
|
||||
The <code>Match</code> and <code>Glob</code> functions now
|
||||
return an error if the unmatched part of the pattern has a
|
||||
syntax error. Previously, the functions returned early on a failed
|
||||
match, and thus did not report any later syntax error in the
|
||||
pattern.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- path/filepath -->
|
||||
|
||||
<dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 248341, golang.org/issues/40281 -->
|
||||
<code>StructTag</code> now allows multiple space-separated keys
|
||||
in key:value pairs, as in <code>`json xml:"field1"`</code>
|
||||
(equivalent to <code>`json:"field1" xml:"field1"`</code>).
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- reflect -->
|
||||
|
||||
<dl id="runtime/debug"><dt><a href="/pkg/runtime/debug/">runtime/debug</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 249677 -->
|
||||
The <a href="/pkg/runtime#Error"><code>runtime.Error</code></a> values
|
||||
used when <code>SetPanicOnFault</code> is enabled may now have an
|
||||
<code>Addr</code> method. If that method exists, it returns the memory
|
||||
address that triggered the fault.
|
||||
</p>
|
||||
</dd>
|
||||
</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 -->
|
||||
|
||||
<dl id="syscall"><dt><a href="/pkg/syscall/">syscall</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 263271 -->
|
||||
<a href="/pkg/syscall/?GOOS=windows#NewCallback"><code>NewCallback</code></a>
|
||||
and
|
||||
<a href="/pkg/syscall/?GOOS=windows#NewCallbackCDecl"><code>NewCallbackCDecl</code></a>
|
||||
now correctly support callback functions with multiple
|
||||
sub-<code>uintptr</code>-sized arguments in a row. This may
|
||||
require changing uses of these functions to eliminate manual
|
||||
padding between small arguments.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 261917 -->
|
||||
<a href="/pkg/syscall/?GOOS=windows#SysProcAttr"><code>SysProcAttr</code></a> on Windows has a new NoInheritHandles field that disables inheriting handles when creating a new process.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 269761, golang.org/issue/42584 -->
|
||||
<a href="/pkg/syscall/?GOOS=windows#DLLError"><code>DLLError</code></a> on Windows now has an Unwrap function for unwrapping its underlying error.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 210639 -->
|
||||
On Linux,
|
||||
<a href="/pkg/syscall/#Setgid"><code>Setgid</code></a>,
|
||||
<a href="/pkg/syscall/#Setuid"><code>Setuid</code></a>,
|
||||
and related calls are now implemented.
|
||||
Previously, they returned an <code>syscall.EOPNOTSUPP</code> error.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- syscall -->
|
||||
|
||||
<dl id="text/template"><dt><a href="/pkg/text/template/">text/template</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 254257, golang.org/issue/29770 -->
|
||||
Newlines characters are now allowed inside action delimiters,
|
||||
permitting actions to span multiple lines.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- text/template -->
|
||||
|
||||
<dl id="text/template/parse"><dt><a href="/pkg/text/template/parse/">text/template/parse</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 229398, golang.org/issue/34652 -->
|
||||
A new <a href="/pkg/text/template/parse/#CommentNode"><code>CommentNode</code></a>
|
||||
was added to the parse tree. The <a href="/pkg/text/template/parse/#Mode"><code>Mode</code></a>
|
||||
field in the <code>parse.Tree</code> enables access to it.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- text/template/parse -->
|
||||
|
||||
<dl id="time/tzdata"><dt><a href="/pkg/time/tzdata/">time/tzdata</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 261877 -->
|
||||
The slim timezone data format is now used for the timezone database in
|
||||
<code>$GOROOT/lib/time/zoneinfo.zip</code> and the embedded copy in this
|
||||
package. This reduces the size of the timezone database by about 350 KB.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- time/tzdata -->
|
||||
|
||||
<dl id="unicode"><dt><a href="/pkg/unicode/">unicode</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 248765 -->
|
||||
The <a href="/pkg/unicode/"><code>unicode</code></a> package and associated
|
||||
support throughout the system has been upgraded from Unicode 12.0.0 to
|
||||
<a href="https://www.unicode.org/versions/Unicode13.0.0/">Unicode 13.0.0</a>,
|
||||
which adds 5,930 new characters, including four new scripts, and 55 new emoji.
|
||||
Unicode 13.0.0 also designates plane 3 (U+30000-U+3FFFF) as the tertiary
|
||||
ideographic plane.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- unicode -->
|
||||
|
|
|
|||
|
|
@ -1647,14 +1647,14 @@ c := signal.Incoming()
|
|||
is
|
||||
</p>
|
||||
<pre>
|
||||
c := make(chan os.Signal)
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c) // ask for all signals
|
||||
</pre>
|
||||
<p>
|
||||
but most code should list the specific signals it wants to handle instead:
|
||||
</p>
|
||||
<pre>
|
||||
c := make(chan os.Signal)
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT)
|
||||
</pre>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of Jan 14, 2020",
|
||||
"Subtitle": "Version of Oct 7, 2020",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
|
|
@ -3594,23 +3594,33 @@ replaced by its left operand alone.
|
|||
</p>
|
||||
|
||||
<pre>
|
||||
var a [1024]byte
|
||||
var s uint = 33
|
||||
var i = 1<<s // 1 has type int
|
||||
var j int32 = 1<<s // 1 has type int32; j == 0
|
||||
var k = uint64(1<<s) // 1 has type uint64; k == 1<<33
|
||||
var m int = 1.0<<s // 1.0 has type int; m == 0 if ints are 32bits in size
|
||||
var n = 1.0<<s == j // 1.0 has type int32; n == true
|
||||
var o = 1<<s == 2<<s // 1 and 2 have type int; o == true if ints are 32bits in size
|
||||
var p = 1<<s == 1<<33 // illegal if ints are 32bits in size: 1 has type int, but 1<<33 overflows int
|
||||
var u = 1.0<<s // illegal: 1.0 has type float64, cannot shift
|
||||
var u1 = 1.0<<s != 0 // illegal: 1.0 has type float64, cannot shift
|
||||
var u2 = 1<<s != 1.0 // illegal: 1 has type float64, cannot shift
|
||||
var v float32 = 1<<s // illegal: 1 has type float32, cannot shift
|
||||
var w int64 = 1.0<<33 // 1.0<<33 is a constant shift expression
|
||||
var x = a[1.0<<s] // 1.0 has type int; x == a[0] if ints are 32bits in size
|
||||
var a = make([]byte, 1.0<<s) // 1.0 has type int; len(a) == 0 if ints are 32bits in size
|
||||
</pre>
|
||||
|
||||
// The results of the following examples are given for 64-bit ints.
|
||||
var i = 1<<s // 1 has type int
|
||||
var j int32 = 1<<s // 1 has type int32; j == 0
|
||||
var k = uint64(1<<s) // 1 has type uint64; k == 1<<33
|
||||
var m int = 1.0<<s // 1.0 has type int; m == 1<<33
|
||||
var n = 1.0<<s == j // 1.0 has type int; n == true
|
||||
var o = 1<<s == 2<<s // 1 and 2 have type int; o == false
|
||||
var p = 1<<s == 1<<33 // 1 has type int; p == true
|
||||
var u = 1.0<<s // illegal: 1.0 has type float64, cannot shift
|
||||
var u1 = 1.0<<s != 0 // illegal: 1.0 has type float64, cannot shift
|
||||
var u2 = 1<<s != 1.0 // illegal: 1 has type float64, cannot shift
|
||||
var v float32 = 1<<s // illegal: 1 has type float32, cannot shift
|
||||
var w int64 = 1.0<<33 // 1.0<<33 is a constant shift expression; w == 1<<33
|
||||
var x = a[1.0<<s] // panics: 1.0 has type int, but 1<<33 overflows array bounds
|
||||
var b = make([]byte, 1.0<<s) // 1.0 has type int; len(b) == 1<<33
|
||||
|
||||
// The results of the following examples are given for 32-bit ints,
|
||||
// which means the shifts will overflow.
|
||||
var mm int = 1.0<<s // 1.0 has type int; mm == 0
|
||||
var oo = 1<<s == 2<<s // 1 and 2 have type int; oo == true
|
||||
var pp = 1<<s == 1<<33 // illegal: 1 has type int, but 1<<33 overflows int
|
||||
var xx = a[1.0<<s] // 1.0 has type int; xx == a[0]
|
||||
var bb = make([]byte, 1.0<<s) // 1.0 has type int; len(bb) == 0
|
||||
</pre>
|
||||
|
||||
<h4 id="Operator_precedence">Operator precedence</h4>
|
||||
<p>
|
||||
|
|
@ -3646,7 +3656,7 @@ For instance, <code>x / y * z</code> is the same as <code>(x / y) * z</code>.
|
|||
x <= f()
|
||||
^a >> b
|
||||
f() || g()
|
||||
x == y+1 && <-chanPtr > 0
|
||||
x == y+1 && <-chanInt > 0
|
||||
</pre>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -119,11 +119,26 @@ The Go toolchain is written in Go. To build it, you need a Go compiler installed
|
|||
The scripts that do the initial build of the tools look for a "go" command
|
||||
in <code>$PATH</code>, so as long as you have Go installed in your
|
||||
system and configured in your <code>$PATH</code>, you are ready to build Go
|
||||
from source.
|
||||
from source.
|
||||
Or if you prefer you can set <code>$GOROOT_BOOTSTRAP</code> to the
|
||||
root of a Go installation to use to build the new Go toolchain;
|
||||
<code>$GOROOT_BOOTSTRAP/bin/go</code> should be the go command to use.</p>
|
||||
|
||||
<p>
|
||||
There are four possible ways to obtain a bootstrap toolchain:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Download a recent binary release of Go.
|
||||
<li>Cross-compile a toolchain using a system with a working Go installation.
|
||||
<li>Use gccgo.
|
||||
<li>Compile a toolchain from Go 1.4, the last Go release with a compiler written in C.
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
These approaches are detailed below.
|
||||
</p>
|
||||
|
||||
<h3 id="bootstrapFromBinaryRelease">Bootstrap toolchain from binary release</h3>
|
||||
|
||||
<p>
|
||||
|
|
@ -132,30 +147,6 @@ To use a binary release as a bootstrap toolchain, see
|
|||
packaged Go distribution.
|
||||
</p>
|
||||
|
||||
<h3 id="bootstrapFromSource">Bootstrap toolchain from source</h3>
|
||||
|
||||
<p>
|
||||
To build a bootstrap toolchain from source, use
|
||||
either the git branch <code>release-branch.go1.4</code> or
|
||||
<a href="https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz">go1.4-bootstrap-20171003.tar.gz</a>,
|
||||
which contains the Go 1.4 source code plus accumulated fixes
|
||||
to keep the tools running on newer operating systems.
|
||||
(Go 1.4 was the last distribution in which the toolchain was written in C.)
|
||||
After unpacking the Go 1.4 source, <code>cd</code> to
|
||||
the <code>src</code> subdirectory, set <code>CGO_ENABLED=0</code> in
|
||||
the environment, and run <code>make.bash</code> (or,
|
||||
on Windows, <code>make.bat</code>).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Once the Go 1.4 source has been unpacked into your GOROOT_BOOTSTRAP directory,
|
||||
you must keep this git clone instance checked out to branch
|
||||
<code>release-branch.go1.4</code>. Specifically, do not attempt to reuse
|
||||
this git clone in the later step named "Fetch the repository." The go1.4
|
||||
bootstrap toolchain <b>must be able</b> to properly traverse the go1.4 sources
|
||||
that it assumes are present under this repository root.
|
||||
</p>
|
||||
|
||||
<h3 id="bootstrapFromCrosscompiledSource">Bootstrap toolchain from cross-compiled source</h3>
|
||||
|
||||
<p>
|
||||
|
|
@ -194,6 +185,36 @@ $ sudo update-alternatives --set go /usr/bin/go-5
|
|||
$ GOROOT_BOOTSTRAP=/usr ./make.bash
|
||||
</pre>
|
||||
|
||||
<h3 id="bootstrapFromSource">Bootstrap toolchain from C source code</h3>
|
||||
|
||||
<p>
|
||||
To build a bootstrap toolchain from C source code, use
|
||||
either the git branch <code>release-branch.go1.4</code> or
|
||||
<a href="https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz">go1.4-bootstrap-20171003.tar.gz</a>,
|
||||
which contains the Go 1.4 source code plus accumulated fixes
|
||||
to keep the tools running on newer operating systems.
|
||||
(Go 1.4 was the last distribution in which the toolchain was written in C.)
|
||||
After unpacking the Go 1.4 source, <code>cd</code> to
|
||||
the <code>src</code> subdirectory, set <code>CGO_ENABLED=0</code> in
|
||||
the environment, and run <code>make.bash</code> (or,
|
||||
on Windows, <code>make.bat</code>).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Once the Go 1.4 source has been unpacked into your GOROOT_BOOTSTRAP directory,
|
||||
you must keep this git clone instance checked out to branch
|
||||
<code>release-branch.go1.4</code>. Specifically, do not attempt to reuse
|
||||
this git clone in the later step named "Fetch the repository." The go1.4
|
||||
bootstrap toolchain <b>must be able</b> to properly traverse the go1.4 sources
|
||||
that it assumes are present under this repository root.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Note that Go 1.4 does not run on all systems that later versions of Go do.
|
||||
In particular, Go 1.4 does not support current versions of macOS.
|
||||
On such systems, the bootstrap toolchain must be obtained using one of the other methods.
|
||||
</p>
|
||||
|
||||
<h2 id="git">Install Git, if needed</h2>
|
||||
|
||||
<p>
|
||||
|
|
@ -507,8 +528,8 @@ These default to the values of <code>$GOHOSTOS</code> and
|
|||
|
||||
<p>
|
||||
Choices for <code>$GOOS</code> are
|
||||
<code>android</code>, <code>darwin</code> (macOS/iOS),
|
||||
<code>dragonfly</code>, <code>freebsd</code>, <code>illumos</code>, <code>js</code>,
|
||||
<code>android</code>, <code>darwin</code>, <code>dragonfly</code>,
|
||||
<code>freebsd</code>, <code>illumos</code>, <code>ios</code>, <code>js</code>,
|
||||
<code>linux</code>, <code>netbsd</code>, <code>openbsd</code>,
|
||||
<code>plan9</code>, <code>solaris</code> and <code>windows</code>.
|
||||
</p>
|
||||
|
|
@ -567,6 +588,9 @@ The valid combinations of <code>$GOOS</code> and <code>$GOARCH</code> are:
|
|||
<td></td><td><code>illumos</code></td> <td><code>amd64</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td><td><code>ios</code></td> <td><code>arm64</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td><td><code>js</code></td> <td><code>wasm</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
@ -663,16 +687,13 @@ For example, you should not set <code>$GOHOSTARCH</code> to
|
|||
<code>arm</code> on an x86 system.
|
||||
</p>
|
||||
|
||||
<li><code>$GO386</code> (for <code>386</code> only, default is auto-detected
|
||||
if built on either <code>386</code> or <code>amd64</code>, <code>387</code> otherwise)
|
||||
<li><code>$GO386</code> (for <code>386</code> only, defaults to <code>sse2</code>)
|
||||
<p>
|
||||
This controls the code generated by gc to use either the 387 floating-point unit
|
||||
(set to <code>387</code>) or SSE2 instructions (set to <code>sse2</code>) for
|
||||
floating point computations.
|
||||
This variable controls how gc implements floating point computations.
|
||||
</p>
|
||||
<ul>
|
||||
<li><code>GO386=387</code>: use x87 for floating point operations; should support all x86 chips (Pentium MMX or later).</li>
|
||||
<li><code>GO386=sse2</code>: use SSE2 for floating point operations; has better performance than 387, but only available on Pentium 4/Opteron/Athlon 64 or later.</li>
|
||||
<li><code>GO386=softfloat</code>: use software floating point operations; should support all x86 chips (Pentium MMX or later).</li>
|
||||
<li><code>GO386=sse2</code>: use SSE2 for floating point operations; has better performance but only available on Pentium 4/Opteron/Athlon 64 or later.</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
# Consult https://www.iana.org/time-zones for the latest versions.
|
||||
|
||||
# Versions to use.
|
||||
CODE=2020a
|
||||
DATA=2020a
|
||||
CODE=2020d
|
||||
DATA=2020d
|
||||
|
||||
set -e
|
||||
rm -rf work
|
||||
|
|
|
|||
Binary file not shown.
216
misc/cgo/errors/badsym_test.go
Normal file
216
misc/cgo/errors/badsym_test.go
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package errorstest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// A manually modified object file could pass unexpected characters
|
||||
// into the files generated by cgo.
|
||||
|
||||
const magicInput = "abcdefghijklmnopqrstuvwxyz0123"
|
||||
const magicReplace = "\n//go:cgo_ldflag \"-badflag\"\n//"
|
||||
|
||||
const cSymbol = "BadSymbol" + magicInput + "Name"
|
||||
const cDefSource = "int " + cSymbol + " = 1;"
|
||||
const cRefSource = "extern int " + cSymbol + "; int F() { return " + cSymbol + "; }"
|
||||
|
||||
// goSource is the source code for the trivial Go file we use.
|
||||
// We will replace TMPDIR with the temporary directory name.
|
||||
const goSource = `
|
||||
package main
|
||||
|
||||
// #cgo LDFLAGS: TMPDIR/cbad.o TMPDIR/cbad.so
|
||||
// extern int F();
|
||||
import "C"
|
||||
|
||||
func main() {
|
||||
println(C.F())
|
||||
}
|
||||
`
|
||||
|
||||
func TestBadSymbol(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
|
||||
mkdir := func(base string) string {
|
||||
ret := filepath.Join(dir, base)
|
||||
if err := os.Mkdir(ret, 0755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
cdir := mkdir("c")
|
||||
godir := mkdir("go")
|
||||
|
||||
makeFile := func(mdir, base, source string) string {
|
||||
ret := filepath.Join(mdir, base)
|
||||
if err := ioutil.WriteFile(ret, []byte(source), 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
cDefFile := makeFile(cdir, "cdef.c", cDefSource)
|
||||
cRefFile := makeFile(cdir, "cref.c", cRefSource)
|
||||
|
||||
ccCmd := cCompilerCmd(t)
|
||||
|
||||
cCompile := func(arg, base, src string) string {
|
||||
out := filepath.Join(cdir, base)
|
||||
run := append(ccCmd, arg, "-o", out, src)
|
||||
output, err := exec.Command(run[0], run[1:]...).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Log(run)
|
||||
t.Logf("%s", output)
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.Remove(src); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Build a shared library that defines a symbol whose name
|
||||
// contains magicInput.
|
||||
|
||||
cShared := cCompile("-shared", "c.so", cDefFile)
|
||||
|
||||
// Build an object file that refers to the symbol whose name
|
||||
// contains magicInput.
|
||||
|
||||
cObj := cCompile("-c", "c.o", cRefFile)
|
||||
|
||||
// Rewrite the shared library and the object file, replacing
|
||||
// magicInput with magicReplace. This will have the effect of
|
||||
// introducing a symbol whose name looks like a cgo command.
|
||||
// The cgo tool will use that name when it generates the
|
||||
// _cgo_import.go file, thus smuggling a magic //go:cgo_ldflag
|
||||
// pragma into a Go file. We used to not check the pragmas in
|
||||
// _cgo_import.go.
|
||||
|
||||
rewrite := func(from, to string) {
|
||||
obj, err := ioutil.ReadFile(from)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if bytes.Count(obj, []byte(magicInput)) == 0 {
|
||||
t.Fatalf("%s: did not find magic string", from)
|
||||
}
|
||||
|
||||
if len(magicInput) != len(magicReplace) {
|
||||
t.Fatalf("internal test error: different magic lengths: %d != %d", len(magicInput), len(magicReplace))
|
||||
}
|
||||
|
||||
obj = bytes.ReplaceAll(obj, []byte(magicInput), []byte(magicReplace))
|
||||
|
||||
if err := ioutil.WriteFile(to, obj, 0644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
cBadShared := filepath.Join(godir, "cbad.so")
|
||||
rewrite(cShared, cBadShared)
|
||||
|
||||
cBadObj := filepath.Join(godir, "cbad.o")
|
||||
rewrite(cObj, cBadObj)
|
||||
|
||||
goSourceBadObject := strings.ReplaceAll(goSource, "TMPDIR", godir)
|
||||
makeFile(godir, "go.go", goSourceBadObject)
|
||||
|
||||
makeFile(godir, "go.mod", "module badsym")
|
||||
|
||||
// Try to build our little package.
|
||||
cmd := exec.Command("go", "build", "-ldflags=-v")
|
||||
cmd.Dir = godir
|
||||
output, err := cmd.CombinedOutput()
|
||||
|
||||
// The build should fail, but we want it to fail because we
|
||||
// detected the error, not because we passed a bad flag to the
|
||||
// C linker.
|
||||
|
||||
if err == nil {
|
||||
t.Errorf("go build succeeded unexpectedly")
|
||||
}
|
||||
|
||||
t.Logf("%s", output)
|
||||
|
||||
for _, line := range bytes.Split(output, []byte("\n")) {
|
||||
if bytes.Contains(line, []byte("dynamic symbol")) && bytes.Contains(line, []byte("contains unsupported character")) {
|
||||
// This is the error from cgo.
|
||||
continue
|
||||
}
|
||||
|
||||
// We passed -ldflags=-v to see the external linker invocation,
|
||||
// which should not include -badflag.
|
||||
if bytes.Contains(line, []byte("-badflag")) {
|
||||
t.Error("output should not mention -badflag")
|
||||
}
|
||||
|
||||
// Also check for compiler errors, just in case.
|
||||
// GCC says "unrecognized command line option".
|
||||
// clang says "unknown argument".
|
||||
if bytes.Contains(line, []byte("unrecognized")) || bytes.Contains(output, []byte("unknown")) {
|
||||
t.Error("problem should have been caught before invoking C linker")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func cCompilerCmd(t *testing.T) []string {
|
||||
cc := []string{goEnv(t, "CC")}
|
||||
|
||||
out := goEnv(t, "GOGCCFLAGS")
|
||||
quote := '\000'
|
||||
start := 0
|
||||
lastSpace := true
|
||||
backslash := false
|
||||
s := string(out)
|
||||
for i, c := range s {
|
||||
if quote == '\000' && unicode.IsSpace(c) {
|
||||
if !lastSpace {
|
||||
cc = append(cc, s[start:i])
|
||||
lastSpace = true
|
||||
}
|
||||
} else {
|
||||
if lastSpace {
|
||||
start = i
|
||||
lastSpace = false
|
||||
}
|
||||
if quote == '\000' && !backslash && (c == '"' || c == '\'') {
|
||||
quote = c
|
||||
backslash = false
|
||||
} else if !backslash && quote == c {
|
||||
quote = '\000'
|
||||
} else if (quote == '\000' || quote == '"') && !backslash && c == '\\' {
|
||||
backslash = true
|
||||
} else {
|
||||
backslash = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if !lastSpace {
|
||||
cc = append(cc, s[start:])
|
||||
}
|
||||
return cc
|
||||
}
|
||||
|
||||
func goEnv(t *testing.T, key string) string {
|
||||
out, err := exec.Command("go", "env", key).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Logf("go env %s\n", key)
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
return strings.TrimSpace(string(out))
|
||||
}
|
||||
|
|
@ -181,7 +181,7 @@ func testCallbackCallers(t *testing.T) {
|
|||
name := []string{
|
||||
"runtime.cgocallbackg1",
|
||||
"runtime.cgocallbackg",
|
||||
"runtime.cgocallback_gofunc",
|
||||
"runtime.cgocallback",
|
||||
"runtime.asmcgocall",
|
||||
"runtime.cgocall",
|
||||
"test._Cfunc_callback",
|
||||
|
|
|
|||
|
|
@ -15,5 +15,6 @@ func TestSetgid(t *testing.T) {
|
|||
}
|
||||
testSetgid(t)
|
||||
}
|
||||
func Test1435(t *testing.T) { test1435(t) }
|
||||
func Test6997(t *testing.T) { test6997(t) }
|
||||
func TestBuildID(t *testing.T) { testBuildID(t) }
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ func TestCheckConst(t *testing.T) { testCheckConst(t) }
|
|||
func TestConst(t *testing.T) { testConst(t) }
|
||||
func TestCthread(t *testing.T) { testCthread(t) }
|
||||
func TestEnum(t *testing.T) { testEnum(t) }
|
||||
func TestNamedEnum(t *testing.T) { testNamedEnum(t) }
|
||||
func TestCastToEnum(t *testing.T) { testCastToEnum(t) }
|
||||
func TestErrno(t *testing.T) { testErrno(t) }
|
||||
func TestFpVar(t *testing.T) { testFpVar(t) }
|
||||
func TestHelpers(t *testing.T) { testHelpers(t) }
|
||||
|
|
|
|||
184
misc/cgo/test/issue1435.go
Normal file
184
misc/cgo/test/issue1435.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux,cgo
|
||||
|
||||
package cgotest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// #include <stdio.h>
|
||||
// #include <stdlib.h>
|
||||
// #include <pthread.h>
|
||||
// #include <unistd.h>
|
||||
// #include <sys/types.h>
|
||||
//
|
||||
// pthread_t *t = NULL;
|
||||
// pthread_mutex_t mu;
|
||||
// int nts = 0;
|
||||
// int all_done = 0;
|
||||
//
|
||||
// static void *aFn(void *vargp) {
|
||||
// int done = 0;
|
||||
// while (!done) {
|
||||
// usleep(100);
|
||||
// pthread_mutex_lock(&mu);
|
||||
// done = all_done;
|
||||
// pthread_mutex_unlock(&mu);
|
||||
// }
|
||||
// return NULL;
|
||||
// }
|
||||
//
|
||||
// void trial(int argc) {
|
||||
// int i;
|
||||
// nts = argc;
|
||||
// t = calloc(nts, sizeof(pthread_t));
|
||||
// pthread_mutex_init(&mu, NULL);
|
||||
// for (i = 0; i < nts; i++) {
|
||||
// pthread_create(&t[i], NULL, aFn, NULL);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// void cleanup(void) {
|
||||
// int i;
|
||||
// pthread_mutex_lock(&mu);
|
||||
// all_done = 1;
|
||||
// pthread_mutex_unlock(&mu);
|
||||
// for (i = 0; i < nts; i++) {
|
||||
// pthread_join(t[i], NULL);
|
||||
// }
|
||||
// pthread_mutex_destroy(&mu);
|
||||
// free(t);
|
||||
// }
|
||||
import "C"
|
||||
|
||||
// compareStatus is used to confirm the contents of the thread
|
||||
// specific status files match expectations.
|
||||
func compareStatus(filter, expect string) error {
|
||||
expected := filter + expect
|
||||
pid := syscall.Getpid()
|
||||
fs, err := ioutil.ReadDir(fmt.Sprintf("/proc/%d/task", pid))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to find %d tasks: %v", pid, err)
|
||||
}
|
||||
expectedProc := fmt.Sprintf("Pid:\t%d", pid)
|
||||
foundAThread := false
|
||||
for _, f := range fs {
|
||||
tf := fmt.Sprintf("/proc/%s/status", f.Name())
|
||||
d, err := ioutil.ReadFile(tf)
|
||||
if err != nil {
|
||||
// There are a surprising number of ways this
|
||||
// can error out on linux. We've seen all of
|
||||
// the following, so treat any error here as
|
||||
// equivalent to the "process is gone":
|
||||
// os.IsNotExist(err),
|
||||
// "... : no such process",
|
||||
// "... : bad file descriptor.
|
||||
continue
|
||||
}
|
||||
lines := strings.Split(string(d), "\n")
|
||||
for _, line := range lines {
|
||||
// Different kernel vintages pad differently.
|
||||
line = strings.TrimSpace(line)
|
||||
if strings.HasPrefix(line, "Pid:\t") {
|
||||
// On loaded systems, it is possible
|
||||
// for a TID to be reused really
|
||||
// quickly. As such, we need to
|
||||
// validate that the thread status
|
||||
// info we just read is a task of the
|
||||
// same process PID as we are
|
||||
// currently running, and not a
|
||||
// recently terminated thread
|
||||
// resurfaced in a different process.
|
||||
if line != expectedProc {
|
||||
break
|
||||
}
|
||||
// Fall through in the unlikely case
|
||||
// that filter at some point is
|
||||
// "Pid:\t".
|
||||
}
|
||||
if strings.HasPrefix(line, filter) {
|
||||
if line != expected {
|
||||
return fmt.Errorf("%q got:%q want:%q (bad) [pid=%d file:'%s' %v]\n", tf, line, expected, pid, string(d), expectedProc)
|
||||
}
|
||||
foundAThread = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !foundAThread {
|
||||
return fmt.Errorf("found no thread /proc/<TID>/status files for process %q", expectedProc)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// test1435 test 9 glibc implemented setuid/gid syscall functions are
|
||||
// mapped. This test is a slightly more expansive test than that of
|
||||
// src/syscall/syscall_linux_test.go:TestSetuidEtc() insofar as it
|
||||
// launches concurrent threads from C code via CGo and validates that
|
||||
// they are subject to the system calls being tested. For the actual
|
||||
// Go functionality being tested here, the syscall_linux_test version
|
||||
// is considered authoritative, but non-trivial improvements to that
|
||||
// should be mirrored here.
|
||||
func test1435(t *testing.T) {
|
||||
if syscall.Getuid() != 0 {
|
||||
t.Skip("skipping root only test")
|
||||
}
|
||||
|
||||
// Launch some threads in C.
|
||||
const cts = 5
|
||||
C.trial(cts)
|
||||
defer C.cleanup()
|
||||
|
||||
vs := []struct {
|
||||
call string
|
||||
fn func() error
|
||||
filter, expect string
|
||||
}{
|
||||
{call: "Setegid(1)", fn: func() error { return syscall.Setegid(1) }, filter: "Gid:", expect: "\t0\t1\t0\t1"},
|
||||
{call: "Setegid(0)", fn: func() error { return syscall.Setegid(0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"},
|
||||
|
||||
{call: "Seteuid(1)", fn: func() error { return syscall.Seteuid(1) }, filter: "Uid:", expect: "\t0\t1\t0\t1"},
|
||||
{call: "Setuid(0)", fn: func() error { return syscall.Setuid(0) }, filter: "Uid:", expect: "\t0\t0\t0\t0"},
|
||||
|
||||
{call: "Setgid(1)", fn: func() error { return syscall.Setgid(1) }, filter: "Gid:", expect: "\t1\t1\t1\t1"},
|
||||
{call: "Setgid(0)", fn: func() error { return syscall.Setgid(0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"},
|
||||
|
||||
{call: "Setgroups([]int{0,1,2,3})", fn: func() error { return syscall.Setgroups([]int{0, 1, 2, 3}) }, filter: "Groups:", expect: "\t0 1 2 3"},
|
||||
{call: "Setgroups(nil)", fn: func() error { return syscall.Setgroups(nil) }, filter: "Groups:", expect: ""},
|
||||
{call: "Setgroups([]int{0})", fn: func() error { return syscall.Setgroups([]int{0}) }, filter: "Groups:", expect: "\t0"},
|
||||
|
||||
{call: "Setregid(101,0)", fn: func() error { return syscall.Setregid(101, 0) }, filter: "Gid:", expect: "\t101\t0\t0\t0"},
|
||||
{call: "Setregid(0,102)", fn: func() error { return syscall.Setregid(0, 102) }, filter: "Gid:", expect: "\t0\t102\t102\t102"},
|
||||
{call: "Setregid(0,0)", fn: func() error { return syscall.Setregid(0, 0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"},
|
||||
|
||||
{call: "Setreuid(1,0)", fn: func() error { return syscall.Setreuid(1, 0) }, filter: "Uid:", expect: "\t1\t0\t0\t0"},
|
||||
{call: "Setreuid(0,2)", fn: func() error { return syscall.Setreuid(0, 2) }, filter: "Uid:", expect: "\t0\t2\t2\t2"},
|
||||
{call: "Setreuid(0,0)", fn: func() error { return syscall.Setreuid(0, 0) }, filter: "Uid:", expect: "\t0\t0\t0\t0"},
|
||||
|
||||
{call: "Setresgid(101,0,102)", fn: func() error { return syscall.Setresgid(101, 0, 102) }, filter: "Gid:", expect: "\t101\t0\t102\t0"},
|
||||
{call: "Setresgid(0,102,101)", fn: func() error { return syscall.Setresgid(0, 102, 101) }, filter: "Gid:", expect: "\t0\t102\t101\t102"},
|
||||
{call: "Setresgid(0,0,0)", fn: func() error { return syscall.Setresgid(0, 0, 0) }, filter: "Gid:", expect: "\t0\t0\t0\t0"},
|
||||
|
||||
{call: "Setresuid(1,0,2)", fn: func() error { return syscall.Setresuid(1, 0, 2) }, filter: "Uid:", expect: "\t1\t0\t2\t0"},
|
||||
{call: "Setresuid(0,2,1)", fn: func() error { return syscall.Setresuid(0, 2, 1) }, filter: "Uid:", expect: "\t0\t2\t1\t2"},
|
||||
{call: "Setresuid(0,0,0)", fn: func() error { return syscall.Setresuid(0, 0, 0) }, filter: "Uid:", expect: "\t0\t0\t0\t0"},
|
||||
}
|
||||
|
||||
for i, v := range vs {
|
||||
if err := v.fn(); err != nil {
|
||||
t.Errorf("[%d] %q failed: %v", i, v.call, err)
|
||||
continue
|
||||
}
|
||||
if err := compareStatus(v.filter, v.expect); err != nil {
|
||||
t.Errorf("[%d] %q comparison: %v", i, v.call, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,7 @@ func test18146(t *testing.T) {
|
|||
t.Skip("skipping in short mode")
|
||||
}
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
||||
t.Skipf("skipping flaky test on %s; see golang.org/issue/18202", runtime.GOOS)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !windows,!static
|
||||
// +build !darwin !internal_pie,!arm64
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dlfcn.h>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,11 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +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
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build windows static
|
||||
// +build windows static darwin,internal_pie darwin,arm64
|
||||
|
||||
package cgotest
|
||||
|
||||
|
|
|
|||
15
misc/cgo/test/issue42495.go
Normal file
15
misc/cgo/test/issue42495.go
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cgotest
|
||||
|
||||
// typedef struct { } T42495A;
|
||||
// typedef struct { int x[0]; } T42495B;
|
||||
import "C"
|
||||
|
||||
//export Issue42495A
|
||||
func Issue42495A(C.T42495A) {}
|
||||
|
||||
//export Issue42495B
|
||||
func Issue42495B(C.T42495B) {}
|
||||
|
|
@ -30,7 +30,7 @@ func TestCrossPackageTests(t *testing.T) {
|
|||
switch runtime.GOOS {
|
||||
case "android":
|
||||
t.Skip("Can't exec cmd/go subprocess on Android.")
|
||||
case "darwin":
|
||||
case "darwin", "ios":
|
||||
switch runtime.GOARCH {
|
||||
case "arm64":
|
||||
t.Skip("Can't exec cmd/go subprocess on iOS.")
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ import (
|
|||
|
||||
func testSigaltstack(t *testing.T) {
|
||||
switch {
|
||||
case runtime.GOOS == "solaris", runtime.GOOS == "illumos", runtime.GOOS == "darwin" && runtime.GOARCH == "arm64":
|
||||
case runtime.GOOS == "solaris", runtime.GOOS == "illumos", runtime.GOOS == "ios" && runtime.GOARCH == "arm64":
|
||||
t.Skipf("switching signal stack not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1000,6 +1000,32 @@ func testEnum(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func testNamedEnum(t *testing.T) {
|
||||
e := new(C.enum_E)
|
||||
|
||||
*e = C.Enum1
|
||||
if *e != 1 {
|
||||
t.Error("bad enum", C.Enum1)
|
||||
}
|
||||
|
||||
*e = C.Enum2
|
||||
if *e != 2 {
|
||||
t.Error("bad enum", C.Enum2)
|
||||
}
|
||||
}
|
||||
|
||||
func testCastToEnum(t *testing.T) {
|
||||
e := C.enum_E(C.Enum1)
|
||||
if e != 1 {
|
||||
t.Error("bad enum", C.Enum1)
|
||||
}
|
||||
|
||||
e = C.enum_E(C.Enum2)
|
||||
if e != 2 {
|
||||
t.Error("bad enum", C.Enum2)
|
||||
}
|
||||
}
|
||||
|
||||
func testAtol(t *testing.T) {
|
||||
l := Atol("123")
|
||||
if l != 123 {
|
||||
|
|
@ -1776,7 +1802,7 @@ func test14838(t *testing.T) {
|
|||
var sink C.int
|
||||
|
||||
func test17065(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
||||
t.Skip("broken on darwin; issue 17065")
|
||||
}
|
||||
for i := range C.ii {
|
||||
|
|
|
|||
20
misc/cgo/test/testdata/issue41761.go
vendored
Normal file
20
misc/cgo/test/testdata/issue41761.go
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cgotest
|
||||
|
||||
/*
|
||||
typedef struct S S;
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"cgotest/issue41761a"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func test41761(t *testing.T) {
|
||||
var x issue41761a.T
|
||||
_ = (*C.struct_S)(x.X)
|
||||
}
|
||||
14
misc/cgo/test/testdata/issue41761a/a.go
vendored
Normal file
14
misc/cgo/test/testdata/issue41761a/a.go
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package issue41761a
|
||||
|
||||
/*
|
||||
typedef struct S S;
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type T struct {
|
||||
X *C.S
|
||||
}
|
||||
31
misc/cgo/test/testdata/issue9400/asm_riscv64.s
vendored
Normal file
31
misc/cgo/test/testdata/issue9400/asm_riscv64.s
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// 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.
|
||||
|
||||
// +build riscv64
|
||||
// +build !gccgo
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
TEXT ·RewindAndSetgid(SB),NOSPLIT|NOFRAME,$0-0
|
||||
// Rewind stack pointer so anything that happens on the stack
|
||||
// will clobber the test pattern created by the caller
|
||||
ADD $(1024*8), X2
|
||||
|
||||
// Ask signaller to setgid
|
||||
MOV $1, X5
|
||||
FENCE
|
||||
MOVW X5, ·Baton(SB)
|
||||
FENCE
|
||||
|
||||
// Wait for setgid completion
|
||||
loop:
|
||||
FENCE
|
||||
MOVW ·Baton(SB), X5
|
||||
OR X6, X6, X6 // hint that we're in a spin loop
|
||||
BNE ZERO, X5, loop
|
||||
FENCE
|
||||
|
||||
// Restore stack
|
||||
ADD $(-1024*8), X2
|
||||
RET
|
||||
|
|
@ -164,7 +164,7 @@ func Add(x int) {
|
|||
}
|
||||
|
||||
func testCthread(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
|
||||
if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && runtime.GOARCH == "arm64" {
|
||||
t.Skip("the iOS exec wrapper is unable to properly handle the panic from Add")
|
||||
}
|
||||
sum.i = 0
|
||||
|
|
|
|||
|
|
@ -118,9 +118,9 @@ func testMain(m *testing.M) int {
|
|||
cc = append(cc, s[start:])
|
||||
}
|
||||
|
||||
if GOOS == "darwin" {
|
||||
if GOOS == "darwin" || GOOS == "ios" {
|
||||
// For Darwin/ARM.
|
||||
// TODO(crawshaw): can we do better?
|
||||
// TODO: do we still need this?
|
||||
cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...)
|
||||
}
|
||||
if GOOS == "aix" {
|
||||
|
|
@ -133,7 +133,7 @@ func testMain(m *testing.M) int {
|
|||
libbase = "gccgo_" + libgodir + "_fPIC"
|
||||
} else {
|
||||
switch GOOS {
|
||||
case "darwin":
|
||||
case "darwin", "ios":
|
||||
if GOARCH == "arm64" {
|
||||
libbase += "_shared"
|
||||
}
|
||||
|
|
@ -303,7 +303,7 @@ func TestInstall(t *testing.T) {
|
|||
|
||||
func TestEarlySignalHandler(t *testing.T) {
|
||||
switch GOOS {
|
||||
case "darwin":
|
||||
case "darwin", "ios":
|
||||
switch GOARCH {
|
||||
case "arm64":
|
||||
t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
|
||||
|
|
@ -384,7 +384,7 @@ func TestSignalForwarding(t *testing.T) {
|
|||
expectSignal(t, err, syscall.SIGSEGV)
|
||||
|
||||
// SIGPIPE is never forwarded on darwin. See golang.org/issue/33384.
|
||||
if runtime.GOOS != "darwin" {
|
||||
if runtime.GOOS != "darwin" && runtime.GOOS != "ios" {
|
||||
// Test SIGPIPE forwarding
|
||||
cmd = exec.Command(bin[0], append(bin[1:], "3")...)
|
||||
|
||||
|
|
@ -485,7 +485,7 @@ func TestSignalForwardingExternal(t *testing.T) {
|
|||
// doesn't work on this platform.
|
||||
func checkSignalForwardingTest(t *testing.T) {
|
||||
switch GOOS {
|
||||
case "darwin":
|
||||
case "darwin", "ios":
|
||||
switch GOARCH {
|
||||
case "arm64":
|
||||
t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH)
|
||||
|
|
@ -603,7 +603,7 @@ func TestExtar(t *testing.T) {
|
|||
if runtime.Compiler == "gccgo" {
|
||||
t.Skip("skipping -extar test when using gccgo")
|
||||
}
|
||||
if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
|
||||
if runtime.GOOS == "ios" {
|
||||
t.Skip("shell scripts are not executable on iOS hosts")
|
||||
}
|
||||
|
||||
|
|
@ -645,7 +645,7 @@ func TestExtar(t *testing.T) {
|
|||
|
||||
func TestPIE(t *testing.T) {
|
||||
switch GOOS {
|
||||
case "windows", "darwin", "plan9":
|
||||
case "windows", "darwin", "ios", "plan9":
|
||||
t.Skipf("skipping PIE test on %s", GOOS)
|
||||
}
|
||||
|
||||
|
|
@ -738,7 +738,7 @@ func TestSIGPROF(t *testing.T) {
|
|||
switch GOOS {
|
||||
case "windows", "plan9":
|
||||
t.Skipf("skipping SIGPROF test on %s", GOOS)
|
||||
case "darwin":
|
||||
case "darwin", "ios":
|
||||
t.Skipf("skipping SIGPROF test on %s; see https://golang.org/issue/19320", GOOS)
|
||||
}
|
||||
|
||||
|
|
@ -841,7 +841,7 @@ func TestCompileWithoutShared(t *testing.T) {
|
|||
expectSignal(t, err, syscall.SIGSEGV)
|
||||
|
||||
// SIGPIPE is never forwarded on darwin. See golang.org/issue/33384.
|
||||
if runtime.GOOS != "darwin" {
|
||||
if runtime.GOOS != "darwin" && runtime.GOOS != "ios" {
|
||||
binArgs := append(cmdToRun(exe), "3")
|
||||
t.Log(binArgs)
|
||||
out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ package cshared_test
|
|||
import (
|
||||
"bytes"
|
||||
"debug/elf"
|
||||
"debug/pe"
|
||||
"encoding/binary"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
|
|
@ -98,7 +100,7 @@ func testMain(m *testing.M) int {
|
|||
}
|
||||
|
||||
switch GOOS {
|
||||
case "darwin":
|
||||
case "darwin", "ios":
|
||||
// For Darwin/ARM.
|
||||
// TODO(crawshaw): can we do better?
|
||||
cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...)
|
||||
|
|
@ -107,7 +109,7 @@ func testMain(m *testing.M) int {
|
|||
}
|
||||
libgodir := GOOS + "_" + GOARCH
|
||||
switch GOOS {
|
||||
case "darwin":
|
||||
case "darwin", "ios":
|
||||
if GOARCH == "arm64" {
|
||||
libgodir += "_shared"
|
||||
}
|
||||
|
|
@ -355,6 +357,101 @@ func TestExportedSymbols(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func checkNumberOfExportedFunctionsWindows(t *testing.T, exportAllSymbols bool) {
|
||||
const prog = `
|
||||
package main
|
||||
|
||||
import "C"
|
||||
|
||||
//export GoFunc
|
||||
func GoFunc() {
|
||||
println(42)
|
||||
}
|
||||
|
||||
//export GoFunc2
|
||||
func GoFunc2() {
|
||||
println(24)
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
`
|
||||
|
||||
tmpdir := t.TempDir()
|
||||
|
||||
srcfile := filepath.Join(tmpdir, "test.go")
|
||||
objfile := filepath.Join(tmpdir, "test.dll")
|
||||
if err := ioutil.WriteFile(srcfile, []byte(prog), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
argv := []string{"build", "-buildmode=c-shared"}
|
||||
if exportAllSymbols {
|
||||
argv = append(argv, "-ldflags", "-extldflags=-Wl,--export-all-symbols")
|
||||
}
|
||||
argv = append(argv, "-o", objfile, srcfile)
|
||||
out, err := exec.Command("go", argv...).CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("build failure: %s\n%s\n", err, string(out))
|
||||
}
|
||||
|
||||
f, err := pe.Open(objfile)
|
||||
if err != nil {
|
||||
t.Fatalf("pe.Open failed: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
section := f.Section(".edata")
|
||||
if section == nil {
|
||||
t.Fatalf(".edata section is not present")
|
||||
}
|
||||
|
||||
// TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
|
||||
type IMAGE_EXPORT_DIRECTORY struct {
|
||||
_ [2]uint32
|
||||
_ [2]uint16
|
||||
_ [2]uint32
|
||||
NumberOfFunctions uint32
|
||||
NumberOfNames uint32
|
||||
_ [3]uint32
|
||||
}
|
||||
var e IMAGE_EXPORT_DIRECTORY
|
||||
if err := binary.Read(section.Open(), binary.LittleEndian, &e); err != nil {
|
||||
t.Fatalf("binary.Read failed: %v", err)
|
||||
}
|
||||
|
||||
// Only the two exported functions and _cgo_dummy_export should be exported
|
||||
expectedNumber := uint32(3)
|
||||
|
||||
if exportAllSymbols {
|
||||
if e.NumberOfFunctions <= expectedNumber {
|
||||
t.Fatalf("missing exported functions: %v", e.NumberOfFunctions)
|
||||
}
|
||||
if e.NumberOfNames <= expectedNumber {
|
||||
t.Fatalf("missing exported names: %v", e.NumberOfNames)
|
||||
}
|
||||
} else {
|
||||
if e.NumberOfFunctions != expectedNumber {
|
||||
t.Fatalf("got %d exported functions; want %d", e.NumberOfFunctions, expectedNumber)
|
||||
}
|
||||
if e.NumberOfNames != expectedNumber {
|
||||
t.Fatalf("got %d exported names; want %d", e.NumberOfNames, expectedNumber)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNumberOfExportedFunctions(t *testing.T) {
|
||||
if GOOS != "windows" {
|
||||
t.Skip("skipping windows only test")
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
t.Run("OnlyExported", func(t *testing.T) {
|
||||
checkNumberOfExportedFunctionsWindows(t, false)
|
||||
})
|
||||
t.Run("All", func(t *testing.T) {
|
||||
checkNumberOfExportedFunctionsWindows(t, true)
|
||||
})
|
||||
}
|
||||
|
||||
// test1: shared library can be dynamically loaded and exported symbols are accessible.
|
||||
func TestExportedSymbolsWithDynamicLoad(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
|
@ -407,7 +504,7 @@ func TestUnexportedSymbols(t *testing.T) {
|
|||
adbPush(t, libname)
|
||||
|
||||
linkFlags := "-Wl,--no-as-needed"
|
||||
if GOOS == "darwin" {
|
||||
if GOOS == "darwin" || GOOS == "ios" {
|
||||
linkFlags = ""
|
||||
}
|
||||
|
||||
|
|
@ -636,7 +733,7 @@ func copyFile(t *testing.T, dst, src string) {
|
|||
|
||||
func TestGo2C2Go(t *testing.T) {
|
||||
switch GOOS {
|
||||
case "darwin":
|
||||
case "darwin", "ios":
|
||||
// Darwin shared libraries don't support the multiple
|
||||
// copies of the runtime package implied by this test.
|
||||
t.Skip("linking c-shared into Go programs not supported on Darwin; issue 29061")
|
||||
|
|
|
|||
31
misc/cgo/testgodefs/testdata/bitfields.go
vendored
Normal file
31
misc/cgo/testgodefs/testdata/bitfields.go
vendored
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// 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.
|
||||
//
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
// This file tests that we don't generate an incorrect field location
|
||||
// for a bitfield that appears aligned.
|
||||
|
||||
/*
|
||||
struct bitfields {
|
||||
unsigned int B1 : 5;
|
||||
unsigned int B2 : 1;
|
||||
unsigned int B3 : 1;
|
||||
unsigned int B4 : 1;
|
||||
unsigned int Short1 : 16; // misaligned on 8 bit boundary
|
||||
unsigned int B5 : 1;
|
||||
unsigned int B6 : 1;
|
||||
unsigned int B7 : 1;
|
||||
unsigned int B8 : 1;
|
||||
unsigned int B9 : 1;
|
||||
unsigned int B10 : 3;
|
||||
unsigned int Short2 : 16; // alignment is OK
|
||||
unsigned int Short3 : 16; // alignment is OK
|
||||
};
|
||||
*/
|
||||
import "C"
|
||||
|
||||
type bitfields C.struct_bitfields
|
||||
28
misc/cgo/testgodefs/testdata/main.go
vendored
28
misc/cgo/testgodefs/testdata/main.go
vendored
|
|
@ -4,6 +4,12 @@
|
|||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Test that the struct field in anonunion.go was promoted.
|
||||
var v1 T
|
||||
var v2 = v1.L
|
||||
|
|
@ -23,4 +29,26 @@ var v7 = S{}
|
|||
var _ = issue38649{X: 0}
|
||||
|
||||
func main() {
|
||||
pass := true
|
||||
|
||||
// The Go translation of bitfields should not have any of the
|
||||
// bitfield types. The order in which bitfields are laid out
|
||||
// in memory is implementation defined, so we can't easily
|
||||
// know how a bitfield should correspond to a Go type, even if
|
||||
// it appears to be aligned correctly.
|
||||
bitfieldType := reflect.TypeOf(bitfields{})
|
||||
check := func(name string) {
|
||||
_, ok := bitfieldType.FieldByName(name)
|
||||
if ok {
|
||||
fmt.Fprintf(os.Stderr, "found unexpected bitfields field %s\n", name)
|
||||
pass = false
|
||||
}
|
||||
}
|
||||
check("Short1")
|
||||
check("Short2")
|
||||
check("Short3")
|
||||
|
||||
if !pass {
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import (
|
|||
// import "C" block. Add more tests here.
|
||||
var filePrefixes = []string{
|
||||
"anonunion",
|
||||
"bitfields",
|
||||
"issue8478",
|
||||
"fieldtypedef",
|
||||
"issue37479",
|
||||
|
|
|
|||
|
|
@ -196,3 +196,17 @@ func TestIssue25756(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestMethod(t *testing.T) {
|
||||
// Exported symbol's method must be live.
|
||||
goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./method/plugin.go")
|
||||
goCmd(t, "build", "-o", "method.exe", "./method/main.go")
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
cmd := exec.CommandContext(ctx, "./method.exe")
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
26
misc/cgo/testplugin/testdata/method/main.go
vendored
Normal file
26
misc/cgo/testplugin/testdata/method/main.go
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
// 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.
|
||||
|
||||
// Issue 42579: methods of symbols exported from plugin must be live.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"plugin"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func main() {
|
||||
p, err := plugin.Open("plugin.so")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
x, err := p.Lookup("X")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
reflect.ValueOf(x).Elem().MethodByName("M").Call(nil)
|
||||
}
|
||||
13
misc/cgo/testplugin/testdata/method/plugin.go
vendored
Normal file
13
misc/cgo/testplugin/testdata/method/plugin.go
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
|
||||
type T int
|
||||
|
||||
func (T) M() { println("M") }
|
||||
|
||||
var X T
|
||||
|
|
@ -28,6 +28,7 @@ func TestMSAN(t *testing.T) {
|
|||
{src: "msan4.go"},
|
||||
{src: "msan5.go"},
|
||||
{src: "msan6.go"},
|
||||
{src: "msan7.go"},
|
||||
{src: "msan_fail.go", wantErr: true},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
|
|
|
|||
38
misc/cgo/testsanitizers/testdata/msan7.go
vendored
Normal file
38
misc/cgo/testsanitizers/testdata/msan7.go
vendored
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2020 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
// Test passing C struct to exported Go function.
|
||||
|
||||
/*
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
// T is a C struct with alignment padding after b.
|
||||
// The padding bytes are not considered initialized by MSAN.
|
||||
// It is big enough to be passed on stack in C ABI (and least
|
||||
// on AMD64).
|
||||
typedef struct { char b; uintptr_t x, y; } T;
|
||||
|
||||
extern void F(T);
|
||||
|
||||
// Use weak as a hack to permit defining a function even though we use export.
|
||||
void CF(int x) __attribute__ ((weak));
|
||||
void CF(int x) {
|
||||
T *t = malloc(sizeof(T));
|
||||
t->b = (char)x;
|
||||
t->x = x;
|
||||
t->y = x;
|
||||
F(*t);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
//export F
|
||||
func F(t C.T) { println(t.b, t.x, t.y) }
|
||||
|
||||
func main() {
|
||||
C.CF(C.int(0))
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ func requireTestSOSupported(t *testing.T) {
|
|||
t.Helper()
|
||||
switch runtime.GOARCH {
|
||||
case "arm64":
|
||||
if runtime.GOOS == "darwin" {
|
||||
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
||||
t.Skip("No exec facility on iOS.")
|
||||
}
|
||||
case "ppc64":
|
||||
|
|
@ -74,7 +74,7 @@ func TestSO(t *testing.T) {
|
|||
ext := "so"
|
||||
args := append(gogccflags, "-shared")
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
case "darwin", "ios":
|
||||
ext = "dylib"
|
||||
args = append(args, "-undefined", "suppress", "-flat_namespace")
|
||||
case "windows":
|
||||
|
|
@ -119,7 +119,7 @@ func TestSO(t *testing.T) {
|
|||
cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
|
||||
if runtime.GOOS != "windows" {
|
||||
s := "LD_LIBRARY_PATH"
|
||||
if runtime.GOOS == "darwin" {
|
||||
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
||||
s = "DYLD_LIBRARY_PATH"
|
||||
}
|
||||
cmd.Env = append(os.Environ(), s+"=.")
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ func requireTestSOSupported(t *testing.T) {
|
|||
t.Helper()
|
||||
switch runtime.GOARCH {
|
||||
case "arm64":
|
||||
if runtime.GOOS == "darwin" {
|
||||
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
||||
t.Skip("No exec facility on iOS.")
|
||||
}
|
||||
case "ppc64":
|
||||
|
|
@ -74,7 +74,7 @@ func TestSO(t *testing.T) {
|
|||
ext := "so"
|
||||
args := append(gogccflags, "-shared")
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
case "darwin", "ios":
|
||||
ext = "dylib"
|
||||
args = append(args, "-undefined", "suppress", "-flat_namespace")
|
||||
case "windows":
|
||||
|
|
@ -119,7 +119,7 @@ func TestSO(t *testing.T) {
|
|||
cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
|
||||
if runtime.GOOS != "windows" {
|
||||
s := "LD_LIBRARY_PATH"
|
||||
if runtime.GOOS == "darwin" {
|
||||
if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
|
||||
s = "DYLD_LIBRARY_PATH"
|
||||
}
|
||||
cmd.Env = append(os.Environ(), s+"=.")
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
Go on iOS
|
||||
=========
|
||||
|
||||
For details on developing Go for iOS on macOS, see the documentation in the mobile
|
||||
subrepository:
|
||||
To run the standard library tests, run all.bash as usual, but with the compiler
|
||||
set to the clang wrapper that invokes clang for iOS. For example, this command runs
|
||||
all.bash on the iOS emulator:
|
||||
|
||||
https://github.com/golang/mobile
|
||||
GOOS=ios GOARCH=amd64 CGO_ENABLED=1 CC_FOR_TARGET=$(pwd)/../misc/ios/clangwrap.sh ./all.bash
|
||||
|
||||
It is necessary to set up the environment before running tests or programs directly on a
|
||||
device.
|
||||
To use the go tool to run individual programs and tests, put $GOROOT/bin into PATH to ensure
|
||||
the go_ios_$GOARCH_exec wrapper is found. For example, to run the archive/tar tests:
|
||||
|
||||
export PATH=$GOROOT/bin:$PATH
|
||||
GOOS=ios GOARCH=amd64 CGO_ENABLED=1 go test archive/tar
|
||||
|
||||
The go_ios_exec wrapper uses GOARCH to select the emulator (amd64) or the device (arm64).
|
||||
However, further setup is required to run tests or programs directly on a device.
|
||||
|
||||
First make sure you have a valid developer certificate and have setup your device properly
|
||||
to run apps signed by your developer certificate. Then install the libimobiledevice and
|
||||
|
|
@ -29,18 +36,10 @@ which will output something similar to
|
|||
export GOIOS_TEAM_ID=ZZZZZZZZ
|
||||
|
||||
If you have multiple devices connected, specify the device UDID with the GOIOS_DEVICE_ID
|
||||
variable. Use `idevice_id -l` to list all available UDIDs.
|
||||
variable. Use `idevice_id -l` to list all available UDIDs. Then, setting GOARCH to arm64
|
||||
will select the device:
|
||||
|
||||
Finally, to run the standard library tests, run all.bash as usual, but with the compiler
|
||||
set to the clang wrapper that invokes clang for iOS. For example,
|
||||
|
||||
GOARCH=arm64 CGO_ENABLED=1 CC_FOR_TARGET=$(pwd)/../misc/ios/clangwrap.sh ./all.bash
|
||||
|
||||
To use the go tool directly to run programs and tests, put $GOROOT/bin into PATH to ensure
|
||||
the go_darwin_$GOARCH_exec wrapper is found. For example, to run the archive/tar tests
|
||||
|
||||
export PATH=$GOROOT/bin:$PATH
|
||||
GOARCH=arm64 CGO_ENABLED=1 go test archive/tar
|
||||
GOOS=ios GOARCH=arm64 CGO_ENABLED=1 CC_FOR_TARGET=$(pwd)/../misc/ios/clangwrap.sh ./all.bash
|
||||
|
||||
Note that the go_darwin_$GOARCH_exec wrapper uninstalls any existing app identified by
|
||||
the bundle id before installing a new app. If the uninstalled app is the last app by
|
||||
|
|
|
|||
|
|
@ -2,17 +2,19 @@
|
|||
# This uses the latest available iOS SDK, which is recommended.
|
||||
# To select a specific SDK, run 'xcodebuild -showsdks'
|
||||
# to see the available SDKs and replace iphoneos with one of them.
|
||||
SDK=iphoneos
|
||||
if [ "$GOARCH" == "arm64" ]; then
|
||||
SDK=iphoneos
|
||||
PLATFORM=ios
|
||||
CLANGARCH="arm64"
|
||||
else
|
||||
SDK=iphonesimulator
|
||||
PLATFORM=ios-simulator
|
||||
CLANGARCH="x86_64"
|
||||
fi
|
||||
|
||||
SDK_PATH=`xcrun --sdk $SDK --show-sdk-path`
|
||||
export IPHONEOS_DEPLOYMENT_TARGET=5.1
|
||||
# cmd/cgo doesn't support llvm-gcc-4.2, so we have to use clang.
|
||||
CLANG=`xcrun --sdk $SDK --find clang`
|
||||
|
||||
if [ "$GOARCH" == "arm64" ]; then
|
||||
CLANGARCH="arm64"
|
||||
else
|
||||
echo "unknown GOARCH=$GOARCH" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec $CLANG -arch $CLANGARCH -isysroot $SDK_PATH -mios-version-min=10.0 "$@"
|
||||
exec "$CLANG" -arch $CLANGARCH -isysroot "$SDK_PATH" -m${PLATFORM}-version-min=10.0 "$@"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
// detect attempts to autodetect the correct
|
||||
// values of the environment variables
|
||||
// used by go_darwin_arm_exec.
|
||||
// used by go_ios_exec.
|
||||
// detect shells out to ideviceinfo, a third party program that can
|
||||
// be obtained by following the instructions at
|
||||
// https://github.com/libimobiledevice/libimobiledevice.
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This program can be used as go_darwin_arm_exec by the Go tool.
|
||||
// This program can be used as go_ios_$GOARCH_exec by the Go tool.
|
||||
// It executes binaries on an iOS device using the XCode toolchain
|
||||
// and the ios-deploy program: https://github.com/phonegap/ios-deploy
|
||||
//
|
||||
|
|
@ -34,6 +34,7 @@ import (
|
|||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
|
@ -58,34 +59,16 @@ var lock *os.File
|
|||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("go_darwin_arm_exec: ")
|
||||
log.SetPrefix("go_ios_exec: ")
|
||||
if debug {
|
||||
log.Println(strings.Join(os.Args, " "))
|
||||
}
|
||||
if len(os.Args) < 2 {
|
||||
log.Fatal("usage: go_darwin_arm_exec a.out")
|
||||
log.Fatal("usage: go_ios_exec a.out")
|
||||
}
|
||||
|
||||
// e.g. B393DDEB490947F5A463FD074299B6C0AXXXXXXX
|
||||
devID = getenv("GOIOS_DEV_ID")
|
||||
|
||||
// e.g. Z8B3JBXXXX.org.golang.sample, Z8B3JBXXXX prefix is available at
|
||||
// https://developer.apple.com/membercenter/index.action#accountSummary as Team ID.
|
||||
appID = getenv("GOIOS_APP_ID")
|
||||
|
||||
// e.g. Z8B3JBXXXX, available at
|
||||
// https://developer.apple.com/membercenter/index.action#accountSummary as Team ID.
|
||||
teamID = getenv("GOIOS_TEAM_ID")
|
||||
|
||||
// Device IDs as listed with ios-deploy -c.
|
||||
deviceID = os.Getenv("GOIOS_DEVICE_ID")
|
||||
|
||||
parts := strings.SplitN(appID, ".", 2)
|
||||
// For compatibility with the old builders, use a fallback bundle ID
|
||||
bundleID = "golang.gotest"
|
||||
if len(parts) == 2 {
|
||||
bundleID = parts[1]
|
||||
}
|
||||
|
||||
exitCode, err := runMain()
|
||||
if err != nil {
|
||||
|
|
@ -96,7 +79,7 @@ func main() {
|
|||
|
||||
func runMain() (int, error) {
|
||||
var err error
|
||||
tmpdir, err = ioutil.TempDir("", "go_darwin_arm_exec_")
|
||||
tmpdir, err = ioutil.TempDir("", "go_ios_exec_")
|
||||
if err != nil {
|
||||
return 1, err
|
||||
}
|
||||
|
|
@ -117,7 +100,7 @@ func runMain() (int, error) {
|
|||
//
|
||||
// The lock file is never deleted, to avoid concurrent locks on distinct
|
||||
// files with the same path.
|
||||
lockName := filepath.Join(os.TempDir(), "go_darwin_arm_exec-"+deviceID+".lock")
|
||||
lockName := filepath.Join(os.TempDir(), "go_ios_exec-"+deviceID+".lock")
|
||||
lock, err = os.OpenFile(lockName, os.O_CREATE|os.O_RDONLY, 0666)
|
||||
if err != nil {
|
||||
return 1, err
|
||||
|
|
@ -126,28 +109,12 @@ func runMain() (int, error) {
|
|||
return 1, err
|
||||
}
|
||||
|
||||
if err := uninstall(bundleID); err != nil {
|
||||
return 1, err
|
||||
if goarch := os.Getenv("GOARCH"); goarch == "arm64" {
|
||||
err = runOnDevice(appdir)
|
||||
} else {
|
||||
err = runOnSimulator(appdir)
|
||||
}
|
||||
|
||||
if err := install(appdir); err != nil {
|
||||
return 1, err
|
||||
}
|
||||
|
||||
if err := mountDevImage(); err != nil {
|
||||
return 1, err
|
||||
}
|
||||
|
||||
// Kill any hanging debug bridges that might take up port 3222.
|
||||
exec.Command("killall", "idevicedebugserverproxy").Run()
|
||||
|
||||
closer, err := startDebugBridge()
|
||||
if err != nil {
|
||||
return 1, err
|
||||
}
|
||||
defer closer()
|
||||
|
||||
if err := run(appdir, bundleID, os.Args[2:]); err != nil {
|
||||
// If the lldb driver completed with an exit code, use that.
|
||||
if err, ok := err.(*exec.ExitError); ok {
|
||||
if ws, ok := err.Sys().(interface{ ExitStatus() int }); ok {
|
||||
|
|
@ -159,6 +126,62 @@ func runMain() (int, error) {
|
|||
return 0, nil
|
||||
}
|
||||
|
||||
func runOnSimulator(appdir string) error {
|
||||
if err := installSimulator(appdir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return runSimulator(appdir, bundleID, os.Args[2:])
|
||||
}
|
||||
|
||||
func runOnDevice(appdir string) error {
|
||||
// e.g. B393DDEB490947F5A463FD074299B6C0AXXXXXXX
|
||||
devID = getenv("GOIOS_DEV_ID")
|
||||
|
||||
// e.g. Z8B3JBXXXX.org.golang.sample, Z8B3JBXXXX prefix is available at
|
||||
// https://developer.apple.com/membercenter/index.action#accountSummary as Team ID.
|
||||
appID = getenv("GOIOS_APP_ID")
|
||||
|
||||
// e.g. Z8B3JBXXXX, available at
|
||||
// https://developer.apple.com/membercenter/index.action#accountSummary as Team ID.
|
||||
teamID = getenv("GOIOS_TEAM_ID")
|
||||
|
||||
// Device IDs as listed with ios-deploy -c.
|
||||
deviceID = os.Getenv("GOIOS_DEVICE_ID")
|
||||
|
||||
parts := strings.SplitN(appID, ".", 2)
|
||||
if len(parts) == 2 {
|
||||
bundleID = parts[1]
|
||||
}
|
||||
|
||||
if err := signApp(appdir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := uninstallDevice(bundleID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := installDevice(appdir); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := mountDevImage(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Kill any hanging debug bridges that might take up port 3222.
|
||||
exec.Command("killall", "idevicedebugserverproxy").Run()
|
||||
|
||||
closer, err := startDebugBridge()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer closer()
|
||||
|
||||
return runDevice(appdir, bundleID, os.Args[2:])
|
||||
}
|
||||
|
||||
func getenv(envvar string) string {
|
||||
s := os.Getenv(envvar)
|
||||
if s == "" {
|
||||
|
|
@ -191,7 +214,11 @@ func assembleApp(appdir, bin string) error {
|
|||
if err := ioutil.WriteFile(filepath.Join(appdir, "ResourceRules.plist"), []byte(resourceRules), 0744); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func signApp(appdir string) error {
|
||||
entitlementsPath := filepath.Join(tmpdir, "Entitlements.plist")
|
||||
cmd := exec.Command(
|
||||
"codesign",
|
||||
"-f",
|
||||
|
|
@ -421,7 +448,20 @@ func parsePlistDict(dict []byte) (map[string]string, error) {
|
|||
return values, nil
|
||||
}
|
||||
|
||||
func uninstall(bundleID string) error {
|
||||
func installSimulator(appdir string) error {
|
||||
cmd := exec.Command(
|
||||
"xcrun", "simctl", "install",
|
||||
"booted", // Install to the booted simulator.
|
||||
appdir,
|
||||
)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
os.Stderr.Write(out)
|
||||
return fmt.Errorf("xcrun simctl install booted %q: %v", appdir, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func uninstallDevice(bundleID string) error {
|
||||
cmd := idevCmd(exec.Command(
|
||||
"ideviceinstaller",
|
||||
"-U", bundleID,
|
||||
|
|
@ -433,7 +473,7 @@ func uninstall(bundleID string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func install(appdir string) error {
|
||||
func installDevice(appdir string) error {
|
||||
attempt := 0
|
||||
for {
|
||||
cmd := idevCmd(exec.Command(
|
||||
|
|
@ -464,15 +504,28 @@ func idevCmd(cmd *exec.Cmd) *exec.Cmd {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func run(appdir, bundleID string, args []string) error {
|
||||
var env []string
|
||||
for _, e := range os.Environ() {
|
||||
// Don't override TMPDIR, HOME, GOCACHE on the device.
|
||||
if strings.HasPrefix(e, "TMPDIR=") || strings.HasPrefix(e, "HOME=") || strings.HasPrefix(e, "GOCACHE=") {
|
||||
continue
|
||||
}
|
||||
env = append(env, e)
|
||||
func runSimulator(appdir, bundleID string, args []string) error {
|
||||
cmd := exec.Command(
|
||||
"xcrun", "simctl", "launch",
|
||||
"--wait-for-debugger",
|
||||
"booted",
|
||||
bundleID,
|
||||
)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
os.Stderr.Write(out)
|
||||
return fmt.Errorf("xcrun simctl launch booted %q: %v", bundleID, err)
|
||||
}
|
||||
var processID int
|
||||
var ignore string
|
||||
if _, err := fmt.Sscanf(string(out), "%s %d", &ignore, &processID); err != nil {
|
||||
return fmt.Errorf("runSimulator: couldn't find processID from `simctl launch`: %v (%q)", err, out)
|
||||
}
|
||||
_, err = runLLDB("ios-simulator", appdir, strconv.Itoa(processID), args)
|
||||
return err
|
||||
}
|
||||
|
||||
func runDevice(appdir, bundleID string, args []string) error {
|
||||
attempt := 0
|
||||
for {
|
||||
// The device app path reported by the device might be stale, so retry
|
||||
|
|
@ -487,37 +540,10 @@ func run(appdir, bundleID string, args []string) error {
|
|||
time.Sleep(5 * time.Second)
|
||||
continue
|
||||
}
|
||||
lldb := exec.Command(
|
||||
"python",
|
||||
"-", // Read script from stdin.
|
||||
appdir,
|
||||
deviceapp,
|
||||
)
|
||||
lldb.Args = append(lldb.Args, args...)
|
||||
lldb.Env = env
|
||||
lldb.Stdin = strings.NewReader(lldbDriver)
|
||||
lldb.Stdout = os.Stdout
|
||||
var out bytes.Buffer
|
||||
lldb.Stderr = io.MultiWriter(&out, os.Stderr)
|
||||
err = lldb.Start()
|
||||
if err == nil {
|
||||
// Forward SIGQUIT to the lldb driver which in turn will forward
|
||||
// to the running program.
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGQUIT)
|
||||
proc := lldb.Process
|
||||
go func() {
|
||||
for sig := range sigs {
|
||||
proc.Signal(sig)
|
||||
}
|
||||
}()
|
||||
err = lldb.Wait()
|
||||
signal.Stop(sigs)
|
||||
close(sigs)
|
||||
}
|
||||
out, err := runLLDB("remote-ios", appdir, deviceapp, args)
|
||||
// If the program was not started it can be retried without papering over
|
||||
// real test failures.
|
||||
started := bytes.HasPrefix(out.Bytes(), []byte("lldb: running program"))
|
||||
started := bytes.HasPrefix(out, []byte("lldb: running program"))
|
||||
if started || err == nil || attempt == 5 {
|
||||
return err
|
||||
}
|
||||
|
|
@ -528,6 +554,47 @@ func run(appdir, bundleID string, args []string) error {
|
|||
}
|
||||
}
|
||||
|
||||
func runLLDB(target, appdir, deviceapp string, args []string) ([]byte, error) {
|
||||
var env []string
|
||||
for _, e := range os.Environ() {
|
||||
// Don't override TMPDIR, HOME, GOCACHE on the device.
|
||||
if strings.HasPrefix(e, "TMPDIR=") || strings.HasPrefix(e, "HOME=") || strings.HasPrefix(e, "GOCACHE=") {
|
||||
continue
|
||||
}
|
||||
env = append(env, e)
|
||||
}
|
||||
lldb := exec.Command(
|
||||
"python",
|
||||
"-", // Read script from stdin.
|
||||
target,
|
||||
appdir,
|
||||
deviceapp,
|
||||
)
|
||||
lldb.Args = append(lldb.Args, args...)
|
||||
lldb.Env = env
|
||||
lldb.Stdin = strings.NewReader(lldbDriver)
|
||||
lldb.Stdout = os.Stdout
|
||||
var out bytes.Buffer
|
||||
lldb.Stderr = io.MultiWriter(&out, os.Stderr)
|
||||
err := lldb.Start()
|
||||
if err == nil {
|
||||
// Forward SIGQUIT to the lldb driver which in turn will forward
|
||||
// to the running program.
|
||||
sigs := make(chan os.Signal, 1)
|
||||
signal.Notify(sigs, syscall.SIGQUIT)
|
||||
proc := lldb.Process
|
||||
go func() {
|
||||
for sig := range sigs {
|
||||
proc.Signal(sig)
|
||||
}
|
||||
}()
|
||||
err = lldb.Wait()
|
||||
signal.Stop(sigs)
|
||||
close(sigs)
|
||||
}
|
||||
return out.Bytes(), err
|
||||
}
|
||||
|
||||
func copyLocalDir(dst, src string) error {
|
||||
if err := os.Mkdir(dst, 0755); err != nil {
|
||||
return err
|
||||
|
|
@ -679,6 +746,7 @@ func infoPlist(pkgpath string) string {
|
|||
<key>CFBundleSupportedPlatforms</key><array><string>iPhoneOS</string></array>
|
||||
<key>CFBundleExecutable</key><string>gotest</string>
|
||||
<key>CFBundleVersion</key><string>1.0</string>
|
||||
<key>CFBundleShortVersionString</key><string>1.0</string>
|
||||
<key>CFBundleIdentifier</key><string>` + bundleID + `</string>
|
||||
<key>CFBundleResourceSpecification</key><string>ResourceRules.plist</string>
|
||||
<key>LSRequiresIPhoneOS</key><true/>
|
||||
|
|
@ -739,7 +807,7 @@ import sys
|
|||
import os
|
||||
import signal
|
||||
|
||||
exe, device_exe, args = sys.argv[1], sys.argv[2], sys.argv[3:]
|
||||
platform, exe, device_exe_or_pid, args = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4:]
|
||||
|
||||
env = []
|
||||
for k, v in os.environ.items():
|
||||
|
|
@ -754,17 +822,21 @@ debugger.SetAsync(True)
|
|||
debugger.SkipLLDBInitFiles(True)
|
||||
|
||||
err = lldb.SBError()
|
||||
target = debugger.CreateTarget(exe, None, 'remote-ios', True, err)
|
||||
target = debugger.CreateTarget(exe, None, platform, True, err)
|
||||
if not target.IsValid() or not err.Success():
|
||||
sys.stderr.write("lldb: failed to setup up target: %s\n" % (err))
|
||||
sys.exit(1)
|
||||
|
||||
target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_exe))
|
||||
|
||||
listener = debugger.GetListener()
|
||||
process = target.ConnectRemote(listener, 'connect://localhost:3222', None, err)
|
||||
|
||||
if platform == 'remote-ios':
|
||||
target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_exe_or_pid))
|
||||
process = target.ConnectRemote(listener, 'connect://localhost:3222', None, err)
|
||||
else:
|
||||
process = target.AttachToProcessWithID(listener, int(device_exe_or_pid), err)
|
||||
|
||||
if not err.Success():
|
||||
sys.stderr.write("lldb: failed to connect to remote target: %s\n" % (err))
|
||||
sys.stderr.write("lldb: failed to connect to remote target %s: %s\n" % (device_exe_or_pid, err))
|
||||
sys.exit(1)
|
||||
|
||||
# Don't stop on signals.
|
||||
|
|
@ -777,6 +849,25 @@ for i in range(0, sigs.GetNumSignals()):
|
|||
event = lldb.SBEvent()
|
||||
running = False
|
||||
prev_handler = None
|
||||
|
||||
def signal_handler(signal, frame):
|
||||
process.Signal(signal)
|
||||
|
||||
def run_program():
|
||||
# Forward SIGQUIT to the program.
|
||||
prev_handler = signal.signal(signal.SIGQUIT, signal_handler)
|
||||
# Tell the Go driver that the program is running and should not be retried.
|
||||
sys.stderr.write("lldb: running program\n")
|
||||
running = True
|
||||
# Process is stopped at attach/launch. Let it run.
|
||||
process.Continue()
|
||||
|
||||
if platform != 'remote-ios':
|
||||
# For the local emulator the program is ready to run.
|
||||
# For remote device runs, we need to wait for eStateConnected,
|
||||
# below.
|
||||
run_program()
|
||||
|
||||
while True:
|
||||
if not listener.WaitForEvent(1, event):
|
||||
continue
|
||||
|
|
@ -800,24 +891,22 @@ while True:
|
|||
signal.signal(signal.SIGQUIT, prev_handler)
|
||||
break
|
||||
elif state == lldb.eStateConnected:
|
||||
process.RemoteLaunch(args, env, None, None, None, None, 0, False, err)
|
||||
if not err.Success():
|
||||
sys.stderr.write("lldb: failed to launch remote process: %s\n" % (err))
|
||||
process.Kill()
|
||||
debugger.Terminate()
|
||||
sys.exit(1)
|
||||
# Forward SIGQUIT to the program.
|
||||
def signal_handler(signal, frame):
|
||||
process.Signal(signal)
|
||||
prev_handler = signal.signal(signal.SIGQUIT, signal_handler)
|
||||
# Tell the Go driver that the program is running and should not be retried.
|
||||
sys.stderr.write("lldb: running program\n")
|
||||
running = True
|
||||
# Process stops once at the beginning. Continue.
|
||||
process.Continue()
|
||||
if platform == 'remote-ios':
|
||||
process.RemoteLaunch(args, env, None, None, None, None, 0, False, err)
|
||||
if not err.Success():
|
||||
sys.stderr.write("lldb: failed to launch remote process: %s\n" % (err))
|
||||
process.Kill()
|
||||
debugger.Terminate()
|
||||
sys.exit(1)
|
||||
run_program()
|
||||
|
||||
exitStatus = process.GetExitStatus()
|
||||
exitDesc = process.GetExitDescription()
|
||||
process.Kill()
|
||||
debugger.Terminate()
|
||||
if exitStatus == 0 and exitDesc is not None:
|
||||
# Ensure tests fail when killed by a signal.
|
||||
exitStatus = 123
|
||||
|
||||
sys.exit(exitStatus)
|
||||
`
|
||||
|
|
@ -102,7 +102,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
if (!global.crypto) {
|
||||
if (!global.crypto && global.require) {
|
||||
const nodeCrypto = require("crypto");
|
||||
global.crypto = {
|
||||
getRandomValues(b) {
|
||||
|
|
@ -110,6 +110,9 @@
|
|||
},
|
||||
};
|
||||
}
|
||||
if (!global.crypto) {
|
||||
throw new Error("global.crypto is not available, polyfill required (getRandomValues only)");
|
||||
}
|
||||
|
||||
if (!global.performance) {
|
||||
global.performance = {
|
||||
|
|
@ -120,13 +123,19 @@
|
|||
};
|
||||
}
|
||||
|
||||
if (!global.TextEncoder) {
|
||||
if (!global.TextEncoder && global.require) {
|
||||
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;
|
||||
}
|
||||
if (!global.TextDecoder) {
|
||||
throw new Error("global.TextDecoder is not available, polyfill required");
|
||||
}
|
||||
|
||||
// End of polyfills for common API.
|
||||
|
||||
|
|
@ -255,6 +264,7 @@
|
|||
|
||||
// func wasmExit(code int32)
|
||||
"runtime.wasmExit": (sp) => {
|
||||
sp >>>= 0;
|
||||
const code = this.mem.getInt32(sp + 8, true);
|
||||
this.exited = true;
|
||||
delete this._inst;
|
||||
|
|
@ -267,6 +277,7 @@
|
|||
|
||||
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
|
||||
"runtime.wasmWrite": (sp) => {
|
||||
sp >>>= 0;
|
||||
const fd = getInt64(sp + 8);
|
||||
const p = getInt64(sp + 16);
|
||||
const n = this.mem.getInt32(sp + 24, true);
|
||||
|
|
@ -275,16 +286,19 @@
|
|||
|
||||
// func resetMemoryDataView()
|
||||
"runtime.resetMemoryDataView": (sp) => {
|
||||
sp >>>= 0;
|
||||
this.mem = new DataView(this._inst.exports.mem.buffer);
|
||||
},
|
||||
|
||||
// func nanotime1() int64
|
||||
"runtime.nanotime1": (sp) => {
|
||||
sp >>>= 0;
|
||||
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
|
||||
},
|
||||
|
||||
// func walltime1() (sec int64, nsec int32)
|
||||
"runtime.walltime1": (sp) => {
|
||||
sp >>>= 0;
|
||||
const msec = (new Date).getTime();
|
||||
setInt64(sp + 8, msec / 1000);
|
||||
this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true);
|
||||
|
|
@ -292,6 +306,7 @@
|
|||
|
||||
// func scheduleTimeoutEvent(delay int64) int32
|
||||
"runtime.scheduleTimeoutEvent": (sp) => {
|
||||
sp >>>= 0;
|
||||
const id = this._nextCallbackTimeoutID;
|
||||
this._nextCallbackTimeoutID++;
|
||||
this._scheduledTimeouts.set(id, setTimeout(
|
||||
|
|
@ -311,6 +326,7 @@
|
|||
|
||||
// func clearTimeoutEvent(id int32)
|
||||
"runtime.clearTimeoutEvent": (sp) => {
|
||||
sp >>>= 0;
|
||||
const id = this.mem.getInt32(sp + 8, true);
|
||||
clearTimeout(this._scheduledTimeouts.get(id));
|
||||
this._scheduledTimeouts.delete(id);
|
||||
|
|
@ -318,11 +334,13 @@
|
|||
|
||||
// func getRandomData(r []byte)
|
||||
"runtime.getRandomData": (sp) => {
|
||||
sp >>>= 0;
|
||||
crypto.getRandomValues(loadSlice(sp + 8));
|
||||
},
|
||||
|
||||
// func finalizeRef(v ref)
|
||||
"syscall/js.finalizeRef": (sp) => {
|
||||
sp >>>= 0;
|
||||
const id = this.mem.getUint32(sp + 8, true);
|
||||
this._goRefCounts[id]--;
|
||||
if (this._goRefCounts[id] === 0) {
|
||||
|
|
@ -335,44 +353,51 @@
|
|||
|
||||
// func stringVal(value string) ref
|
||||
"syscall/js.stringVal": (sp) => {
|
||||
sp >>>= 0;
|
||||
storeValue(sp + 24, loadString(sp + 8));
|
||||
},
|
||||
|
||||
// func valueGet(v ref, p string) ref
|
||||
"syscall/js.valueGet": (sp) => {
|
||||
sp >>>= 0;
|
||||
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);
|
||||
},
|
||||
|
||||
// func valueSet(v ref, p string, x ref)
|
||||
"syscall/js.valueSet": (sp) => {
|
||||
sp >>>= 0;
|
||||
Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
|
||||
},
|
||||
|
||||
// func valueDelete(v ref, p string)
|
||||
"syscall/js.valueDelete": (sp) => {
|
||||
sp >>>= 0;
|
||||
Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16));
|
||||
},
|
||||
|
||||
// func valueIndex(v ref, i int) ref
|
||||
"syscall/js.valueIndex": (sp) => {
|
||||
sp >>>= 0;
|
||||
storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
|
||||
},
|
||||
|
||||
// valueSetIndex(v ref, i int, x ref)
|
||||
"syscall/js.valueSetIndex": (sp) => {
|
||||
sp >>>= 0;
|
||||
Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
|
||||
},
|
||||
|
||||
// func valueCall(v ref, m string, args []ref) (ref, bool)
|
||||
"syscall/js.valueCall": (sp) => {
|
||||
sp >>>= 0;
|
||||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
const m = Reflect.get(v, loadString(sp + 16));
|
||||
const args = loadSliceOfValues(sp + 32);
|
||||
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);
|
||||
this.mem.setUint8(sp + 64, 1);
|
||||
} catch (err) {
|
||||
|
|
@ -383,11 +408,12 @@
|
|||
|
||||
// func valueInvoke(v ref, args []ref) (ref, bool)
|
||||
"syscall/js.valueInvoke": (sp) => {
|
||||
sp >>>= 0;
|
||||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
const args = loadSliceOfValues(sp + 16);
|
||||
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);
|
||||
this.mem.setUint8(sp + 48, 1);
|
||||
} catch (err) {
|
||||
|
|
@ -398,11 +424,12 @@
|
|||
|
||||
// func valueNew(v ref, args []ref) (ref, bool)
|
||||
"syscall/js.valueNew": (sp) => {
|
||||
sp >>>= 0;
|
||||
try {
|
||||
const v = loadValue(sp + 8);
|
||||
const args = loadSliceOfValues(sp + 16);
|
||||
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);
|
||||
this.mem.setUint8(sp + 48, 1);
|
||||
} catch (err) {
|
||||
|
|
@ -413,11 +440,13 @@
|
|||
|
||||
// func valueLength(v ref) int
|
||||
"syscall/js.valueLength": (sp) => {
|
||||
sp >>>= 0;
|
||||
setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
|
||||
},
|
||||
|
||||
// valuePrepareString(v ref) (ref, int)
|
||||
"syscall/js.valuePrepareString": (sp) => {
|
||||
sp >>>= 0;
|
||||
const str = encoder.encode(String(loadValue(sp + 8)));
|
||||
storeValue(sp + 16, str);
|
||||
setInt64(sp + 24, str.length);
|
||||
|
|
@ -425,17 +454,20 @@
|
|||
|
||||
// valueLoadString(v ref, b []byte)
|
||||
"syscall/js.valueLoadString": (sp) => {
|
||||
sp >>>= 0;
|
||||
const str = loadValue(sp + 8);
|
||||
loadSlice(sp + 16).set(str);
|
||||
},
|
||||
|
||||
// func valueInstanceOf(v ref, t ref) bool
|
||||
"syscall/js.valueInstanceOf": (sp) => {
|
||||
sp >>>= 0;
|
||||
this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0);
|
||||
},
|
||||
|
||||
// func copyBytesToGo(dst []byte, src ref) (int, bool)
|
||||
"syscall/js.copyBytesToGo": (sp) => {
|
||||
sp >>>= 0;
|
||||
const dst = loadSlice(sp + 8);
|
||||
const src = loadValue(sp + 32);
|
||||
if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {
|
||||
|
|
@ -450,6 +482,7 @@
|
|||
|
||||
// func copyBytesToJS(dst ref, src []byte) (int, bool)
|
||||
"syscall/js.copyBytesToJS": (sp) => {
|
||||
sp >>>= 0;
|
||||
const dst = loadValue(sp + 8);
|
||||
const src = loadSlice(sp + 16);
|
||||
if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {
|
||||
|
|
@ -470,6 +503,9 @@
|
|||
}
|
||||
|
||||
async run(instance) {
|
||||
if (!(instance instanceof WebAssembly.Instance)) {
|
||||
throw new Error("Go.run: WebAssembly.Instance expected");
|
||||
}
|
||||
this._inst = instance;
|
||||
this.mem = new DataView(this._inst.exports.mem.buffer);
|
||||
this._values = [ // JS values that Go currently has references to, indexed by reference id
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ package tar
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
|
@ -525,12 +525,12 @@ func (h Header) allowedFormats() (format Format, paxHdrs map[string]string, err
|
|||
return format, paxHdrs, err
|
||||
}
|
||||
|
||||
// FileInfo returns an os.FileInfo for the Header.
|
||||
func (h *Header) FileInfo() os.FileInfo {
|
||||
// FileInfo returns an fs.FileInfo for the Header.
|
||||
func (h *Header) FileInfo() fs.FileInfo {
|
||||
return headerFileInfo{h}
|
||||
}
|
||||
|
||||
// headerFileInfo implements os.FileInfo.
|
||||
// headerFileInfo implements fs.FileInfo.
|
||||
type headerFileInfo struct {
|
||||
h *Header
|
||||
}
|
||||
|
|
@ -549,57 +549,57 @@ func (fi headerFileInfo) Name() string {
|
|||
}
|
||||
|
||||
// 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.
|
||||
mode = os.FileMode(fi.h.Mode).Perm()
|
||||
mode = fs.FileMode(fi.h.Mode).Perm()
|
||||
|
||||
// Set setuid, setgid and sticky bits.
|
||||
if fi.h.Mode&c_ISUID != 0 {
|
||||
mode |= os.ModeSetuid
|
||||
mode |= fs.ModeSetuid
|
||||
}
|
||||
if fi.h.Mode&c_ISGID != 0 {
|
||||
mode |= os.ModeSetgid
|
||||
mode |= fs.ModeSetgid
|
||||
}
|
||||
if fi.h.Mode&c_ISVTX != 0 {
|
||||
mode |= os.ModeSticky
|
||||
mode |= fs.ModeSticky
|
||||
}
|
||||
|
||||
// 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:
|
||||
mode |= os.ModeDir
|
||||
mode |= fs.ModeDir
|
||||
case c_ISFIFO:
|
||||
mode |= os.ModeNamedPipe
|
||||
mode |= fs.ModeNamedPipe
|
||||
case c_ISLNK:
|
||||
mode |= os.ModeSymlink
|
||||
mode |= fs.ModeSymlink
|
||||
case c_ISBLK:
|
||||
mode |= os.ModeDevice
|
||||
mode |= fs.ModeDevice
|
||||
case c_ISCHR:
|
||||
mode |= os.ModeDevice
|
||||
mode |= os.ModeCharDevice
|
||||
mode |= fs.ModeDevice
|
||||
mode |= fs.ModeCharDevice
|
||||
case c_ISSOCK:
|
||||
mode |= os.ModeSocket
|
||||
mode |= fs.ModeSocket
|
||||
}
|
||||
|
||||
switch fi.h.Typeflag {
|
||||
case TypeSymlink:
|
||||
mode |= os.ModeSymlink
|
||||
mode |= fs.ModeSymlink
|
||||
case TypeChar:
|
||||
mode |= os.ModeDevice
|
||||
mode |= os.ModeCharDevice
|
||||
mode |= fs.ModeDevice
|
||||
mode |= fs.ModeCharDevice
|
||||
case TypeBlock:
|
||||
mode |= os.ModeDevice
|
||||
mode |= fs.ModeDevice
|
||||
case TypeDir:
|
||||
mode |= os.ModeDir
|
||||
mode |= fs.ModeDir
|
||||
case TypeFifo:
|
||||
mode |= os.ModeNamedPipe
|
||||
mode |= fs.ModeNamedPipe
|
||||
}
|
||||
|
||||
return mode
|
||||
}
|
||||
|
||||
// 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 (
|
||||
// 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 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
|
||||
// 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 {
|
||||
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():
|
||||
h.Typeflag = TypeDir
|
||||
h.Name += "/"
|
||||
case fm&os.ModeSymlink != 0:
|
||||
case fm&fs.ModeSymlink != 0:
|
||||
h.Typeflag = TypeSymlink
|
||||
h.Linkname = link
|
||||
case fm&os.ModeDevice != 0:
|
||||
if fm&os.ModeCharDevice != 0 {
|
||||
case fm&fs.ModeDevice != 0:
|
||||
if fm&fs.ModeCharDevice != 0 {
|
||||
h.Typeflag = TypeChar
|
||||
} else {
|
||||
h.Typeflag = TypeBlock
|
||||
}
|
||||
case fm&os.ModeNamedPipe != 0:
|
||||
case fm&fs.ModeNamedPipe != 0:
|
||||
h.Typeflag = TypeFifo
|
||||
case fm&os.ModeSocket != 0:
|
||||
case fm&fs.ModeSocket != 0:
|
||||
return nil, fmt.Errorf("archive/tar: sockets not supported")
|
||||
default:
|
||||
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
|
||||
}
|
||||
if fm&os.ModeSetgid != 0 {
|
||||
if fm&fs.ModeSetgid != 0 {
|
||||
h.Mode |= c_ISGID
|
||||
}
|
||||
if fm&os.ModeSticky != 0 {
|
||||
if fm&fs.ModeSticky != 0 {
|
||||
h.Mode |= c_ISVTX
|
||||
}
|
||||
// If possible, populate additional fields from OS-specific
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ package tar
|
|||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -104,7 +103,7 @@ func (tr *Reader) next() (*Header, error) {
|
|||
continue // This is a meta header affecting the next header
|
||||
case TypeGNULongName, TypeGNULongLink:
|
||||
format.mayOnlyBe(FormatGNU)
|
||||
realname, err := ioutil.ReadAll(tr)
|
||||
realname, err := io.ReadAll(tr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -294,7 +293,7 @@ func mergePAX(hdr *Header, paxHdrs map[string]string) (err error) {
|
|||
// parsePAX parses PAX headers.
|
||||
// If an extended header (type 'x') is invalid, ErrHeader is returned
|
||||
func parsePAX(r io.Reader) (map[string]string, error) {
|
||||
buf, err := ioutil.ReadAll(r)
|
||||
buf, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
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 {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
|
|
@ -773,7 +772,7 @@ func TestReadTruncation(t *testing.T) {
|
|||
"testdata/pax-path-hdr.tar",
|
||||
"testdata/sparse-formats.tar",
|
||||
} {
|
||||
buf, err := ioutil.ReadFile(p)
|
||||
buf, err := os.ReadFile(p)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
|
@ -865,7 +864,7 @@ func TestReadTruncation(t *testing.T) {
|
|||
}
|
||||
cnt++
|
||||
if s2 == "manual" {
|
||||
if _, err = tr.writeTo(ioutil.Discard); err != nil {
|
||||
if _, err = tr.writeTo(io.Discard); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
package tar
|
||||
|
||||
import (
|
||||
"os"
|
||||
"io/fs"
|
||||
"os/user"
|
||||
"runtime"
|
||||
"strconv"
|
||||
|
|
@ -23,7 +23,7 @@ func init() {
|
|||
// The downside is that renaming uname or gname by the OS never takes effect.
|
||||
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)
|
||||
if !ok {
|
||||
return nil
|
||||
|
|
@ -66,7 +66,7 @@ func statUnix(fi os.FileInfo, h *Header) error {
|
|||
minor := uint32((dev & 0x00000000000000ff) >> 0)
|
||||
minor |= uint32((dev & 0x00000ffffff00000) >> 12)
|
||||
h.Devmajor, h.Devminor = int64(major), int64(minor)
|
||||
case "darwin":
|
||||
case "darwin", "ios":
|
||||
// Copied from golang.org/x/sys/unix/dev_darwin.go.
|
||||
major := uint32((dev >> 24) & 0xff)
|
||||
minor := uint32(dev & 0xffffff)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import (
|
|||
"fmt"
|
||||
"internal/testenv"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"io/fs"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
|
|
@ -262,7 +262,7 @@ func TestFileInfoHeaderDir(t *testing.T) {
|
|||
func TestFileInfoHeaderSymlink(t *testing.T) {
|
||||
testenv.MustHaveSymlink(t)
|
||||
|
||||
tmpdir, err := ioutil.TempDir("", "TestFileInfoHeaderSymlink")
|
||||
tmpdir, err := os.MkdirTemp("", "TestFileInfoHeaderSymlink")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -327,7 +327,7 @@ func TestRoundTrip(t *testing.T) {
|
|||
if !reflect.DeepEqual(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 {
|
||||
t.Fatalf("Read: %v", err)
|
||||
}
|
||||
|
|
@ -338,7 +338,7 @@ func TestRoundTrip(t *testing.T) {
|
|||
|
||||
type headerRoundTripTest struct {
|
||||
h *Header
|
||||
fm os.FileMode
|
||||
fm fs.FileMode
|
||||
}
|
||||
|
||||
func TestHeaderRoundTrip(t *testing.T) {
|
||||
|
|
@ -361,7 +361,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
|||
ModTime: time.Unix(1360600852, 0),
|
||||
Typeflag: TypeSymlink,
|
||||
},
|
||||
fm: 0777 | os.ModeSymlink,
|
||||
fm: 0777 | fs.ModeSymlink,
|
||||
}, {
|
||||
// character device node.
|
||||
h: &Header{
|
||||
|
|
@ -371,7 +371,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
|||
ModTime: time.Unix(1360578951, 0),
|
||||
Typeflag: TypeChar,
|
||||
},
|
||||
fm: 0666 | os.ModeDevice | os.ModeCharDevice,
|
||||
fm: 0666 | fs.ModeDevice | fs.ModeCharDevice,
|
||||
}, {
|
||||
// block device node.
|
||||
h: &Header{
|
||||
|
|
@ -381,7 +381,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
|||
ModTime: time.Unix(1360578954, 0),
|
||||
Typeflag: TypeBlock,
|
||||
},
|
||||
fm: 0660 | os.ModeDevice,
|
||||
fm: 0660 | fs.ModeDevice,
|
||||
}, {
|
||||
// directory.
|
||||
h: &Header{
|
||||
|
|
@ -391,7 +391,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
|||
ModTime: time.Unix(1360601116, 0),
|
||||
Typeflag: TypeDir,
|
||||
},
|
||||
fm: 0755 | os.ModeDir,
|
||||
fm: 0755 | fs.ModeDir,
|
||||
}, {
|
||||
// fifo node.
|
||||
h: &Header{
|
||||
|
|
@ -401,7 +401,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
|||
ModTime: time.Unix(1360578949, 0),
|
||||
Typeflag: TypeFifo,
|
||||
},
|
||||
fm: 0600 | os.ModeNamedPipe,
|
||||
fm: 0600 | fs.ModeNamedPipe,
|
||||
}, {
|
||||
// setuid.
|
||||
h: &Header{
|
||||
|
|
@ -411,7 +411,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
|||
ModTime: time.Unix(1355405093, 0),
|
||||
Typeflag: TypeReg,
|
||||
},
|
||||
fm: 0755 | os.ModeSetuid,
|
||||
fm: 0755 | fs.ModeSetuid,
|
||||
}, {
|
||||
// setguid.
|
||||
h: &Header{
|
||||
|
|
@ -421,7 +421,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
|||
ModTime: time.Unix(1360602346, 0),
|
||||
Typeflag: TypeReg,
|
||||
},
|
||||
fm: 0750 | os.ModeSetgid,
|
||||
fm: 0750 | fs.ModeSetgid,
|
||||
}, {
|
||||
// sticky.
|
||||
h: &Header{
|
||||
|
|
@ -431,7 +431,7 @@ func TestHeaderRoundTrip(t *testing.T) {
|
|||
ModTime: time.Unix(1360602540, 0),
|
||||
Typeflag: TypeReg,
|
||||
},
|
||||
fm: 0600 | os.ModeSticky,
|
||||
fm: 0600 | fs.ModeSticky,
|
||||
}, {
|
||||
// hard link.
|
||||
h: &Header{
|
||||
|
|
@ -804,9 +804,9 @@ func Benchmark(b *testing.B) {
|
|||
b.Run(v.label, func(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
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.
|
||||
tw := NewWriter(ioutil.Discard)
|
||||
tw := NewWriter(io.Discard)
|
||||
for _, file := range v.files {
|
||||
if err := tw.WriteHeader(file.hdr); err != nil {
|
||||
b.Errorf("unexpected WriteHeader error: %v", err)
|
||||
|
|
@ -844,7 +844,7 @@ func Benchmark(b *testing.B) {
|
|||
if _, err := tr.Next(); err != nil {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
"encoding/hex"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
|
|
@ -520,7 +519,7 @@ func TestWriter(t *testing.T) {
|
|||
}
|
||||
|
||||
if v.file != "" {
|
||||
want, err := ioutil.ReadFile(v.file)
|
||||
want, err := os.ReadFile(v.file)
|
||||
if err != nil {
|
||||
t.Fatalf("ReadFile() = %v, want nil", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,12 @@ import (
|
|||
"hash"
|
||||
"hash/crc32"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -21,18 +26,28 @@ var (
|
|||
ErrChecksum = errors.New("zip: checksum error")
|
||||
)
|
||||
|
||||
// A Reader serves content from a ZIP archive.
|
||||
type Reader struct {
|
||||
r io.ReaderAt
|
||||
File []*File
|
||||
Comment string
|
||||
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 {
|
||||
f *os.File
|
||||
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 {
|
||||
FileHeader
|
||||
zip *Reader
|
||||
|
|
@ -187,6 +202,10 @@ type checksumReader struct {
|
|||
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) {
|
||||
if r.err != nil {
|
||||
return 0, r.err
|
||||
|
|
@ -607,3 +626,173 @@ func (b *readBuf) sub(n int) readBuf {
|
|||
*b = (*b)[n:]
|
||||
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 fs.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,13 @@ import (
|
|||
"encoding/hex"
|
||||
"internal/obscuretestdata"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
"testing/fstest"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -30,7 +31,7 @@ type ZipTest struct {
|
|||
|
||||
type ZipTestFile struct {
|
||||
Name string
|
||||
Mode os.FileMode
|
||||
Mode fs.FileMode
|
||||
NonUTF8 bool
|
||||
ModTime time.Time
|
||||
Modified time.Time
|
||||
|
|
@ -107,7 +108,7 @@ var tests = []ZipTest{
|
|||
Name: "symlink",
|
||||
Content: []byte("../target"),
|
||||
Modified: time.Date(2012, 2, 3, 19, 56, 48, 0, timeZone(-2*time.Hour)),
|
||||
Mode: 0777 | os.ModeSymlink,
|
||||
Mode: 0777 | fs.ModeSymlink,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -149,7 +150,7 @@ var tests = []ZipTest{
|
|||
Name: "dir/empty/",
|
||||
Content: []byte{},
|
||||
Modified: time.Date(2011, 12, 8, 10, 8, 6, 0, time.UTC),
|
||||
Mode: os.ModeDir | 0777,
|
||||
Mode: fs.ModeDir | 0777,
|
||||
},
|
||||
{
|
||||
Name: "readonly",
|
||||
|
|
@ -179,7 +180,7 @@ var tests = []ZipTest{
|
|||
Name: "dir/empty/",
|
||||
Content: []byte{},
|
||||
Modified: time.Date(2011, 12, 8, 10, 8, 6, 0, timeZone(0)),
|
||||
Mode: os.ModeDir | 0777,
|
||||
Mode: fs.ModeDir | 0777,
|
||||
},
|
||||
{
|
||||
Name: "readonly",
|
||||
|
|
@ -627,7 +628,7 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
|
|||
var c []byte
|
||||
if ft.Content != nil {
|
||||
c = ft.Content
|
||||
} else if c, err = ioutil.ReadFile("testdata/" + ft.File); err != nil {
|
||||
} else if c, err = os.ReadFile("testdata/" + ft.File); err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
|
|
@ -645,7 +646,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()
|
||||
if want == 0 {
|
||||
t.Errorf("%s mode: got %v, want none", f.Name, mode)
|
||||
|
|
@ -683,7 +684,7 @@ func TestInvalidFiles(t *testing.T) {
|
|||
}
|
||||
|
||||
func messWith(fileName string, corrupter func(b []byte)) (r io.ReaderAt, size int64) {
|
||||
data, err := ioutil.ReadFile(filepath.Join("testdata", fileName))
|
||||
data, err := os.ReadFile(filepath.Join("testdata", fileName))
|
||||
if err != nil {
|
||||
panic("Error reading " + fileName + ": " + err.Error())
|
||||
}
|
||||
|
|
@ -790,17 +791,17 @@ func returnRecursiveZip() (r io.ReaderAt, size int64) {
|
|||
//
|
||||
// func main() {
|
||||
// bigZip := makeZip("big.file", io.LimitReader(zeros{}, 1<<32-1))
|
||||
// if err := ioutil.WriteFile("/tmp/big.zip", bigZip, 0666); err != nil {
|
||||
// if err := os.WriteFile("/tmp/big.zip", bigZip, 0666); err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
//
|
||||
// biggerZip := makeZip("big.zip", bytes.NewReader(bigZip))
|
||||
// if err := ioutil.WriteFile("/tmp/bigger.zip", biggerZip, 0666); err != nil {
|
||||
// if err := os.WriteFile("/tmp/bigger.zip", biggerZip, 0666); err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
//
|
||||
// biggestZip := makeZip("bigger.zip", bytes.NewReader(biggerZip))
|
||||
// if err := ioutil.WriteFile("/tmp/biggest.zip", biggestZip, 0666); err != nil {
|
||||
// if err := os.WriteFile("/tmp/biggest.zip", biggestZip, 0666); err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
// }
|
||||
|
|
@ -928,7 +929,7 @@ func returnBigZipBytes() (r io.ReaderAt, size int64) {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
b, err = ioutil.ReadAll(f)
|
||||
b, err = io.ReadAll(f)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
|
@ -985,7 +986,7 @@ func TestIssue10957(t *testing.T) {
|
|||
continue
|
||||
}
|
||||
if f.UncompressedSize64 < 1e6 {
|
||||
n, err := io.Copy(ioutil.Discard, r)
|
||||
n, err := io.Copy(io.Discard, r)
|
||||
if i == 3 && err != io.ErrUnexpectedEOF {
|
||||
t.Errorf("File[3] error = %v; want io.ErrUnexpectedEOF", err)
|
||||
}
|
||||
|
|
@ -1027,7 +1028,7 @@ func TestIssue11146(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, err = ioutil.ReadAll(r)
|
||||
_, err = io.ReadAll(r)
|
||||
if err != io.ErrUnexpectedEOF {
|
||||
t.Errorf("File[0] error = %v; want io.ErrUnexpectedEOF", err)
|
||||
}
|
||||
|
|
@ -1070,3 +1071,13 @@ func TestIssue12449(t *testing.T) {
|
|||
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"
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
)
|
||||
|
||||
|
|
@ -111,7 +110,7 @@ func init() {
|
|||
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 }))
|
||||
|
||||
decompressors.Store(Store, Decompressor(ioutil.NopCloser))
|
||||
decompressors.Store(Store, Decompressor(io.NopCloser))
|
||||
decompressors.Store(Deflate, Decompressor(newFlateReader))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ fields must be used instead.
|
|||
package zip
|
||||
|
||||
import (
|
||||
"os"
|
||||
"io/fs"
|
||||
"path"
|
||||
"time"
|
||||
)
|
||||
|
|
@ -137,12 +137,12 @@ type FileHeader struct {
|
|||
ExternalAttrs uint32 // Meaning depends on CreatorVersion
|
||||
}
|
||||
|
||||
// FileInfo returns an os.FileInfo for the FileHeader.
|
||||
func (h *FileHeader) FileInfo() os.FileInfo {
|
||||
// FileInfo returns an fs.FileInfo for the FileHeader.
|
||||
func (h *FileHeader) FileInfo() fs.FileInfo {
|
||||
return headerFileInfo{h}
|
||||
}
|
||||
|
||||
// headerFileInfo implements os.FileInfo.
|
||||
// headerFileInfo implements fs.FileInfo.
|
||||
type headerFileInfo struct {
|
||||
fh *FileHeader
|
||||
}
|
||||
|
|
@ -161,17 +161,20 @@ func (fi headerFileInfo) ModTime() time.Time {
|
|||
}
|
||||
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) Info() (fs.FileInfo, error) { return fi, nil }
|
||||
|
||||
// FileInfoHeader creates a partially-populated FileHeader from an
|
||||
// os.FileInfo.
|
||||
// Because os.FileInfo's Name method returns only the base name of
|
||||
// fs.FileInfo.
|
||||
// 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
|
||||
// of the returned header to provide the full path name of the file.
|
||||
// If compression is desired, callers should set the FileHeader.Method
|
||||
// field; it is unset by default.
|
||||
func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) {
|
||||
func FileInfoHeader(fi fs.FileInfo) (*FileHeader, error) {
|
||||
size := fi.Size()
|
||||
fh := &FileHeader{
|
||||
Name: fi.Name(),
|
||||
|
|
@ -280,7 +283,7 @@ const (
|
|||
)
|
||||
|
||||
// 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 {
|
||||
case creatorUnix, creatorMacOSX:
|
||||
mode = unixModeToFileMode(h.ExternalAttrs >> 16)
|
||||
|
|
@ -288,18 +291,18 @@ func (h *FileHeader) Mode() (mode os.FileMode) {
|
|||
mode = msdosModeToFileMode(h.ExternalAttrs)
|
||||
}
|
||||
if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' {
|
||||
mode |= os.ModeDir
|
||||
mode |= fs.ModeDir
|
||||
}
|
||||
return mode
|
||||
}
|
||||
|
||||
// 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.ExternalAttrs = fileModeToUnixMode(mode) << 16
|
||||
|
||||
// set MSDOS attributes too, as the original zip does.
|
||||
if mode&os.ModeDir != 0 {
|
||||
if mode&fs.ModeDir != 0 {
|
||||
h.ExternalAttrs |= msdosDir
|
||||
}
|
||||
if mode&0200 == 0 {
|
||||
|
|
@ -312,9 +315,9 @@ func (h *FileHeader) isZip64() bool {
|
|||
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 {
|
||||
mode = os.ModeDir | 0777
|
||||
mode = fs.ModeDir | 0777
|
||||
} else {
|
||||
mode = 0666
|
||||
}
|
||||
|
|
@ -324,64 +327,64 @@ func msdosModeToFileMode(m uint32) (mode os.FileMode) {
|
|||
return mode
|
||||
}
|
||||
|
||||
func fileModeToUnixMode(mode os.FileMode) uint32 {
|
||||
func fileModeToUnixMode(mode fs.FileMode) uint32 {
|
||||
var m uint32
|
||||
switch mode & os.ModeType {
|
||||
switch mode & fs.ModeType {
|
||||
default:
|
||||
m = s_IFREG
|
||||
case os.ModeDir:
|
||||
case fs.ModeDir:
|
||||
m = s_IFDIR
|
||||
case os.ModeSymlink:
|
||||
case fs.ModeSymlink:
|
||||
m = s_IFLNK
|
||||
case os.ModeNamedPipe:
|
||||
case fs.ModeNamedPipe:
|
||||
m = s_IFIFO
|
||||
case os.ModeSocket:
|
||||
case fs.ModeSocket:
|
||||
m = s_IFSOCK
|
||||
case os.ModeDevice:
|
||||
if mode&os.ModeCharDevice != 0 {
|
||||
case fs.ModeDevice:
|
||||
if mode&fs.ModeCharDevice != 0 {
|
||||
m = s_IFCHR
|
||||
} else {
|
||||
m = s_IFBLK
|
||||
}
|
||||
}
|
||||
if mode&os.ModeSetuid != 0 {
|
||||
if mode&fs.ModeSetuid != 0 {
|
||||
m |= s_ISUID
|
||||
}
|
||||
if mode&os.ModeSetgid != 0 {
|
||||
if mode&fs.ModeSetgid != 0 {
|
||||
m |= s_ISGID
|
||||
}
|
||||
if mode&os.ModeSticky != 0 {
|
||||
if mode&fs.ModeSticky != 0 {
|
||||
m |= s_ISVTX
|
||||
}
|
||||
return m | uint32(mode&0777)
|
||||
}
|
||||
|
||||
func unixModeToFileMode(m uint32) os.FileMode {
|
||||
mode := os.FileMode(m & 0777)
|
||||
func unixModeToFileMode(m uint32) fs.FileMode {
|
||||
mode := fs.FileMode(m & 0777)
|
||||
switch m & s_IFMT {
|
||||
case s_IFBLK:
|
||||
mode |= os.ModeDevice
|
||||
mode |= fs.ModeDevice
|
||||
case s_IFCHR:
|
||||
mode |= os.ModeDevice | os.ModeCharDevice
|
||||
mode |= fs.ModeDevice | fs.ModeCharDevice
|
||||
case s_IFDIR:
|
||||
mode |= os.ModeDir
|
||||
mode |= fs.ModeDir
|
||||
case s_IFIFO:
|
||||
mode |= os.ModeNamedPipe
|
||||
mode |= fs.ModeNamedPipe
|
||||
case s_IFLNK:
|
||||
mode |= os.ModeSymlink
|
||||
mode |= fs.ModeSymlink
|
||||
case s_IFREG:
|
||||
// nothing to do
|
||||
case s_IFSOCK:
|
||||
mode |= os.ModeSocket
|
||||
mode |= fs.ModeSocket
|
||||
}
|
||||
if m&s_ISGID != 0 {
|
||||
mode |= os.ModeSetgid
|
||||
mode |= fs.ModeSetgid
|
||||
}
|
||||
if m&s_ISUID != 0 {
|
||||
mode |= os.ModeSetuid
|
||||
mode |= fs.ModeSetuid
|
||||
}
|
||||
if m&s_ISVTX != 0 {
|
||||
mode |= os.ModeSticky
|
||||
mode |= fs.ModeSticky
|
||||
}
|
||||
return mode
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"io/fs"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strings"
|
||||
|
|
@ -23,7 +23,7 @@ type WriteTest struct {
|
|||
Name string
|
||||
Data []byte
|
||||
Method uint16
|
||||
Mode os.FileMode
|
||||
Mode fs.FileMode
|
||||
}
|
||||
|
||||
var writeTests = []WriteTest{
|
||||
|
|
@ -43,19 +43,19 @@ var writeTests = []WriteTest{
|
|||
Name: "setuid",
|
||||
Data: []byte("setuid file"),
|
||||
Method: Deflate,
|
||||
Mode: 0755 | os.ModeSetuid,
|
||||
Mode: 0755 | fs.ModeSetuid,
|
||||
},
|
||||
{
|
||||
Name: "setgid",
|
||||
Data: []byte("setgid file"),
|
||||
Method: Deflate,
|
||||
Mode: 0755 | os.ModeSetgid,
|
||||
Mode: 0755 | fs.ModeSetgid,
|
||||
},
|
||||
{
|
||||
Name: "symlink",
|
||||
Data: []byte("../link/target"),
|
||||
Method: Deflate,
|
||||
Mode: 0755 | os.ModeSymlink,
|
||||
Mode: 0755 | fs.ModeSymlink,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -237,7 +237,7 @@ func TestWriterTime(t *testing.T) {
|
|||
t.Fatalf("unexpected Close error: %v", err)
|
||||
}
|
||||
|
||||
want, err := ioutil.ReadFile("testdata/time-go.zip")
|
||||
want, err := os.ReadFile("testdata/time-go.zip")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected ReadFile error: %v", err)
|
||||
}
|
||||
|
|
@ -301,7 +301,7 @@ func TestWriterFlush(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestWriterDir(t *testing.T) {
|
||||
w := NewWriter(ioutil.Discard)
|
||||
w := NewWriter(io.Discard)
|
||||
dw, err := w.Create("dir/")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -380,7 +380,7 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) {
|
|||
if err != nil {
|
||||
t.Fatal("opening:", err)
|
||||
}
|
||||
b, err := ioutil.ReadAll(rc)
|
||||
b, err := io.ReadAll(rc)
|
||||
if err != nil {
|
||||
t.Fatal("reading:", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import (
|
|||
"hash"
|
||||
"internal/testenv"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
|
|
@ -620,7 +619,7 @@ func testZip64(t testing.TB, size int64) *rleBuffer {
|
|||
t.Fatal("read:", err)
|
||||
}
|
||||
}
|
||||
gotEnd, err := ioutil.ReadAll(rc)
|
||||
gotEnd, err := io.ReadAll(rc)
|
||||
if err != nil {
|
||||
t.Fatal("read end:", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
"testing/iotest"
|
||||
|
|
@ -147,7 +146,7 @@ func TestReader(t *testing.T) {
|
|||
for i := 0; i < len(texts)-1; i++ {
|
||||
texts[i] = str + "\n"
|
||||
all += texts[i]
|
||||
str += string(rune(i)%26 + 'a')
|
||||
str += string(rune(i%26 + 'a'))
|
||||
}
|
||||
texts[len(texts)-1] = all
|
||||
|
||||
|
|
@ -886,7 +885,7 @@ func TestReadEmptyBuffer(t *testing.T) {
|
|||
|
||||
func TestLinesAfterRead(t *testing.T) {
|
||||
l := NewReaderSize(bytes.NewReader([]byte("foo")), minReadBufferSize)
|
||||
_, err := ioutil.ReadAll(l)
|
||||
_, err := io.ReadAll(l)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
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.
|
||||
type writeCountingDiscard int
|
||||
|
||||
|
|
@ -1300,7 +1299,7 @@ func TestReaderReset(t *testing.T) {
|
|||
t.Errorf("buf = %q; want foo", buf)
|
||||
}
|
||||
r.Reset(strings.NewReader("bar bar"))
|
||||
all, err := ioutil.ReadAll(r)
|
||||
all, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -1645,13 +1644,13 @@ func BenchmarkReaderWriteToOptimal(b *testing.B) {
|
|||
buf := make([]byte, bufSize)
|
||||
r := bytes.NewReader(buf)
|
||||
srcReader := NewReaderSize(onlyReader{r}, 1<<10)
|
||||
if _, ok := ioutil.Discard.(io.ReaderFrom); !ok {
|
||||
b.Fatal("ioutil.Discard doesn't support ReaderFrom")
|
||||
if _, ok := io.Discard.(io.ReaderFrom); !ok {
|
||||
b.Fatal("io.Discard doesn't support ReaderFrom")
|
||||
}
|
||||
for i := 0; i < b.N; i++ {
|
||||
r.Seek(0, io.SeekStart)
|
||||
srcReader.Reset(onlyReader{r})
|
||||
n, err := srcReader.WriteTo(ioutil.Discard)
|
||||
n, err := srcReader.WriteTo(io.Discard)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
|
@ -1722,7 +1721,7 @@ func BenchmarkReaderEmpty(b *testing.B) {
|
|||
str := strings.Repeat("x", 16<<10)
|
||||
for i := 0; i < b.N; i++ {
|
||||
br := NewReader(strings.NewReader(str))
|
||||
n, err := io.Copy(ioutil.Discard, br)
|
||||
n, err := io.Copy(io.Discard, br)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
|
|
@ -1737,7 +1736,7 @@ func BenchmarkWriterEmpty(b *testing.B) {
|
|||
str := strings.Repeat("x", 1<<10)
|
||||
bs := []byte(str)
|
||||
for i := 0; i < b.N; i++ {
|
||||
bw := NewWriter(ioutil.Discard)
|
||||
bw := NewWriter(io.Discard)
|
||||
bw.Flush()
|
||||
bw.WriteByte('a')
|
||||
bw.Flush()
|
||||
|
|
@ -1752,7 +1751,7 @@ func BenchmarkWriterEmpty(b *testing.B) {
|
|||
|
||||
func BenchmarkWriterFlush(b *testing.B) {
|
||||
b.ReportAllocs()
|
||||
bw := NewWriter(ioutil.Discard)
|
||||
bw := NewWriter(io.Discard)
|
||||
str := strings.Repeat("x", 50)
|
||||
for i := 0; i < b.N; i++ {
|
||||
bw.WriteString(str)
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
# Use of this source code is governed by a BSD-style
|
||||
# license that can be found in the LICENSE file.
|
||||
|
||||
# Usage: buildall.sh [-e] [pattern]
|
||||
# Usage: buildall.bash [-e] [pattern]
|
||||
#
|
||||
# buildall.bash builds the standard library for all Go-supported
|
||||
# architectures. It is used by the "all-compile" trybot builder,
|
||||
# architectures. It is used by the "misc-compile" trybot builders,
|
||||
# as a smoke test to quickly flag portability issues.
|
||||
#
|
||||
# Options:
|
||||
|
|
@ -37,12 +37,11 @@ GOROOT="$(cd .. && pwd)"
|
|||
|
||||
gettargets() {
|
||||
../bin/go tool dist list | sed -e 's|/|-|'
|
||||
echo linux-386-387
|
||||
echo linux-arm-arm5
|
||||
}
|
||||
|
||||
selectedtargets() {
|
||||
gettargets | egrep -v 'android-arm|darwin-arm64' | egrep "$pattern"
|
||||
gettargets | egrep "$pattern"
|
||||
}
|
||||
|
||||
# put linux first in the target list to get all the architectures up front.
|
||||
|
|
@ -64,15 +63,11 @@ do
|
|||
echo "### Building $target"
|
||||
export GOOS=$(echo $target | sed 's/-.*//')
|
||||
export GOARCH=$(echo $target | sed 's/.*-//')
|
||||
unset GO386 GOARM
|
||||
unset GOARM
|
||||
if [ "$GOARCH" = "arm5" ]; then
|
||||
export GOARCH=arm
|
||||
export GOARM=5
|
||||
fi
|
||||
if [ "$GOARCH" = "387" ]; then
|
||||
export GOARCH=386
|
||||
export GO386=387
|
||||
fi
|
||||
|
||||
# Build and vet everything.
|
||||
# cmd/go/internal/work/exec.go enables the same vet flags during go test of std cmd
|
||||
|
|
|
|||
|
|
@ -227,19 +227,26 @@ func IndexAny(s []byte, chars string) int {
|
|||
continue
|
||||
}
|
||||
r, width = utf8.DecodeRune(s[i:])
|
||||
if r == utf8.RuneError {
|
||||
for _, r = range chars {
|
||||
if r == utf8.RuneError {
|
||||
if r != utf8.RuneError {
|
||||
// r is 2 to 4 bytes
|
||||
if len(chars) == width {
|
||||
if chars == string(r) {
|
||||
return i
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Use bytealg.IndexString for performance if available.
|
||||
if bytealg.MaxLen >= width {
|
||||
if bytealg.IndexString(chars, string(r)) >= 0 {
|
||||
return i
|
||||
}
|
||||
continue
|
||||
}
|
||||
continue
|
||||
}
|
||||
// r is 2 to 4 bytes. Using strings.Index is more reasonable, but as the bytes
|
||||
// package should not import the strings package, use bytealg.IndexString
|
||||
// instead. And this does not seem to lose much performance.
|
||||
if chars == string(r) || bytealg.IndexString(chars, string(r)) >= 0 {
|
||||
return i
|
||||
for _, ch := range chars {
|
||||
if r == ch {
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
|
|
@ -304,19 +311,26 @@ func LastIndexAny(s []byte, chars string) int {
|
|||
}
|
||||
r, size := utf8.DecodeLastRune(s[:i])
|
||||
i -= size
|
||||
if r == utf8.RuneError {
|
||||
for _, r = range chars {
|
||||
if r == utf8.RuneError {
|
||||
if r != utf8.RuneError {
|
||||
// r is 2 to 4 bytes
|
||||
if len(chars) == size {
|
||||
if chars == string(r) {
|
||||
return i
|
||||
}
|
||||
continue
|
||||
}
|
||||
// Use bytealg.IndexString for performance if available.
|
||||
if bytealg.MaxLen >= size {
|
||||
if bytealg.IndexString(chars, string(r)) >= 0 {
|
||||
return i
|
||||
}
|
||||
continue
|
||||
}
|
||||
continue
|
||||
}
|
||||
// r is 2 to 4 bytes. Using strings.Index is more reasonable, but as the bytes
|
||||
// package should not import the strings package, use bytealg.IndexString
|
||||
// instead. And this does not seem to lose much performance.
|
||||
if chars == string(r) || bytealg.IndexString(chars, string(r)) >= 0 {
|
||||
return i
|
||||
for _, ch := range chars {
|
||||
if r == ch {
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1
|
||||
|
|
|
|||
|
|
@ -30,6 +30,13 @@ func ExampleBuffer_reader() {
|
|||
// Output: Gophers rule!
|
||||
}
|
||||
|
||||
func ExampleBuffer_Bytes() {
|
||||
buf := bytes.Buffer{}
|
||||
buf.Write([]byte{'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'})
|
||||
os.Stdout.Write(buf.Bytes())
|
||||
// Output: hello world
|
||||
}
|
||||
|
||||
func ExampleBuffer_Grow() {
|
||||
var b bytes.Buffer
|
||||
b.Grow(64)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
. "bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
|
@ -235,7 +234,7 @@ func TestReaderCopyNothing(t *testing.T) {
|
|||
type justWriter struct {
|
||||
io.Writer
|
||||
}
|
||||
discard := justWriter{ioutil.Discard} // hide ReadFrom
|
||||
discard := justWriter{io.Discard} // hide ReadFrom
|
||||
|
||||
var with, withOut nErr
|
||||
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.
|
||||
func TestReaderLenSize(t *testing.T) {
|
||||
r := NewReader([]byte("abc"))
|
||||
io.CopyN(ioutil.Discard, r, 1)
|
||||
io.CopyN(io.Discard, r, 1)
|
||||
if r.Len() != 2 {
|
||||
t.Errorf("Len = %d; want 2", r.Len())
|
||||
}
|
||||
|
|
@ -268,7 +267,7 @@ func TestReaderReset(t *testing.T) {
|
|||
if err := r.UnreadRune(); err == nil {
|
||||
t.Errorf("UnreadRune: expected error, got nil")
|
||||
}
|
||||
buf, err := ioutil.ReadAll(r)
|
||||
buf, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Errorf("ReadAll: unexpected error: %v", err)
|
||||
}
|
||||
|
|
@ -314,7 +313,7 @@ func TestReaderZero(t *testing.T) {
|
|||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import (
|
|||
"bufio"
|
||||
"bytes"
|
||||
"internal/testenv"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
|
@ -73,33 +72,41 @@ func testAddr2Line(t *testing.T, exepath, addr string) {
|
|||
if err != nil {
|
||||
t.Fatalf("Stat failed: %v", err)
|
||||
}
|
||||
|
||||
// Debug paths are stored slash-separated, so convert to system-native.
|
||||
srcPath = filepath.FromSlash(srcPath)
|
||||
fi2, err := os.Stat(srcPath)
|
||||
if gorootFinal := os.Getenv("GOROOT_FINAL"); gorootFinal != "" && strings.HasPrefix(srcPath, gorootFinal) {
|
||||
if os.IsNotExist(err) || (err == nil && !os.SameFile(fi1, fi2)) {
|
||||
// srcPath has had GOROOT_FINAL substituted for GOROOT, and it doesn't
|
||||
// match the actual file. GOROOT probably hasn't been moved to its final
|
||||
// location yet, so try the original location instead.
|
||||
|
||||
// If GOROOT_FINAL is set and srcPath is not the file we expect, perhaps
|
||||
// srcPath has had GOROOT_FINAL substituted for GOROOT and GOROOT hasn't been
|
||||
// moved to its final location yet. If so, try the original location instead.
|
||||
if gorootFinal := os.Getenv("GOROOT_FINAL"); gorootFinal != "" &&
|
||||
(os.IsNotExist(err) || (err == nil && !os.SameFile(fi1, fi2))) {
|
||||
// srcPath is clean, but GOROOT_FINAL itself might not be.
|
||||
// (See https://golang.org/issue/41447.)
|
||||
gorootFinal = filepath.Clean(gorootFinal)
|
||||
|
||||
if strings.HasPrefix(srcPath, gorootFinal) {
|
||||
fi2, err = os.Stat(runtime.GOROOT() + strings.TrimPrefix(srcPath, gorootFinal))
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Stat failed: %v", err)
|
||||
}
|
||||
if !os.SameFile(fi1, fi2) {
|
||||
t.Fatalf("addr2line_test.go and %s are not same file", srcPath)
|
||||
}
|
||||
if srcLineNo != "99" {
|
||||
t.Fatalf("line number = %v; want 99", srcLineNo)
|
||||
if srcLineNo != "106" {
|
||||
t.Fatalf("line number = %v; want 106", srcLineNo)
|
||||
}
|
||||
}
|
||||
|
||||
// This is line 98. The test depends on that.
|
||||
// This is line 106. The test depends on that.
|
||||
func TestAddr2Line(t *testing.T) {
|
||||
testenv.MustHaveGoBuild(t)
|
||||
|
||||
tmpDir, err := ioutil.TempDir("", "TestAddr2Line")
|
||||
tmpDir, err := os.MkdirTemp("", "TestAddr2Line")
|
||||
if err != nil {
|
||||
t.Fatal("TempDir failed: ", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ import (
|
|||
"go/token"
|
||||
"go/types"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
|
@ -87,7 +86,10 @@ var contexts = []*build.Context{
|
|||
func contextName(c *build.Context) string {
|
||||
s := c.GOOS + "-" + c.GOARCH
|
||||
if c.CgoEnabled {
|
||||
return s + "-cgo"
|
||||
s += "-cgo"
|
||||
}
|
||||
if c.Dir != "" {
|
||||
s += fmt.Sprintf(" [%s]", c.Dir)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
|
@ -323,15 +325,29 @@ func compareAPI(w io.Writer, features, required, optional, exception []string, a
|
|||
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 {
|
||||
if filename == "" {
|
||||
return nil
|
||||
}
|
||||
bs, err := ioutil.ReadFile(filename)
|
||||
bs, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
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
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
|
|
@ -478,6 +494,9 @@ func (w *Walker) loadImports() {
|
|||
|
||||
cmd := exec.Command(goCmd(), "list", "-e", "-deps", "-json", "std")
|
||||
cmd.Env = listEnv(w.context)
|
||||
if w.context.Dir != "" {
|
||||
cmd.Dir = w.context.Dir
|
||||
}
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
log.Fatalf("loading imports: %v\n%s", err, out)
|
||||
|
|
@ -491,6 +510,7 @@ func (w *Walker) loadImports() {
|
|||
var pkg struct {
|
||||
ImportPath, Dir string
|
||||
ImportMap map[string]string
|
||||
Standard bool
|
||||
}
|
||||
err := dec.Decode(&pkg)
|
||||
if err == io.EOF {
|
||||
|
|
@ -503,11 +523,13 @@ func (w *Walker) loadImports() {
|
|||
// - Package "unsafe" contains special signatures requiring
|
||||
// extra care when printing them - ignore since it is not
|
||||
// going to change w/o a language change.
|
||||
// - internal and vendored packages do not contribute to our
|
||||
// API surface.
|
||||
// - Internal and vendored packages do not contribute to our
|
||||
// API surface. (If we are running within the "std" module,
|
||||
// vendored dependencies appear as themselves instead of
|
||||
// their "vendor/" standard-library copies.)
|
||||
// - 'go list std' does not include commands, which cannot be
|
||||
// imported anyway.
|
||||
if ip := pkg.ImportPath; ip != "unsafe" && !strings.HasPrefix(ip, "vendor/") && !internalPkg.MatchString(ip) {
|
||||
if ip := pkg.ImportPath; pkg.Standard && ip != "unsafe" && !strings.HasPrefix(ip, "vendor/") && !internalPkg.MatchString(ip) {
|
||||
stdPackages = append(stdPackages, ip)
|
||||
}
|
||||
importDir[pkg.ImportPath] = pkg.Dir
|
||||
|
|
@ -847,6 +869,10 @@ func (w *Walker) emitObj(obj types.Object) {
|
|||
func (w *Walker) emitType(obj *types.TypeName) {
|
||||
name := obj.Name()
|
||||
typ := obj.Type()
|
||||
if obj.IsAlias() {
|
||||
w.emitf("type %s = %s", name, w.typeString(typ))
|
||||
return
|
||||
}
|
||||
switch typ := typ.Underlying().(type) {
|
||||
case *types.Struct:
|
||||
w.emitStructType(name, typ)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
|
@ -75,7 +74,7 @@ func TestGolden(t *testing.T) {
|
|||
f.Close()
|
||||
}
|
||||
|
||||
bs, err := ioutil.ReadFile(goldenFile)
|
||||
bs, err := os.ReadFile(goldenFile)
|
||||
if err != nil {
|
||||
t.Fatalf("opening golden.txt for package %q: %v", fi.Name(), err)
|
||||
}
|
||||
|
|
@ -216,3 +215,16 @@ func TestIssue29837(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue41358(t *testing.T) {
|
||||
context := new(build.Context)
|
||||
*context = build.Default
|
||||
context.Dir = filepath.Join(context.GOROOT, "src")
|
||||
|
||||
w := NewWalker(context, context.Dir)
|
||||
for _, pkg := range w.stdPackages {
|
||||
if strings.HasPrefix(pkg, "vendor/") || strings.HasPrefix(pkg, "golang.org/x/") {
|
||||
t.Fatalf("stdPackages contains unexpected package %s", pkg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -535,6 +535,9 @@ func archRISCV64() *Arch {
|
|||
|
||||
// Standard register names.
|
||||
for i := riscv.REG_X0; i <= riscv.REG_X31; i++ {
|
||||
if i == riscv.REG_G {
|
||||
continue
|
||||
}
|
||||
name := fmt.Sprintf("X%d", i-riscv.REG_X0)
|
||||
register[name] = int16(i)
|
||||
}
|
||||
|
|
@ -571,7 +574,7 @@ func archRISCV64() *Arch {
|
|||
register["S8"] = riscv.REG_S8
|
||||
register["S9"] = riscv.REG_S9
|
||||
register["S10"] = riscv.REG_S10
|
||||
register["S11"] = riscv.REG_S11
|
||||
// Skip S11 as it is the g register.
|
||||
register["T3"] = riscv.REG_T3
|
||||
register["T4"] = riscv.REG_T4
|
||||
register["T5"] = riscv.REG_T5
|
||||
|
|
|
|||
|
|
@ -75,13 +75,35 @@ func IsARM64STLXR(op obj.As) bool {
|
|||
arm64.ASTXP, arm64.ASTXPW, arm64.ASTLXP, arm64.ASTLXPW:
|
||||
return true
|
||||
}
|
||||
// atomic instructions
|
||||
// LDADDx/SWPx/CASx atomic instructions
|
||||
if arm64.IsAtomicInstruction(op) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsARM64TBL reports whether the op (as defined by an arm64.A*
|
||||
// constant) is one of the TBL-like instructions and one of its
|
||||
// inputs does not fit into prog.Reg, so require special handling.
|
||||
func IsARM64TBL(op obj.As) bool {
|
||||
switch op {
|
||||
case arm64.AVTBL, arm64.AVMOVQ:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsARM64CASP reports whether the op (as defined by an arm64.A*
|
||||
// constant) is one of the CASP-like instructions, and its 2nd
|
||||
// destination is a register pair that require special handling.
|
||||
func IsARM64CASP(op obj.As) bool {
|
||||
switch op {
|
||||
case arm64.ACASPD, arm64.ACASPW:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ARM64Suffix handles the special suffix for the ARM64.
|
||||
// It returns a boolean to indicate success; failure means
|
||||
// cond was unrecognized.
|
||||
|
|
@ -125,13 +147,6 @@ func arm64RegisterNumber(name string, n int16) (int16, bool) {
|
|||
return 0, false
|
||||
}
|
||||
|
||||
// IsARM64TBL reports whether the op (as defined by an arm64.A*
|
||||
// constant) is one of the table lookup instructions that require special
|
||||
// handling.
|
||||
func IsARM64TBL(op obj.As) bool {
|
||||
return op == arm64.AVTBL
|
||||
}
|
||||
|
||||
// ARM64RegisterExtension parses an ARM64 register with extension or arrangement.
|
||||
func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
|
||||
Rnum := (reg & 31) + int16(num<<5)
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ func (p *Parser) asmText(operands [][]lex.Token) {
|
|||
// Argsize set below.
|
||||
},
|
||||
}
|
||||
nameAddr.Sym.Func.Text = prog
|
||||
nameAddr.Sym.Func().Text = prog
|
||||
prog.To.Val = int32(argSize)
|
||||
p.append(prog, "", true)
|
||||
}
|
||||
|
|
@ -622,8 +622,9 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
|||
prog.SetFrom3(a[1])
|
||||
prog.To = a[2]
|
||||
case sys.ARM64:
|
||||
// ARM64 instructions with one input and two outputs.
|
||||
if arch.IsARM64STLXR(op) {
|
||||
switch {
|
||||
case arch.IsARM64STLXR(op):
|
||||
// ARM64 instructions with one input and two outputs.
|
||||
prog.From = a[0]
|
||||
prog.To = a[1]
|
||||
if a[2].Type != obj.TYPE_REG {
|
||||
|
|
@ -631,20 +632,28 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
|||
return
|
||||
}
|
||||
prog.RegTo2 = a[2].Reg
|
||||
break
|
||||
}
|
||||
if arch.IsARM64TBL(op) {
|
||||
case arch.IsARM64TBL(op):
|
||||
// one of its inputs does not fit into prog.Reg.
|
||||
prog.From = a[0]
|
||||
if a[1].Type != obj.TYPE_REGLIST {
|
||||
p.errorf("%s: expected list; found %s", op, obj.Dconv(prog, &a[1]))
|
||||
}
|
||||
prog.SetFrom3(a[1])
|
||||
prog.To = a[2]
|
||||
break
|
||||
case arch.IsARM64CASP(op):
|
||||
prog.From = a[0]
|
||||
prog.To = a[1]
|
||||
// both 1st operand and 3rd operand are (Rs, Rs+1) register pair.
|
||||
// And the register pair must be contiguous.
|
||||
if (a[0].Type != obj.TYPE_REGREG) || (a[2].Type != obj.TYPE_REGREG) {
|
||||
p.errorf("invalid addressing modes for 1st or 3rd operand to %s instruction, must be register pair", op)
|
||||
return
|
||||
}
|
||||
// For ARM64 CASP-like instructions, its 2nd destination operand is register pair(Rt, Rt+1) that can
|
||||
// not fit into prog.RegTo2, so save it to the prog.RestArgs.
|
||||
prog.SetTo2(a[2])
|
||||
default:
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
prog.To = a[2]
|
||||
}
|
||||
prog.From = a[0]
|
||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||
prog.To = a[2]
|
||||
case sys.I386:
|
||||
prog.From = a[0]
|
||||
prog.SetFrom3(a[1])
|
||||
|
|
@ -728,7 +737,7 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
|||
}
|
||||
if p.arch.Family == sys.AMD64 {
|
||||
prog.From = a[0]
|
||||
prog.RestArgs = []obj.Addr{a[1], a[2]}
|
||||
prog.SetRestArgs([]obj.Addr{a[1], a[2]})
|
||||
prog.To = a[3]
|
||||
break
|
||||
}
|
||||
|
|
@ -811,13 +820,13 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
|||
}
|
||||
if p.arch.Family == sys.AMD64 {
|
||||
prog.From = a[0]
|
||||
prog.RestArgs = []obj.Addr{a[1], a[2], a[3]}
|
||||
prog.SetRestArgs([]obj.Addr{a[1], a[2], a[3]})
|
||||
prog.To = a[4]
|
||||
break
|
||||
}
|
||||
if p.arch.Family == sys.S390X {
|
||||
prog.From = a[0]
|
||||
prog.RestArgs = []obj.Addr{a[1], a[2], a[3]}
|
||||
prog.SetRestArgs([]obj.Addr{a[1], a[2], a[3]})
|
||||
prog.To = a[4]
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ func testEndToEnd(t *testing.T, goarch, file string) {
|
|||
architecture, ctxt := setArch(goarch)
|
||||
architecture.Init(ctxt)
|
||||
lexer := lex.NewLexer(input)
|
||||
parser := NewParser(ctxt, architecture, lexer)
|
||||
parser := NewParser(ctxt, architecture, lexer, false)
|
||||
pList := new(obj.Plist)
|
||||
var ok bool
|
||||
testOut = new(bytes.Buffer) // The assembler writes test output to this buffer.
|
||||
|
|
@ -257,11 +257,11 @@ func isHexes(s string) bool {
|
|||
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,
|
||||
// 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.
|
||||
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
|
||||
var (
|
||||
|
|
@ -273,7 +273,7 @@ func testErrors(t *testing.T, goarch, file string) {
|
|||
input := filepath.Join("testdata", file+".s")
|
||||
architecture, ctxt := setArch(goarch)
|
||||
lexer := lex.NewLexer(input)
|
||||
parser := NewParser(ctxt, architecture, lexer)
|
||||
parser := NewParser(ctxt, architecture, lexer, false)
|
||||
pList := new(obj.Plist)
|
||||
var ok bool
|
||||
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()
|
||||
failed := false
|
||||
var errBuf bytes.Buffer
|
||||
parser.errorWriter = &errBuf
|
||||
ctxt.DiagFunc = func(format string, args ...interface{}) {
|
||||
failed = true
|
||||
s := fmt.Sprintf(format, args...)
|
||||
|
|
@ -292,7 +293,7 @@ func testErrors(t *testing.T, goarch, file string) {
|
|||
pList.Firstpc, ok = parser.Parse()
|
||||
obj.Flushplist(ctxt, pList, nil, "")
|
||||
if ok && !failed {
|
||||
t.Errorf("asm: %s had no errors", goarch)
|
||||
t.Errorf("asm: %s had no errors", file)
|
||||
}
|
||||
|
||||
errors := map[string]string{}
|
||||
|
|
@ -353,12 +354,7 @@ func testErrors(t *testing.T, goarch, file string) {
|
|||
}
|
||||
|
||||
func Test386EndToEnd(t *testing.T) {
|
||||
defer func(old string) { objabi.GO386 = old }(objabi.GO386)
|
||||
for _, go386 := range []string{"387", "sse2"} {
|
||||
t.Logf("GO386=%v", go386)
|
||||
objabi.GO386 = go386
|
||||
testEndToEnd(t, "386", "386")
|
||||
}
|
||||
testEndToEnd(t, "386", "386")
|
||||
}
|
||||
|
||||
func TestARMEndToEnd(t *testing.T) {
|
||||
|
|
@ -373,6 +369,10 @@ func TestARMEndToEnd(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGoBuildErrors(t *testing.T) {
|
||||
testErrors(t, "amd64", "buildtagerror")
|
||||
}
|
||||
|
||||
func TestARMErrors(t *testing.T) {
|
||||
testErrors(t, "arm", "armerror")
|
||||
}
|
||||
|
|
@ -390,12 +390,7 @@ func TestARM64Errors(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestAMD64EndToEnd(t *testing.T) {
|
||||
defer func(old string) { objabi.GOAMD64 = old }(objabi.GOAMD64)
|
||||
for _, goamd64 := range []string{"normaljumps", "alignedjumps"} {
|
||||
t.Logf("GOAMD64=%s", goamd64)
|
||||
objabi.GOAMD64 = goamd64
|
||||
testEndToEnd(t, "amd64", "amd64")
|
||||
}
|
||||
testEndToEnd(t, "amd64", "amd64")
|
||||
}
|
||||
|
||||
func Test386Encoder(t *testing.T) {
|
||||
|
|
@ -442,10 +437,6 @@ func TestPPC64EndToEnd(t *testing.T) {
|
|||
testEndToEnd(t, "ppc64", "ppc64")
|
||||
}
|
||||
|
||||
func TestPPC64Encoder(t *testing.T) {
|
||||
testEndToEnd(t, "ppc64", "ppc64enc")
|
||||
}
|
||||
|
||||
func TestRISCVEncoder(t *testing.T) {
|
||||
testEndToEnd(t, "riscv64", "riscvenc")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ var exprTests = []exprTest{
|
|||
}
|
||||
|
||||
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 {
|
||||
p.start(lex.Tokenize(test.input))
|
||||
result := int64(p.expr())
|
||||
|
|
@ -113,7 +113,7 @@ func TestBadExpr(t *testing.T) {
|
|||
}
|
||||
|
||||
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))
|
||||
return tryParse(t, func() {
|
||||
p.expr()
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ func testBadInstParser(t *testing.T, goarch string, tests []badInstTest) {
|
|||
for i, test := range tests {
|
||||
arch, ctxt := setArch(goarch)
|
||||
tokenizer := lex.NewTokenizer("", strings.NewReader(test.input+"\n"), nil)
|
||||
parser := NewParser(ctxt, arch, tokenizer)
|
||||
parser := NewParser(ctxt, arch, tokenizer, false)
|
||||
|
||||
err := tryParse(t, func() {
|
||||
parser.Parse()
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ func setArch(goarch string) (*arch.Arch, *obj.Link) {
|
|||
|
||||
func newParser(goarch string) *Parser {
|
||||
architecture, ctxt := setArch(goarch)
|
||||
return NewParser(ctxt, architecture, nil)
|
||||
return NewParser(ctxt, architecture, nil, false)
|
||||
}
|
||||
|
||||
// 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))
|
||||
addr := obj.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 {
|
||||
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")
|
||||
testOperandParser(t, parser, amd64OperandTests)
|
||||
testBadOperandParser(t, parser, amd64BadOperandTests)
|
||||
parser.compilingRuntime = true
|
||||
testOperandParser(t, parser, amd64RuntimeOperandTests)
|
||||
testBadOperandParser(t, parser, amd64BadOperandRuntimeTests)
|
||||
}
|
||||
|
||||
func Test386OperandParser(t *testing.T) {
|
||||
|
|
@ -141,7 +149,7 @@ func TestFuncAddress(t *testing.T) {
|
|||
parser := newParser(sub.arch)
|
||||
for _, test := range sub.tests {
|
||||
parser.start(lex.Tokenize(test.input))
|
||||
name, ok := parser.funcAddress()
|
||||
name, _, ok := parser.funcAddress()
|
||||
|
||||
isFuncSym := strings.HasSuffix(test.input, "(SB)") &&
|
||||
// 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.
|
||||
}
|
||||
|
||||
var amd64RuntimeOperandTests = []operandTest{
|
||||
{"$bar<ABI0>(SB)", "$bar<ABI0>(SB)"},
|
||||
{"$foo<ABIInternal>(SB)", "$foo<ABIInternal>(SB)"},
|
||||
}
|
||||
|
||||
var amd64BadOperandTests = []badOperandTest{
|
||||
{"[", "register list: expected ']', found EOF"},
|
||||
{"[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,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{
|
||||
|
|
|
|||
|
|
@ -25,24 +25,26 @@ import (
|
|||
)
|
||||
|
||||
type Parser struct {
|
||||
lex lex.TokenReader
|
||||
lineNum int // Line number in source file.
|
||||
errorLine int // Line number of last error.
|
||||
errorCount int // Number of errors.
|
||||
pc int64 // virtual PC; count of Progs; doesn't advance for GLOBL or DATA.
|
||||
input []lex.Token
|
||||
inputPos int
|
||||
pendingLabels []string // Labels to attach to next instruction.
|
||||
labels map[string]*obj.Prog
|
||||
toPatch []Patch
|
||||
addr []obj.Addr
|
||||
arch *arch.Arch
|
||||
ctxt *obj.Link
|
||||
firstProg *obj.Prog
|
||||
lastProg *obj.Prog
|
||||
dataAddr map[string]int64 // Most recent address for DATA for this symbol.
|
||||
isJump bool // Instruction being assembled is a jump.
|
||||
errorWriter io.Writer
|
||||
lex lex.TokenReader
|
||||
lineNum int // Line number in source file.
|
||||
errorLine int // Line number of last error.
|
||||
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.
|
||||
input []lex.Token
|
||||
inputPos int
|
||||
pendingLabels []string // Labels to attach to next instruction.
|
||||
labels map[string]*obj.Prog
|
||||
toPatch []Patch
|
||||
addr []obj.Addr
|
||||
arch *arch.Arch
|
||||
ctxt *obj.Link
|
||||
firstProg *obj.Prog
|
||||
lastProg *obj.Prog
|
||||
dataAddr map[string]int64 // Most recent address for DATA for this symbol.
|
||||
isJump bool // Instruction being assembled is a jump.
|
||||
compilingRuntime bool
|
||||
errorWriter io.Writer
|
||||
}
|
||||
|
||||
type Patch struct {
|
||||
|
|
@ -50,14 +52,15 @@ type Patch struct {
|
|||
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{
|
||||
ctxt: ctxt,
|
||||
arch: ar,
|
||||
lex: lexer,
|
||||
labels: make(map[string]*obj.Prog),
|
||||
dataAddr: make(map[string]int64),
|
||||
errorWriter: os.Stderr,
|
||||
ctxt: ctxt,
|
||||
arch: ar,
|
||||
lex: lexer,
|
||||
labels: make(map[string]*obj.Prog),
|
||||
dataAddr: make(map[string]int64),
|
||||
errorWriter: os.Stderr,
|
||||
compilingRuntime: compilingRuntime,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,6 +135,30 @@ func (p *Parser) ParseSymABIs(w io.Writer) bool {
|
|||
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
|
||||
//
|
||||
// {label:} WORD[.cond] [ arg {, arg} ] (';' | '\n')
|
||||
|
|
@ -146,7 +173,7 @@ next:
|
|||
// Skip newlines.
|
||||
var tok lex.ScanToken
|
||||
for {
|
||||
tok = p.lex.Next()
|
||||
tok = p.nextToken()
|
||||
// We save the line number here so error messages from this instruction
|
||||
// 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.
|
||||
|
|
@ -179,11 +206,11 @@ next:
|
|||
items = make([]lex.Token, 0, 3)
|
||||
}
|
||||
for {
|
||||
tok = p.lex.Next()
|
||||
tok = p.nextToken()
|
||||
if len(operands) == 0 && len(items) == 0 {
|
||||
if p.arch.InFamily(sys.ARM, sys.ARM64, sys.AMD64, sys.I386) && tok == '.' {
|
||||
// Suffixes: ARM conditionals or x86 modifiers.
|
||||
tok = p.lex.Next()
|
||||
tok = p.nextToken()
|
||||
str := p.lex.Text()
|
||||
if tok != scanner.Ident {
|
||||
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].
|
||||
if len(operands) > 0 {
|
||||
p.start(operands[0])
|
||||
if name, ok := p.funcAddress(); ok {
|
||||
fmt.Fprintf(w, "def %s ABI0\n", name)
|
||||
if name, abi, ok := p.funcAddress(); ok {
|
||||
fmt.Fprintf(w, "def %s %s\n", name, abi)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
|
@ -304,8 +331,8 @@ func (p *Parser) symDefRef(w io.Writer, word string, operands [][]lex.Token) {
|
|||
// Search for symbol references.
|
||||
for _, op := range operands {
|
||||
p.start(op)
|
||||
if name, ok := p.funcAddress(); ok {
|
||||
fmt.Fprintf(w, "ref %s ABI0\n", name)
|
||||
if name, abi, ok := p.funcAddress(); ok {
|
||||
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 '*':
|
||||
a.Type = obj.TYPE_INDIR
|
||||
}
|
||||
// Weirdness with statics: Might now have "<>".
|
||||
isStatic := false
|
||||
if p.peek() == '<' {
|
||||
isStatic = true
|
||||
p.next()
|
||||
p.get('>')
|
||||
}
|
||||
|
||||
// Parse optional <> (indicates a static symbol) or
|
||||
// <ABIxxx> (selecting text symbol with specific ABI).
|
||||
doIssueError := true
|
||||
isStatic, abi := p.symRefAttrs(name, doIssueError)
|
||||
|
||||
if p.peek() == '+' || p.peek() == '-' {
|
||||
a.Offset = int64(p.expr())
|
||||
}
|
||||
if isStatic {
|
||||
a.Sym = p.ctxt.LookupStatic(name)
|
||||
} else {
|
||||
a.Sym = p.ctxt.Lookup(name)
|
||||
a.Sym = p.ctxt.LookupABI(name, abi)
|
||||
}
|
||||
if p.peek() == scanner.EOF {
|
||||
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
|
||||
// constrained form of the operand syntax that's always SB-based,
|
||||
// non-static, and has at most a simple integer offset:
|
||||
//
|
||||
// [$|*]sym[+Int](SB)
|
||||
func (p *Parser) funcAddress() (string, bool) {
|
||||
// [$|*]sym[<abi>][+Int](SB)
|
||||
func (p *Parser) funcAddress() (string, obj.ABI, bool) {
|
||||
switch p.peek() {
|
||||
case '$', '*':
|
||||
// Skip prefix.
|
||||
|
|
@ -813,25 +887,32 @@ func (p *Parser) funcAddress() (string, bool) {
|
|||
tok := p.next()
|
||||
name := tok.String()
|
||||
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()
|
||||
if tok.ScanToken == '+' {
|
||||
if p.next().ScanToken != scanner.Int {
|
||||
return "", false
|
||||
return "", obj.ABI0, false
|
||||
}
|
||||
tok = p.next()
|
||||
}
|
||||
if tok.ScanToken != '(' {
|
||||
return "", false
|
||||
return "", obj.ABI0, false
|
||||
}
|
||||
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 {
|
||||
return "", false
|
||||
return "", obj.ABI0, false
|
||||
}
|
||||
return name, true
|
||||
return name, abi, true
|
||||
}
|
||||
|
||||
// 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:(SB, 0, $1", "expected '(', found 0"}, // Issue 12468.
|
||||
{"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", "(SB ", "expect two operands for FUNCDATA"},
|
||||
{"DATA", "", "expect two operands for DATA"},
|
||||
|
|
|
|||
809
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
809
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
|
|
@ -10,14 +10,8 @@
|
|||
|
||||
TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||
|
||||
//
|
||||
// ADD
|
||||
//
|
||||
// LTYPE1 imsr ',' spreg ',' reg
|
||||
// {
|
||||
// outcode($1, &$2, $4, &$6);
|
||||
// }
|
||||
// imsr comes from the old 7a, we only support immediates and registers
|
||||
|
||||
// arithmetic operations
|
||||
ADDW $1, R2, R3
|
||||
ADDW R1, R2, R3
|
||||
ADDW R1, ZR, R3
|
||||
|
|
@ -25,18 +19,29 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
ADD R1, R2, R3
|
||||
ADD R1, ZR, R3
|
||||
ADD $1, R2, R3
|
||||
ADD $0x000aaa, R2, R3 // ADD $2730, R2, R3 // 43a82a91
|
||||
ADD $0x000aaa, R2 // ADD $2730, R2 // 42a82a91
|
||||
ADD $0xaaa000, R2, R3 // ADD $11182080, R2, R3 // 43a86a91
|
||||
ADD $0xaaa000, R2 // ADD $11182080, R2 // 42a86a91
|
||||
ADD $0xaaaaaa, R2, R3 // ADD $11184810, R2, R3 // 43a82a9163a86a91
|
||||
ADD $0xaaaaaa, R2 // ADD $11184810, R2 // 42a82a9142a86a91
|
||||
SUB $0x000aaa, R2, R3 // SUB $2730, R2, R3 // 43a82ad1
|
||||
SUB $0x000aaa, R2 // SUB $2730, R2 // 42a82ad1
|
||||
SUB $0xaaa000, R2, R3 // SUB $11182080, R2, R3 // 43a86ad1
|
||||
SUB $0xaaa000, R2 // SUB $11182080, R2 // 42a86ad1
|
||||
SUB $0xaaaaaa, R2, R3 // SUB $11184810, R2, R3 // 43a82ad163a86ad1
|
||||
SUB $0xaaaaaa, R2 // SUB $11184810, R2 // 42a82ad142a86ad1
|
||||
ADDW $1, R2
|
||||
ADDW R1, R2
|
||||
ADD $1, R2
|
||||
ADD R1, R2
|
||||
ADD R1>>11, R2
|
||||
ADD R1<<22, R2
|
||||
ADD R1->33, R2
|
||||
ADD $0x000aaa, R2, R3 // ADD $2730, R2, R3 // 43a82a91
|
||||
ADD $0x000aaa, R2 // ADD $2730, R2 // 42a82a91
|
||||
ADD $0xaaa000, R2, R3 // ADD $11182080, R2, R3 // 43a86a91
|
||||
ADD $0xaaa000, R2 // ADD $11182080, R2 // 42a86a91
|
||||
ADD $0xaaaaaa, R2, R3 // ADD $11184810, R2, R3 // 43a82a9163a86a91
|
||||
ADD $0xaaaaaa, R2 // ADD $11184810, R2 // 42a82a9142a86a91
|
||||
SUB $0x000aaa, R2, R3 // SUB $2730, R2, R3 // 43a82ad1
|
||||
SUB $0x000aaa, R2 // SUB $2730, R2 // 42a82ad1
|
||||
SUB $0xaaa000, R2, R3 // SUB $11182080, R2, R3 // 43a86ad1
|
||||
SUB $0xaaa000, R2 // SUB $11182080, R2 // 42a86ad1
|
||||
SUB $0xaaaaaa, R2, R3 // SUB $11184810, R2, R3 // 43a82ad163a86ad1
|
||||
SUB $0xaaaaaa, R2 // SUB $11184810, R2 // 42a82ad142a86ad1
|
||||
ADDW $0x60060, R2 // ADDW $393312, R2 // 4280011142804111
|
||||
ADD $0x186a0, R2, R5 // ADD $100000, R2, R5 // 45801a91a5604091
|
||||
SUB $0xe7791f700, R3, R1 // SUB $62135596800, R3, R1 // 1be09ed23bf2aef2db01c0f261001bcb
|
||||
ADD $0x3fffffffc000, R5 // ADD $70368744161280, R5 // fb7f72b2a5001b8b
|
||||
ADD R1>>11, R2, R3
|
||||
ADD R1<<22, R2, R3
|
||||
ADD R1->33, R2, R3
|
||||
|
|
@ -59,6 +64,30 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
CMN R1.SXTX<<2, R10 // 5fe921ab
|
||||
CMPW R2.UXTH<<3, R11 // 7f2d226b
|
||||
CMNW R1.SXTB, R9 // 3f81212b
|
||||
CMPW $0x60060, R2 // CMPW $393312, R2 // 1b0c8052db00a0725f001b6b
|
||||
CMPW $40960, R0 // 1f284071
|
||||
CMPW $27745, R2 // 3b8c8d525f001b6b
|
||||
CMNW $0x3fffffc0, R2 // CMNW $1073741760, R2 // fb5f1a325f001b2b
|
||||
CMPW $0xffff0, R1 // CMPW $1048560, R1 // fb3f1c323f001b6b
|
||||
CMP $0xffffffffffa0, R3 // CMP $281474976710560, R3 // fb0b80921b00e0f27f001beb
|
||||
CMP $0xf4240, R1 // CMP $1000000, R1 // 1b4888d2fb01a0f23f001beb
|
||||
CMP $3343198598084851058, R3 // 5bae8ed2db8daef23badcdf2bbcce5f27f001beb
|
||||
CMP $3, R2
|
||||
CMP R1, R2
|
||||
CMP R1->11, R2
|
||||
CMP R1>>22, R2
|
||||
CMP R1<<33, R2
|
||||
CMP R22.SXTX, RSP // ffe336eb
|
||||
CMP $0x22220000, RSP // CMP $572653568, RSP // 5b44a4d2ff633beb
|
||||
CMPW $0x22220000, RSP // CMPW $572653568, RSP // 5b44a452ff633b6b
|
||||
CCMN MI, ZR, R1, $4 // e44341ba
|
||||
// MADD Rn,Rm,Ra,Rd
|
||||
MADD R1, R2, R3, R4 // 6408019b
|
||||
// CLS
|
||||
CLSW R1, R2
|
||||
CLS R1, R2
|
||||
|
||||
// fp/simd instructions.
|
||||
VADDP V1.B16, V2.B16, V3.B16 // 43bc214e
|
||||
VADDP V1.S4, V2.S4, V3.S4 // 43bca14e
|
||||
VADDP V1.D2, V2.D2, V3.D2 // 43bce14e
|
||||
|
|
@ -67,20 +96,6 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
VORR V5.B16, V4.B16, V3.B16 // 831ca54e
|
||||
VADD V16.S4, V5.S4, V9.S4 // a984b04e
|
||||
VEOR V0.B16, V1.B16, V0.B16 // 201c206e
|
||||
SHA256H V9.S4, V3, V2 // 6240095e
|
||||
SHA256H2 V9.S4, V4, V3 // 8350095e
|
||||
SHA256SU0 V8.S4, V7.S4 // 0729285e
|
||||
SHA256SU1 V6.S4, V5.S4, V7.S4 // a760065e
|
||||
SHA1SU0 V11.S4, V8.S4, V6.S4 // 06310b5e
|
||||
SHA1SU1 V5.S4, V1.S4 // a118285e
|
||||
SHA1C V1.S4, V2, V3 // 4300015e
|
||||
SHA1H V5, V4 // a408285e
|
||||
SHA1M V8.S4, V7, V6 // e620085e
|
||||
SHA1P V11.S4, V10, V9 // 49110b5e
|
||||
SHA512H V2.D2, V1, V0 // 208062ce
|
||||
SHA512H2 V4.D2, V3, V2 // 628464ce
|
||||
SHA512SU0 V9.D2, V8.D2 // 2881c0ce
|
||||
SHA512SU1 V7.D2, V6.D2, V5.D2 // c58867ce
|
||||
VADDV V0.S4, V0 // 00b8b14e
|
||||
VMOVI $82, V0.B16 // 40e6024f
|
||||
VUADDLV V6.B16, V6 // c638306e
|
||||
|
|
@ -94,10 +109,6 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
VFMLS V1.D2, V12.D2, V1.D2 // 81cde14e
|
||||
VFMLS V1.S2, V12.S2, V1.S2 // 81cda10e
|
||||
VFMLS V1.S4, V12.S4, V1.S4 // 81cda14e
|
||||
VPMULL V2.D1, V1.D1, V3.Q1 // 23e0e20e
|
||||
VPMULL2 V2.D2, V1.D2, V4.Q1 // 24e0e24e
|
||||
VPMULL V2.B8, V1.B8, V3.H8 // 23e0220e
|
||||
VPMULL2 V2.B16, V1.B16, V4.H8 // 24e0224e
|
||||
VEXT $4, V2.B8, V1.B8, V3.B8 // 2320022e
|
||||
VEXT $8, V2.B16, V1.B16, V3.B16 // 2340026e
|
||||
VRBIT V24.B16, V24.B16 // 185b606e
|
||||
|
|
@ -123,6 +134,14 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
VSRI $8, V1.H8, V2.H8 // 2244186f
|
||||
VSRI $2, V1.B8, V2.B8 // 22440e2f
|
||||
VSRI $2, V1.B16, V2.B16 // 22440e6f
|
||||
VSLI $7, V2.B16, V3.B16 // 43540f6f
|
||||
VSLI $15, V3.H4, V4.H4 // 64541f2f
|
||||
VSLI $31, V5.S4, V6.S4 // a6543f6f
|
||||
VSLI $63, V7.D2, V8.D2 // e8547f6f
|
||||
VUSRA $8, V2.B16, V3.B16 // 4314086f
|
||||
VUSRA $16, V3.H4, V4.H4 // 6414102f
|
||||
VUSRA $32, V5.S4, V6.S4 // a614206f
|
||||
VUSRA $64, V7.D2, V8.D2 // e814406f
|
||||
VTBL V22.B16, [V28.B16, V29.B16], V11.B16 // 8b23164e
|
||||
VTBL V18.B8, [V17.B16, V18.B16, V19.B16], V22.B8 // 3642120e
|
||||
VTBL V31.B8, [V14.B16, V15.B16, V16.B16, V17.B16], V15.B8 // cf611f0e
|
||||
|
|
@ -145,108 +164,126 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
VZIP2 V10.D2, V13.D2, V3.D2 // a379ca4e
|
||||
VZIP1 V17.S2, V4.S2, V26.S2 // 9a38910e
|
||||
VZIP2 V25.S2, V14.S2, V25.S2 // d979990e
|
||||
MOVD (R2)(R6.SXTW), R4 // 44c866f8
|
||||
MOVD (R3)(R6), R5 // MOVD (R3)(R6*1), R5 // 656866f8
|
||||
MOVD (R2)(R6), R4 // MOVD (R2)(R6*1), R4 // 446866f8
|
||||
MOVWU (R19)(R20<<2), R20 // 747a74b8
|
||||
MOVD (R2)(R6<<3), R4 // 447866f8
|
||||
MOVD (R3)(R7.SXTX<<3), R8 // 68f867f8
|
||||
MOVWU (R5)(R4.UXTW), R10 // aa4864b8
|
||||
MOVBU (R3)(R9.UXTW), R8 // 68486938
|
||||
MOVBU (R5)(R8), R10 // MOVBU (R5)(R8*1), R10 // aa686838
|
||||
MOVHU (R2)(R7.SXTW<<1), R11 // 4bd86778
|
||||
MOVHU (R1)(R2<<1), R5 // 25786278
|
||||
MOVB (R9)(R3.UXTW), R6 // 2649a338
|
||||
MOVB (R10)(R6), R15 // MOVB (R10)(R6*1), R15 // 4f69a638
|
||||
MOVH (R5)(R7.SXTX<<1), R19 // b3f8a778
|
||||
MOVH (R8)(R4<<1), R10 // 0a79a478
|
||||
MOVW (R9)(R8.SXTW<<2), R19 // 33d9a8b8
|
||||
MOVW (R1)(R4.SXTX), R11 // 2be8a4b8
|
||||
MOVW (R1)(R4.SXTX), ZR // 3fe8a4b8
|
||||
MOVW (R2)(R5), R12 // MOVW (R2)(R5*1), R12 // 4c68a5b8
|
||||
MOVD R5, (R2)(R6<<3) // 457826f8
|
||||
MOVD R9, (R6)(R7.SXTX<<3) // c9f827f8
|
||||
MOVD ZR, (R6)(R7.SXTX<<3) // dff827f8
|
||||
MOVW R8, (R2)(R3.UXTW<<2) // 485823b8
|
||||
MOVW R7, (R3)(R4.SXTW) // 67c824b8
|
||||
MOVB R4, (R2)(R6.SXTX) // 44e82638
|
||||
MOVB R8, (R3)(R9.UXTW) // 68482938
|
||||
MOVB R10, (R5)(R8) // MOVB R10, (R5)(R8*1) // aa682838
|
||||
MOVH R11, (R2)(R7.SXTW<<1) // 4bd82778
|
||||
MOVH R5, (R1)(R2<<1) // 25782278
|
||||
MOVH R7, (R2)(R5.SXTX<<1) // 47f82578
|
||||
MOVH R8, (R3)(R6.UXTW) // 68482678
|
||||
MOVB (R29)(R30<<0), R14 // ae7bbe38
|
||||
MOVB (R29)(R30), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38
|
||||
MOVB R4, (R2)(R6.SXTX) // 44e82638
|
||||
VUXTL V30.B8, V30.H8 // dea7082f
|
||||
VUXTL V30.H4, V29.S4 // dda7102f
|
||||
VUXTL V29.S2, V2.D2 // a2a7202f
|
||||
VUXTL2 V30.H8, V30.S4 // dea7106f
|
||||
VUXTL2 V29.S4, V2.D2 // a2a7206f
|
||||
VUXTL2 V30.B16, V2.H8 // c2a7086f
|
||||
VBIT V21.B16, V25.B16, V4.B16 // 241fb56e
|
||||
VBSL V23.B16, V3.B16, V7.B16 // 671c776e
|
||||
VCMTST V2.B8, V29.B8, V2.B8 // a28f220e
|
||||
VCMTST V2.D2, V23.D2, V3.D2 // e38ee24e
|
||||
VSUB V2.B8, V30.B8, V30.B8 // de87222e
|
||||
VUZP1 V0.B8, V30.B8, V1.B8 // c11b000e
|
||||
VUZP1 V1.B16, V29.B16, V2.B16 // a21b014e
|
||||
VUZP1 V2.H4, V28.H4, V3.H4 // 831b420e
|
||||
VUZP1 V3.H8, V27.H8, V4.H8 // 641b434e
|
||||
VUZP1 V28.S2, V2.S2, V5.S2 // 45189c0e
|
||||
VUZP1 V29.S4, V1.S4, V6.S4 // 26189d4e
|
||||
VUZP1 V30.D2, V0.D2, V7.D2 // 0718de4e
|
||||
VUZP2 V0.D2, V30.D2, V1.D2 // c15bc04e
|
||||
VUZP2 V30.D2, V0.D2, V29.D2 // 1d58de4e
|
||||
VUSHLL $0, V30.B8, V30.H8 // dea7082f
|
||||
VUSHLL $0, V30.H4, V29.S4 // dda7102f
|
||||
VUSHLL $0, V29.S2, V2.D2 // a2a7202f
|
||||
VUSHLL2 $0, V30.B16, V2.H8 // c2a7086f
|
||||
VUSHLL2 $0, V30.H8, V30.S4 // dea7106f
|
||||
VUSHLL2 $0, V29.S4, V2.D2 // a2a7206f
|
||||
VUSHLL $7, V30.B8, V30.H8 // dea70f2f
|
||||
VUSHLL $15, V30.H4, V29.S4 // dda71f2f
|
||||
VUSHLL2 $31, V30.S4, V2.D2 // c2a73f6f
|
||||
VBIF V0.B8, V30.B8, V1.B8 // c11fe02e
|
||||
VBIF V30.B16, V0.B16, V2.B16 // 021cfe6e
|
||||
FMOVS $(4.0), F0 // 0010221e
|
||||
FMOVD $(4.0), F0 // 0010621e
|
||||
FMOVS $(0.265625), F1 // 01302a1e
|
||||
FMOVD $(0.1796875), F2 // 02f0681e
|
||||
FMOVS $(0.96875), F3 // 03f02d1e
|
||||
FMOVD $(28.0), F4 // 0490671e
|
||||
VUADDW V9.B8, V12.H8, V14.H8 // 8e11292e
|
||||
VUADDW V13.H4, V10.S4, V11.S4 // 4b116d2e
|
||||
VUADDW V21.S2, V24.D2, V29.D2 // 1d13b52e
|
||||
VUADDW2 V9.B16, V12.H8, V14.H8 // 8e11296e
|
||||
VUADDW2 V13.H8, V20.S4, V30.S4 // 9e126d6e
|
||||
VUADDW2 V21.S4, V24.D2, V29.D2 // 1d13b56e
|
||||
FCCMPS LT, F1, F2, $1 // 41b4211e
|
||||
FMADDS F1, F3, F2, F4 // 440c011f
|
||||
FMADDD F4, F5, F4, F4 // 8414441f
|
||||
FMSUBS F13, F21, F13, F19 // b3d50d1f
|
||||
FMSUBD F11, F7, F15, F31 // ff9d4b1f
|
||||
FNMADDS F1, F3, F2, F4 // 440c211f
|
||||
FNMADDD F1, F3, F2, F4 // 440c611f
|
||||
FNMSUBS F1, F3, F2, F4 // 448c211f
|
||||
FNMSUBD F1, F3, F2, F4 // 448c611f
|
||||
FADDS F2, F3, F4 // 6428221e
|
||||
FADDD F1, F2 // 4228611e
|
||||
VDUP V19.S[0], V17.S4 // 7106044e
|
||||
|
||||
FMOVS (R2)(R6), F4 // FMOVS (R2)(R6*1), F4 // 446866bc
|
||||
FMOVS (R2)(R6<<2), F4 // 447866bc
|
||||
FMOVD (R2)(R6), F4 // FMOVD (R2)(R6*1), F4 // 446866fc
|
||||
FMOVD (R2)(R6<<3), F4 // 447866fc
|
||||
FMOVS F4, (R2)(R6) // FMOVS F4, (R2)(R6*1) // 446826bc
|
||||
FMOVS F4, (R2)(R6<<2) // 447826bc
|
||||
FMOVD F4, (R2)(R6) // FMOVD F4, (R2)(R6*1) // 446826fc
|
||||
FMOVD F4, (R2)(R6<<3) // 447826fc
|
||||
|
||||
CMPW $40960, R0 // 1f284071
|
||||
CMPW $27745, R2 // 3b8c8d525f001b6b
|
||||
CMNW $0x3fffffc0, R2 // CMNW $1073741760, R2 // fb5f1a325f001b2b
|
||||
CMPW $0xffff0, R1 // CMPW $1048560, R1 // fb3f1c323f001b6b
|
||||
CMP $0xffffffffffa0, R3 // CMP $281474976710560, R3 // fb0b80921b00e0f27f001beb
|
||||
CMP $0xf4240, R1 // CMP $1000000, R1 // 1b4888d2fb01a0f23f001beb
|
||||
ADD $0x186a0, R2, R5 // ADD $100000, R2, R5 // 45801a91a5604091
|
||||
SUB $0xe7791f700, R3, R1 // SUB $62135596800, R3, R1 // 1be09ed23bf2aef2db01c0f261001bcb
|
||||
CMP $3343198598084851058, R3 // 5bae8ed2db8daef23badcdf2bbcce5f27f001beb
|
||||
ADD $0x3fffffffc000, R5 // ADD $70368744161280, R5 // fb7f72b2a5001b8b
|
||||
// LTYPE1 imsr ',' spreg ','
|
||||
// {
|
||||
// outcode($1, &$2, $4, &nullgen);
|
||||
// }
|
||||
// LTYPE1 imsr ',' reg
|
||||
// {
|
||||
// outcode($1, &$2, NREG, &$4);
|
||||
// }
|
||||
ADDW $1, R2
|
||||
ADDW R1, R2
|
||||
ADD $1, R2
|
||||
ADD R1, R2
|
||||
ADD R1>>11, R2
|
||||
ADD R1<<22, R2
|
||||
ADD R1->33, R2
|
||||
AND R1@>33, R2
|
||||
// special
|
||||
PRFM (R2), PLDL1KEEP // 400080f9
|
||||
PRFM 16(R2), PLDL1KEEP // 400880f9
|
||||
PRFM 48(R6), PSTL2STRM // d31880f9
|
||||
PRFM 8(R12), PLIL3STRM // 8d0580f9
|
||||
PRFM (R8), $25 // 190180f9
|
||||
PRFM 8(R9), $30 // 3e0580f9
|
||||
NOOP // 1f2003d5
|
||||
HINT $0 // 1f2003d5
|
||||
DMB $1
|
||||
SVC
|
||||
|
||||
// encryption
|
||||
SHA256H V9.S4, V3, V2 // 6240095e
|
||||
SHA256H2 V9.S4, V4, V3 // 8350095e
|
||||
SHA256SU0 V8.S4, V7.S4 // 0729285e
|
||||
SHA256SU1 V6.S4, V5.S4, V7.S4 // a760065e
|
||||
SHA1SU0 V11.S4, V8.S4, V6.S4 // 06310b5e
|
||||
SHA1SU1 V5.S4, V1.S4 // a118285e
|
||||
SHA1C V1.S4, V2, V3 // 4300015e
|
||||
SHA1H V5, V4 // a408285e
|
||||
SHA1M V8.S4, V7, V6 // e620085e
|
||||
SHA1P V11.S4, V10, V9 // 49110b5e
|
||||
SHA512H V2.D2, V1, V0 // 208062ce
|
||||
SHA512H2 V4.D2, V3, V2 // 628464ce
|
||||
SHA512SU0 V9.D2, V8.D2 // 2881c0ce
|
||||
SHA512SU1 V7.D2, V6.D2, V5.D2 // c58867ce
|
||||
VRAX1 V26.D2, V29.D2, V30.D2 // be8f7ace
|
||||
VXAR $63, V27.D2, V21.D2, V26.D2 // bafe9bce
|
||||
VPMULL V2.D1, V1.D1, V3.Q1 // 23e0e20e
|
||||
VPMULL2 V2.D2, V1.D2, V4.Q1 // 24e0e24e
|
||||
VPMULL V2.B8, V1.B8, V3.H8 // 23e0220e
|
||||
VPMULL2 V2.B16, V1.B16, V4.H8 // 24e0224e
|
||||
VEOR3 V2.B16, V7.B16, V12.B16, V25.B16 // 990907ce
|
||||
VBCAX V1.B16, V2.B16, V26.B16, V31.B16 // 5f0722ce
|
||||
VREV32 V5.B16, V5.B16 // a508206e
|
||||
VREV64 V2.S2, V3.S2 // 4308a00e
|
||||
VREV64 V2.S4, V3.S4 // 4308a04e
|
||||
|
||||
// logical ops
|
||||
//
|
||||
// make sure constants get encoded into an instruction when it could
|
||||
AND $(1<<63), R1 // AND $-9223372036854775808, R1 // 21004192
|
||||
AND $(1<<63-1), R1 // AND $9223372036854775807, R1 // 21f84092
|
||||
ORR $(1<<63), R1 // ORR $-9223372036854775808, R1 // 210041b2
|
||||
ORR $(1<<63-1), R1 // ORR $9223372036854775807, R1 // 21f840b2
|
||||
EOR $(1<<63), R1 // EOR $-9223372036854775808, R1 // 210041d2
|
||||
EOR $(1<<63-1), R1 // EOR $9223372036854775807, R1 // 21f840d2
|
||||
|
||||
ANDW $0x3ff00000, R2 // ANDW $1072693248, R2 // 42240c12
|
||||
BICW $0x3ff00000, R2 // BICW $1072693248, R2 // 42540212
|
||||
ORRW $0x3ff00000, R2 // ORRW $1072693248, R2 // 42240c32
|
||||
ORNW $0x3ff00000, R2 // ORNW $1072693248, R2 // 42540232
|
||||
EORW $0x3ff00000, R2 // EORW $1072693248, R2 // 42240c52
|
||||
EONW $0x3ff00000, R2 // EONW $1072693248, R2 // 42540252
|
||||
|
||||
AND $0x22220000, R3, R4 // AND $572653568, R3, R4 // 5b44a4d264001b8a
|
||||
ORR $0x22220000, R3, R4 // ORR $572653568, R3, R4 // 5b44a4d264001baa
|
||||
EOR $0x22220000, R3, R4 // EOR $572653568, R3, R4 // 5b44a4d264001bca
|
||||
BIC $0x22220000, R3, R4 // BIC $572653568, R3, R4 // 5b44a4d264003b8a
|
||||
ORN $0x22220000, R3, R4 // ORN $572653568, R3, R4 // 5b44a4d264003baa
|
||||
EON $0x22220000, R3, R4 // EON $572653568, R3, R4 // 5b44a4d264003bca
|
||||
ANDS $0x22220000, R3, R4 // ANDS $572653568, R3, R4 // 5b44a4d264001bea
|
||||
BICS $0x22220000, R3, R4 // BICS $572653568, R3, R4 // 5b44a4d264003bea
|
||||
|
||||
AND R1@>33, R2
|
||||
AND $(1<<63), R1 // AND $-9223372036854775808, R1 // 21004192
|
||||
AND $(1<<63-1), R1 // AND $9223372036854775807, R1 // 21f84092
|
||||
ORR $(1<<63), R1 // ORR $-9223372036854775808, R1 // 210041b2
|
||||
ORR $(1<<63-1), R1 // ORR $9223372036854775807, R1 // 21f840b2
|
||||
EOR $(1<<63), R1 // EOR $-9223372036854775808, R1 // 210041d2
|
||||
EOR $(1<<63-1), R1 // EOR $9223372036854775807, R1 // 21f840d2
|
||||
ANDW $0x3ff00000, R2 // ANDW $1072693248, R2 // 42240c12
|
||||
BICW $0x3ff00000, R2 // BICW $1072693248, R2 // 42540212
|
||||
ORRW $0x3ff00000, R2 // ORRW $1072693248, R2 // 42240c32
|
||||
ORNW $0x3ff00000, R2 // ORNW $1072693248, R2 // 42540232
|
||||
EORW $0x3ff00000, R2 // EORW $1072693248, R2 // 42240c52
|
||||
EONW $0x3ff00000, R2 // EONW $1072693248, R2 // 42540252
|
||||
AND $0x22220000, R3, R4 // AND $572653568, R3, R4 // 5b44a4d264001b8a
|
||||
ORR $0x22220000, R3, R4 // ORR $572653568, R3, R4 // 5b44a4d264001baa
|
||||
EOR $0x22220000, R3, R4 // EOR $572653568, R3, R4 // 5b44a4d264001bca
|
||||
BIC $0x22220000, R3, R4 // BIC $572653568, R3, R4 // 5b44a4d264003b8a
|
||||
ORN $0x22220000, R3, R4 // ORN $572653568, R3, R4 // 5b44a4d264003baa
|
||||
EON $0x22220000, R3, R4 // EON $572653568, R3, R4 // 5b44a4d264003bca
|
||||
ANDS $0x22220000, R3, R4 // ANDS $572653568, R3, R4 // 5b44a4d264001bea
|
||||
BICS $0x22220000, R3, R4 // BICS $572653568, R3, R4 // 5b44a4d264003bea
|
||||
EOR $0xe03fffffffffffff, R20, R22 // EOR $-2287828610704211969, R20, R22 // 96e243d2
|
||||
TSTW $0x600000006, R1 // TSTW $25769803782, R1 // 3f041f72
|
||||
TST $0x4900000049, R0 // TST $313532612681, R0 // 3b0980d23b09c0f21f001bea
|
||||
|
|
@ -275,19 +312,22 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
EONW $0x6006000060060, R5 // EONW $1689262177517664, R5 // 1b0c8052db00a072a5003b4a
|
||||
ORNW $0x6006000060060, R5 // ORNW $1689262177517664, R5 // 1b0c8052db00a072a5003b2a
|
||||
BICSW $0x6006000060060, R5 // BICSW $1689262177517664, R5 // 1b0c8052db00a072a5003b6a
|
||||
ADDW $0x60060, R2 // ADDW $393312, R2 // 4280011142804111
|
||||
CMPW $0x60060, R2 // CMPW $393312, R2 // 1b0c8052db00a0725f001b6b
|
||||
|
||||
// TODO: this could have better encoding
|
||||
ANDW $-1, R10 // 1b0080124a011b0a
|
||||
|
||||
AND $8, R0, RSP // 1f007d92
|
||||
ORR $8, R0, RSP // 1f007db2
|
||||
EOR $8, R0, RSP // 1f007dd2
|
||||
BIC $8, R0, RSP // 1ff87c92
|
||||
ORN $8, R0, RSP // 1ff87cb2
|
||||
EON $8, R0, RSP // 1ff87cd2
|
||||
ANDW $-1, R10 // 1b0080124a011b0a
|
||||
AND $8, R0, RSP // 1f007d92
|
||||
ORR $8, R0, RSP // 1f007db2
|
||||
EOR $8, R0, RSP // 1f007dd2
|
||||
BIC $8, R0, RSP // 1ff87c92
|
||||
ORN $8, R0, RSP // 1ff87cb2
|
||||
EON $8, R0, RSP // 1ff87cd2
|
||||
TST $15, R2 // 5f0c40f2
|
||||
TST R1, R2 // 5f0001ea
|
||||
TST R1->11, R2 // 5f2c81ea
|
||||
TST R1>>22, R2 // 5f5841ea
|
||||
TST R1<<33, R2 // 5f8401ea
|
||||
TST $0x22220000, R3 // TST $572653568, R3 // 5b44a4d27f001bea
|
||||
|
||||
// move an immediate to a Rn.
|
||||
MOVD $0x3fffffffc000, R0 // MOVD $70368744161280, R0 // e07f72b2
|
||||
MOVW $1000000, R4 // 04488852e401a072
|
||||
MOVW $0xaaaa0000, R1 // MOVW $2863267840, R1 // 4155b552
|
||||
|
|
@ -305,37 +345,39 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
MOVD $0x1111ffff1111aaaa, R1 // MOVD $1230045644216969898, R1 // a1aa8a922122a2f22122e2f2
|
||||
MOVD $0, R1 // 010080d2
|
||||
MOVD $-1, R1 // 01008092
|
||||
MOVD $0x210000, R0 // MOVD $2162688, R0 // 2004a0d2
|
||||
MOVD $0xffffffffffffaaaa, R1 // MOVD $-21846, R1 // a1aa8a92
|
||||
MOVD $0x210000, R0 // MOVD $2162688, R0 // 2004a0d2
|
||||
MOVD $0xffffffffffffaaaa, R1 // MOVD $-21846, R1 // a1aa8a92
|
||||
MOVW $1, ZR
|
||||
MOVW $1, R1
|
||||
MOVD $1, ZR
|
||||
MOVD $1, R1
|
||||
MOVK $1, R1
|
||||
|
||||
//
|
||||
// CLS
|
||||
//
|
||||
// LTYPE2 imsr ',' reg
|
||||
// {
|
||||
// outcode($1, &$2, NREG, &$4);
|
||||
// }
|
||||
CLSW R1, R2
|
||||
CLS R1, R2
|
||||
// move a large constant to a Vd.
|
||||
VMOVS $0x80402010, V11 // VMOVS $2151686160, V11
|
||||
VMOVD $0x8040201008040201, V20 // VMOVD $-9205322385119247871, V20
|
||||
VMOVQ $0x7040201008040201, $0x8040201008040201, V10 // VMOVQ $8088500183983456769, $-9205322385119247871, V10
|
||||
VMOVQ $0x8040201008040202, $0x7040201008040201, V20 // VMOVQ $-9205322385119247870, $8088500183983456769, V20
|
||||
|
||||
//
|
||||
// MOV
|
||||
//
|
||||
// LTYPE3 addr ',' addr
|
||||
// {
|
||||
// outcode($1, &$2, NREG, &$4);
|
||||
// }
|
||||
// mov(to/from sp)
|
||||
MOVD $0x1002(RSP), R1 // MOVD $4098(RSP), R1 // fb074091610b0091
|
||||
MOVD $0x1708(RSP), RSP // MOVD $5896(RSP), RSP // fb0740917f231c91
|
||||
MOVD $0x2001(R7), R1 // MOVD $8193(R7), R1 // fb08409161070091
|
||||
MOVD $0xffffff(R7), R1 // MOVD $16777215(R7), R1 // fbfc7f9161ff3f91
|
||||
MOVD $-0x1(R7), R1 // MOVD $-1(R7), R1 // e10400d1
|
||||
MOVD $-0x30(R7), R1 // MOVD $-48(R7), R1 // e1c000d1
|
||||
MOVD $-0x708(R7), R1 // MOVD $-1800(R7), R1 // e1201cd1
|
||||
MOVD $-0x2000(RSP), R1 // MOVD $-8192(RSP), R1 // e10b40d1
|
||||
MOVD $-0x10000(RSP), RSP // MOVD $-65536(RSP), RSP // ff4340d1
|
||||
MOVW R1, R2
|
||||
MOVW ZR, R1
|
||||
MOVW R1, ZR
|
||||
MOVW $1, ZR
|
||||
MOVW $1, R1
|
||||
MOVW ZR, (R1)
|
||||
MOVD R1, R2
|
||||
MOVD ZR, R1
|
||||
MOVD $1, ZR
|
||||
MOVD $1, R1
|
||||
MOVD ZR, (R1)
|
||||
|
||||
// store and load
|
||||
//
|
||||
// LD1/ST1
|
||||
VLD1 (R8), [V1.B16, V2.B16] // 01a1404c
|
||||
VLD1.P (R3), [V31.H8, V0.H8] // 7fa4df4c
|
||||
VLD1.P (R8)(R20), [V21.B16, V22.B16] // VLD1.P (R8)(R20*1), [V21.B16,V22.B16] // 15a1d44c
|
||||
|
|
@ -393,34 +435,21 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
VST4 [V22.D2, V23.D2, V24.D2, V25.D2], (R3) // 760c004c
|
||||
VST4.P [V14.D2, V15.D2, V16.D2, V17.D2], 64(R15) // ee0d9f4c
|
||||
VST4.P [V24.B8, V25.B8, V26.B8, V27.B8], (R3)(R23) // VST4.P [V24.B8, V25.B8, V26.B8, V27.B8], (R3)(R23*1) // 7800970c
|
||||
FMOVS F20, (R0) // 140000bd
|
||||
|
||||
// pre/post-indexed
|
||||
FMOVS.P F20, 4(R0) // 144400bc
|
||||
FMOVS.W F20, 4(R0) // 144c00bc
|
||||
FMOVS (R0), F20 // 140040bd
|
||||
FMOVD.P F20, 8(R1) // 348400fc
|
||||
FMOVQ.P F13, 11(R10) // 4db5803c
|
||||
FMOVQ.W F15, 11(R20) // 8fbe803c
|
||||
|
||||
FMOVS.P 8(R0), F20 // 148440bc
|
||||
FMOVS.W 8(R0), F20 // 148c40bc
|
||||
FMOVD F20, (R2) // 540000fd
|
||||
FMOVD.P F20, 8(R1) // 348400fc
|
||||
FMOVD.W 8(R1), F20 // 348c40fc
|
||||
PRFM (R2), PLDL1KEEP // 400080f9
|
||||
PRFM 16(R2), PLDL1KEEP // 400880f9
|
||||
PRFM 48(R6), PSTL2STRM // d31880f9
|
||||
PRFM 8(R12), PLIL3STRM // 8d0580f9
|
||||
PRFM (R8), $25 // 190180f9
|
||||
PRFM 8(R9), $30 // 3e0580f9
|
||||
FMOVQ.P 11(R10), F13 // 4db5c03c
|
||||
FMOVQ.W 11(R20), F15 // 8fbec03c
|
||||
|
||||
// small offset fits into instructions
|
||||
MOVB 1(R1), R2 // 22048039
|
||||
MOVH 1(R1), R2 // 22108078
|
||||
MOVH 2(R1), R2 // 22048079
|
||||
MOVW 1(R1), R2 // 221080b8
|
||||
MOVW 4(R1), R2 // 220480b9
|
||||
MOVD 1(R1), R2 // 221040f8
|
||||
MOVD 8(R1), R2 // 220440f9
|
||||
FMOVS 1(R1), F2 // 221040bc
|
||||
FMOVS 4(R1), F2 // 220440bd
|
||||
FMOVD 1(R1), F2 // 221040fc
|
||||
FMOVD 8(R1), F2 // 220440fd
|
||||
// small offset fits into instructions
|
||||
MOVB R1, 1(R2) // 41040039
|
||||
MOVH R1, 1(R2) // 41100078
|
||||
MOVH R1, 2(R2) // 41040079
|
||||
|
|
@ -428,18 +457,37 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
MOVW R1, 4(R2) // 410400b9
|
||||
MOVD R1, 1(R2) // 411000f8
|
||||
MOVD R1, 8(R2) // 410400f9
|
||||
MOVD ZR, (R1)
|
||||
MOVW ZR, (R1)
|
||||
FMOVS F1, 1(R2) // 411000bc
|
||||
FMOVS F1, 4(R2) // 410400bd
|
||||
FMOVS F20, (R0) // 140000bd
|
||||
FMOVD F1, 1(R2) // 411000fc
|
||||
FMOVD F1, 8(R2) // 410400fd
|
||||
FMOVD F20, (R2) // 540000fd
|
||||
FMOVQ F0, 32(R5)// a008803d
|
||||
FMOVQ F10, 65520(R10) // 4afdbf3d
|
||||
FMOVQ F11, 64(RSP) // eb13803d
|
||||
FMOVQ F11, 8(R20) // 8b82803c
|
||||
FMOVQ F11, 4(R20) // 8b42803c
|
||||
|
||||
// large aligned offset, use two instructions
|
||||
MOVB 0x1001(R1), R2 // MOVB 4097(R1), R2 // 3b04409162078039
|
||||
MOVH 0x2002(R1), R2 // MOVH 8194(R1), R2 // 3b08409162078079
|
||||
MOVW 0x4004(R1), R2 // MOVW 16388(R1), R2 // 3b104091620780b9
|
||||
MOVD 0x8008(R1), R2 // MOVD 32776(R1), R2 // 3b204091620740f9
|
||||
FMOVS 0x4004(R1), F2 // FMOVS 16388(R1), F2 // 3b104091620740bd
|
||||
FMOVD 0x8008(R1), F2 // FMOVD 32776(R1), F2 // 3b204091620740fd
|
||||
MOVB 1(R1), R2 // 22048039
|
||||
MOVH 1(R1), R2 // 22108078
|
||||
MOVH 2(R1), R2 // 22048079
|
||||
MOVW 1(R1), R2 // 221080b8
|
||||
MOVW 4(R1), R2 // 220480b9
|
||||
MOVD 1(R1), R2 // 221040f8
|
||||
MOVD 8(R1), R2 // 220440f9
|
||||
FMOVS (R0), F20 // 140040bd
|
||||
FMOVS 1(R1), F2 // 221040bc
|
||||
FMOVS 4(R1), F2 // 220440bd
|
||||
FMOVD 1(R1), F2 // 221040fc
|
||||
FMOVD 8(R1), F2 // 220440fd
|
||||
FMOVQ 32(R5), F2 // a208c03d
|
||||
FMOVQ 65520(R10), F10 // 4afdff3d
|
||||
FMOVQ 64(RSP), F11 // eb13c03d
|
||||
|
||||
// large aligned offset, use two instructions(add+ldr/store).
|
||||
MOVB R1, 0x1001(R2) // MOVB R1, 4097(R2) // 5b04409161070039
|
||||
MOVH R1, 0x2002(R2) // MOVH R1, 8194(R2) // 5b08409161070079
|
||||
MOVW R1, 0x4004(R2) // MOVW R1, 16388(R2) // 5b104091610700b9
|
||||
|
|
@ -447,15 +495,16 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
FMOVS F1, 0x4004(R2) // FMOVS F1, 16388(R2) // 5b104091610700bd
|
||||
FMOVD F1, 0x8008(R2) // FMOVD F1, 32776(R2) // 5b204091610700fd
|
||||
|
||||
// very large or unaligned offset uses constant pool
|
||||
// the encoding cannot be checked as the address of the constant pool is unknown.
|
||||
// here we only test that they can be assembled.
|
||||
MOVB 0x44332211(R1), R2 // MOVB 1144201745(R1), R2
|
||||
MOVH 0x44332211(R1), R2 // MOVH 1144201745(R1), R2
|
||||
MOVW 0x44332211(R1), R2 // MOVW 1144201745(R1), R2
|
||||
MOVD 0x44332211(R1), R2 // MOVD 1144201745(R1), R2
|
||||
FMOVS 0x44332211(R1), F2 // FMOVS 1144201745(R1), F2
|
||||
FMOVD 0x44332211(R1), F2 // FMOVD 1144201745(R1), F2
|
||||
MOVB 0x1001(R1), R2 // MOVB 4097(R1), R2 // 3b04409162078039
|
||||
MOVH 0x2002(R1), R2 // MOVH 8194(R1), R2 // 3b08409162078079
|
||||
MOVW 0x4004(R1), R2 // MOVW 16388(R1), R2 // 3b104091620780b9
|
||||
MOVD 0x8008(R1), R2 // MOVD 32776(R1), R2 // 3b204091620740f9
|
||||
FMOVS 0x4004(R1), F2 // FMOVS 16388(R1), F2 // 3b104091620740bd
|
||||
FMOVD 0x8008(R1), F2 // FMOVD 32776(R1), F2 // 3b204091620740fd
|
||||
|
||||
// very large or unaligned offset uses constant pool.
|
||||
// the encoding cannot be checked as the address of the constant pool is unknown.
|
||||
// here we only test that they can be assembled.
|
||||
MOVB R1, 0x44332211(R2) // MOVB R1, 1144201745(R2)
|
||||
MOVH R1, 0x44332211(R2) // MOVH R1, 1144201745(R2)
|
||||
MOVW R1, 0x44332211(R2) // MOVW R1, 1144201745(R2)
|
||||
|
|
@ -463,14 +512,59 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
FMOVS F1, 0x44332211(R2) // FMOVS F1, 1144201745(R2)
|
||||
FMOVD F1, 0x44332211(R2) // FMOVD F1, 1144201745(R2)
|
||||
|
||||
//
|
||||
// MOVK
|
||||
//
|
||||
// LMOVK imm ',' reg
|
||||
// {
|
||||
// outcode($1, &$2, NREG, &$4);
|
||||
// }
|
||||
MOVK $1, R1
|
||||
MOVB 0x44332211(R1), R2 // MOVB 1144201745(R1), R2
|
||||
MOVH 0x44332211(R1), R2 // MOVH 1144201745(R1), R2
|
||||
MOVW 0x44332211(R1), R2 // MOVW 1144201745(R1), R2
|
||||
MOVD 0x44332211(R1), R2 // MOVD 1144201745(R1), R2
|
||||
FMOVS 0x44332211(R1), F2 // FMOVS 1144201745(R1), F2
|
||||
FMOVD 0x44332211(R1), F2 // FMOVD 1144201745(R1), F2
|
||||
|
||||
// shifted or extended register offset.
|
||||
MOVD (R2)(R6.SXTW), R4 // 44c866f8
|
||||
MOVD (R3)(R6), R5 // MOVD (R3)(R6*1), R5 // 656866f8
|
||||
MOVD (R2)(R6), R4 // MOVD (R2)(R6*1), R4 // 446866f8
|
||||
MOVWU (R19)(R20<<2), R20 // 747a74b8
|
||||
MOVD (R2)(R6<<3), R4 // 447866f8
|
||||
MOVD (R3)(R7.SXTX<<3), R8 // 68f867f8
|
||||
MOVWU (R5)(R4.UXTW), R10 // aa4864b8
|
||||
MOVBU (R3)(R9.UXTW), R8 // 68486938
|
||||
MOVBU (R5)(R8), R10 // MOVBU (R5)(R8*1), R10 // aa686838
|
||||
MOVHU (R2)(R7.SXTW<<1), R11 // 4bd86778
|
||||
MOVHU (R1)(R2<<1), R5 // 25786278
|
||||
MOVB (R9)(R3.UXTW), R6 // 2649a338
|
||||
MOVB (R10)(R6), R15 // MOVB (R10)(R6*1), R15 // 4f69a638
|
||||
MOVB (R29)(R30<<0), R14 // ae7bbe38
|
||||
MOVB (R29)(R30), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38
|
||||
MOVH (R5)(R7.SXTX<<1), R19 // b3f8a778
|
||||
MOVH (R8)(R4<<1), R10 // 0a79a478
|
||||
MOVW (R9)(R8.SXTW<<2), R19 // 33d9a8b8
|
||||
MOVW (R1)(R4.SXTX), R11 // 2be8a4b8
|
||||
MOVW (R1)(R4.SXTX), ZR // 3fe8a4b8
|
||||
MOVW (R2)(R5), R12 // MOVW (R2)(R5*1), R12 // 4c68a5b8
|
||||
FMOVS (R2)(R6), F4 // FMOVS (R2)(R6*1), F4 // 446866bc
|
||||
FMOVS (R2)(R6<<2), F4 // 447866bc
|
||||
FMOVD (R2)(R6), F4 // FMOVD (R2)(R6*1), F4 // 446866fc
|
||||
FMOVD (R2)(R6<<3), F4 // 447866fc
|
||||
|
||||
MOVD R5, (R2)(R6<<3) // 457826f8
|
||||
MOVD R9, (R6)(R7.SXTX<<3) // c9f827f8
|
||||
MOVD ZR, (R6)(R7.SXTX<<3) // dff827f8
|
||||
MOVW R8, (R2)(R3.UXTW<<2) // 485823b8
|
||||
MOVW R7, (R3)(R4.SXTW) // 67c824b8
|
||||
MOVB R4, (R2)(R6.SXTX) // 44e82638
|
||||
MOVB R8, (R3)(R9.UXTW) // 68482938
|
||||
MOVB R10, (R5)(R8) // MOVB R10, (R5)(R8*1) // aa682838
|
||||
MOVH R11, (R2)(R7.SXTW<<1) // 4bd82778
|
||||
MOVH R5, (R1)(R2<<1) // 25782278
|
||||
MOVH R7, (R2)(R5.SXTX<<1) // 47f82578
|
||||
MOVH R8, (R3)(R6.UXTW) // 68482678
|
||||
MOVB R4, (R2)(R6.SXTX) // 44e82638
|
||||
FMOVS F4, (R2)(R6) // FMOVS F4, (R2)(R6*1) // 446826bc
|
||||
FMOVS F4, (R2)(R6<<2) // 447826bc
|
||||
FMOVD F4, (R2)(R6) // FMOVD F4, (R2)(R6*1) // 446826fc
|
||||
FMOVD F4, (R2)(R6<<3) // 447826fc
|
||||
|
||||
// vmov
|
||||
VMOV V8.S[1], R1 // 013d0c0e
|
||||
VMOV V0.D[0], R11 // 0b3c084e
|
||||
VMOV V0.D[1], R11 // 0b3c184e
|
||||
|
|
@ -485,205 +579,28 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
VMOV V9.H[0], V12.H[1] // 2c05066e
|
||||
VMOV V8.B[0], V12.B[1] // 0c05036e
|
||||
VMOV V8.B[7], V4.B[8] // 043d116e
|
||||
VREV32 V5.B16, V5.B16 // a508206e
|
||||
VREV64 V2.S2, V3.S2 // 4308a00e
|
||||
VREV64 V2.S4, V3.S4 // 4308a04e
|
||||
VDUP V19.S[0], V17.S4 // 7106044e
|
||||
//
|
||||
// B/BL
|
||||
//
|
||||
// LTYPE4 comma rel
|
||||
// {
|
||||
// outcode($1, &nullgen, NREG, &$3);
|
||||
// }
|
||||
BL 1(PC) // CALL 1(PC)
|
||||
|
||||
// LTYPE4 comma nireg
|
||||
// {
|
||||
// outcode($1, &nullgen, NREG, &$3);
|
||||
// }
|
||||
BL (R2) // CALL (R2)
|
||||
BL foo(SB) // CALL foo(SB)
|
||||
BL bar<>(SB) // CALL bar<>(SB)
|
||||
//
|
||||
// BEQ
|
||||
//
|
||||
// LTYPE5 comma rel
|
||||
// {
|
||||
// outcode($1, &nullgen, NREG, &$3);
|
||||
// }
|
||||
BEQ 1(PC)
|
||||
//
|
||||
// SVC
|
||||
//
|
||||
// LTYPE6
|
||||
// {
|
||||
// outcode($1, &nullgen, NREG, &nullgen);
|
||||
// }
|
||||
SVC
|
||||
|
||||
//
|
||||
// CMP
|
||||
//
|
||||
// LTYPE7 imsr ',' spreg comma
|
||||
// {
|
||||
// outcode($1, &$2, $4, &nullgen);
|
||||
// }
|
||||
CMP $3, R2
|
||||
CMP R1, R2
|
||||
CMP R1->11, R2
|
||||
CMP R1>>22, R2
|
||||
CMP R1<<33, R2
|
||||
CMP R22.SXTX, RSP // ffe336eb
|
||||
|
||||
CMP $0x22220000, RSP // CMP $572653568, RSP // 5b44a4d2ff633beb
|
||||
CMPW $0x22220000, RSP // CMPW $572653568, RSP // 5b44a452ff633b6b
|
||||
|
||||
// TST
|
||||
TST $15, R2 // 5f0c40f2
|
||||
TST R1, R2 // 5f0001ea
|
||||
TST R1->11, R2 // 5f2c81ea
|
||||
TST R1>>22, R2 // 5f5841ea
|
||||
TST R1<<33, R2 // 5f8401ea
|
||||
TST $0x22220000, R3 // TST $572653568, R3 // 5b44a4d27f001bea
|
||||
|
||||
//
|
||||
// CBZ
|
||||
//
|
||||
// LTYPE8 reg ',' rel
|
||||
// {
|
||||
// outcode($1, &$2, NREG, &$4);
|
||||
// }
|
||||
again:
|
||||
CBZ R1, again // CBZ R1
|
||||
|
||||
//
|
||||
// CSET
|
||||
//
|
||||
// LTYPER cond ',' reg
|
||||
// {
|
||||
// outcode($1, &$2, NREG, &$4);
|
||||
// }
|
||||
CSET GT, R1 // e1d79f9a
|
||||
CSETW HI, R2 // e2979f1a
|
||||
//
|
||||
// CSEL/CSINC/CSNEG/CSINV
|
||||
//
|
||||
// LTYPES cond ',' reg ',' reg ',' reg
|
||||
// {
|
||||
// outgcode($1, &$2, $6.reg, &$4, &$8);
|
||||
// }
|
||||
// conditional operations
|
||||
CSET GT, R1 // e1d79f9a
|
||||
CSETW HI, R2 // e2979f1a
|
||||
CSEL LT, R1, R2, ZR // 3fb0829a
|
||||
CSELW LT, R2, R3, R4 // 44b0831a
|
||||
CSINC GT, R1, ZR, R3 // 23c49f9a
|
||||
CSNEG MI, R1, R2, R3 // 234482da
|
||||
CSINV CS, R1, R2, R3 // CSINV HS, R1, R2, R3 // 232082da
|
||||
CSINVW MI, R2, ZR, R2 // 42409f5a
|
||||
|
||||
// LTYPES cond ',' reg ',' reg
|
||||
// {
|
||||
// outcode($1, &$2, $4.reg, &$6);
|
||||
// }
|
||||
CINC EQ, R4, R9 // 8914849a
|
||||
CINCW PL, R2, ZR // 5f44821a
|
||||
CINV PL, R11, R22 // 76418bda
|
||||
CINVW LS, R7, R13 // ed80875a
|
||||
CNEG LS, R13, R7 // a7858dda
|
||||
CNEGW EQ, R8, R13 // 0d15885a
|
||||
//
|
||||
// CCMN
|
||||
//
|
||||
// LTYPEU cond ',' imsr ',' reg ',' imm comma
|
||||
// {
|
||||
// outgcode($1, &$2, $6.reg, &$4, &$8);
|
||||
// }
|
||||
CCMN MI, ZR, R1, $4 // e44341ba
|
||||
|
||||
//
|
||||
// FADDD
|
||||
//
|
||||
// LTYPEK frcon ',' freg
|
||||
// {
|
||||
// outcode($1, &$2, NREG, &$4);
|
||||
// }
|
||||
// FADDD $0.5, F1 // FADDD $(0.5), F1
|
||||
FADDD F1, F2
|
||||
|
||||
// LTYPEK frcon ',' freg ',' freg
|
||||
// {
|
||||
// outcode($1, &$2, $4.reg, &$6);
|
||||
// }
|
||||
// FADDD $0.7, F1, F2 // FADDD $(0.69999999999999996), F1, F2
|
||||
FADDD F1, F2, F3
|
||||
|
||||
//
|
||||
// FCMP
|
||||
//
|
||||
// LTYPEL frcon ',' freg comma
|
||||
// {
|
||||
// outcode($1, &$2, $4.reg, &nullgen);
|
||||
// }
|
||||
// FCMP $0.2, F1
|
||||
// FCMP F1, F2
|
||||
|
||||
//
|
||||
// FCCMP
|
||||
//
|
||||
// LTYPEF cond ',' freg ',' freg ',' imm comma
|
||||
// {
|
||||
// outgcode($1, &$2, $6.reg, &$4, &$8);
|
||||
// }
|
||||
FCCMPS LT, F1, F2, $1 // 41b4211e
|
||||
|
||||
//
|
||||
// FMULA
|
||||
//
|
||||
// LTYPE9 freg ',' freg ',' freg ',' freg comma
|
||||
// {
|
||||
// outgcode($1, &$2, $4.reg, &$6, &$8);
|
||||
// }
|
||||
// FMULA F1, F2, F3, F4
|
||||
|
||||
//
|
||||
// FCSEL
|
||||
//
|
||||
// LFCSEL cond ',' freg ',' freg ',' freg
|
||||
// {
|
||||
// outgcode($1, &$2, $6.reg, &$4, &$8);
|
||||
// }
|
||||
//
|
||||
// MADD Rn,Rm,Ra,Rd
|
||||
//
|
||||
// LTYPEM reg ',' reg ',' sreg ',' reg
|
||||
// {
|
||||
// outgcode($1, &$2, $6, &$4, &$8);
|
||||
// }
|
||||
// MADD R1, R2, R3, R4
|
||||
|
||||
FMADDS F1, F3, F2, F4 // 440c011f
|
||||
FMADDD F4, F5, F4, F4 // 8414441f
|
||||
FMSUBS F13, F21, F13, F19 // b3d50d1f
|
||||
FMSUBD F11, F7, F15, F31 // ff9d4b1f
|
||||
FNMADDS F1, F3, F2, F4 // 440c211f
|
||||
FNMADDD F1, F3, F2, F4 // 440c611f
|
||||
FNMSUBS F1, F3, F2, F4 // 448c211f
|
||||
FNMSUBD F1, F3, F2, F4 // 448c611f
|
||||
|
||||
// DMB, HINT
|
||||
//
|
||||
// LDMB imm
|
||||
// {
|
||||
// outcode($1, &$2, NREG, &nullgen);
|
||||
// }
|
||||
DMB $1
|
||||
|
||||
//
|
||||
// STXR
|
||||
//
|
||||
// LSTXR reg ',' addr ',' reg
|
||||
// {
|
||||
// outcode($1, &$2, &$4, &$6);
|
||||
// }
|
||||
// atomic ops
|
||||
LDARB (R25), R2 // 22ffdf08
|
||||
LDARH (R5), R7 // a7fcdf48
|
||||
LDAXPW (R10), (R20, R16) // 54c17f88
|
||||
|
|
@ -764,38 +681,38 @@ again:
|
|||
LDADDLH R5, (RSP), R7 // e7036578
|
||||
LDADDLB R5, (R6), R7 // c7006538
|
||||
LDADDLB R5, (RSP), R7 // e7036538
|
||||
LDANDAD R5, (R6), R7 // c710a5f8
|
||||
LDANDAD R5, (RSP), R7 // e713a5f8
|
||||
LDANDAW R5, (R6), R7 // c710a5b8
|
||||
LDANDAW R5, (RSP), R7 // e713a5b8
|
||||
LDANDAH R5, (R6), R7 // c710a578
|
||||
LDANDAH R5, (RSP), R7 // e713a578
|
||||
LDANDAB R5, (R6), R7 // c710a538
|
||||
LDANDAB R5, (RSP), R7 // e713a538
|
||||
LDANDALD R5, (R6), R7 // c710e5f8
|
||||
LDANDALD R5, (RSP), R7 // e713e5f8
|
||||
LDANDALW R5, (R6), R7 // c710e5b8
|
||||
LDANDALW R5, (RSP), R7 // e713e5b8
|
||||
LDANDALH R5, (R6), R7 // c710e578
|
||||
LDANDALH R5, (RSP), R7 // e713e578
|
||||
LDANDALB R5, (R6), R7 // c710e538
|
||||
LDANDALB R5, (RSP), R7 // e713e538
|
||||
LDANDD R5, (R6), R7 // c71025f8
|
||||
LDANDD R5, (RSP), R7 // e71325f8
|
||||
LDANDW R5, (R6), R7 // c71025b8
|
||||
LDANDW R5, (RSP), R7 // e71325b8
|
||||
LDANDH R5, (R6), R7 // c7102578
|
||||
LDANDH R5, (RSP), R7 // e7132578
|
||||
LDANDB R5, (R6), R7 // c7102538
|
||||
LDANDB R5, (RSP), R7 // e7132538
|
||||
LDANDLD R5, (R6), R7 // c71065f8
|
||||
LDANDLD R5, (RSP), R7 // e71365f8
|
||||
LDANDLW R5, (R6), R7 // c71065b8
|
||||
LDANDLW R5, (RSP), R7 // e71365b8
|
||||
LDANDLH R5, (R6), R7 // c7106578
|
||||
LDANDLH R5, (RSP), R7 // e7136578
|
||||
LDANDLB R5, (R6), R7 // c7106538
|
||||
LDANDLB R5, (RSP), R7 // e7136538
|
||||
LDCLRAD R5, (R6), R7 // c710a5f8
|
||||
LDCLRAD R5, (RSP), R7 // e713a5f8
|
||||
LDCLRAW R5, (R6), R7 // c710a5b8
|
||||
LDCLRAW R5, (RSP), R7 // e713a5b8
|
||||
LDCLRAH R5, (R6), R7 // c710a578
|
||||
LDCLRAH R5, (RSP), R7 // e713a578
|
||||
LDCLRAB R5, (R6), R7 // c710a538
|
||||
LDCLRAB R5, (RSP), R7 // e713a538
|
||||
LDCLRALD R5, (R6), R7 // c710e5f8
|
||||
LDCLRALD R5, (RSP), R7 // e713e5f8
|
||||
LDCLRALW R5, (R6), R7 // c710e5b8
|
||||
LDCLRALW R5, (RSP), R7 // e713e5b8
|
||||
LDCLRALH R5, (R6), R7 // c710e578
|
||||
LDCLRALH R5, (RSP), R7 // e713e578
|
||||
LDCLRALB R5, (R6), R7 // c710e538
|
||||
LDCLRALB R5, (RSP), R7 // e713e538
|
||||
LDCLRD R5, (R6), R7 // c71025f8
|
||||
LDCLRD R5, (RSP), R7 // e71325f8
|
||||
LDCLRW R5, (R6), R7 // c71025b8
|
||||
LDCLRW R5, (RSP), R7 // e71325b8
|
||||
LDCLRH R5, (R6), R7 // c7102578
|
||||
LDCLRH R5, (RSP), R7 // e7132578
|
||||
LDCLRB R5, (R6), R7 // c7102538
|
||||
LDCLRB R5, (RSP), R7 // e7132538
|
||||
LDCLRLD R5, (R6), R7 // c71065f8
|
||||
LDCLRLD R5, (RSP), R7 // e71365f8
|
||||
LDCLRLW R5, (R6), R7 // c71065b8
|
||||
LDCLRLW R5, (RSP), R7 // e71365b8
|
||||
LDCLRLH R5, (R6), R7 // c7106578
|
||||
LDCLRLH R5, (RSP), R7 // e7136578
|
||||
LDCLRLB R5, (R6), R7 // c7106538
|
||||
LDCLRLB R5, (RSP), R7 // e7136538
|
||||
LDEORAD R5, (R6), R7 // c720a5f8
|
||||
LDEORAD R5, (RSP), R7 // e723a5f8
|
||||
LDEORAW R5, (R6), R7 // c720a5b8
|
||||
|
|
@ -860,21 +777,36 @@ again:
|
|||
LDORLH R5, (RSP), R7 // e7336578
|
||||
LDORLB R5, (R6), R7 // c7306538
|
||||
LDORLB R5, (RSP), R7 // e7336538
|
||||
CASD R1, (R2), ZR // 5f7ca1c8
|
||||
CASW R1, (RSP), ZR // ff7fa188
|
||||
CASB ZR, (R5), R3 // a37cbf08
|
||||
CASH R3, (RSP), ZR // ff7fa348
|
||||
CASW R5, (R7), R6 // e67ca588
|
||||
CASLD ZR, (RSP), R8 // e8ffbfc8
|
||||
CASLW R9, (R10), ZR // 5ffda988
|
||||
CASAD R7, (R11), R15 // 6f7de7c8
|
||||
CASAW R10, (RSP), R19 // f37fea88
|
||||
CASALD R5, (R6), R7 // c7fce5c8
|
||||
CASALD R5, (RSP), R7 // e7ffe5c8
|
||||
CASALW R5, (R6), R7 // c7fce588
|
||||
CASALW R5, (RSP), R7 // e7ffe588
|
||||
CASALH ZR, (R5), R8 // a8fcff48
|
||||
CASALB R8, (R9), ZR // 3ffde808
|
||||
CASPD (R30, ZR), (RSP), (R8, R9) // e87f3e48
|
||||
CASPW (R6, R7), (R8), (R4, R5) // 047d2608
|
||||
CASPD (R2, R3), (R2), (R8, R9) // 487c2248
|
||||
|
||||
// RET
|
||||
//
|
||||
// LTYPEA comma
|
||||
// {
|
||||
// outcode($1, &nullgen, NREG, &nullgen);
|
||||
// }
|
||||
BEQ 2(PC)
|
||||
RET
|
||||
RET foo(SB)
|
||||
|
||||
// More B/BL cases, and canonical names JMP, CALL.
|
||||
|
||||
BEQ 2(PC)
|
||||
B foo(SB) // JMP foo(SB)
|
||||
BL foo(SB) // CALL foo(SB)
|
||||
// B/BL/B.cond cases, and canonical names JMP, CALL.
|
||||
BL 1(PC) // CALL 1(PC)
|
||||
BL (R2) // CALL (R2)
|
||||
BL foo(SB) // CALL foo(SB)
|
||||
BL bar<>(SB) // CALL bar<>(SB)
|
||||
B foo(SB) // JMP foo(SB)
|
||||
BEQ 1(PC)
|
||||
BEQ 2(PC)
|
||||
TBZ $1, R1, 2(PC)
|
||||
TBNZ $2, R2, 2(PC)
|
||||
|
|
@ -1049,8 +981,6 @@ again:
|
|||
FSTPS (F3, F4), 1024(RSP) // fb0310916313002d
|
||||
FSTPS (F3, F4), x(SB)
|
||||
FSTPS (F3, F4), x+8(SB)
|
||||
NOOP // 1f2003d5
|
||||
HINT $0 // 1f2003d5
|
||||
|
||||
// System Register
|
||||
MSR $1, SPSel // bf4100d5
|
||||
|
|
@ -1612,11 +1542,4 @@ again:
|
|||
MSR R13, ZCR_EL1 // 0d1218d5
|
||||
MRS ZCR_EL1, R23 // 171238d5
|
||||
MSR R17, ZCR_EL1 // 111218d5
|
||||
|
||||
// END
|
||||
//
|
||||
// LTYPEE comma
|
||||
// {
|
||||
// outcode($1, &nullgen, NREG, &nullgen);
|
||||
// }
|
||||
END
|
||||
|
|
|
|||
81
src/cmd/asm/internal/asm/testdata/arm64error.s
vendored
81
src/cmd/asm/internal/asm/testdata/arm64error.s
vendored
|
|
@ -87,13 +87,13 @@ TEXT errors(SB),$0
|
|||
VLD1.P 32(R1), [V8.S4, V9.S4, V10.S4] // ERROR "invalid post-increment offset"
|
||||
VLD1.P 48(R1), [V7.S4, V8.S4, V9.S4, V10.S4] // ERROR "invalid post-increment offset"
|
||||
VPMULL V1.D1, V2.H4, V3.Q1 // ERROR "invalid arrangement"
|
||||
VPMULL V1.H4, V2.H4, V3.Q1 // ERROR "invalid arrangement"
|
||||
VPMULL V1.D2, V2.D2, V3.Q1 // ERROR "invalid arrangement"
|
||||
VPMULL V1.B16, V2.B16, V3.H8 // ERROR "invalid arrangement"
|
||||
VPMULL V1.H4, V2.H4, V3.Q1 // ERROR "operand mismatch"
|
||||
VPMULL V1.D2, V2.D2, V3.Q1 // ERROR "operand mismatch"
|
||||
VPMULL V1.B16, V2.B16, V3.H8 // ERROR "operand mismatch"
|
||||
VPMULL2 V1.D2, V2.H4, V3.Q1 // ERROR "invalid arrangement"
|
||||
VPMULL2 V1.H4, V2.H4, V3.Q1 // ERROR "invalid arrangement"
|
||||
VPMULL2 V1.D1, V2.D1, V3.Q1 // ERROR "invalid arrangement"
|
||||
VPMULL2 V1.B8, V2.B8, V3.H8 // ERROR "invalid arrangement"
|
||||
VPMULL2 V1.H4, V2.H4, V3.Q1 // ERROR "operand mismatch"
|
||||
VPMULL2 V1.D1, V2.D1, V3.Q1 // ERROR "operand mismatch"
|
||||
VPMULL2 V1.B8, V2.B8, V3.H8 // ERROR "operand mismatch"
|
||||
VEXT $8, V1.B16, V2.B8, V2.B16 // ERROR "invalid arrangement"
|
||||
VEXT $8, V1.H8, V2.H8, V2.H8 // ERROR "invalid arrangement"
|
||||
VRBIT V1.B16, V2.B8 // ERROR "invalid arrangement"
|
||||
|
|
@ -123,14 +123,14 @@ TEXT errors(SB),$0
|
|||
LDADDLW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDADDLH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDADDLB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDLD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDLW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDLH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDLB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDCLRD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDCLRW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDCLRH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDCLRB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDCLRLD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDCLRLW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDCLRLH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDCLRLB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDEORD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDEORW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDEORH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
|
|
@ -163,22 +163,22 @@ TEXT errors(SB),$0
|
|||
LDADDLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDAB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDALD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDALW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDALH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDALB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDLD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRAB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRALD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRALW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRALH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRALB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRLD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDCLRLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
|
|
@ -340,4 +340,25 @@ TEXT errors(SB),$0
|
|||
MRS PMSWINC_EL0, R3 // ERROR "system register is not readable"
|
||||
MRS OSLAR_EL1, R3 // ERROR "system register is not readable"
|
||||
VLD3R.P 24(R15), [V15.H4,V16.H4,V17.H4] // ERROR "invalid post-increment offset"
|
||||
VBIT V1.H4, V12.H4, V3.H4 // ERROR "invalid arrangement"
|
||||
VBSL V1.D2, V12.D2, V3.D2 // ERROR "invalid arrangement"
|
||||
VUXTL V30.D2, V30.H8 // ERROR "operand mismatch"
|
||||
VUXTL2 V20.B8, V21.H8 // ERROR "operand mismatch"
|
||||
VUXTL V3.D2, V4.B8 // ERROR "operand mismatch"
|
||||
VUZP1 V0.B8, V30.B8, V1.B16 // ERROR "operand mismatch"
|
||||
VUZP2 V0.Q1, V30.Q1, V1.Q1 // ERROR "invalid arrangement"
|
||||
VUSHLL $0, V30.D2, V30.H8 // ERROR "operand mismatch"
|
||||
VUSHLL2 $0, V20.B8, V21.H8 // ERROR "operand mismatch"
|
||||
VUSHLL $8, V30.B8, V30.H8 // ERROR "shift amount out of range"
|
||||
VUSHLL2 $32, V30.S4, V2.D2 // ERROR "shift amount out of range"
|
||||
VBIF V0.B8, V1.B8, V2.B16 // ERROR "operand mismatch"
|
||||
VBIF V0.D2, V1.D2, V2.D2 // ERROR "invalid arrangement"
|
||||
VUADDW V9.B8, V12.H8, V14.B8 // ERROR "invalid arrangement"
|
||||
VUADDW2 V9.B8, V12.S4, V14.S4 // ERROR "operand mismatch"
|
||||
VSLI $64, V7.D2, V8.D2 // ERROR "shift out of range"
|
||||
VUSRA $0, V7.D2, V8.D2 // ERROR "shift out of range"
|
||||
CASPD (R3, R4), (R2), (R8, R9) // ERROR "source register pair must start from even register"
|
||||
CASPD (R2, R3), (R2), (R9, R10) // ERROR "destination register pair must start from even register"
|
||||
CASPD (R2, R4), (R2), (R8, R9) // ERROR "source register pair must be contiguous"
|
||||
CASPD (R2, R3), (R2), (R8, R10) // ERROR "destination register pair must be contiguous"
|
||||
RET
|
||||
|
|
|
|||
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"
|
||||
|
||||
2000
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
2000
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
File diff suppressed because it is too large
Load diff
633
src/cmd/asm/internal/asm/testdata/ppc64enc.s
vendored
633
src/cmd/asm/internal/asm/testdata/ppc64enc.s
vendored
|
|
@ -1,633 +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
|
||||
MULLWCC R3, R4, R5 // 7ca419d7
|
||||
MULHW R3, R4, R5 // 7ca41896
|
||||
|
||||
MULHWU R3, R4, R5 // 7ca41816
|
||||
MULLD R3, R4 // 7c8419d2
|
||||
MULLD R4, R4, R5 // 7ca421d2
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
29
src/cmd/asm/internal/asm/testdata/riscvenc.s
vendored
29
src/cmd/asm/internal/asm/testdata/riscvenc.s
vendored
|
|
@ -297,6 +297,13 @@ start:
|
|||
MOVW X5, (X6) // 23205300
|
||||
MOVW X5, 4(X6) // 23225300
|
||||
|
||||
MOVB X5, X6 // 1393820313538343
|
||||
MOVH X5, X6 // 1393020313530343
|
||||
MOVW X5, X6 // 1b830200
|
||||
MOVBU X5, X6 // 13f3f20f
|
||||
MOVHU X5, X6 // 1393020313530303
|
||||
MOVWU X5, X6 // 1393020213530302
|
||||
|
||||
MOVF 4(X5), F0 // 07a04200
|
||||
MOVF F0, 4(X5) // 27a20200
|
||||
MOVF F0, F1 // d3000020
|
||||
|
|
@ -318,7 +325,7 @@ start:
|
|||
// These jumps can get printed as jumps to 2 because they go to the
|
||||
// second instruction in the function (the first instruction is an
|
||||
// invisible stack pointer adjustment).
|
||||
JMP start // JMP 2 // 6ff01fc5
|
||||
JMP start // JMP 2 // 6ff09fc2
|
||||
JMP (X5) // 67800200
|
||||
JMP 4(X5) // 67804200
|
||||
|
||||
|
|
@ -331,16 +338,16 @@ start:
|
|||
JMP asmtest(SB) // 970f0000
|
||||
|
||||
// Branch pseudo-instructions
|
||||
BEQZ X5, start // BEQZ X5, 2 // e38a02c2
|
||||
BGEZ X5, start // BGEZ X5, 2 // e3d802c2
|
||||
BGT X5, X6, start // BGT X5, X6, 2 // e3c662c2
|
||||
BGTU X5, X6, start // BGTU X5, X6, 2 // e3e462c2
|
||||
BGTZ X5, start // BGTZ X5, 2 // e34250c2
|
||||
BLE X5, X6, start // BLE X5, X6, 2 // e3d062c2
|
||||
BLEU X5, X6, start // BLEU X5, X6, 2 // e3fe62c0
|
||||
BLEZ X5, start // BLEZ X5, 2 // e35c50c0
|
||||
BLTZ X5, start // BLTZ X5, 2 // e3ca02c0
|
||||
BNEZ X5, start // BNEZ X5, 2 // e39802c0
|
||||
BEQZ X5, start // BEQZ X5, 2 // e38602c0
|
||||
BGEZ X5, start // BGEZ X5, 2 // e3d402c0
|
||||
BGT X5, X6, start // BGT X5, X6, 2 // e34253c0
|
||||
BGTU X5, X6, start // BGTU X5, X6, 2 // e36053c0
|
||||
BGTZ X5, start // BGTZ X5, 2 // e34e50be
|
||||
BLE X5, X6, start // BLE X5, X6, 2 // e35c53be
|
||||
BLEU X5, X6, start // BLEU X5, X6, 2 // e37a53be
|
||||
BLEZ X5, start // BLEZ X5, 2 // e35850be
|
||||
BLTZ X5, start // BLTZ X5, 2 // e3c602be
|
||||
BNEZ X5, start // BNEZ X5, 2 // e39402be
|
||||
|
||||
// Set pseudo-instructions
|
||||
SEQZ X15, X15 // 93b71700
|
||||
|
|
|
|||
2
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
2
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
|
|
@ -412,6 +412,8 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
|
|||
UNDEF // 00000000
|
||||
NOPH // 0700
|
||||
|
||||
SYNC // 07e0
|
||||
|
||||
// vector add and sub instructions
|
||||
VAB V3, V4, V4 // e743400000f3
|
||||
VAH V3, V4, V4 // e743400010f3
|
||||
|
|
|
|||
|
|
@ -15,27 +15,30 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
Debug = flag.Bool("debug", false, "dump instructions as they are parsed")
|
||||
OutputFile = flag.String("o", "", "output file; default foo.o for /a/b/c/foo.s as first argument")
|
||||
PrintOut = flag.Bool("S", false, "print assembly and machine code")
|
||||
TrimPath = flag.String("trimpath", "", "remove prefix from recorded source file paths")
|
||||
Shared = flag.Bool("shared", false, "generate code that can be linked into a shared library")
|
||||
Dynlink = flag.Bool("dynlink", false, "support references to Go symbols defined in other shared libraries")
|
||||
AllErrors = flag.Bool("e", false, "no limit on number of errors reported")
|
||||
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")
|
||||
Spectre = flag.String("spectre", "", "enable spectre mitigations in `list` (all, ret)")
|
||||
Debug = flag.Bool("debug", false, "dump instructions as they are parsed")
|
||||
OutputFile = flag.String("o", "", "output file; default foo.o for /a/b/c/foo.s as first argument")
|
||||
TrimPath = flag.String("trimpath", "", "remove prefix from recorded source file paths")
|
||||
Shared = flag.Bool("shared", false, "generate code that can be linked into a shared library")
|
||||
Dynlink = flag.Bool("dynlink", false, "support references to Go symbols defined in other shared libraries")
|
||||
Linkshared = flag.Bool("linkshared", false, "generate code that will be linked against Go shared libraries")
|
||||
AllErrors = flag.Bool("e", false, "no limit on number of errors reported")
|
||||
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")
|
||||
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 (
|
||||
D MultiFlag
|
||||
I MultiFlag
|
||||
D MultiFlag
|
||||
I MultiFlag
|
||||
PrintOut int
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.Var(&D, "D", "predefined symbol with optional simple value -D=identifier=value; can be set multiple times")
|
||||
flag.Var(&I, "I", "include directory; can be set multiple times")
|
||||
objabi.AddVersionFlag() // -V
|
||||
objabi.Flagcount("S", "print assembly and machine code", &PrintOut)
|
||||
}
|
||||
|
||||
// MultiFlag allows setting a value multiple times to collect a list, as in -I=dir1 -I=dir2.
|
||||
|
|
|
|||
|
|
@ -109,6 +109,9 @@ func (in *Input) Next() ScanToken {
|
|||
in.Error("'#' must be first item on line")
|
||||
}
|
||||
in.beginningOfLine = in.hash()
|
||||
in.text = "#"
|
||||
return '#'
|
||||
|
||||
case scanner.Ident:
|
||||
// Is it a macro name?
|
||||
name := in.Stack.Text()
|
||||
|
|
|
|||
|
|
@ -22,11 +22,13 @@ type ScanToken rune
|
|||
const (
|
||||
// Asm defines some two-character lexemes. We make up
|
||||
// a rune/ScanToken value for them - ugly but simple.
|
||||
LSH ScanToken = -1000 - iota // << Left shift.
|
||||
RSH // >> Logical right shift.
|
||||
ARR // -> Used on ARM for shift type 3, arithmetic right shift.
|
||||
ROT // @> Used on ARM for shift type 4, rotate right.
|
||||
macroName // name of macro that should not be expanded
|
||||
LSH ScanToken = -1000 - iota // << Left shift.
|
||||
RSH // >> Logical right shift.
|
||||
ARR // -> Used on ARM for shift type 3, arithmetic right shift.
|
||||
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
|
||||
)
|
||||
|
||||
// IsRegisterShift reports whether the token is one of the ARM register shift operators.
|
||||
|
|
|
|||
|
|
@ -281,6 +281,9 @@ func drain(input *Input) string {
|
|||
if tok == scanner.EOF {
|
||||
return buf.String()
|
||||
}
|
||||
if tok == '#' {
|
||||
continue
|
||||
}
|
||||
if buf.Len() > 0 {
|
||||
buf.WriteByte('.')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,10 +107,13 @@ func (t *Tokenizer) Next() ScanToken {
|
|||
if t.tok != scanner.Comment {
|
||||
break
|
||||
}
|
||||
length := strings.Count(s.TokenText(), "\n")
|
||||
t.line += length
|
||||
// TODO: If we ever have //go: comments in assembly, will need to keep them here.
|
||||
// For now, just discard all comments.
|
||||
text := s.TokenText()
|
||||
t.line += strings.Count(text, "\n")
|
||||
// TODO: Use constraint.IsGoBuild once it exists.
|
||||
if strings.HasPrefix(text, "//go:build") {
|
||||
t.tok = BuildComment
|
||||
break
|
||||
}
|
||||
}
|
||||
switch t.tok {
|
||||
case '\n':
|
||||
|
|
|
|||
|
|
@ -35,10 +35,9 @@ func main() {
|
|||
flags.Parse()
|
||||
|
||||
ctxt := obj.Linknew(architecture.LinkArch)
|
||||
if *flags.PrintOut {
|
||||
ctxt.Debugasm = 1
|
||||
}
|
||||
ctxt.Debugasm = flags.PrintOut
|
||||
ctxt.Flag_dynlink = *flags.Dynlink
|
||||
ctxt.Flag_linkshared = *flags.Linkshared
|
||||
ctxt.Flag_shared = *flags.Shared || *flags.Dynlink
|
||||
ctxt.IsAsm = true
|
||||
ctxt.Pkgpath = *flags.Importpath
|
||||
|
|
@ -76,7 +75,8 @@ func main() {
|
|||
var failedFile string
|
||||
for _, f := range flag.Args() {
|
||||
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{}) {
|
||||
diag = true
|
||||
log.Printf(format, args...)
|
||||
|
|
|
|||
|
|
@ -22,21 +22,6 @@ func usage() {
|
|||
|
||||
var wflag = flag.Bool("w", false, "write build ID")
|
||||
|
||||
// taken from cmd/go/internal/work/buildid.go
|
||||
func hashToString(h [32]byte) string {
|
||||
const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
|
||||
const chunks = 5
|
||||
var dst [chunks * 4]byte
|
||||
for i := 0; i < chunks; i++ {
|
||||
v := uint32(h[3*i])<<16 | uint32(h[3*i+1])<<8 | uint32(h[3*i+2])
|
||||
dst[4*i+0] = b64[(v>>18)&0x3F]
|
||||
dst[4*i+1] = b64[(v>>12)&0x3F]
|
||||
dst[4*i+2] = b64[(v>>6)&0x3F]
|
||||
dst[4*i+3] = b64[v&0x3F]
|
||||
}
|
||||
return string(dst[:])
|
||||
}
|
||||
|
||||
func main() {
|
||||
log.SetPrefix("buildid: ")
|
||||
log.SetFlags(0)
|
||||
|
|
@ -63,12 +48,12 @@ func main() {
|
|||
log.Fatal(err)
|
||||
}
|
||||
matches, hash, err := buildid.FindAndHash(f, id, 0)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
f.Close()
|
||||
|
||||
newID := id[:strings.LastIndex(id, "/")] + "/" + hashToString(hash)
|
||||
newID := id[:strings.LastIndex(id, "/")] + "/" + buildid.HashToString(hash)
|
||||
if len(newID) != len(id) {
|
||||
log.Fatalf("%s: build ID length mismatch %q vs %q", file, id, newID)
|
||||
}
|
||||
|
|
@ -77,7 +62,7 @@ func main() {
|
|||
return
|
||||
}
|
||||
|
||||
f, err = os.OpenFile(file, os.O_WRONLY, 0)
|
||||
f, err = os.OpenFile(file, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import (
|
|||
"go/scanner"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
|
@ -44,14 +43,7 @@ func sourceLine(n ast.Node) int {
|
|||
// attached to the import "C" comment, a list of references to C.xxx,
|
||||
// a list of exported functions, and the actual AST, to be rewritten and
|
||||
// printed.
|
||||
func (f *File) ParseGo(name string, src []byte) {
|
||||
// Create absolute path for file, so that it will be used in error
|
||||
// messages and recorded in debug line number information.
|
||||
// This matches the rest of the toolchain. See golang.org/issue/5122.
|
||||
if aname, err := filepath.Abs(name); err == nil {
|
||||
name = aname
|
||||
}
|
||||
|
||||
func (f *File) ParseGo(abspath string, src []byte) {
|
||||
// Two different parses: once with comments, once without.
|
||||
// The printer is not good enough at printing comments in the
|
||||
// right place when we start editing the AST behind its back,
|
||||
|
|
@ -60,8 +52,8 @@ func (f *File) ParseGo(name string, src []byte) {
|
|||
// and reprinting.
|
||||
// In cgo mode, we ignore ast2 and just apply edits directly
|
||||
// the text behind ast1. In godefs mode we modify and print ast2.
|
||||
ast1 := parse(name, src, parser.ParseComments)
|
||||
ast2 := parse(name, src, 0)
|
||||
ast1 := parse(abspath, src, parser.ParseComments)
|
||||
ast2 := parse(abspath, src, 0)
|
||||
|
||||
f.Package = ast1.Name.Name
|
||||
f.Name = make(map[string]*Name)
|
||||
|
|
@ -88,7 +80,7 @@ func (f *File) ParseGo(name string, src []byte) {
|
|||
cg = d.Doc
|
||||
}
|
||||
if cg != nil {
|
||||
f.Preamble += fmt.Sprintf("#line %d %q\n", sourceLine(cg), name)
|
||||
f.Preamble += fmt.Sprintf("#line %d %q\n", sourceLine(cg), abspath)
|
||||
f.Preamble += commentText(cg) + "\n"
|
||||
f.Preamble += "#line 1 \"cgo-generated-wrapper\"\n"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -721,7 +721,7 @@ linkage to the desired libraries. The main function is provided by
|
|||
_cgo_main.c:
|
||||
|
||||
int main() { return 0; }
|
||||
void crosscall2(void(*fn)(void*, int, uintptr_t), void *a, int c, uintptr_t ctxt) { }
|
||||
void crosscall2(void(*fn)(void*), void *a, int c, uintptr_t ctxt) { }
|
||||
uintptr_t _cgo_wait_runtime_init_done(void) { return 0; }
|
||||
void _cgo_release_context(uintptr_t ctxt) { }
|
||||
char* _cgo_topofstack(void) { return (char*)0; }
|
||||
|
|
|
|||
|
|
@ -298,7 +298,7 @@ func (p *Package) guessKinds(f *File) []*Name {
|
|||
continue
|
||||
}
|
||||
|
||||
if goos == "darwin" && strings.HasSuffix(n.C, "Ref") {
|
||||
if (goos == "darwin" || goos == "ios") && strings.HasSuffix(n.C, "Ref") {
|
||||
// For FooRef, find out if FooGetTypeID exists.
|
||||
s := n.C[:len(n.C)-3] + "GetTypeID"
|
||||
n := &Name{Go: s, C: s}
|
||||
|
|
@ -2448,6 +2448,18 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
|||
tt := *t
|
||||
tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}}
|
||||
tt.Go = c.Ident("struct{}")
|
||||
if dt.Kind == "struct" {
|
||||
// We don't know what the representation of this struct is, so don't let
|
||||
// anyone allocate one on the Go side. As a side effect of this annotation,
|
||||
// pointers to this type will not be considered pointers in Go. They won't
|
||||
// get writebarrier-ed or adjusted during a stack copy. This should handle
|
||||
// all the cases badPointerTypedef used to handle, but hopefully will
|
||||
// continue to work going forward without any more need for cgo changes.
|
||||
tt.NotInHeap = true
|
||||
// TODO: we should probably do the same for unions. Unions can't live
|
||||
// on the Go heap, right? It currently doesn't work for unions because
|
||||
// they are defined as a type alias for struct{}, not a defined type.
|
||||
}
|
||||
typedef[name.Name] = &tt
|
||||
break
|
||||
}
|
||||
|
|
@ -2518,6 +2530,7 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
|||
}
|
||||
t.Go = name
|
||||
t.BadPointer = sub.BadPointer
|
||||
t.NotInHeap = sub.NotInHeap
|
||||
if unionWithPointer[sub.Go] {
|
||||
unionWithPointer[t.Go] = true
|
||||
}
|
||||
|
|
@ -2528,6 +2541,7 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
|||
tt := *t
|
||||
tt.Go = sub.Go
|
||||
tt.BadPointer = sub.BadPointer
|
||||
tt.NotInHeap = sub.NotInHeap
|
||||
typedef[name.Name] = &tt
|
||||
}
|
||||
|
||||
|
|
@ -2831,21 +2845,11 @@ func (c *typeConv) Struct(dt *dwarf.StructType, pos token.Pos) (expr *ast.Struct
|
|||
tgo := t.Go
|
||||
size := t.Size
|
||||
talign := t.Align
|
||||
if f.BitSize > 0 {
|
||||
switch f.BitSize {
|
||||
case 8, 16, 32, 64:
|
||||
default:
|
||||
continue
|
||||
}
|
||||
size = f.BitSize / 8
|
||||
name := tgo.(*ast.Ident).String()
|
||||
if strings.HasPrefix(name, "int") {
|
||||
name = "int"
|
||||
} else {
|
||||
name = "uint"
|
||||
}
|
||||
tgo = ast.NewIdent(name + fmt.Sprint(f.BitSize))
|
||||
talign = size
|
||||
if f.BitOffset > 0 || f.BitSize > 0 {
|
||||
// The layout of bitfields is implementation defined,
|
||||
// so we don't know how they correspond to Go fields
|
||||
// even if they are aligned at byte boundaries.
|
||||
continue
|
||||
}
|
||||
|
||||
if talign > 0 && f.ByteOffset%talign != 0 {
|
||||
|
|
@ -3036,6 +3040,7 @@ func (c *typeConv) anonymousStructTypedef(dt *dwarf.TypedefType) bool {
|
|||
// non-pointers in this type.
|
||||
// TODO: Currently our best solution is to find these manually and list them as
|
||||
// they come up. A better solution is desired.
|
||||
// Note: DEPRECATED. There is now a better solution. Search for NotInHeap in this file.
|
||||
func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
|
||||
if c.badCFType(dt) {
|
||||
return true
|
||||
|
|
@ -3070,7 +3075,7 @@ func (c *typeConv) badCFType(dt *dwarf.TypedefType) bool {
|
|||
// We identify the correct set of types as those ending in Ref and for which
|
||||
// there exists a corresponding GetTypeID function.
|
||||
// See comment below for details about the bad pointers.
|
||||
if goos != "darwin" {
|
||||
if goos != "darwin" && goos != "ios" {
|
||||
return false
|
||||
}
|
||||
s := dt.Name
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import (
|
|||
)
|
||||
|
||||
// godefs returns the output for -godefs mode.
|
||||
func (p *Package) godefs(f *File, srcfile string) string {
|
||||
func (p *Package) godefs(f *File) string {
|
||||
var buf bytes.Buffer
|
||||
|
||||
fmt.Fprintf(&buf, "// Code generated by cmd/cgo -godefs; DO NOT EDIT.\n")
|
||||
|
|
|
|||
|
|
@ -151,7 +151,8 @@ type Type struct {
|
|||
Go ast.Expr
|
||||
EnumValues map[string]int64
|
||||
Typedef string
|
||||
BadPointer bool
|
||||
BadPointer bool // this pointer type should be represented as a uintptr (deprecated)
|
||||
NotInHeap bool // this type should have a go:notinheap annotation
|
||||
}
|
||||
|
||||
// A FuncType collects information about a function type in both the C and Go worlds.
|
||||
|
|
@ -169,35 +170,51 @@ func usage() {
|
|||
|
||||
var ptrSizeMap = map[string]int64{
|
||||
"386": 4,
|
||||
"alpha": 8,
|
||||
"amd64": 8,
|
||||
"arm": 4,
|
||||
"arm64": 8,
|
||||
"m68k": 4,
|
||||
"mips": 4,
|
||||
"mipsle": 4,
|
||||
"mips64": 8,
|
||||
"mips64le": 8,
|
||||
"nios2": 4,
|
||||
"ppc": 4,
|
||||
"ppc64": 8,
|
||||
"ppc64le": 8,
|
||||
"riscv": 4,
|
||||
"riscv64": 8,
|
||||
"s390": 4,
|
||||
"s390x": 8,
|
||||
"sh": 4,
|
||||
"shbe": 4,
|
||||
"sparc": 4,
|
||||
"sparc64": 8,
|
||||
}
|
||||
|
||||
var intSizeMap = map[string]int64{
|
||||
"386": 4,
|
||||
"alpha": 8,
|
||||
"amd64": 8,
|
||||
"arm": 4,
|
||||
"arm64": 8,
|
||||
"m68k": 4,
|
||||
"mips": 4,
|
||||
"mipsle": 4,
|
||||
"mips64": 8,
|
||||
"mips64le": 8,
|
||||
"nios2": 4,
|
||||
"ppc": 4,
|
||||
"ppc64": 8,
|
||||
"ppc64le": 8,
|
||||
"riscv": 4,
|
||||
"riscv64": 8,
|
||||
"s390": 4,
|
||||
"s390x": 8,
|
||||
"sh": 4,
|
||||
"shbe": 4,
|
||||
"sparc": 4,
|
||||
"sparc64": 8,
|
||||
}
|
||||
|
||||
|
|
@ -223,10 +240,11 @@ var exportHeader = flag.String("exportheader", "", "where to write export header
|
|||
var gccgo = flag.Bool("gccgo", false, "generate files for use with gccgo")
|
||||
var gccgoprefix = flag.String("gccgoprefix", "", "-fgo-prefix option used with gccgo")
|
||||
var gccgopkgpath = flag.String("gccgopkgpath", "", "-fgo-pkgpath option used with gccgo")
|
||||
var gccgoMangleCheckDone bool
|
||||
var gccgoNewmanglingInEffect bool
|
||||
var gccgoMangler func(string) string
|
||||
var importRuntimeCgo = flag.Bool("import_runtime_cgo", true, "import runtime/cgo in generated code")
|
||||
var importSyscall = flag.Bool("import_syscall", true, "import syscall in generated code")
|
||||
var trimpath = flag.String("trimpath", "", "applies supplied rewrites or trims prefixes to recorded source file paths")
|
||||
|
||||
var goarch, goos string
|
||||
|
||||
func main() {
|
||||
|
|
@ -306,6 +324,13 @@ func main() {
|
|||
input = filepath.Join(*srcDir, input)
|
||||
}
|
||||
|
||||
// Create absolute path for file, so that it will be used in error
|
||||
// messages and recorded in debug line number information.
|
||||
// This matches the rest of the toolchain. See golang.org/issue/5122.
|
||||
if aname, err := filepath.Abs(input); err == nil {
|
||||
input = aname
|
||||
}
|
||||
|
||||
b, err := ioutil.ReadFile(input)
|
||||
if err != nil {
|
||||
fatalf("%s", err)
|
||||
|
|
@ -314,6 +339,10 @@ func main() {
|
|||
fatalf("%s", err)
|
||||
}
|
||||
|
||||
// Apply trimpath to the file path. The path won't be read from after this point.
|
||||
input, _ = objabi.ApplyRewrites(input, *trimpath)
|
||||
goFiles[i] = input
|
||||
|
||||
f := new(File)
|
||||
f.Edit = edit.NewBuffer(b)
|
||||
f.ParseGo(input, b)
|
||||
|
|
@ -351,7 +380,7 @@ func main() {
|
|||
p.PackagePath = f.Package
|
||||
p.Record(f)
|
||||
if *godefs {
|
||||
os.Stdout.WriteString(p.godefs(f, input))
|
||||
os.Stdout.WriteString(p.godefs(f))
|
||||
} else {
|
||||
p.writeOutput(f, input)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"cmd/internal/pkgpath"
|
||||
"debug/elf"
|
||||
"debug/macho"
|
||||
"debug/pe"
|
||||
|
|
@ -15,7 +16,6 @@ import (
|
|||
"go/token"
|
||||
"internal/xcoff"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
|
@ -59,14 +59,14 @@ func (p *Package) writeDefs() {
|
|||
// Write C main file for using gcc to resolve imports.
|
||||
fmt.Fprintf(fm, "int main() { return 0; }\n")
|
||||
if *importRuntimeCgo {
|
||||
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt) { }\n")
|
||||
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*), void *a, int c, __SIZE_TYPE__ ctxt) { }\n")
|
||||
fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done(void) { return 0; }\n")
|
||||
fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__ ctxt) { }\n")
|
||||
fmt.Fprintf(fm, "char* _cgo_topofstack(void) { return (char*)0; }\n")
|
||||
} else {
|
||||
// If we're not importing runtime/cgo, we *are* runtime/cgo,
|
||||
// which provides these functions. We just need a prototype.
|
||||
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int, __SIZE_TYPE__), void *a, int c, __SIZE_TYPE__ ctxt);\n")
|
||||
fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*), void *a, int c, __SIZE_TYPE__ ctxt);\n")
|
||||
fmt.Fprintf(fm, "__SIZE_TYPE__ _cgo_wait_runtime_init_done(void);\n")
|
||||
fmt.Fprintf(fm, "void _cgo_release_context(__SIZE_TYPE__);\n")
|
||||
}
|
||||
|
|
@ -108,6 +108,9 @@ func (p *Package) writeDefs() {
|
|||
sort.Strings(typedefNames)
|
||||
for _, name := range typedefNames {
|
||||
def := typedef[name]
|
||||
if def.NotInHeap {
|
||||
fmt.Fprintf(fgo2, "//go:notinheap\n")
|
||||
}
|
||||
fmt.Fprintf(fgo2, "type %s ", name)
|
||||
// We don't have source info for these types, so write them out without source info.
|
||||
// Otherwise types would look like:
|
||||
|
|
@ -183,7 +186,7 @@ func (p *Package) writeDefs() {
|
|||
panic(fmt.Errorf("invalid var kind %q", n.Kind))
|
||||
}
|
||||
if *gccgo {
|
||||
fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, n.Mangle)
|
||||
fmt.Fprintf(fc, `extern void *%s __asm__("%s.%s");`, n.Mangle, gccgoSymbolPrefix, gccgoToSymbol(n.Mangle))
|
||||
fmt.Fprintf(&gccgoInit, "\t%s = &%s;\n", n.Mangle, n.C)
|
||||
fmt.Fprintf(fc, "\n")
|
||||
}
|
||||
|
|
@ -334,6 +337,8 @@ func dynimport(obj string) {
|
|||
if s.Version != "" {
|
||||
targ += "#" + s.Version
|
||||
}
|
||||
checkImportSymName(s.Name)
|
||||
checkImportSymName(targ)
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, targ, s.Library)
|
||||
}
|
||||
lib, _ := f.ImportedLibraries()
|
||||
|
|
@ -349,6 +354,7 @@ func dynimport(obj string) {
|
|||
if len(s) > 0 && s[0] == '_' {
|
||||
s = s[1:]
|
||||
}
|
||||
checkImportSymName(s)
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s, s, "")
|
||||
}
|
||||
lib, _ := f.ImportedLibraries()
|
||||
|
|
@ -363,6 +369,8 @@ func dynimport(obj string) {
|
|||
for _, s := range sym {
|
||||
ss := strings.Split(s, ":")
|
||||
name := strings.Split(ss[0], "@")[0]
|
||||
checkImportSymName(name)
|
||||
checkImportSymName(ss[0])
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", name, ss[0], strings.ToLower(ss[1]))
|
||||
}
|
||||
return
|
||||
|
|
@ -380,6 +388,7 @@ func dynimport(obj string) {
|
|||
// Go symbols.
|
||||
continue
|
||||
}
|
||||
checkImportSymName(s.Name)
|
||||
fmt.Fprintf(stdout, "//go:cgo_import_dynamic %s %s %q\n", s.Name, s.Name, s.Library)
|
||||
}
|
||||
lib, err := f.ImportedLibraries()
|
||||
|
|
@ -395,6 +404,23 @@ func dynimport(obj string) {
|
|||
fatalf("cannot parse %s as ELF, Mach-O, PE or XCOFF", obj)
|
||||
}
|
||||
|
||||
// checkImportSymName checks a symbol name we are going to emit as part
|
||||
// of a //go:cgo_import_dynamic pragma. These names come from object
|
||||
// files, so they may be corrupt. We are going to emit them unquoted,
|
||||
// so while they don't need to be valid symbol names (and in some cases,
|
||||
// involving symbol versions, they won't be) they must contain only
|
||||
// graphic characters and must not contain Go comments.
|
||||
func checkImportSymName(s string) {
|
||||
for _, c := range s {
|
||||
if !unicode.IsGraphic(c) || unicode.IsSpace(c) {
|
||||
fatalf("dynamic symbol %q contains unsupported character", s)
|
||||
}
|
||||
}
|
||||
if strings.Index(s, "//") >= 0 || strings.Index(s, "/*") >= 0 {
|
||||
fatalf("dynamic symbol %q contains Go comment")
|
||||
}
|
||||
}
|
||||
|
||||
// Construct a gcc struct matching the gc argument frame.
|
||||
// Assumes that in gcc, char is 1 byte, short 2 bytes, int 4 bytes, long long 8 bytes.
|
||||
// These assumptions are checked by the gccProlog.
|
||||
|
|
@ -849,7 +875,7 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
|||
fmt.Fprintf(fgcc, "#pragma GCC diagnostic ignored \"-Wpragmas\"\n")
|
||||
fmt.Fprintf(fgcc, "#pragma GCC diagnostic ignored \"-Waddress-of-packed-member\"\n")
|
||||
|
||||
fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *, int, __SIZE_TYPE__), void *, int, __SIZE_TYPE__);\n")
|
||||
fmt.Fprintf(fgcc, "extern void crosscall2(void (*fn)(void *), void *, int, __SIZE_TYPE__);\n")
|
||||
fmt.Fprintf(fgcc, "extern __SIZE_TYPE__ _cgo_wait_runtime_init_done(void);\n")
|
||||
fmt.Fprintf(fgcc, "extern void _cgo_release_context(__SIZE_TYPE__);\n\n")
|
||||
fmt.Fprintf(fgcc, "extern char* _cgo_topofstack(void);")
|
||||
|
|
@ -859,59 +885,48 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
|||
for _, exp := range p.ExpFunc {
|
||||
fn := exp.Func
|
||||
|
||||
// Construct a gcc struct matching the gc argument and
|
||||
// result frame. The gcc struct will be compiled with
|
||||
// __attribute__((packed)) so all padding must be accounted
|
||||
// for explicitly.
|
||||
// Construct a struct that will be used to communicate
|
||||
// arguments from C to Go. The C and Go definitions
|
||||
// just have to agree. The gcc struct will be compiled
|
||||
// with __attribute__((packed)) so all padding must be
|
||||
// accounted for explicitly.
|
||||
ctype := "struct {\n"
|
||||
gotype := new(bytes.Buffer)
|
||||
fmt.Fprintf(gotype, "struct {\n")
|
||||
off := int64(0)
|
||||
npad := 0
|
||||
if fn.Recv != nil {
|
||||
t := p.cgoType(fn.Recv.List[0].Type)
|
||||
ctype += fmt.Sprintf("\t\t%s recv;\n", t.C)
|
||||
argField := func(typ ast.Expr, namePat string, args ...interface{}) {
|
||||
name := fmt.Sprintf(namePat, args...)
|
||||
t := p.cgoType(typ)
|
||||
if off%t.Align != 0 {
|
||||
pad := t.Align - off%t.Align
|
||||
ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
|
||||
off += pad
|
||||
npad++
|
||||
}
|
||||
ctype += fmt.Sprintf("\t\t%s %s;\n", t.C, name)
|
||||
fmt.Fprintf(gotype, "\t\t%s ", name)
|
||||
noSourceConf.Fprint(gotype, fset, typ)
|
||||
fmt.Fprintf(gotype, "\n")
|
||||
off += t.Size
|
||||
}
|
||||
if fn.Recv != nil {
|
||||
argField(fn.Recv.List[0].Type, "recv")
|
||||
}
|
||||
fntype := fn.Type
|
||||
forFieldList(fntype.Params,
|
||||
func(i int, aname string, atype ast.Expr) {
|
||||
t := p.cgoType(atype)
|
||||
if off%t.Align != 0 {
|
||||
pad := t.Align - off%t.Align
|
||||
ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
|
||||
off += pad
|
||||
npad++
|
||||
}
|
||||
ctype += fmt.Sprintf("\t\t%s p%d;\n", t.C, i)
|
||||
off += t.Size
|
||||
argField(atype, "p%d", i)
|
||||
})
|
||||
if off%p.PtrSize != 0 {
|
||||
pad := p.PtrSize - off%p.PtrSize
|
||||
ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
|
||||
off += pad
|
||||
npad++
|
||||
}
|
||||
forFieldList(fntype.Results,
|
||||
func(i int, aname string, atype ast.Expr) {
|
||||
t := p.cgoType(atype)
|
||||
if off%t.Align != 0 {
|
||||
pad := t.Align - off%t.Align
|
||||
ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
|
||||
off += pad
|
||||
npad++
|
||||
}
|
||||
ctype += fmt.Sprintf("\t\t%s r%d;\n", t.C, i)
|
||||
off += t.Size
|
||||
argField(atype, "r%d", i)
|
||||
})
|
||||
if off%p.PtrSize != 0 {
|
||||
pad := p.PtrSize - off%p.PtrSize
|
||||
ctype += fmt.Sprintf("\t\tchar __pad%d[%d];\n", npad, pad)
|
||||
off += pad
|
||||
npad++
|
||||
}
|
||||
if ctype == "struct {\n" {
|
||||
ctype += "\t\tchar unused;\n" // avoid empty struct
|
||||
}
|
||||
ctype += "\t}"
|
||||
fmt.Fprintf(gotype, "\t}")
|
||||
|
||||
// Get the return type of the wrapper function
|
||||
// compiled by gcc.
|
||||
|
|
@ -936,7 +951,11 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
|||
}
|
||||
|
||||
// Build the wrapper function compiled by gcc.
|
||||
s := fmt.Sprintf("%s %s(", gccResult, exp.ExpName)
|
||||
gccExport := ""
|
||||
if goos == "windows" {
|
||||
gccExport = "__declspec(dllexport)"
|
||||
}
|
||||
s := fmt.Sprintf("%s %s %s(", gccExport, gccResult, exp.ExpName)
|
||||
if fn.Recv != nil {
|
||||
s += p.cgoType(fn.Recv.List[0].Type).C.String()
|
||||
s += " recv"
|
||||
|
|
@ -958,12 +977,23 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
|||
}
|
||||
fmt.Fprintf(fgcch, "extern %s;\n", s)
|
||||
|
||||
fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *, int, __SIZE_TYPE__);\n", cPrefix, exp.ExpName)
|
||||
fmt.Fprintf(fgcc, "extern void _cgoexp%s_%s(void *);\n", cPrefix, exp.ExpName)
|
||||
fmt.Fprintf(fgcc, "\nCGO_NO_SANITIZE_THREAD")
|
||||
fmt.Fprintf(fgcc, "\n%s\n", s)
|
||||
fmt.Fprintf(fgcc, "{\n")
|
||||
fmt.Fprintf(fgcc, "\t__SIZE_TYPE__ _cgo_ctxt = _cgo_wait_runtime_init_done();\n")
|
||||
fmt.Fprintf(fgcc, "\t%s %v _cgo_a;\n", ctype, p.packedAttribute())
|
||||
// The results part of the argument structure must be
|
||||
// initialized to 0 so the write barriers generated by
|
||||
// the assignments to these fields in Go are safe.
|
||||
//
|
||||
// We use a local static variable to get the zeroed
|
||||
// value of the argument type. This avoids including
|
||||
// string.h for memset, and is also robust to C++
|
||||
// types with constructors. Both GCC and LLVM optimize
|
||||
// this into just zeroing _cgo_a.
|
||||
fmt.Fprintf(fgcc, "\ttypedef %s %v _cgo_argtype;\n", ctype, p.packedAttribute())
|
||||
fmt.Fprintf(fgcc, "\tstatic _cgo_argtype _cgo_zero;\n")
|
||||
fmt.Fprintf(fgcc, "\t_cgo_argtype _cgo_a = _cgo_zero;\n")
|
||||
if gccResult != "void" && (len(fntype.Results.List) > 1 || len(fntype.Results.List[0].Names) > 1) {
|
||||
fmt.Fprintf(fgcc, "\t%s r;\n", gccResult)
|
||||
}
|
||||
|
|
@ -992,82 +1022,28 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
|||
fmt.Fprintf(fgcc, "}\n")
|
||||
|
||||
// Build the wrapper function compiled by cmd/compile.
|
||||
goname := "_cgoexpwrap" + cPrefix + "_"
|
||||
if fn.Recv != nil {
|
||||
goname += fn.Recv.List[0].Names[0].Name + "_"
|
||||
}
|
||||
goname += exp.Func.Name.Name
|
||||
// This unpacks the argument struct above and calls the Go function.
|
||||
fmt.Fprintf(fgo2, "//go:cgo_export_dynamic %s\n", exp.ExpName)
|
||||
fmt.Fprintf(fgo2, "//go:linkname _cgoexp%s_%s _cgoexp%s_%s\n", cPrefix, exp.ExpName, cPrefix, exp.ExpName)
|
||||
fmt.Fprintf(fgo2, "//go:cgo_export_static _cgoexp%s_%s\n", cPrefix, exp.ExpName)
|
||||
fmt.Fprintf(fgo2, "//go:nosplit\n") // no split stack, so no use of m or g
|
||||
fmt.Fprintf(fgo2, "//go:norace\n") // must not have race detector calls inserted
|
||||
fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a unsafe.Pointer, n int32, ctxt uintptr) {\n", cPrefix, exp.ExpName)
|
||||
fmt.Fprintf(fgo2, "\tfn := %s\n", goname)
|
||||
// The indirect here is converting from a Go function pointer to a C function pointer.
|
||||
fmt.Fprintf(fgo2, "\t_cgo_runtime_cgocallback(**(**unsafe.Pointer)(unsafe.Pointer(&fn)), a, uintptr(n), ctxt);\n")
|
||||
fmt.Fprintf(fgo2, "}\n")
|
||||
fmt.Fprintf(fgo2, "func _cgoexp%s_%s(a *%s) {\n", cPrefix, exp.ExpName, gotype)
|
||||
|
||||
fmt.Fprintf(fm, "int _cgoexp%s_%s;\n", cPrefix, exp.ExpName)
|
||||
|
||||
// This code uses printer.Fprint, not conf.Fprint,
|
||||
// because we don't want //line comments in the middle
|
||||
// of the function types.
|
||||
fmt.Fprintf(fgo2, "\n")
|
||||
fmt.Fprintf(fgo2, "func %s(", goname)
|
||||
comma := false
|
||||
if fn.Recv != nil {
|
||||
fmt.Fprintf(fgo2, "recv ")
|
||||
printer.Fprint(fgo2, fset, fn.Recv.List[0].Type)
|
||||
comma = true
|
||||
}
|
||||
forFieldList(fntype.Params,
|
||||
func(i int, aname string, atype ast.Expr) {
|
||||
if comma {
|
||||
fmt.Fprintf(fgo2, ", ")
|
||||
}
|
||||
fmt.Fprintf(fgo2, "p%d ", i)
|
||||
printer.Fprint(fgo2, fset, atype)
|
||||
comma = true
|
||||
})
|
||||
fmt.Fprintf(fgo2, ")")
|
||||
if gccResult != "void" {
|
||||
fmt.Fprint(fgo2, " (")
|
||||
// Write results back to frame.
|
||||
fmt.Fprintf(fgo2, "\t")
|
||||
forFieldList(fntype.Results,
|
||||
func(i int, aname string, atype ast.Expr) {
|
||||
if i > 0 {
|
||||
fmt.Fprint(fgo2, ", ")
|
||||
fmt.Fprintf(fgo2, ", ")
|
||||
}
|
||||
fmt.Fprintf(fgo2, "r%d ", i)
|
||||
printer.Fprint(fgo2, fset, atype)
|
||||
fmt.Fprintf(fgo2, "a.r%d", i)
|
||||
})
|
||||
fmt.Fprint(fgo2, ")")
|
||||
}
|
||||
fmt.Fprint(fgo2, " {\n")
|
||||
if gccResult == "void" {
|
||||
fmt.Fprint(fgo2, "\t")
|
||||
} else {
|
||||
// Verify that any results don't contain any
|
||||
// Go pointers.
|
||||
addedDefer := false
|
||||
forFieldList(fntype.Results,
|
||||
func(i int, aname string, atype ast.Expr) {
|
||||
if !p.hasPointer(nil, atype, false) {
|
||||
return
|
||||
}
|
||||
if !addedDefer {
|
||||
fmt.Fprint(fgo2, "\tdefer func() {\n")
|
||||
addedDefer = true
|
||||
}
|
||||
fmt.Fprintf(fgo2, "\t\t_cgoCheckResult(r%d)\n", i)
|
||||
})
|
||||
if addedDefer {
|
||||
fmt.Fprint(fgo2, "\t}()\n")
|
||||
}
|
||||
fmt.Fprint(fgo2, "\treturn ")
|
||||
fmt.Fprintf(fgo2, " = ")
|
||||
}
|
||||
if fn.Recv != nil {
|
||||
fmt.Fprintf(fgo2, "recv.")
|
||||
fmt.Fprintf(fgo2, "a.recv.")
|
||||
}
|
||||
fmt.Fprintf(fgo2, "%s(", exp.Func.Name)
|
||||
forFieldList(fntype.Params,
|
||||
|
|
@ -1075,9 +1051,20 @@ func (p *Package) writeExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
|||
if i > 0 {
|
||||
fmt.Fprint(fgo2, ", ")
|
||||
}
|
||||
fmt.Fprintf(fgo2, "p%d", i)
|
||||
fmt.Fprintf(fgo2, "a.p%d", i)
|
||||
})
|
||||
fmt.Fprint(fgo2, ")\n")
|
||||
if gccResult != "void" {
|
||||
// Verify that any results don't contain any
|
||||
// Go pointers.
|
||||
forFieldList(fntype.Results,
|
||||
func(i int, aname string, atype ast.Expr) {
|
||||
if !p.hasPointer(nil, atype, false) {
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(fgo2, "\t_cgoCheckResult(a.r%d)\n", i)
|
||||
})
|
||||
}
|
||||
fmt.Fprint(fgo2, "}\n")
|
||||
}
|
||||
|
||||
|
|
@ -1161,7 +1148,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
|||
// will not be able to link against it from the C
|
||||
// code.
|
||||
goName := "Cgoexp_" + exp.ExpName
|
||||
fmt.Fprintf(fgcc, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, goName)
|
||||
fmt.Fprintf(fgcc, `extern %s %s %s __asm__("%s.%s");`, cRet, goName, cParams, gccgoSymbolPrefix, gccgoToSymbol(goName))
|
||||
fmt.Fprint(fgcc, "\n")
|
||||
|
||||
fmt.Fprint(fgcc, "\nCGO_NO_SANITIZE_THREAD\n")
|
||||
|
|
@ -1195,7 +1182,7 @@ func (p *Package) writeGccgoExports(fgo2, fm, fgcc, fgcch io.Writer) {
|
|||
fmt.Fprint(fgcc, "}\n")
|
||||
|
||||
// Dummy declaration for _cgo_main.c
|
||||
fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, goName)
|
||||
fmt.Fprintf(fm, `char %s[1] __asm__("%s.%s");`, goName, gccgoSymbolPrefix, gccgoToSymbol(goName))
|
||||
fmt.Fprint(fm, "\n")
|
||||
|
||||
// For gccgo we use a wrapper function in Go, in order
|
||||
|
|
@ -1279,112 +1266,23 @@ func (p *Package) writeExportHeader(fgcch io.Writer) {
|
|||
fmt.Fprintf(fgcch, "%s\n", p.gccExportHeaderProlog())
|
||||
}
|
||||
|
||||
// gccgoUsesNewMangling reports whether gccgo uses the new collision-free
|
||||
// packagepath mangling scheme (see determineGccgoManglingScheme for more
|
||||
// info).
|
||||
func gccgoUsesNewMangling() bool {
|
||||
if !gccgoMangleCheckDone {
|
||||
gccgoNewmanglingInEffect = determineGccgoManglingScheme()
|
||||
gccgoMangleCheckDone = true
|
||||
}
|
||||
return gccgoNewmanglingInEffect
|
||||
}
|
||||
|
||||
const mangleCheckCode = `
|
||||
package läufer
|
||||
func Run(x int) int {
|
||||
return 1
|
||||
}
|
||||
`
|
||||
|
||||
// determineGccgoManglingScheme performs a runtime test to see which
|
||||
// flavor of packagepath mangling gccgo is using. Older versions of
|
||||
// gccgo use a simple mangling scheme where there can be collisions
|
||||
// between packages whose paths are different but mangle to the same
|
||||
// string. More recent versions of gccgo use a new mangler that avoids
|
||||
// these collisions. Return value is whether gccgo uses the new mangling.
|
||||
func determineGccgoManglingScheme() bool {
|
||||
|
||||
// Emit a small Go file for gccgo to compile.
|
||||
filepat := "*_gccgo_manglecheck.go"
|
||||
var f *os.File
|
||||
var err error
|
||||
if f, err = ioutil.TempFile(*objDir, filepat); err != nil {
|
||||
fatalf("%v", err)
|
||||
}
|
||||
gofilename := f.Name()
|
||||
defer os.Remove(gofilename)
|
||||
|
||||
if err = ioutil.WriteFile(gofilename, []byte(mangleCheckCode), 0666); err != nil {
|
||||
fatalf("%v", err)
|
||||
}
|
||||
|
||||
// Compile with gccgo, capturing generated assembly.
|
||||
gccgocmd := os.Getenv("GCCGO")
|
||||
if gccgocmd == "" {
|
||||
gpath, gerr := exec.LookPath("gccgo")
|
||||
if gerr != nil {
|
||||
fatalf("unable to locate gccgo: %v", gerr)
|
||||
// gccgoToSymbol converts a name to a mangled symbol for gccgo.
|
||||
func gccgoToSymbol(ppath string) string {
|
||||
if gccgoMangler == nil {
|
||||
var err error
|
||||
cmd := os.Getenv("GCCGO")
|
||||
if cmd == "" {
|
||||
cmd, err = exec.LookPath("gccgo")
|
||||
if err != nil {
|
||||
fatalf("unable to locate gccgo: %v", err)
|
||||
}
|
||||
}
|
||||
gccgocmd = gpath
|
||||
}
|
||||
cmd := exec.Command(gccgocmd, "-S", "-o", "-", gofilename)
|
||||
buf, cerr := cmd.CombinedOutput()
|
||||
if cerr != nil {
|
||||
fatalf("%s", cerr)
|
||||
}
|
||||
|
||||
// New mangling: expect go.l..u00e4ufer.Run
|
||||
// Old mangling: expect go.l__ufer.Run
|
||||
return regexp.MustCompile(`go\.l\.\.u00e4ufer\.Run`).Match(buf)
|
||||
}
|
||||
|
||||
// gccgoPkgpathToSymbolNew converts a package path to a gccgo-style
|
||||
// package symbol.
|
||||
func gccgoPkgpathToSymbolNew(ppath string) string {
|
||||
bsl := []byte{}
|
||||
changed := false
|
||||
for _, c := range []byte(ppath) {
|
||||
switch {
|
||||
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z',
|
||||
'0' <= c && c <= '9', c == '_':
|
||||
bsl = append(bsl, c)
|
||||
case c == '.':
|
||||
bsl = append(bsl, ".x2e"...)
|
||||
default:
|
||||
changed = true
|
||||
encbytes := []byte(fmt.Sprintf("..z%02x", c))
|
||||
bsl = append(bsl, encbytes...)
|
||||
gccgoMangler, err = pkgpath.ToSymbolFunc(cmd, *objDir)
|
||||
if err != nil {
|
||||
fatalf("%v", err)
|
||||
}
|
||||
}
|
||||
if !changed {
|
||||
return ppath
|
||||
}
|
||||
return string(bsl)
|
||||
}
|
||||
|
||||
// gccgoPkgpathToSymbolOld converts a package path to a gccgo-style
|
||||
// package symbol using the older mangling scheme.
|
||||
func gccgoPkgpathToSymbolOld(ppath string) string {
|
||||
clean := func(r rune) rune {
|
||||
switch {
|
||||
case 'A' <= r && r <= 'Z', 'a' <= r && r <= 'z',
|
||||
'0' <= r && r <= '9':
|
||||
return r
|
||||
}
|
||||
return '_'
|
||||
}
|
||||
return strings.Map(clean, ppath)
|
||||
}
|
||||
|
||||
// gccgoPkgpathToSymbol converts a package path to a mangled packagepath
|
||||
// symbol.
|
||||
func gccgoPkgpathToSymbol(ppath string) string {
|
||||
if gccgoUsesNewMangling() {
|
||||
return gccgoPkgpathToSymbolNew(ppath)
|
||||
} else {
|
||||
return gccgoPkgpathToSymbolOld(ppath)
|
||||
}
|
||||
return gccgoMangler(ppath)
|
||||
}
|
||||
|
||||
// Return the package prefix when using gccgo.
|
||||
|
|
@ -1394,12 +1292,12 @@ func (p *Package) gccgoSymbolPrefix() string {
|
|||
}
|
||||
|
||||
if *gccgopkgpath != "" {
|
||||
return gccgoPkgpathToSymbol(*gccgopkgpath)
|
||||
return gccgoToSymbol(*gccgopkgpath)
|
||||
}
|
||||
if *gccgoprefix == "" && p.PackageName == "main" {
|
||||
return "main"
|
||||
}
|
||||
prefix := gccgoPkgpathToSymbol(*gccgoprefix)
|
||||
prefix := gccgoToSymbol(*gccgoprefix)
|
||||
if prefix == "" {
|
||||
prefix = "go"
|
||||
}
|
||||
|
|
@ -1663,9 +1561,6 @@ const goProlog = `
|
|||
//go:linkname _cgo_runtime_cgocall runtime.cgocall
|
||||
func _cgo_runtime_cgocall(unsafe.Pointer, uintptr) int32
|
||||
|
||||
//go:linkname _cgo_runtime_cgocallback runtime.cgocallback
|
||||
func _cgo_runtime_cgocallback(unsafe.Pointer, unsafe.Pointer, uintptr, uintptr)
|
||||
|
||||
//go:linkname _cgoCheckPointer runtime.cgoCheckPointer
|
||||
func _cgoCheckPointer(interface{}, interface{})
|
||||
|
||||
|
|
@ -1791,8 +1686,12 @@ void _cgoPREFIX_Cfunc__Cmalloc(void *v) {
|
|||
`
|
||||
|
||||
func (p *Package) cPrologGccgo() string {
|
||||
return strings.Replace(strings.Replace(cPrologGccgo, "PREFIX", cPrefix, -1),
|
||||
"GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(), -1)
|
||||
r := strings.NewReplacer(
|
||||
"PREFIX", cPrefix,
|
||||
"GCCGOSYMBOLPREF", p.gccgoSymbolPrefix(),
|
||||
"_cgoCheckPointer", gccgoToSymbol("_cgoCheckPointer"),
|
||||
"_cgoCheckResult", gccgoToSymbol("_cgoCheckResult"))
|
||||
return r.Replace(cPrologGccgo)
|
||||
}
|
||||
|
||||
const cPrologGccgo = `
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ import (
|
|||
"go/types"
|
||||
"internal/testenv"
|
||||
"io"
|
||||
"io/fs"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
|
@ -89,7 +90,7 @@ func TestFormats(t *testing.T) {
|
|||
testenv.MustHaveGoBuild(t) // more restrictive than necessary, but that's ok
|
||||
|
||||
// process all directories
|
||||
filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
|
||||
filepath.WalkDir(".", func(path string, info fs.DirEntry, err error) error {
|
||||
if info.IsDir() {
|
||||
if info.Name() == "testdata" {
|
||||
return filepath.SkipDir
|
||||
|
|
|
|||
|
|
@ -105,10 +105,8 @@ var knownFormats = map[string]string{
|
|||
"cmd/compile/internal/ssa.GCNode %v": "",
|
||||
"cmd/compile/internal/ssa.ID %d": "",
|
||||
"cmd/compile/internal/ssa.ID %v": "",
|
||||
"cmd/compile/internal/ssa.LocPair %s": "",
|
||||
"cmd/compile/internal/ssa.LocalSlot %s": "",
|
||||
"cmd/compile/internal/ssa.LocalSlot %v": "",
|
||||
"cmd/compile/internal/ssa.Location %T": "",
|
||||
"cmd/compile/internal/ssa.Location %s": "",
|
||||
"cmd/compile/internal/ssa.Op %s": "",
|
||||
"cmd/compile/internal/ssa.Op %v": "",
|
||||
|
|
|
|||
|
|
@ -42,10 +42,11 @@ func ssaMarkMoves(s *gc.SSAGenState, b *ssa.Block) {
|
|||
// loadByType returns the load instruction of the given type.
|
||||
func loadByType(t *types.Type) obj.As {
|
||||
// Avoid partial register write
|
||||
if !t.IsFloat() && t.Size() <= 2 {
|
||||
if t.Size() == 1 {
|
||||
if !t.IsFloat() {
|
||||
switch t.Size() {
|
||||
case 1:
|
||||
return x86.AMOVBLZX
|
||||
} else {
|
||||
case 2:
|
||||
return x86.AMOVWLZX
|
||||
}
|
||||
}
|
||||
|
|
@ -75,7 +76,7 @@ func storeByType(t *types.Type) obj.As {
|
|||
return x86.AMOVQ
|
||||
}
|
||||
}
|
||||
panic("bad store type")
|
||||
panic(fmt.Sprintf("bad store type %v", t))
|
||||
}
|
||||
|
||||
// moveByType returns the reg->reg move instruction of the given type.
|
||||
|
|
@ -100,7 +101,7 @@ func moveByType(t *types.Type) obj.As {
|
|||
case 16:
|
||||
return x86.AMOVUPS // int128s are in SSE registers
|
||||
default:
|
||||
panic(fmt.Sprintf("bad int register width %d:%s", t.Size(), t))
|
||||
panic(fmt.Sprintf("bad int register width %d:%v", t.Size(), t))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1070,7 +1071,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
p := s.Prog(v.Op.Asm())
|
||||
val := v.AuxInt
|
||||
// 0 means math.RoundToEven, 1 Floor, 2 Ceil, 3 Trunc
|
||||
if val != 0 && val != 1 && val != 2 && val != 3 {
|
||||
if val < 0 || val > 3 {
|
||||
v.Fatalf("Invalid rounding mode")
|
||||
}
|
||||
p.From.Offset = val
|
||||
|
|
@ -1210,7 +1211,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
p = s.Prog(x86.ASETEQ)
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = v.Reg0()
|
||||
case ssa.OpAMD64ANDBlock, ssa.OpAMD64ORBlock:
|
||||
case ssa.OpAMD64ANDBlock, ssa.OpAMD64ANDLlock, ssa.OpAMD64ORBlock, ssa.OpAMD64ORLlock:
|
||||
s.Prog(x86.ALOCK)
|
||||
p := s.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_REG
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
"cmd/internal/objabi"
|
||||
)
|
||||
|
||||
var darwin = objabi.GOOS == "darwin"
|
||||
var darwin = objabi.GOOS == "darwin" || objabi.GOOS == "ios"
|
||||
|
||||
func padframe(frame int64) int64 {
|
||||
// arm64 requires that the frame size (not counting saved FP&LR)
|
||||
|
|
|
|||
|
|
@ -581,6 +581,24 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
p2.From.Reg = arm64.REGTMP
|
||||
p2.To.Type = obj.TYPE_BRANCH
|
||||
gc.Patch(p2, p)
|
||||
case ssa.OpARM64LoweredAtomicExchange64Variant,
|
||||
ssa.OpARM64LoweredAtomicExchange32Variant:
|
||||
swap := arm64.ASWPALD
|
||||
if v.Op == ssa.OpARM64LoweredAtomicExchange32Variant {
|
||||
swap = arm64.ASWPALW
|
||||
}
|
||||
r0 := v.Args[0].Reg()
|
||||
r1 := v.Args[1].Reg()
|
||||
out := v.Reg0()
|
||||
|
||||
// SWPALD Rarg1, (Rarg0), Rout
|
||||
p := s.Prog(swap)
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = r1
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Reg = r0
|
||||
p.RegTo2 = out
|
||||
|
||||
case ssa.OpARM64LoweredAtomicAdd64,
|
||||
ssa.OpARM64LoweredAtomicAdd32:
|
||||
// LDAXR (Rarg0), Rout
|
||||
|
|
@ -687,16 +705,74 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
p5.To.Type = obj.TYPE_REG
|
||||
p5.To.Reg = out
|
||||
gc.Patch(p2, p5)
|
||||
case ssa.OpARM64LoweredAtomicCas64Variant,
|
||||
ssa.OpARM64LoweredAtomicCas32Variant:
|
||||
// Rarg0: ptr
|
||||
// Rarg1: old
|
||||
// Rarg2: new
|
||||
// MOV Rarg1, Rtmp
|
||||
// CASAL Rtmp, (Rarg0), Rarg2
|
||||
// CMP Rarg1, Rtmp
|
||||
// CSET EQ, Rout
|
||||
cas := arm64.ACASALD
|
||||
cmp := arm64.ACMP
|
||||
mov := arm64.AMOVD
|
||||
if v.Op == ssa.OpARM64LoweredAtomicCas32Variant {
|
||||
cas = arm64.ACASALW
|
||||
cmp = arm64.ACMPW
|
||||
mov = arm64.AMOVW
|
||||
}
|
||||
r0 := v.Args[0].Reg()
|
||||
r1 := v.Args[1].Reg()
|
||||
r2 := v.Args[2].Reg()
|
||||
out := v.Reg0()
|
||||
|
||||
// MOV Rarg1, Rtmp
|
||||
p := s.Prog(mov)
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = r1
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = arm64.REGTMP
|
||||
|
||||
// CASAL Rtmp, (Rarg0), Rarg2
|
||||
p1 := s.Prog(cas)
|
||||
p1.From.Type = obj.TYPE_REG
|
||||
p1.From.Reg = arm64.REGTMP
|
||||
p1.To.Type = obj.TYPE_MEM
|
||||
p1.To.Reg = r0
|
||||
p1.RegTo2 = r2
|
||||
|
||||
// CMP Rarg1, Rtmp
|
||||
p2 := s.Prog(cmp)
|
||||
p2.From.Type = obj.TYPE_REG
|
||||
p2.From.Reg = r1
|
||||
p2.Reg = arm64.REGTMP
|
||||
|
||||
// CSET EQ, Rout
|
||||
p3 := s.Prog(arm64.ACSET)
|
||||
p3.From.Type = obj.TYPE_REG
|
||||
p3.From.Reg = arm64.COND_EQ
|
||||
p3.To.Type = obj.TYPE_REG
|
||||
p3.To.Reg = out
|
||||
|
||||
case ssa.OpARM64LoweredAtomicAnd8,
|
||||
ssa.OpARM64LoweredAtomicOr8:
|
||||
// LDAXRB (Rarg0), Rout
|
||||
ssa.OpARM64LoweredAtomicAnd32,
|
||||
ssa.OpARM64LoweredAtomicOr8,
|
||||
ssa.OpARM64LoweredAtomicOr32:
|
||||
// LDAXRB/LDAXRW (Rarg0), Rout
|
||||
// AND/OR Rarg1, Rout
|
||||
// STLXRB Rout, (Rarg0), Rtmp
|
||||
// STLXRB/STLXRB Rout, (Rarg0), Rtmp
|
||||
// CBNZ Rtmp, -3(PC)
|
||||
ld := arm64.ALDAXRB
|
||||
st := arm64.ASTLXRB
|
||||
if v.Op == ssa.OpARM64LoweredAtomicAnd32 || v.Op == ssa.OpARM64LoweredAtomicOr32 {
|
||||
ld = arm64.ALDAXRW
|
||||
st = arm64.ASTLXRW
|
||||
}
|
||||
r0 := v.Args[0].Reg()
|
||||
r1 := v.Args[1].Reg()
|
||||
out := v.Reg0()
|
||||
p := s.Prog(arm64.ALDAXRB)
|
||||
p := s.Prog(ld)
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = r0
|
||||
p.To.Type = obj.TYPE_REG
|
||||
|
|
@ -706,7 +782,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
p1.From.Reg = r1
|
||||
p1.To.Type = obj.TYPE_REG
|
||||
p1.To.Reg = out
|
||||
p2 := s.Prog(arm64.ASTLXRB)
|
||||
p2 := s.Prog(st)
|
||||
p2.From.Type = obj.TYPE_REG
|
||||
p2.From.Reg = out
|
||||
p2.To.Type = obj.TYPE_MEM
|
||||
|
|
@ -717,6 +793,63 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
|||
p3.From.Reg = arm64.REGTMP
|
||||
p3.To.Type = obj.TYPE_BRANCH
|
||||
gc.Patch(p3, p)
|
||||
case ssa.OpARM64LoweredAtomicAnd8Variant,
|
||||
ssa.OpARM64LoweredAtomicAnd32Variant:
|
||||
atomic_clear := arm64.ALDCLRALW
|
||||
if v.Op == ssa.OpARM64LoweredAtomicAnd8Variant {
|
||||
atomic_clear = arm64.ALDCLRALB
|
||||
}
|
||||
r0 := v.Args[0].Reg()
|
||||
r1 := v.Args[1].Reg()
|
||||
out := v.Reg0()
|
||||
|
||||
// MNV Rarg1 Rtemp
|
||||
p := s.Prog(arm64.AMVN)
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = r1
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = arm64.REGTMP
|
||||
|
||||
// LDCLRALW Rtemp, (Rarg0), Rout
|
||||
p1 := s.Prog(atomic_clear)
|
||||
p1.From.Type = obj.TYPE_REG
|
||||
p1.From.Reg = arm64.REGTMP
|
||||
p1.To.Type = obj.TYPE_MEM
|
||||
p1.To.Reg = r0
|
||||
p1.RegTo2 = out
|
||||
|
||||
// AND Rarg1, Rout
|
||||
p2 := s.Prog(arm64.AAND)
|
||||
p2.From.Type = obj.TYPE_REG
|
||||
p2.From.Reg = r1
|
||||
p2.To.Type = obj.TYPE_REG
|
||||
p2.To.Reg = out
|
||||
|
||||
case ssa.OpARM64LoweredAtomicOr8Variant,
|
||||
ssa.OpARM64LoweredAtomicOr32Variant:
|
||||
atomic_or := arm64.ALDORALW
|
||||
if v.Op == ssa.OpARM64LoweredAtomicOr8Variant {
|
||||
atomic_or = arm64.ALDORALB
|
||||
}
|
||||
r0 := v.Args[0].Reg()
|
||||
r1 := v.Args[1].Reg()
|
||||
out := v.Reg0()
|
||||
|
||||
// LDORALW Rarg1, (Rarg0), Rout
|
||||
p := s.Prog(atomic_or)
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = r1
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Reg = r0
|
||||
p.RegTo2 = out
|
||||
|
||||
// ORR Rarg1, Rout
|
||||
p2 := s.Prog(arm64.AORR)
|
||||
p2.From.Type = obj.TYPE_REG
|
||||
p2.From.Reg = r1
|
||||
p2.To.Type = obj.TYPE_REG
|
||||
p2.To.Reg = out
|
||||
|
||||
case ssa.OpARM64MOVBreg,
|
||||
ssa.OpARM64MOVBUreg,
|
||||
ssa.OpARM64MOVHreg,
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ func genhash(t *types.Type) *obj.LSym {
|
|||
}
|
||||
|
||||
sym := typesymprefix(".hash", t)
|
||||
if Debug['r'] != 0 {
|
||||
if Debug.r != 0 {
|
||||
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)
|
||||
fn.Nbody.Append(r)
|
||||
|
||||
if Debug['r'] != 0 {
|
||||
if Debug.r != 0 {
|
||||
dumplist("genhash body", fn.Nbody)
|
||||
}
|
||||
|
||||
|
|
@ -392,7 +392,7 @@ func genhash(t *types.Type) *obj.LSym {
|
|||
}
|
||||
|
||||
fn.Func.SetNilCheckDisabled(true)
|
||||
funccompile(fn)
|
||||
xtop = append(xtop, fn)
|
||||
|
||||
// Build closure. It doesn't close over any variables, so
|
||||
// it contains just the function pointer.
|
||||
|
|
@ -509,7 +509,7 @@ func geneq(t *types.Type) *obj.LSym {
|
|||
return closure
|
||||
}
|
||||
sym := typesymprefix(".eq", t)
|
||||
if Debug['r'] != 0 {
|
||||
if Debug.r != 0 {
|
||||
fmt.Printf("geneq %v\n", t)
|
||||
}
|
||||
|
||||
|
|
@ -529,6 +529,10 @@ func geneq(t *types.Type) *obj.LSym {
|
|||
fn := dclfunc(sym, tfn)
|
||||
np := asNode(tfn.Type.Params().Field(0).Nname)
|
||||
nq := asNode(tfn.Type.Params().Field(1).Nname)
|
||||
nr := asNode(tfn.Type.Results().Field(0).Nname)
|
||||
|
||||
// Label to jump to if an equality test fails.
|
||||
neq := autolabel(".neq")
|
||||
|
||||
// We reach here only for types that have equality but
|
||||
// cannot be handled by the standard algorithms,
|
||||
|
|
@ -555,13 +559,13 @@ func geneq(t *types.Type) *obj.LSym {
|
|||
// for i := 0; i < nelem; i++ {
|
||||
// if eq(p[i], q[i]) {
|
||||
// } else {
|
||||
// return
|
||||
// goto neq
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// TODO(josharian): consider doing some loop unrolling
|
||||
// for larger nelem as well, processing a few elements at a time in a loop.
|
||||
checkAll := func(unroll int64, eq func(pi, qi *Node) *Node) {
|
||||
checkAll := func(unroll int64, last bool, eq func(pi, qi *Node) *Node) {
|
||||
// checkIdx generates a node to check for equality at index i.
|
||||
checkIdx := func(i *Node) *Node {
|
||||
// pi := p[i]
|
||||
|
|
@ -576,37 +580,38 @@ func geneq(t *types.Type) *obj.LSym {
|
|||
}
|
||||
|
||||
if nelem <= unroll {
|
||||
// Generate a series of checks.
|
||||
var cond *Node
|
||||
for i := int64(0); i < nelem; i++ {
|
||||
c := nodintconst(i)
|
||||
check := checkIdx(c)
|
||||
if cond == nil {
|
||||
cond = check
|
||||
continue
|
||||
}
|
||||
cond = nod(OANDAND, cond, check)
|
||||
if last {
|
||||
// Do last comparison in a different manner.
|
||||
nelem--
|
||||
}
|
||||
// Generate a series of checks.
|
||||
for i := int64(0); i < nelem; i++ {
|
||||
// if check {} else { goto neq }
|
||||
nif := nod(OIF, checkIdx(nodintconst(i)), nil)
|
||||
nif.Rlist.Append(nodSym(OGOTO, nil, neq))
|
||||
fn.Nbody.Append(nif)
|
||||
}
|
||||
if last {
|
||||
fn.Nbody.Append(nod(OAS, nr, checkIdx(nodintconst(nelem))))
|
||||
}
|
||||
} else {
|
||||
// Generate a for loop.
|
||||
// for i := 0; i < nelem; i++
|
||||
i := temp(types.Types[TINT])
|
||||
init := nod(OAS, i, nodintconst(0))
|
||||
cond := nod(OLT, i, nodintconst(nelem))
|
||||
post := nod(OAS, i, nod(OADD, i, nodintconst(1)))
|
||||
loop := nod(OFOR, cond, post)
|
||||
loop.Ninit.Append(init)
|
||||
// if eq(pi, qi) {} else { goto neq }
|
||||
nif := nod(OIF, checkIdx(i), nil)
|
||||
nif.Rlist.Append(nodSym(OGOTO, nil, neq))
|
||||
loop.Nbody.Append(nif)
|
||||
fn.Nbody.Append(loop)
|
||||
if last {
|
||||
fn.Nbody.Append(nod(OAS, nr, nodbool(true)))
|
||||
}
|
||||
nif := nod(OIF, cond, nil)
|
||||
nif.Rlist.Append(nod(ORETURN, nil, nil))
|
||||
fn.Nbody.Append(nif)
|
||||
return
|
||||
}
|
||||
|
||||
// Generate a for loop.
|
||||
// for i := 0; i < nelem; i++
|
||||
i := temp(types.Types[TINT])
|
||||
init := nod(OAS, i, nodintconst(0))
|
||||
cond := nod(OLT, i, nodintconst(nelem))
|
||||
post := nod(OAS, i, nod(OADD, i, nodintconst(1)))
|
||||
loop := nod(OFOR, cond, post)
|
||||
loop.Ninit.Append(init)
|
||||
// if eq(pi, qi) {} else { return }
|
||||
check := checkIdx(i)
|
||||
nif := nod(OIF, check, nil)
|
||||
nif.Rlist.Append(nod(ORETURN, nil, nil))
|
||||
loop.Nbody.Append(nif)
|
||||
fn.Nbody.Append(loop)
|
||||
}
|
||||
|
||||
switch t.Elem().Etype {
|
||||
|
|
@ -614,32 +619,28 @@ func geneq(t *types.Type) *obj.LSym {
|
|||
// Do two loops. First, check that all the lengths match (cheap).
|
||||
// Second, check that all the contents match (expensive).
|
||||
// TODO: when the array size is small, unroll the length match checks.
|
||||
checkAll(3, func(pi, qi *Node) *Node {
|
||||
checkAll(3, false, func(pi, qi *Node) *Node {
|
||||
// Compare lengths.
|
||||
eqlen, _ := eqstring(pi, qi)
|
||||
return eqlen
|
||||
})
|
||||
checkAll(1, func(pi, qi *Node) *Node {
|
||||
checkAll(1, true, func(pi, qi *Node) *Node {
|
||||
// Compare contents.
|
||||
_, eqmem := eqstring(pi, qi)
|
||||
return eqmem
|
||||
})
|
||||
case TFLOAT32, TFLOAT64:
|
||||
checkAll(2, func(pi, qi *Node) *Node {
|
||||
checkAll(2, true, func(pi, qi *Node) *Node {
|
||||
// p[i] == q[i]
|
||||
return nod(OEQ, pi, qi)
|
||||
})
|
||||
// TODO: pick apart structs, do them piecemeal too
|
||||
default:
|
||||
checkAll(1, func(pi, qi *Node) *Node {
|
||||
checkAll(1, true, func(pi, qi *Node) *Node {
|
||||
// p[i] == q[i]
|
||||
return nod(OEQ, pi, qi)
|
||||
})
|
||||
}
|
||||
// return true
|
||||
ret := nod(ORETURN, nil, nil)
|
||||
ret.List.Append(nodbool(true))
|
||||
fn.Nbody.Append(ret)
|
||||
|
||||
case TSTRUCT:
|
||||
// Build a list of conditions to satisfy.
|
||||
|
|
@ -717,22 +718,42 @@ func geneq(t *types.Type) *obj.LSym {
|
|||
flatConds = append(flatConds, c...)
|
||||
}
|
||||
|
||||
var cond *Node
|
||||
if len(flatConds) == 0 {
|
||||
cond = nodbool(true)
|
||||
fn.Nbody.Append(nod(OAS, nr, nodbool(true)))
|
||||
} else {
|
||||
cond = flatConds[0]
|
||||
for _, c := range flatConds[1:] {
|
||||
cond = nod(OANDAND, cond, c)
|
||||
for _, c := range flatConds[:len(flatConds)-1] {
|
||||
// if cond {} else { goto neq }
|
||||
n := nod(OIF, c, nil)
|
||||
n.Rlist.Append(nodSym(OGOTO, nil, neq))
|
||||
fn.Nbody.Append(n)
|
||||
}
|
||||
fn.Nbody.Append(nod(OAS, nr, flatConds[len(flatConds)-1]))
|
||||
}
|
||||
|
||||
ret := nod(ORETURN, nil, nil)
|
||||
ret.List.Append(cond)
|
||||
fn.Nbody.Append(ret)
|
||||
}
|
||||
|
||||
if Debug['r'] != 0 {
|
||||
// ret:
|
||||
// return
|
||||
ret := autolabel(".ret")
|
||||
fn.Nbody.Append(nodSym(OLABEL, nil, ret))
|
||||
fn.Nbody.Append(nod(ORETURN, nil, nil))
|
||||
|
||||
// neq:
|
||||
// r = false
|
||||
// return (or goto ret)
|
||||
fn.Nbody.Append(nodSym(OLABEL, nil, neq))
|
||||
fn.Nbody.Append(nod(OAS, nr, nodbool(false)))
|
||||
if EqCanPanic(t) || hasCall(fn) {
|
||||
// Epilogue is large, so share it with the equal case.
|
||||
fn.Nbody.Append(nodSym(OGOTO, nil, ret))
|
||||
} else {
|
||||
// Epilogue is small, so don't bother sharing.
|
||||
fn.Nbody.Append(nod(ORETURN, nil, nil))
|
||||
}
|
||||
// TODO(khr): the epilogue size detection condition above isn't perfect.
|
||||
// We should really do a generic CL that shares epilogues across
|
||||
// the board. See #24936.
|
||||
|
||||
if Debug.r != 0 {
|
||||
dumplist("geneq body", fn.Nbody)
|
||||
}
|
||||
|
||||
|
|
@ -754,7 +775,7 @@ func geneq(t *types.Type) *obj.LSym {
|
|||
// neither of which can be nil, and our comparisons
|
||||
// are shallow.
|
||||
fn.Func.SetNilCheckDisabled(true)
|
||||
funccompile(fn)
|
||||
xtop = append(xtop, fn)
|
||||
|
||||
// Generate a closure which points at the function we just generated.
|
||||
dsymptr(closure, 0, sym.Linksym(), 0)
|
||||
|
|
@ -762,6 +783,39 @@ func geneq(t *types.Type) *obj.LSym {
|
|||
return closure
|
||||
}
|
||||
|
||||
func hasCall(n *Node) bool {
|
||||
if n.Op == OCALL || n.Op == OCALLFUNC {
|
||||
return true
|
||||
}
|
||||
if n.Left != nil && hasCall(n.Left) {
|
||||
return true
|
||||
}
|
||||
if n.Right != nil && hasCall(n.Right) {
|
||||
return true
|
||||
}
|
||||
for _, x := range n.Ninit.Slice() {
|
||||
if hasCall(x) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, x := range n.Nbody.Slice() {
|
||||
if hasCall(x) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, x := range n.List.Slice() {
|
||||
if hasCall(x) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, x := range n.Rlist.Slice() {
|
||||
if hasCall(x) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// eqfield returns the node
|
||||
// p.field == q.field
|
||||
func eqfield(p *Node, q *Node, field *types.Sym) *Node {
|
||||
|
|
|
|||
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