[dev.fuzz] all: merge master into dev.fuzz

Change-Id: I5d8c8329ccc9d747bd81ade6b1cb7cb8ae2e94b2
This commit is contained in:
Katie Hockman 2020-12-14 10:03:05 -05:00
commit 0345ede87e
2192 changed files with 121081 additions and 62689 deletions

View file

@ -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"

View file

@ -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

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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 -->

View file

@ -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>

View file

@ -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&lt;&lt;s // 1 has type int
var j int32 = 1&lt;&lt;s // 1 has type int32; j == 0
var k = uint64(1&lt;&lt;s) // 1 has type uint64; k == 1&lt;&lt;33
var m int = 1.0&lt;&lt;s // 1.0 has type int; m == 0 if ints are 32bits in size
var n = 1.0&lt;&lt;s == j // 1.0 has type int32; n == true
var o = 1&lt;&lt;s == 2&lt;&lt;s // 1 and 2 have type int; o == true if ints are 32bits in size
var p = 1&lt;&lt;s == 1&lt;&lt;33 // illegal if ints are 32bits in size: 1 has type int, but 1&lt;&lt;33 overflows int
var u = 1.0&lt;&lt;s // illegal: 1.0 has type float64, cannot shift
var u1 = 1.0&lt;&lt;s != 0 // illegal: 1.0 has type float64, cannot shift
var u2 = 1&lt;&lt;s != 1.0 // illegal: 1 has type float64, cannot shift
var v float32 = 1&lt;&lt;s // illegal: 1 has type float32, cannot shift
var w int64 = 1.0&lt;&lt;33 // 1.0&lt;&lt;33 is a constant shift expression
var x = a[1.0&lt;&lt;s] // 1.0 has type int; x == a[0] if ints are 32bits in size
var a = make([]byte, 1.0&lt;&lt;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&lt;&lt;s // 1 has type int
var j int32 = 1&lt;&lt;s // 1 has type int32; j == 0
var k = uint64(1&lt;&lt;s) // 1 has type uint64; k == 1&lt;&lt;33
var m int = 1.0&lt;&lt;s // 1.0 has type int; m == 1&lt;&lt;33
var n = 1.0&lt;&lt;s == j // 1.0 has type int; n == true
var o = 1&lt;&lt;s == 2&lt;&lt;s // 1 and 2 have type int; o == false
var p = 1&lt;&lt;s == 1&lt;&lt;33 // 1 has type int; p == true
var u = 1.0&lt;&lt;s // illegal: 1.0 has type float64, cannot shift
var u1 = 1.0&lt;&lt;s != 0 // illegal: 1.0 has type float64, cannot shift
var u2 = 1&lt;&lt;s != 1.0 // illegal: 1 has type float64, cannot shift
var v float32 = 1&lt;&lt;s // illegal: 1 has type float32, cannot shift
var w int64 = 1.0&lt;&lt;33 // 1.0&lt;&lt;33 is a constant shift expression; w == 1&lt;&lt;33
var x = a[1.0&lt;&lt;s] // panics: 1.0 has type int, but 1&lt;&lt;33 overflows array bounds
var b = make([]byte, 1.0&lt;&lt;s) // 1.0 has type int; len(b) == 1&lt;&lt;33
// The results of the following examples are given for 32-bit ints,
// which means the shifts will overflow.
var mm int = 1.0&lt;&lt;s // 1.0 has type int; mm == 0
var oo = 1&lt;&lt;s == 2&lt;&lt;s // 1 and 2 have type int; oo == true
var pp = 1&lt;&lt;s == 1&lt;&lt;33 // illegal: 1 has type int, but 1&lt;&lt;33 overflows int
var xx = a[1.0&lt;&lt;s] // 1.0 has type int; xx == a[0]
var bb = make([]byte, 1.0&lt;&lt;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 &lt;= f()
^a &gt;&gt; b
f() || g()
x == y+1 &amp;&amp; &lt;-chanPtr &gt; 0
x == y+1 &amp;&amp; &lt;-chanInt &gt; 0
</pre>

View file

@ -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>

View file

@ -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.

View 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))
}

View file

@ -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",

View file

@ -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) }

View file

@ -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
View 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)
}
}
}

View file

@ -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)
}

View file

@ -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>

View file

@ -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

View file

@ -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

View 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) {}

View file

@ -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.")

View file

@ -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)
}

View file

@ -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
View 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
View 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
}

View 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

View file

@ -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

View file

@ -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()

View file

@ -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")

View 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

View file

@ -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)
}
}

View file

@ -19,6 +19,7 @@ import (
// import "C" block. Add more tests here.
var filePrefixes = []string{
"anonunion",
"bitfields",
"issue8478",
"fieldtypedef",
"issue37479",

View file

@ -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)
}
}

View 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)
}

View 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

View file

@ -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 {

View 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))
}

View file

@ -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+"=.")

View file

@ -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+"=.")

View file

@ -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

View file

@ -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 "$@"

View file

@ -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.

View file

@ -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)
`

View file

@ -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

View file

@ -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

View file

@ -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
}

View file

@ -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
}
}

View file

@ -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)

View file

@ -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)
}
}

View file

@ -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)
}

View file

@ -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
}

View file

@ -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)
}
}

View file

@ -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))
}

View file

@ -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
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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)
}
}

View file

@ -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)
}

View file

@ -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)

View file

@ -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)
}
}
}

View file

@ -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

View file

@ -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)

View file

@ -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
}

View file

@ -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")
}

View file

@ -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()

View file

@ -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()

View file

@ -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{

View file

@ -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.

View file

@ -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"},

View file

@ -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

View file

@ -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

View 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"

File diff suppressed because it is too large Load diff

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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()

View file

@ -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.

View file

@ -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('.')
}

View file

@ -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':

View file

@ -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...)

View file

@ -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)
}

View file

@ -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"
}

View file

@ -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; }

View file

@ -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

View file

@ -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")

View file

@ -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)
}

View file

@ -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 = `

View file

@ -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

View file

@ -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": "",

View file

@ -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

View file

@ -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)

View file

@ -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,

View file

@ -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