mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.boringcrypto] all: merge commit 9d0819b27c (CL 314609) into dev.boringcrypto
There used to be two BoringCrypto-specific behaviors related to cipher suites in crypto/tls: 1. in FIPS-only mode, only a restricted set of AES ciphers is allowed 2. NOT in FIPS-only mode, AES would be prioritized over ChaCha20 even if AES hardware was not available The motivation of (2) is unclear, and BoringSSL doesn't have equivalent logic. This merge drops (2), and keeps (1). Note that the list of FIPS-only ciphers does not have priority semantics anymore, but the default logic still sorts them the same way as they used to be. Change-Id: I50544011085cfa2b087f323aebf5338c0bd2dd33
This commit is contained in:
commit
ed1f812cef
3217 changed files with 116892 additions and 55301 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -37,6 +37,7 @@ _testmain.go
|
||||||
/src/cmd/internal/objabi/zbootstrap.go
|
/src/cmd/internal/objabi/zbootstrap.go
|
||||||
/src/go/build/zcgo.go
|
/src/go/build/zcgo.go
|
||||||
/src/go/doc/headscan
|
/src/go/doc/headscan
|
||||||
|
/src/internal/buildcfg/zbootstrap.go
|
||||||
/src/runtime/internal/sys/zversion.go
|
/src/runtime/internal/sys/zversion.go
|
||||||
/src/unicode/maketables
|
/src/unicode/maketables
|
||||||
/test.out
|
/test.out
|
||||||
|
|
|
||||||
5
AUTHORS
5
AUTHORS
|
|
@ -145,7 +145,7 @@ Andy Davis <andy@bigandian.com>
|
||||||
Andy Finkenstadt <afinkenstadt@zynga.com>
|
Andy Finkenstadt <afinkenstadt@zynga.com>
|
||||||
Andy Lindeman <andy@lindeman.io>
|
Andy Lindeman <andy@lindeman.io>
|
||||||
Andy Maloney <asmaloney@gmail.com>
|
Andy Maloney <asmaloney@gmail.com>
|
||||||
Andy Pan <panjf2000@gmail.com>
|
Andy Pan <panjf2000@gmail.com> <panjf2000@golangcn.org> <i@andypan.me>
|
||||||
Andy Walker <walkeraj@gmail.com>
|
Andy Walker <walkeraj@gmail.com>
|
||||||
Anfernee Yongkun Gui <anfernee.gui@gmail.com>
|
Anfernee Yongkun Gui <anfernee.gui@gmail.com>
|
||||||
Angelo Bulfone <mbulfone@gmail.com>
|
Angelo Bulfone <mbulfone@gmail.com>
|
||||||
|
|
@ -195,7 +195,7 @@ Ayanamist Yang <ayanamist@gmail.com>
|
||||||
Aymerick Jéhanne <aymerick@jehanne.org>
|
Aymerick Jéhanne <aymerick@jehanne.org>
|
||||||
Azat Kaumov <kaumov.a.r@gmail.com>
|
Azat Kaumov <kaumov.a.r@gmail.com>
|
||||||
Baiju Muthukadan <baiju.m.mail@gmail.com>
|
Baiju Muthukadan <baiju.m.mail@gmail.com>
|
||||||
Baokun Lee <nototon@gmail.com>
|
Baokun Lee <nototon@gmail.com> <bk@golangcn.org>
|
||||||
Bartosz Grzybowski <melkorm@gmail.com>
|
Bartosz Grzybowski <melkorm@gmail.com>
|
||||||
Bastian Ike <bastian.ike@gmail.com>
|
Bastian Ike <bastian.ike@gmail.com>
|
||||||
Ben Burkert <ben@benburkert.com>
|
Ben Burkert <ben@benburkert.com>
|
||||||
|
|
@ -1425,6 +1425,7 @@ Wèi Cōngruì <crvv.mail@gmail.com>
|
||||||
Wei Fu <fhfuwei@163.com>
|
Wei Fu <fhfuwei@163.com>
|
||||||
Wei Guangjing <vcc.163@gmail.com>
|
Wei Guangjing <vcc.163@gmail.com>
|
||||||
Weichao Tang <tevic.tt@gmail.com>
|
Weichao Tang <tevic.tt@gmail.com>
|
||||||
|
Weixie Cui <cuiweixie@gmail.com> <523516579@qq.com>
|
||||||
Wembley G. Leach, Jr <wembley.gl@gmail.com>
|
Wembley G. Leach, Jr <wembley.gl@gmail.com>
|
||||||
Will Faught <will.faught@gmail.com>
|
Will Faught <will.faught@gmail.com>
|
||||||
Will Storey <will@summercat.com>
|
Will Storey <will@summercat.com>
|
||||||
|
|
|
||||||
|
|
@ -240,7 +240,7 @@ Andy Davis <andy@bigandian.com>
|
||||||
Andy Finkenstadt <afinkenstadt@zynga.com>
|
Andy Finkenstadt <afinkenstadt@zynga.com>
|
||||||
Andy Lindeman <andy@lindeman.io>
|
Andy Lindeman <andy@lindeman.io>
|
||||||
Andy Maloney <asmaloney@gmail.com>
|
Andy Maloney <asmaloney@gmail.com>
|
||||||
Andy Pan <panjf2000@gmail.com>
|
Andy Pan <panjf2000@gmail.com> <panjf2000@golangcn.org> <i@andypan.me>
|
||||||
Andy Walker <walkeraj@gmail.com>
|
Andy Walker <walkeraj@gmail.com>
|
||||||
Andy Wang <cbeuw.andy@gmail.com>
|
Andy Wang <cbeuw.andy@gmail.com>
|
||||||
Andy Williams <andy@andy.xyz>
|
Andy Williams <andy@andy.xyz>
|
||||||
|
|
@ -321,7 +321,7 @@ Azat Kaumov <kaumov.a.r@gmail.com>
|
||||||
Baiju Muthukadan <baiju.m.mail@gmail.com>
|
Baiju Muthukadan <baiju.m.mail@gmail.com>
|
||||||
Balaram Makam <bmakam.qdt@qualcommdatacenter.com>
|
Balaram Makam <bmakam.qdt@qualcommdatacenter.com>
|
||||||
Balazs Lecz <leczb@google.com>
|
Balazs Lecz <leczb@google.com>
|
||||||
Baokun Lee <nototon@gmail.com>
|
Baokun Lee <nototon@gmail.com> <bk@golangcn.org>
|
||||||
Barnaby Keene <accounts@southcla.ws>
|
Barnaby Keene <accounts@southcla.ws>
|
||||||
Bartosz Grzybowski <melkorm@gmail.com>
|
Bartosz Grzybowski <melkorm@gmail.com>
|
||||||
Bartosz Oler <brtsz@google.com>
|
Bartosz Oler <brtsz@google.com>
|
||||||
|
|
@ -466,7 +466,7 @@ Charlotte Brandhorst-Satzkorn <catzkorn@gmail.com>
|
||||||
Chauncy Cullitan <chauncyc@google.com>
|
Chauncy Cullitan <chauncyc@google.com>
|
||||||
Chen Zhidong <njutczd@gmail.com>
|
Chen Zhidong <njutczd@gmail.com>
|
||||||
Chen Zhihan <energiehund@gmail.com>
|
Chen Zhihan <energiehund@gmail.com>
|
||||||
Cherry Zhang <cherryyz@google.com>
|
Cherry Mui <cherryyz@google.com>
|
||||||
Chew Choon Keat <choonkeat@gmail.com>
|
Chew Choon Keat <choonkeat@gmail.com>
|
||||||
Chiawen Chen <golopot@gmail.com>
|
Chiawen Chen <golopot@gmail.com>
|
||||||
Chirag Sukhala <cchirag77@gmail.com>
|
Chirag Sukhala <cchirag77@gmail.com>
|
||||||
|
|
@ -2526,6 +2526,7 @@ Wei Guangjing <vcc.163@gmail.com>
|
||||||
Wei Xiao <wei.xiao@arm.com>
|
Wei Xiao <wei.xiao@arm.com>
|
||||||
Wei Xikai <xykwei@gmail.com>
|
Wei Xikai <xykwei@gmail.com>
|
||||||
Weichao Tang <tevic.tt@gmail.com>
|
Weichao Tang <tevic.tt@gmail.com>
|
||||||
|
Weixie Cui <cuiweixie@gmail.com> <523516579@qq.com>
|
||||||
Wembley G. Leach, Jr <wembley.gl@gmail.com>
|
Wembley G. Leach, Jr <wembley.gl@gmail.com>
|
||||||
Wenlei (Frank) He <wlhe@google.com>
|
Wenlei (Frank) He <wlhe@google.com>
|
||||||
Wenzel Lowe <lowewenzel@gmail.com>
|
Wenzel Lowe <lowewenzel@gmail.com>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
pkg encoding/json, method (*RawMessage) MarshalJSON() ([]uint8, error)
|
pkg encoding/json, method (*RawMessage) MarshalJSON() ([]uint8, error)
|
||||||
|
pkg math, const MaxFloat64 = 1.79769e+308 // 179769313486231570814527423731704356798100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
pkg math, const SmallestNonzeroFloat32 = 1.4013e-45 // 17516230804060213386546619791123951641/12500000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
pkg math, const SmallestNonzeroFloat64 = 4.94066e-324 // 4940656458412465441765687928682213723651/1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
pkg math/big, const MaxBase = 36
|
pkg math/big, const MaxBase = 36
|
||||||
pkg math/big, type Word uintptr
|
pkg math/big, type Word uintptr
|
||||||
pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)
|
pkg net, func ListenUnixgram(string, *UnixAddr) (*UDPConn, error)
|
||||||
|
|
|
||||||
99
api/next.txt
99
api/next.txt
|
|
@ -0,0 +1,99 @@
|
||||||
|
pkg compress/lzw, method (*Reader) Close() error
|
||||||
|
pkg compress/lzw, method (*Reader) Read([]uint8) (int, error)
|
||||||
|
pkg compress/lzw, method (*Reader) Reset(io.Reader, Order, int)
|
||||||
|
pkg compress/lzw, method (*Writer) Close() error
|
||||||
|
pkg compress/lzw, method (*Writer) Reset(io.Writer, Order, int)
|
||||||
|
pkg compress/lzw, method (*Writer) Write([]uint8) (int, error)
|
||||||
|
pkg compress/lzw, type Reader struct
|
||||||
|
pkg compress/lzw, type Writer struct
|
||||||
|
pkg crypto/tls, method (*CertificateRequestInfo) Context() context.Context
|
||||||
|
pkg crypto/tls, method (*ClientHelloInfo) Context() context.Context
|
||||||
|
pkg crypto/tls, method (*Conn) HandshakeContext(context.Context) error
|
||||||
|
pkg debug/elf, const SHT_MIPS_ABIFLAGS = 1879048234
|
||||||
|
pkg debug/elf, const SHT_MIPS_ABIFLAGS SectionType
|
||||||
|
pkg encoding/csv, method (*Reader) FieldPos(int) (int, int)
|
||||||
|
pkg go/ast, method (*FuncDecl) IsMethod() bool
|
||||||
|
pkg go/build, type Context struct, ToolTags []string
|
||||||
|
pkg go/parser, const SkipObjectResolution = 64
|
||||||
|
pkg go/parser, const SkipObjectResolution Mode
|
||||||
|
pkg go/types, type Config struct, GoVersion string
|
||||||
|
pkg io/fs, func FileInfoToDirEntry(FileInfo) DirEntry
|
||||||
|
pkg net, method (*ParseError) Temporary() bool
|
||||||
|
pkg net, method (*ParseError) Timeout() bool
|
||||||
|
pkg net, method (IP) IsPrivate() bool
|
||||||
|
pkg reflect, func VisibleFields(Type) []StructField
|
||||||
|
pkg reflect, method (Method) IsExported() bool
|
||||||
|
pkg reflect, method (StructField) IsExported() bool
|
||||||
|
pkg runtime/cgo (darwin-amd64-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (darwin-amd64-cgo), type Handle uintptr
|
||||||
|
pkg runtime/cgo (freebsd-386-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (freebsd-386-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (freebsd-386-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (freebsd-386-cgo), type Handle uintptr
|
||||||
|
pkg runtime/cgo (freebsd-amd64-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (freebsd-amd64-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (freebsd-amd64-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (freebsd-amd64-cgo), type Handle uintptr
|
||||||
|
pkg runtime/cgo (freebsd-arm-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (freebsd-arm-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (freebsd-arm-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (freebsd-arm-cgo), type Handle uintptr
|
||||||
|
pkg runtime/cgo (linux-386-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (linux-386-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (linux-386-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (linux-386-cgo), type Handle uintptr
|
||||||
|
pkg runtime/cgo (linux-amd64-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (linux-amd64-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (linux-amd64-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (linux-amd64-cgo), type Handle uintptr
|
||||||
|
pkg runtime/cgo (linux-arm-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (linux-arm-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (linux-arm-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (linux-arm-cgo), type Handle uintptr
|
||||||
|
pkg runtime/cgo (netbsd-386-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (netbsd-386-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (netbsd-386-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (netbsd-386-cgo), type Handle uintptr
|
||||||
|
pkg runtime/cgo (netbsd-amd64-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (netbsd-amd64-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (netbsd-amd64-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (netbsd-amd64-cgo), type Handle uintptr
|
||||||
|
pkg runtime/cgo (netbsd-arm-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (netbsd-arm-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (netbsd-arm-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (netbsd-arm-cgo), type Handle uintptr
|
||||||
|
pkg runtime/cgo (netbsd-arm64-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (netbsd-arm64-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (netbsd-arm64-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (netbsd-arm64-cgo), type Handle uintptr
|
||||||
|
pkg runtime/cgo (openbsd-386-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (openbsd-386-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (openbsd-386-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (openbsd-386-cgo), type Handle uintptr
|
||||||
|
pkg runtime/cgo (openbsd-amd64-cgo), func NewHandle(interface{}) Handle
|
||||||
|
pkg runtime/cgo (openbsd-amd64-cgo), method (Handle) Delete()
|
||||||
|
pkg runtime/cgo (openbsd-amd64-cgo), method (Handle) Value() interface{}
|
||||||
|
pkg runtime/cgo (openbsd-amd64-cgo), type Handle uintptr
|
||||||
|
pkg syscall (openbsd-386), const MSG_CMSG_CLOEXEC = 2048
|
||||||
|
pkg syscall (openbsd-386), const MSG_CMSG_CLOEXEC ideal-int
|
||||||
|
pkg syscall (openbsd-386-cgo), const MSG_CMSG_CLOEXEC = 2048
|
||||||
|
pkg syscall (openbsd-386-cgo), const MSG_CMSG_CLOEXEC ideal-int
|
||||||
|
pkg syscall (openbsd-amd64), const MSG_CMSG_CLOEXEC = 2048
|
||||||
|
pkg syscall (openbsd-amd64), const MSG_CMSG_CLOEXEC ideal-int
|
||||||
|
pkg syscall (openbsd-amd64-cgo), const MSG_CMSG_CLOEXEC = 2048
|
||||||
|
pkg syscall (openbsd-amd64-cgo), const MSG_CMSG_CLOEXEC ideal-int
|
||||||
|
pkg syscall (windows-386), type SysProcAttr struct, AdditionalInheritedHandles []Handle
|
||||||
|
pkg syscall (windows-386), type SysProcAttr struct, ParentProcess Handle
|
||||||
|
pkg syscall (windows-amd64), type SysProcAttr struct, AdditionalInheritedHandles []Handle
|
||||||
|
pkg syscall (windows-amd64), type SysProcAttr struct, ParentProcess Handle
|
||||||
|
pkg testing, method (*B) Setenv(string, string)
|
||||||
|
pkg testing, method (*T) Setenv(string, string)
|
||||||
|
pkg text/template/parse, const SkipFuncCheck = 2
|
||||||
|
pkg text/template/parse, const SkipFuncCheck Mode
|
||||||
|
pkg time, func UnixMicro(int64) Time
|
||||||
|
pkg time, func UnixMilli(int64) Time
|
||||||
|
pkg time, method (*Time) IsDST() bool
|
||||||
|
pkg time, method (Time) UnixMicro() int64
|
||||||
|
pkg time, method (Time) UnixMilli() int64
|
||||||
1220
doc/go1.16.html
1220
doc/go1.16.html
File diff suppressed because it is too large
Load diff
535
doc/go1.17.html
Normal file
535
doc/go1.17.html
Normal file
|
|
@ -0,0 +1,535 @@
|
||||||
|
<!--{
|
||||||
|
"Title": "Go 1.17 Release Notes",
|
||||||
|
"Path": "/doc/go1.17"
|
||||||
|
}-->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
NOTE: In this document and others in this directory, the convention is to
|
||||||
|
set fixed-width phrases with non-fixed-width spaces, as in
|
||||||
|
<code>hello</code> <code>world</code>.
|
||||||
|
Do not send CLs removing the interior tags from such phrases.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
main ul li { margin: 0.5em 0; }
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<h2 id="introduction">DRAFT RELEASE NOTES — Introduction to Go 1.17</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<strong>
|
||||||
|
Go 1.17 is not yet released. These are work-in-progress
|
||||||
|
release notes. Go 1.17 is expected to be released in August 2021.
|
||||||
|
</strong>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="language">Changes to the language</h2>
|
||||||
|
|
||||||
|
<p><!-- CL 216424 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/216424">https://golang.org/cl/216424</a>: allow conversion from slice to array ptr
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 312212 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/312212">https://golang.org/cl/312212</a>: add unsafe.Add and unsafe.Slice
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="ports">Ports</h2>
|
||||||
|
|
||||||
|
<h3 id="darwin">Darwin</h3>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/23011 -->
|
||||||
|
As <a href="go1.16#darwin">announced</a> in the Go 1.16 release
|
||||||
|
notes, Go 1.17 requires macOS 10.13 High Sierra or later; support
|
||||||
|
for previous versions has been discontinued.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
TODO: complete the Ports section
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="tools">Tools</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
TODO: complete the Tools section
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="go-command">Go command</h3>
|
||||||
|
|
||||||
|
<h4 id="lazy-loading">Lazy module loading</h4>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/36460 -->
|
||||||
|
If a module specifies <code>go</code> <code>1.17</code> or higher in its
|
||||||
|
<code>go.mod</code> file, its transitive requirements are now loaded lazily,
|
||||||
|
avoding the need to download or read <code>go.mod</code> files for
|
||||||
|
otherwise-irrelevant dependencies. To support lazy loading, in Go 1.17 modules
|
||||||
|
the <code>go</code> command maintains <em>explicit</em> requirements in
|
||||||
|
the <code>go.mod</code> file for every dependency that provides any package
|
||||||
|
transitively imported by any package or test within the module.
|
||||||
|
See <a href="https://golang.org/design/36460-lazy-module-loading">the design
|
||||||
|
document</a> for more detail.
|
||||||
|
<!-- TODO(bcmills): replace the design-doc link with proper documentation. -->
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/45094 --> To facilitate the upgrade to lazy loading,
|
||||||
|
the <code>go</code> <code>mod</code> <code>tidy</code> subcommand now supports
|
||||||
|
a <code>-go</code> flag to set or change the <code>go</code> version in
|
||||||
|
the <code>go.mod</code> file. To enable lazy loading for an existing module
|
||||||
|
without changing the selected versions of its dependencies, run:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
go mod tidy -go=1.17
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h4 id="module-deprecation-comments">Module deprecation comments</h4>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/40357 -->
|
||||||
|
Module authors may deprecate a module by adding a
|
||||||
|
<a href="/ref/mod#go-mod-file-module-deprecation"><code>// Deprecated:</code>
|
||||||
|
comment</a> to <code>go.mod</code>, then tagging a new version.
|
||||||
|
<code>go</code> <code>get</code> now prints a warning if a module needed to
|
||||||
|
build packages named on the command line is deprecated. <code>go</code>
|
||||||
|
<code>list</code> <code>-m</code> <code>-u</code> prints deprecations for all
|
||||||
|
dependencies (use <code>-f</code> or <code>-json</code> to show the full
|
||||||
|
message). The <code>go</code> command considers different major versions to
|
||||||
|
be distinct modules, so this mechanism may be used, for example, to provide
|
||||||
|
users with migration instructions for a new major version.
|
||||||
|
</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 has been removed. To permit the use of insecure schemes
|
||||||
|
when fetching dependencies, please use the <code>GOINSECURE</code>
|
||||||
|
environment variable. The <code>-insecure</code> flag also bypassed module
|
||||||
|
sum validation, use <code>GOPRIVATE</code> or <code>GONOSUMDB</code> if
|
||||||
|
you need that functionality. See <code>go</code> <code>help</code>
|
||||||
|
<code>environment</code> for details.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 id="missing-go-directive"><code>go.mod</code> files missing <code>go</code> directives</h4>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/44976 -->
|
||||||
|
If the main module's <code>go.mod</code> file does not contain
|
||||||
|
a <a href="/doc/modules/gomod-ref#go"><code>go</code> directive</a> and
|
||||||
|
the <code>go</code> command cannot update the <code>go.mod</code> file, the
|
||||||
|
<code>go</code> command now assumes <code>go 1.11</code> instead of the
|
||||||
|
current release. (<code>go</code> <code>mod</code> <code>init</code> has added
|
||||||
|
<code>go</code> directives automatically <a href="/doc/go1.12#modules">since
|
||||||
|
Go 1.12</a>.)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/44976 -->
|
||||||
|
If a module dependency lacks an explicit <code>go.mod</code> file, or
|
||||||
|
its <code>go.mod</code> file does not contain
|
||||||
|
a <a href="/doc/modules/gomod-ref#go"><code>go</code> directive</a>,
|
||||||
|
the <code>go</code> command now assumes <code>go 1.16</code> for that
|
||||||
|
dependency instead of the current release. (Dependencies developed in GOPATH
|
||||||
|
mode may lack a <code>go.mod</code> file, and
|
||||||
|
the <code>vendor/modules.txt</code> has to date never recorded
|
||||||
|
the <code>go</code> versions indicated by dependencies' <code>go.mod</code>
|
||||||
|
files.)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 id="vendor"><code>vendor</code> contents</h4>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/36876 -->
|
||||||
|
If the main module specifies <code>go</code> <code>1.17</code> or higher,
|
||||||
|
<code>go</code> <code>mod</code> <code>vendor</code> now annotates
|
||||||
|
<code>vendor/modules.txt</code> with the <code>go</code> version indicated by
|
||||||
|
each vendored module in its own <code>go.mod</code> file. The annotated
|
||||||
|
version is used when building the module's packages from vendored source code.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/42970 -->
|
||||||
|
If the main module specifies <code>go</code> <code>1.17</code> or higher,
|
||||||
|
<code>go</code> <code>mod</code> <code>vendor</code> now omits <code>go.mod</code>
|
||||||
|
and <code>go.sum</code> files for vendored dependencies, which can otherwise
|
||||||
|
interfere with the ability of the <code>go</code> command to identify the correct
|
||||||
|
module root when invoked within the <code>vendor</code> tree.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 id="password-prompts">Password prompts</h4>
|
||||||
|
|
||||||
|
<p><!-- golang.org/issue/44904 -->
|
||||||
|
The <code>go</code> command by default now suppresses SSH password prompts and
|
||||||
|
Git Credential Manager prompts when fetching Git repositories using SSH, as it
|
||||||
|
already did previously for other Git password prompts. Users authenticating to
|
||||||
|
private Git repos with password-protected SSH may configure
|
||||||
|
an <code>ssh-agent</code> to enable the <code>go</code> command to use
|
||||||
|
password-protected SSH keys.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 249759 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/249759">https://golang.org/cl/249759</a>: cmd/cover: replace code using optimized golang.org/x/tools/cover
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="vet">Vet</h3>
|
||||||
|
|
||||||
|
<p><!-- CL 299532 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/299532">https://golang.org/cl/299532</a>: cmd/vet: bring in sigchanyzer to report unbuffered channels to signal.Notify
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
TODO: complete the Vet section
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="runtime">Runtime</h2>
|
||||||
|
|
||||||
|
<p><!-- CL 304470 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/304470">https://golang.org/cl/304470</a>: cmd/compile, runtime: add metadata for argument printing in traceback
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
TODO: complete the Runtime section
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="compiler">Compiler</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
TODO: complete the Compiler section, or delete if not needed
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="linker">Linker</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
TODO: complete the Linker section, or delete if not needed
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 id="library">Core library</h2>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
TODO: complete the Core library section
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="crypto/tls"><a href="/pkg/crypto/tls">crypto/tls</a></h3>
|
||||||
|
|
||||||
|
<p><!-- CL 295370 -->
|
||||||
|
<a href="/pkg/crypto/tls#Conn.HandshakeContext">(*Conn).HandshakeContext</a> was added to
|
||||||
|
allow the user to control cancellation of an in-progress TLS Handshake.
|
||||||
|
The context provided is propagated into the
|
||||||
|
<a href="/pkg/crypto/tls#ClientHelloInfo">ClientHelloInfo</a>
|
||||||
|
and <a href="/pkg/crypto/tls#CertificateRequestInfo">CertificateRequestInfo</a>
|
||||||
|
structs and accessible through the new
|
||||||
|
<a href="/pkg/crypto/tls#ClientHelloInfo.Context">(*ClientHelloInfo).Context</a>
|
||||||
|
and
|
||||||
|
<a href="/pkg/crypto/tls#CertificateRequestInfo.Context">
|
||||||
|
(*CertificateRequestInfo).Context
|
||||||
|
</a> methods respectively. Canceling the context after the handshake has finished
|
||||||
|
has no effect.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 289209 -->
|
||||||
|
When <a href="/pkg/crypto/tls#Config">Config.NextProtos</a> is set, servers now
|
||||||
|
enforce that there is an overlap between the configured protocols and the protocols
|
||||||
|
advertised by the client, if any. If there is no overlap the connection is closed
|
||||||
|
with the <code>no_application_protocol</code> alert, as required by RFC 7301.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="runtime/cgo"><a href="/pkg/runtime/cgo">Cgo</a></h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The <a href="/pkg/runtime/cgo">runtime/cgo</a> package now provides a
|
||||||
|
new facility that allows to turn any Go values to a safe representation
|
||||||
|
that can be used to pass values between C and Go safely. See
|
||||||
|
<a href="/pkg/runtime/cgo#Handle">runtime/cgo.Handle</a> for more information.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 id="minor_library_changes">Minor changes to the library</h3>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
As always, there are various minor changes and updates to the library,
|
||||||
|
made with the Go 1 <a href="/doc/go1compat">promise of compatibility</a>
|
||||||
|
in mind.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<dl id="archive/zip"><dt><a href="/pkg/archive/zip/">archive/zip</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 312310 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/312310">https://golang.org/cl/312310</a>: add File.OpenRaw, Writer.CreateRaw, Writer.Copy
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- archive/zip -->
|
||||||
|
|
||||||
|
<dl id="bufio"><dt><a href="/pkg/bufio/">bufio</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 280492 -->
|
||||||
|
The <a href="/pkg/bufio/#Writer.WriteRune"><code>Writer.WriteRune</code></a> method
|
||||||
|
now writes the replacement character U+FFFD for negative rune values,
|
||||||
|
as it does for other invalid runes.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- bufio -->
|
||||||
|
|
||||||
|
<dl id="bytes"><dt><a href="/pkg/bytes/">bytes</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 280492 -->
|
||||||
|
The <a href="/pkg/bytes/#Buffer.WriteRune"><code>Buffer.WriteRune</code></a> method
|
||||||
|
now writes the replacement character U+FFFD for negative rune values,
|
||||||
|
as it does for other invalid runes.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- bytes -->
|
||||||
|
|
||||||
|
<dl id="compress/lzw"><dt><a href="/pkg/compress/lzw/">compress/lzw</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 273667 -->
|
||||||
|
The new
|
||||||
|
<a href="/pkg/compress/lzw/#Reader.Reset"><code>Reader.Reset</code></a>
|
||||||
|
and
|
||||||
|
<a href="/pkg/compress/lzw/#Writer.Reset"><code>Writer.Reset</code></a>
|
||||||
|
methods allow reuse of a <code>Reader</code> or <code>Writer</code>.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- compress/lzw -->
|
||||||
|
|
||||||
|
<dl id="crypto/rsa"><dt><a href="/pkg/crypto/rsa/">crypto/rsa</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 302230 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/302230">https://golang.org/cl/302230</a>: fix salt length calculation with PSSSaltLengthAuto
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- crypto/rsa -->
|
||||||
|
|
||||||
|
<dl id="database/sql"><dt><a href="/pkg/database/sql/">database/sql</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 258360 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/258360">https://golang.org/cl/258360</a>: close driver.Connector if it implements io.Closer
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 311572 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/311572">https://golang.org/cl/311572</a>: add NullInt16 and NullByte
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- database/sql -->
|
||||||
|
|
||||||
|
<dl id="encoding/binary"><dt><a href="/pkg/encoding/binary/">encoding/binary</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 299531 -->
|
||||||
|
<code>binary.Uvarint</code> will stop reading after <code>10 bytes</code> to avoid
|
||||||
|
wasted computations. If more than <code>10 bytes</code> are needed, the byte count returned is <code>-11</code>.
|
||||||
|
<br />
|
||||||
|
Previous Go versions could return larger negative counts when reading incorrectly encoded varints.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- encoding/binary -->
|
||||||
|
|
||||||
|
<dl id="flag"><dt><a href="/pkg/flag/">flag</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 271788 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/271788">https://golang.org/cl/271788</a>: panic if flag name begins with - or contains =
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- flag -->
|
||||||
|
|
||||||
|
<dl id="io/fs"><dt><a href="/pkg/io/fs/">io/fs</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 293649 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/293649">https://golang.org/cl/293649</a>: implement FileInfoToDirEntry
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- io/fs -->
|
||||||
|
|
||||||
|
<dl id="math"><dt><a href="/pkg/math/">math</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 247058 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/247058">https://golang.org/cl/247058</a>: add MaxUint, MinInt, MaxInt
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- math -->
|
||||||
|
|
||||||
|
<dl id="mime"><dt><a href="/pkg/mime/">mime</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 305230 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/305230">https://golang.org/cl/305230</a>: support reading shared mime-info database on unix systems
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- mime -->
|
||||||
|
|
||||||
|
<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 272668 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/272668">https://golang.org/cl/272668</a>: add IP.IsPrivate
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 301709 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/301709">https://golang.org/cl/301709</a>: make go resolver aware of network parameter
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 307030 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/307030">https://golang.org/cl/307030</a>: make ErrClosed and ParseError implement net.Error
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- net -->
|
||||||
|
|
||||||
|
<dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 295370 -->
|
||||||
|
The <a href="/pkg/net/http/"><code>net/http</code></a> package now uses the new
|
||||||
|
<a href="/pkg/crypto/tls#Conn.HandshakeContext"><code>(*tls.Conn).HandshakeContext</code></a>
|
||||||
|
with the <a href="/pkg/net/http/#Request"><code>Request</code></a> context
|
||||||
|
when performing TLS handshakes in the client or server.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 235437 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/235437">https://golang.org/cl/235437</a>: add to deadlines only when positive
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 308952 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/308952">https://golang.org/cl/308952</a>: make ReadRequest return an error when requests have multiple Host headers
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- net/http -->
|
||||||
|
|
||||||
|
<dl id="net/http/httptest"><dt><a href="/pkg/net/http/httptest/">net/http/httptest</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 308950 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/308950">https://golang.org/cl/308950</a>: panic on non-3 digit (XXX) status code in Recorder.WriteHeader
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- net/http/httptest -->
|
||||||
|
|
||||||
|
<dl id="net/url"><dt><a href="/pkg/net/url/">net/url</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 314850 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/314850">https://golang.org/cl/314850</a>: add Values.Has
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- net/url -->
|
||||||
|
|
||||||
|
<dl id="os"><dt><a href="/pkg/os/">os</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 268020 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/268020">https://golang.org/cl/268020</a>: avoid allocation in File.WriteString
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- os -->
|
||||||
|
|
||||||
|
<dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 266197 -->
|
||||||
|
The new
|
||||||
|
<a href="/pkg/reflect/#StructField.IsExported"><code>StructField.IsExported</code></a>
|
||||||
|
and
|
||||||
|
<a href="/pkg/reflect/#Method.IsExported"><code>Method.IsExported</code></a>
|
||||||
|
methods report whether a struct field or type method is exported.
|
||||||
|
They provide a more readable alternative to checking whether <code>PkgPath</code>
|
||||||
|
is empty.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 281233 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/281233">https://golang.org/cl/281233</a>: add VisibleFields function
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 284136 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/284136">https://golang.org/cl/284136</a>: panic if ArrayOf is called with negative length
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- reflect -->
|
||||||
|
|
||||||
|
<dl id="strconv"><dt><a href="/pkg/strconv/">strconv</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 170079 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/170079">https://golang.org/cl/170079</a>: implement Ryū-like algorithm for fixed precision ftoa
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 170080 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/170080">https://golang.org/cl/170080</a>: Implement Ryū algorithm for ftoa shortest mode
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 314775 -->
|
||||||
|
The new <a href="/pkg/strconv/#QuotedPrefix"><code>QuotedPrefix</code></a> function
|
||||||
|
returns the quoted string (as understood by
|
||||||
|
<a href="/pkg/strconv/#Unquote"><code>Unquote</code></a>)
|
||||||
|
at the start of input.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- strconv -->
|
||||||
|
|
||||||
|
<dl id="strings"><dt><a href="/pkg/strings/">strings</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 280492 -->
|
||||||
|
The <a href="/pkg/strings/#Builder.WriteRune"><code>Builder.WriteRune</code></a> method
|
||||||
|
now writes the replacement character U+FFFD for negative rune values,
|
||||||
|
as it does for other invalid runes.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- strings -->
|
||||||
|
|
||||||
|
<dl id="sync/atomic"><dt><a href="/pkg/sync/atomic/">sync/atomic</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 241678 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/241678">https://golang.org/cl/241678</a>: add (*Value).Swap and (*Value).CompareAndSwap
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- sync/atomic -->
|
||||||
|
|
||||||
|
<dl id="syscall"><dt><a href="/pkg/syscall/">syscall</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 295371 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/295371">https://golang.org/cl/295371</a>: do not overflow key memory in GetQueuedCompletionStatus
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 313653 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/313653">https://golang.org/cl/313653</a>: restore signal mask after setting foreground process group
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- syscall -->
|
||||||
|
|
||||||
|
<dl id="testing"><dt><a href="/pkg/testing/">testing</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 310033 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/310033">https://golang.org/cl/310033</a>: add -shuffle=off|on|N to alter the execution order of tests and benchmarks
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- testing -->
|
||||||
|
|
||||||
|
<dl id="text/template/parse"><dt><a href="/pkg/text/template/parse/">text/template/parse</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 301493 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/301493">https://golang.org/cl/301493</a>: add a mode to skip func-check on parsing
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- text/template/parse -->
|
||||||
|
|
||||||
|
<dl id="time"><dt><a href="/pkg/time/">time</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 260858 -->
|
||||||
|
time.Time now has a <a href="/pkg/time/#Time.GoString">GoString</a>
|
||||||
|
method that will return a more useful value for times when printed with
|
||||||
|
the <code>"%#v"</code> format specifier in the fmt package.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 264077 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/264077">https://golang.org/cl/264077</a>: add Time.IsDST() to check if its Location is in Daylight Savings Time
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 293349 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/293349">https://golang.org/cl/293349</a>: add Time.Unix{Milli,Micro} and to-Time helpers UnixMicro, UnixMilli
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p><!-- CL 300996 -->
|
||||||
|
TODO: <a href="https://golang.org/cl/300996">https://golang.org/cl/300996</a>: support "," as separator for fractional seconds
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- time -->
|
||||||
|
|
||||||
|
<dl id="unicode"><dt><a href="/pkg/unicode/">unicode</a></dt>
|
||||||
|
<dd>
|
||||||
|
<p><!-- CL 280493 -->
|
||||||
|
The <a href="/pkg/unicode/#Is"><code>Is</code></a>,
|
||||||
|
<a href="/pkg/unicode/#IsGraphic"><code>IsGraphic</code></a>,
|
||||||
|
<a href="/pkg/unicode/#IsLetter"><code>IsLetter</code></a>,
|
||||||
|
<a href="/pkg/unicode/#IsLower"><code>IsLower</code></a>,
|
||||||
|
<a href="/pkg/unicode/#IsMark"><code>IsMark</code></a>,
|
||||||
|
<a href="/pkg/unicode/#IsNumber"><code>IsNumber</code></a>,
|
||||||
|
<a href="/pkg/unicode/#IsPrint"><code>IsPrint</code></a>,
|
||||||
|
<a href="/pkg/unicode/#IsPunct"><code>IsPunct</code></a>,
|
||||||
|
<a href="/pkg/unicode/#IsSpace"><code>IsSpace</code></a>,
|
||||||
|
<a href="/pkg/unicode/#IsSymbol"><code>IsSymbol</code></a>, and
|
||||||
|
<a href="/pkg/unicode/#IsUpper"><code>IsUpper</code></a> functions
|
||||||
|
now return <code>false</code> on negative rune values, as they do for other invalid runes.
|
||||||
|
</p>
|
||||||
|
</dd>
|
||||||
|
</dl><!-- unicode -->
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!--{
|
<!--{
|
||||||
"Title": "The Go Programming Language Specification",
|
"Title": "The Go Programming Language Specification",
|
||||||
"Subtitle": "Version of Feb 19, 2021",
|
"Subtitle": "Version of Apr 28, 2021",
|
||||||
"Path": "/ref/spec"
|
"Path": "/ref/spec"
|
||||||
}-->
|
}-->
|
||||||
|
|
||||||
|
|
@ -3532,9 +3532,9 @@ within <code>Greeting</code>, <code>who</code> will have the value
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If the final argument is assignable to a slice type <code>[]T</code>, it is
|
If the final argument is assignable to a slice type <code>[]T</code> and
|
||||||
passed unchanged as the value for a <code>...T</code> parameter if the argument
|
is followed by <code>...</code>, it is passed unchanged as the value
|
||||||
is followed by <code>...</code>. In this case no new slice is created.
|
for a <code>...T</code> parameter. In this case no new slice is created.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -3681,8 +3681,8 @@ The bitwise logical and shift operators apply to integers only.
|
||||||
^ bitwise XOR integers
|
^ bitwise XOR integers
|
||||||
&^ bit clear (AND NOT) integers
|
&^ bit clear (AND NOT) integers
|
||||||
|
|
||||||
<< left shift integer << unsigned integer
|
<< left shift integer << integer >= 0
|
||||||
>> right shift integer >> unsigned integer
|
>> right shift integer >> integer >= 0
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -4164,6 +4164,10 @@ in any of these cases:
|
||||||
<li>
|
<li>
|
||||||
<code>x</code> is a string and <code>T</code> is a slice of bytes or runes.
|
<code>x</code> is a string and <code>T</code> is a slice of bytes or runes.
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<code>x</code> is a slice, <code>T</code> is a pointer to an array,
|
||||||
|
and the slice and array types have <a href="#Type_identity">identical</a> element types.
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -4314,6 +4318,24 @@ MyRunes("白鵬翔") // []rune{0x767d, 0x9d6c, 0x7fd4}
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
|
|
||||||
|
<h4 id="Conversions_from_slice_to_array_pointer">Conversions from slice to array pointer</h4>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Converting a slice to an array pointer yields a pointer to the underlying array of the slice.
|
||||||
|
If the <a href="#Length_and_capacity">length</a> of the slice is less than the length of the array,
|
||||||
|
a <a href="#Run_time_panics">run-time panic</a> occurs.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
s := make([]byte, 2, 4)
|
||||||
|
s0 := (*[0]byte)(s) // s0 != nil
|
||||||
|
s2 := (*[2]byte)(s) // &s2[0] == &s[0]
|
||||||
|
s4 := (*[4]byte)(s) // panics: len([4]byte) > len(s)
|
||||||
|
|
||||||
|
var t []string
|
||||||
|
t0 := (*[0]string)(t) // t0 == nil
|
||||||
|
t1 := (*[1]string)(t) // panics: len([1]string) > len(s)
|
||||||
|
</pre>
|
||||||
|
|
||||||
<h3 id="Constant_expressions">Constant expressions</h3>
|
<h3 id="Constant_expressions">Constant expressions</h3>
|
||||||
|
|
||||||
|
|
@ -4931,9 +4953,9 @@ ExprSwitchCase = "case" ExpressionList | "default" .
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
If the switch expression evaluates to an untyped constant, it is first implicitly
|
If the switch expression evaluates to an untyped constant, it is first implicitly
|
||||||
<a href="#Conversions">converted</a> to its <a href="#Constants">default type</a>;
|
<a href="#Conversions">converted</a> to its <a href="#Constants">default type</a>.
|
||||||
if it is an untyped boolean value, it is first implicitly converted to type <code>bool</code>.
|
|
||||||
The predeclared untyped value <code>nil</code> cannot be used as a switch expression.
|
The predeclared untyped value <code>nil</code> cannot be used as a switch expression.
|
||||||
|
The switch expression type must be <a href="#Comparison_operators">comparable</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -6689,6 +6711,10 @@ type Pointer *ArbitraryType
|
||||||
func Alignof(variable ArbitraryType) uintptr
|
func Alignof(variable ArbitraryType) uintptr
|
||||||
func Offsetof(selector ArbitraryType) uintptr
|
func Offsetof(selector ArbitraryType) uintptr
|
||||||
func Sizeof(variable ArbitraryType) uintptr
|
func Sizeof(variable ArbitraryType) uintptr
|
||||||
|
|
||||||
|
type IntegerType int // shorthand for an integer type; it is not a real type
|
||||||
|
func Add(ptr Pointer, len IntegerType) Pointer
|
||||||
|
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -6745,6 +6771,32 @@ Calls to <code>Alignof</code>, <code>Offsetof</code>, and
|
||||||
<code>Sizeof</code> are compile-time constant expressions of type <code>uintptr</code>.
|
<code>Sizeof</code> are compile-time constant expressions of type <code>uintptr</code>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The function <code>Add</code> adds <code>len</code> to <code>ptr</code>
|
||||||
|
and returns the updated pointer <code>unsafe.Pointer(uintptr(ptr) + uintptr(len))</code>.
|
||||||
|
The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>.
|
||||||
|
A constant <code>len</code> argument must be <a href="#Representability">representable</a> by a value of type <code>int</code>;
|
||||||
|
if it is an untyped constant it is given type <code>int</code>.
|
||||||
|
The rules for <a href="/pkg/unsafe#Pointer">valid uses</a> of <code>Pointer</code> still apply.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The function <code>Slice</code> returns a slice whose underlying array starts at <code>ptr</code>
|
||||||
|
and whose length and capacity are <code>len</code>:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
(*[len]ArbitraryType)(unsafe.Pointer(ptr))[:]
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The <code>len</code> argument must be of integer type or an untyped <a href="#Constants">constant</a>.
|
||||||
|
A constant <code>len</code> argument must be non-negative and <a href="#Representability">representable</a> by a value of type <code>int</code>;
|
||||||
|
if it is an untyped constant it is given type <code>int</code>.
|
||||||
|
If <code>ptr</code> is <code>nil</code> or <code>len</code> is negative at run time,
|
||||||
|
a <a href="#Run_time_panics">run-time panic</a> occurs.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="Size_and_alignment_guarantees">Size and alignment guarantees</h3>
|
<h3 id="Size_and_alignment_guarantees">Size and alignment guarantees</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
||||||
BIN
favicon.ico
BIN
favicon.ico
Binary file not shown.
|
Before Width: | Height: | Size: 5.6 KiB |
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
@ -276,7 +275,7 @@ func adbCopyGoroot() error {
|
||||||
if err := syscall.Flock(int(stat.Fd()), syscall.LOCK_EX); err != nil {
|
if err := syscall.Flock(int(stat.Fd()), syscall.LOCK_EX); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s, err := ioutil.ReadAll(stat)
|
s, err := io.ReadAll(stat)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -294,7 +293,7 @@ func adbCopyGoroot() error {
|
||||||
goroot := runtime.GOROOT()
|
goroot := runtime.GOROOT()
|
||||||
// Build go for android.
|
// Build go for android.
|
||||||
goCmd := filepath.Join(goroot, "bin", "go")
|
goCmd := filepath.Join(goroot, "bin", "go")
|
||||||
tmpGo, err := ioutil.TempFile("", "go_android_exec-cmd-go-*")
|
tmpGo, err := os.CreateTemp("", "go_android_exec-cmd-go-*")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
134
misc/cgo/errors/argposition_test.go
Normal file
134
misc/cgo/errors/argposition_test.go
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Issue 42580: cmd/cgo: shifting identifier position in ast
|
||||||
|
|
||||||
|
package errorstest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/ast"
|
||||||
|
"go/parser"
|
||||||
|
"go/token"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ShortPosition struct {
|
||||||
|
Line int
|
||||||
|
Column int
|
||||||
|
Visited bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type IdentPositionInfo map[string][]ShortPosition
|
||||||
|
|
||||||
|
type Visitor struct {
|
||||||
|
identPosInfo IdentPositionInfo
|
||||||
|
fset *token.FileSet
|
||||||
|
t *testing.T
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *Visitor) Visit(node ast.Node) ast.Visitor {
|
||||||
|
if ident, ok := node.(*ast.Ident); ok {
|
||||||
|
if expectedPositions, ok := v.identPosInfo[ident.Name]; ok {
|
||||||
|
gotMatch := false
|
||||||
|
var errorMessage strings.Builder
|
||||||
|
for caseIndex, expectedPos := range expectedPositions {
|
||||||
|
actualPosition := v.fset.PositionFor(ident.Pos(), true)
|
||||||
|
errorOccured := false
|
||||||
|
if expectedPos.Line != actualPosition.Line {
|
||||||
|
fmt.Fprintf(&errorMessage, "wrong line number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Line, actualPosition.Line)
|
||||||
|
errorOccured = true
|
||||||
|
}
|
||||||
|
if expectedPos.Column != actualPosition.Column {
|
||||||
|
fmt.Fprintf(&errorMessage, "wrong column number for ident %s: expected: %d got: %d\n", ident.Name, expectedPos.Column, actualPosition.Column)
|
||||||
|
errorOccured = true
|
||||||
|
}
|
||||||
|
if errorOccured {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
gotMatch = true
|
||||||
|
expectedPositions[caseIndex].Visited = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !gotMatch {
|
||||||
|
v.t.Errorf(errorMessage.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestArgumentsPositions(t *testing.T) {
|
||||||
|
testdata, err := filepath.Abs("testdata")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpPath := t.TempDir()
|
||||||
|
|
||||||
|
dir := filepath.Join(tmpPath, "src", "testpositions")
|
||||||
|
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command("go", "tool", "cgo",
|
||||||
|
"-srcdir", testdata,
|
||||||
|
"-objdir", dir,
|
||||||
|
"issue42580.go")
|
||||||
|
cmd.Stderr = new(bytes.Buffer)
|
||||||
|
|
||||||
|
err = cmd.Run()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%s: %v\n%s", cmd, err, cmd.Stderr)
|
||||||
|
}
|
||||||
|
mainProcessed, err := ioutil.ReadFile(filepath.Join(dir, "issue42580.cgo1.go"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
f, err := parser.ParseFile(fset, "", mainProcessed, parser.AllErrors)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
expectation := IdentPositionInfo{
|
||||||
|
"checkedPointer": []ShortPosition{
|
||||||
|
ShortPosition{
|
||||||
|
Line: 32,
|
||||||
|
Column: 56,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"singleInnerPointerChecked": []ShortPosition{
|
||||||
|
ShortPosition{
|
||||||
|
Line: 37,
|
||||||
|
Column: 91,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"doublePointerChecked": []ShortPosition{
|
||||||
|
ShortPosition{
|
||||||
|
Line: 42,
|
||||||
|
Column: 91,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, decl := range f.Decls {
|
||||||
|
if fdecl, ok := decl.(*ast.FuncDecl); ok {
|
||||||
|
ast.Walk(&Visitor{expectation, fset, t}, fdecl.Body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for ident, positions := range expectation {
|
||||||
|
for _, position := range positions {
|
||||||
|
if !position.Visited {
|
||||||
|
t.Errorf("Position %d:%d missed for %s ident", position.Line, position.Column, ident)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,6 @@ package errorstest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -55,7 +54,7 @@ func TestBadSymbol(t *testing.T) {
|
||||||
|
|
||||||
makeFile := func(mdir, base, source string) string {
|
makeFile := func(mdir, base, source string) string {
|
||||||
ret := filepath.Join(mdir, base)
|
ret := filepath.Join(mdir, base)
|
||||||
if err := ioutil.WriteFile(ret, []byte(source), 0644); err != nil {
|
if err := os.WriteFile(ret, []byte(source), 0644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
|
|
@ -100,7 +99,7 @@ func TestBadSymbol(t *testing.T) {
|
||||||
// _cgo_import.go.
|
// _cgo_import.go.
|
||||||
|
|
||||||
rewrite := func(from, to string) {
|
rewrite := func(from, to string) {
|
||||||
obj, err := ioutil.ReadFile(from)
|
obj, err := os.ReadFile(from)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -115,7 +114,7 @@ func TestBadSymbol(t *testing.T) {
|
||||||
|
|
||||||
obj = bytes.ReplaceAll(obj, []byte(magicInput), []byte(magicReplace))
|
obj = bytes.ReplaceAll(obj, []byte(magicInput), []byte(magicReplace))
|
||||||
|
|
||||||
if err := ioutil.WriteFile(to, obj, 0644); err != nil {
|
if err := os.WriteFile(to, obj, 0644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@ package errorstest
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -25,7 +24,7 @@ func check(t *testing.T, file string) {
|
||||||
t.Run(file, func(t *testing.T) {
|
t.Run(file, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
contents, err := ioutil.ReadFile(path(file))
|
contents, err := os.ReadFile(path(file))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +55,7 @@ func check(t *testing.T, file string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func expect(t *testing.T, file string, errors []*regexp.Regexp) {
|
func expect(t *testing.T, file string, errors []*regexp.Regexp) {
|
||||||
dir, err := ioutil.TempDir("", filepath.Base(t.Name()))
|
dir, err := os.MkdirTemp("", filepath.Base(t.Name()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -463,7 +462,7 @@ func buildPtrTests(t *testing.T) (dir, exe string) {
|
||||||
gopath = *tmp
|
gopath = *tmp
|
||||||
dir = ""
|
dir = ""
|
||||||
} else {
|
} else {
|
||||||
d, err := ioutil.TempDir("", filepath.Base(t.Name()))
|
d, err := os.MkdirTemp("", filepath.Base(t.Name()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -475,7 +474,7 @@ func buildPtrTests(t *testing.T) (dir, exe string) {
|
||||||
if err := os.MkdirAll(src, 0777); err != nil {
|
if err := os.MkdirAll(src, 0777); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(src, "go.mod"), []byte("module ptrtest"), 0666); err != nil {
|
if err := os.WriteFile(filepath.Join(src, "go.mod"), []byte("module ptrtest"), 0666); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -535,10 +534,10 @@ func buildPtrTests(t *testing.T) (dir, exe string) {
|
||||||
fmt.Fprintf(&cgo1, "}\n\n")
|
fmt.Fprintf(&cgo1, "}\n\n")
|
||||||
fmt.Fprintf(&cgo1, "%s\n", ptrTestMain)
|
fmt.Fprintf(&cgo1, "%s\n", ptrTestMain)
|
||||||
|
|
||||||
if err := ioutil.WriteFile(filepath.Join(src, "cgo1.go"), cgo1.Bytes(), 0666); err != nil {
|
if err := os.WriteFile(filepath.Join(src, "cgo1.go"), cgo1.Bytes(), 0666); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(src, "cgo2.go"), cgo2.Bytes(), 0666); err != nil {
|
if err := os.WriteFile(filepath.Join(src, "cgo2.go"), cgo2.Bytes(), 0666); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
44
misc/cgo/errors/testdata/issue42580.go
vendored
Normal file
44
misc/cgo/errors/testdata/issue42580.go
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Issue 42580: cmd/cgo: shifting identifier position in ast
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
// typedef int (*intFunc) ();
|
||||||
|
//
|
||||||
|
// char* strarg = "";
|
||||||
|
//
|
||||||
|
// int func_with_char(char* arg, void* dummy)
|
||||||
|
// {return 5;}
|
||||||
|
//
|
||||||
|
// int* get_arr(char* arg, void* dummy)
|
||||||
|
// {return NULL;}
|
||||||
|
import "C"
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
// Test variables
|
||||||
|
var (
|
||||||
|
checkedPointer = []byte{1}
|
||||||
|
doublePointerChecked = []byte{1}
|
||||||
|
singleInnerPointerChecked = []byte{1}
|
||||||
|
)
|
||||||
|
|
||||||
|
// This test checks the positions of variable identifiers.
|
||||||
|
// Changing the positions of the test variables idents after this point will break the test.
|
||||||
|
|
||||||
|
func TestSingleArgumentCast() C.int {
|
||||||
|
retcode := C.func_with_char((*C.char)(unsafe.Pointer(&checkedPointer[0])), unsafe.Pointer(C.strarg))
|
||||||
|
return retcode
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSingleArgumentCastRecFuncAsSimpleArg() C.int {
|
||||||
|
retcode := C.func_with_char((*C.char)(unsafe.Pointer(C.get_arr((*C.char)(unsafe.Pointer(&singleInnerPointerChecked[0])), unsafe.Pointer(C.strarg)))), nil)
|
||||||
|
return retcode
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSingleArgumentCastRecFunc() C.int {
|
||||||
|
retcode := C.func_with_char((*C.char)(unsafe.Pointer(C.get_arr((*C.char)(unsafe.Pointer(&doublePointerChecked[0])), unsafe.Pointer(C.strarg)))), unsafe.Pointer(C.strarg))
|
||||||
|
return retcode
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,6 @@ package life_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
@ -21,7 +20,7 @@ func TestMain(m *testing.M) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testMain(m *testing.M) int {
|
func testMain(m *testing.M) int {
|
||||||
GOPATH, err := ioutil.TempDir("", "cgolife")
|
GOPATH, err := os.MkdirTemp("", "cgolife")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +37,7 @@ func testMain(m *testing.M) int {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
os.Setenv("PWD", modRoot)
|
os.Setenv("PWD", modRoot)
|
||||||
if err := ioutil.WriteFile("go.mod", []byte("module cgolife\n"), 0666); err != nil {
|
if err := os.WriteFile("go.mod", []byte("module cgolife\n"), 0666); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ package stdio_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
@ -21,7 +20,7 @@ func TestMain(m *testing.M) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func testMain(m *testing.M) int {
|
func testMain(m *testing.M) int {
|
||||||
GOPATH, err := ioutil.TempDir("", "cgostdio")
|
GOPATH, err := os.MkdirTemp("", "cgostdio")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -38,7 +37,7 @@ func testMain(m *testing.M) int {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
os.Setenv("PWD", modRoot)
|
os.Setenv("PWD", modRoot)
|
||||||
if err := ioutil.WriteFile("go.mod", []byte("module cgostdio\n"), 0666); err != nil {
|
if err := os.WriteFile("go.mod", []byte("module cgostdio\n"), 0666); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ func Test28896(t *testing.T) { test28896(t) }
|
||||||
func Test30065(t *testing.T) { test30065(t) }
|
func Test30065(t *testing.T) { test30065(t) }
|
||||||
func Test32579(t *testing.T) { test32579(t) }
|
func Test32579(t *testing.T) { test32579(t) }
|
||||||
func Test31891(t *testing.T) { test31891(t) }
|
func Test31891(t *testing.T) { test31891(t) }
|
||||||
|
func Test45451(t *testing.T) { test45451(t) }
|
||||||
func TestAlign(t *testing.T) { testAlign(t) }
|
func TestAlign(t *testing.T) { testAlign(t) }
|
||||||
func TestAtol(t *testing.T) { testAtol(t) }
|
func TestAtol(t *testing.T) { testAtol(t) }
|
||||||
func TestBlocking(t *testing.T) { testBlocking(t) }
|
func TestBlocking(t *testing.T) { testBlocking(t) }
|
||||||
|
|
@ -80,6 +81,7 @@ func TestNamedEnum(t *testing.T) { testNamedEnum(t) }
|
||||||
func TestCastToEnum(t *testing.T) { testCastToEnum(t) }
|
func TestCastToEnum(t *testing.T) { testCastToEnum(t) }
|
||||||
func TestErrno(t *testing.T) { testErrno(t) }
|
func TestErrno(t *testing.T) { testErrno(t) }
|
||||||
func TestFpVar(t *testing.T) { testFpVar(t) }
|
func TestFpVar(t *testing.T) { testFpVar(t) }
|
||||||
|
func TestHandle(t *testing.T) { testHandle(t) }
|
||||||
func TestHelpers(t *testing.T) { testHelpers(t) }
|
func TestHelpers(t *testing.T) { testHelpers(t) }
|
||||||
func TestLibgcc(t *testing.T) { testLibgcc(t) }
|
func TestLibgcc(t *testing.T) { testLibgcc(t) }
|
||||||
func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) }
|
func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) }
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ package cgotest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -64,7 +64,7 @@ import "C"
|
||||||
func compareStatus(filter, expect string) error {
|
func compareStatus(filter, expect string) error {
|
||||||
expected := filter + expect
|
expected := filter + expect
|
||||||
pid := syscall.Getpid()
|
pid := syscall.Getpid()
|
||||||
fs, err := ioutil.ReadDir(fmt.Sprintf("/proc/%d/task", pid))
|
fs, err := os.ReadDir(fmt.Sprintf("/proc/%d/task", pid))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to find %d tasks: %v", pid, err)
|
return fmt.Errorf("unable to find %d tasks: %v", pid, err)
|
||||||
}
|
}
|
||||||
|
|
@ -72,7 +72,7 @@ func compareStatus(filter, expect string) error {
|
||||||
foundAThread := false
|
foundAThread := false
|
||||||
for _, f := range fs {
|
for _, f := range fs {
|
||||||
tf := fmt.Sprintf("/proc/%s/status", f.Name())
|
tf := fmt.Sprintf("/proc/%s/status", f.Name())
|
||||||
d, err := ioutil.ReadFile(tf)
|
d, err := os.ReadFile(tf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// There are a surprising number of ways this
|
// There are a surprising number of ways this
|
||||||
// can error out on linux. We've seen all of
|
// can error out on linux. We've seen all of
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build !android
|
// +build !android
|
||||||
|
|
||||||
// Test that pthread_cancel works as expected
|
// Test that pthread_cancel works as expected
|
||||||
// (NPTL uses SIGRTMIN to implement thread cancelation)
|
// (NPTL uses SIGRTMIN to implement thread cancellation)
|
||||||
// See https://golang.org/issue/6997
|
// See https://golang.org/issue/6997
|
||||||
package cgotest
|
package cgotest
|
||||||
|
|
||||||
|
|
@ -17,8 +17,10 @@ extern int CancelThread();
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import "testing"
|
import (
|
||||||
import "time"
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
func test6997(t *testing.T) {
|
func test6997(t *testing.T) {
|
||||||
r := C.StartThread()
|
r := C.StartThread()
|
||||||
|
|
|
||||||
11
misc/cgo/test/issue8148.c
Normal file
11
misc/cgo/test/issue8148.c
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2014 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "_cgo_export.h"
|
||||||
|
|
||||||
|
int get8148(void) {
|
||||||
|
T t;
|
||||||
|
t.i = 42;
|
||||||
|
return issue8148Callback(&t);
|
||||||
|
}
|
||||||
|
|
@ -10,14 +10,7 @@ package cgotest
|
||||||
|
|
||||||
/*
|
/*
|
||||||
typedef struct { int i; } T;
|
typedef struct { int i; } T;
|
||||||
|
int get8148(void);
|
||||||
int issue8148Callback(T*);
|
|
||||||
|
|
||||||
static int get() {
|
|
||||||
T t;
|
|
||||||
t.i = 42;
|
|
||||||
return issue8148Callback(&t);
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
|
@ -27,5 +20,5 @@ func issue8148Callback(t *C.T) C.int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Issue8148() int {
|
func Issue8148() int {
|
||||||
return int(C.get())
|
return int(C.get8148())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
package cgotest
|
package cgotest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -37,7 +36,7 @@ func TestCrossPackageTests(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GOPATH, err := ioutil.TempDir("", "cgotest")
|
GOPATH, err := os.MkdirTemp("", "cgotest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +46,7 @@ func TestCrossPackageTests(t *testing.T) {
|
||||||
if err := overlayDir(modRoot, "testdata"); err != nil {
|
if err := overlayDir(modRoot, "testdata"); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgotest\n"), 0666); err != nil {
|
if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgotest\n"), 0666); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Test that setgid does not hang on GNU/Linux.
|
// Test that setgid does not hang on Linux.
|
||||||
// See https://golang.org/issue/3871 for details.
|
// See https://golang.org/issue/3871 for details.
|
||||||
|
|
||||||
package cgotest
|
package cgotest
|
||||||
|
|
|
||||||
|
|
@ -899,6 +899,10 @@ static uint16_t issue31093F(uint16_t v) { return v; }
|
||||||
// issue 32579
|
// issue 32579
|
||||||
typedef struct S32579 { unsigned char data[1]; } S32579;
|
typedef struct S32579 { unsigned char data[1]; } S32579;
|
||||||
|
|
||||||
|
// issue 37033, cgo.Handle
|
||||||
|
extern void GoFunc37033(uintptr_t handle);
|
||||||
|
void cFunc37033(uintptr_t handle) { GoFunc37033(handle); }
|
||||||
|
|
||||||
// issue 38649
|
// issue 38649
|
||||||
// Test that #define'd type aliases work.
|
// Test that #define'd type aliases work.
|
||||||
#define netbsd_gid unsigned int
|
#define netbsd_gid unsigned int
|
||||||
|
|
@ -908,6 +912,9 @@ typedef struct S32579 { unsigned char data[1]; } S32579;
|
||||||
enum Enum40494 { X_40494 };
|
enum Enum40494 { X_40494 };
|
||||||
union Union40494 { int x; };
|
union Union40494 { int x; };
|
||||||
void issue40494(enum Enum40494 e, union Union40494* up) {}
|
void issue40494(enum Enum40494 e, union Union40494* up) {}
|
||||||
|
|
||||||
|
// Issue 45451, bad handling of go:notinheap types.
|
||||||
|
typedef struct issue45451Undefined issue45451;
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
|
@ -920,6 +927,7 @@ import (
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"runtime/cgo"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -2230,6 +2238,23 @@ func test32579(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// issue 37033, check if cgo.Handle works properly
|
||||||
|
|
||||||
|
func testHandle(t *testing.T) {
|
||||||
|
ch := make(chan int)
|
||||||
|
|
||||||
|
for i := 0; i < 42; i++ {
|
||||||
|
h := cgo.NewHandle(ch)
|
||||||
|
go func() {
|
||||||
|
C.cFunc37033(C.uintptr_t(h))
|
||||||
|
}()
|
||||||
|
if v := <-ch; issue37033 != v {
|
||||||
|
t.Fatalf("unexpected receiving value: got %d, want %d", v, issue37033)
|
||||||
|
}
|
||||||
|
h.Delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// issue 38649
|
// issue 38649
|
||||||
|
|
||||||
var issue38649 C.netbsd_gid = 42
|
var issue38649 C.netbsd_gid = 42
|
||||||
|
|
@ -2244,3 +2269,19 @@ var issue39877 *C.void = nil
|
||||||
func Issue40494() {
|
func Issue40494() {
|
||||||
C.issue40494(C.enum_Enum40494(C.X_40494), (*C.union_Union40494)(nil))
|
C.issue40494(C.enum_Enum40494(C.X_40494), (*C.union_Union40494)(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue 45451.
|
||||||
|
func test45451(t *testing.T) {
|
||||||
|
var u *C.issue45451
|
||||||
|
typ := reflect.ValueOf(u).Type().Elem()
|
||||||
|
|
||||||
|
// The type is undefined in C so allocating it should panic.
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r == nil {
|
||||||
|
t.Error("expected panic")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
_ = reflect.New(typ)
|
||||||
|
t.Errorf("reflect.New(%v) should have panicked", typ)
|
||||||
|
}
|
||||||
|
|
|
||||||
2
misc/cgo/test/testdata/issue9400/asm_386.s
vendored
2
misc/cgo/test/testdata/issue9400/asm_386.s
vendored
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !gccgo
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build amd64 amd64p32
|
// +build amd64 amd64p32
|
||||||
// +build !gccgo
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
||||||
2
misc/cgo/test/testdata/issue9400/asm_arm.s
vendored
2
misc/cgo/test/testdata/issue9400/asm_arm.s
vendored
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !gccgo
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
||||||
2
misc/cgo/test/testdata/issue9400/asm_arm64.s
vendored
2
misc/cgo/test/testdata/issue9400/asm_arm64.s
vendored
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !gccgo
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build mips64 mips64le
|
// +build mips64 mips64le
|
||||||
// +build !gccgo
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
||||||
2
misc/cgo/test/testdata/issue9400/asm_mipsx.s
vendored
2
misc/cgo/test/testdata/issue9400/asm_mipsx.s
vendored
|
|
@ -3,7 +3,7 @@
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build mips mipsle
|
// +build mips mipsle
|
||||||
// +build !gccgo
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build ppc64 ppc64le
|
// +build ppc64 ppc64le
|
||||||
// +build !gccgo
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build riscv64
|
// +build riscv64
|
||||||
// +build !gccgo
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
||||||
2
misc/cgo/test/testdata/issue9400/asm_s390x.s
vendored
2
misc/cgo/test/testdata/issue9400/asm_s390x.s
vendored
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !gccgo
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
||||||
24
misc/cgo/test/testx.c
Normal file
24
misc/cgo/test/testx.c
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "_cgo_export.h"
|
||||||
|
|
||||||
|
void lockOSThreadC(void) {
|
||||||
|
lockOSThreadCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
void issue7978c(uint32_t *sync) {
|
||||||
|
while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 0)
|
||||||
|
;
|
||||||
|
__atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
|
||||||
|
while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 2)
|
||||||
|
;
|
||||||
|
issue7978cb();
|
||||||
|
__atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
|
||||||
|
while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 6)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void f7665(void) {
|
||||||
|
}
|
||||||
|
|
@ -12,6 +12,7 @@ package cgotest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"runtime/cgo"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -26,7 +27,6 @@ import (
|
||||||
extern void doAdd(int, int);
|
extern void doAdd(int, int);
|
||||||
|
|
||||||
// issue 1328
|
// issue 1328
|
||||||
extern void BackIntoGo(void);
|
|
||||||
void IntoC(void);
|
void IntoC(void);
|
||||||
|
|
||||||
// issue 1560
|
// issue 1560
|
||||||
|
|
@ -38,11 +38,7 @@ long long mysleep(int seconds);
|
||||||
long long twoSleep(int);
|
long long twoSleep(int);
|
||||||
|
|
||||||
// issue 3775
|
// issue 3775
|
||||||
void lockOSThreadCallback(void);
|
void lockOSThreadC(void);
|
||||||
inline static void lockOSThreadC(void)
|
|
||||||
{
|
|
||||||
lockOSThreadCallback();
|
|
||||||
}
|
|
||||||
int usleep(unsigned usec);
|
int usleep(unsigned usec);
|
||||||
|
|
||||||
// issue 4054 part 2 - part 1 in test.go
|
// issue 4054 part 2 - part 1 in test.go
|
||||||
|
|
@ -81,21 +77,9 @@ extern void f7665(void);
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void issue7978cb(void);
|
|
||||||
|
|
||||||
// use ugly atomic variable sync since that doesn't require calling back into
|
// use ugly atomic variable sync since that doesn't require calling back into
|
||||||
// Go code or OS dependencies
|
// Go code or OS dependencies
|
||||||
static void issue7978c(uint32_t *sync) {
|
void issue7978c(uint32_t *sync);
|
||||||
while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 0)
|
|
||||||
;
|
|
||||||
__atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
|
|
||||||
while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 2)
|
|
||||||
;
|
|
||||||
issue7978cb();
|
|
||||||
__atomic_add_fetch(sync, 1, __ATOMIC_SEQ_CST);
|
|
||||||
while(__atomic_load_n(sync, __ATOMIC_SEQ_CST) != 6)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
// issue 8331 part 2 - part 1 in test.go
|
// issue 8331 part 2 - part 1 in test.go
|
||||||
// A typedef of an unnamed struct is the same struct when
|
// A typedef of an unnamed struct is the same struct when
|
||||||
|
|
@ -428,9 +412,6 @@ func test6907Go(t *testing.T) {
|
||||||
|
|
||||||
// issue 7665
|
// issue 7665
|
||||||
|
|
||||||
//export f7665
|
|
||||||
func f7665() {}
|
|
||||||
|
|
||||||
var bad7665 unsafe.Pointer = C.f7665
|
var bad7665 unsafe.Pointer = C.f7665
|
||||||
var good7665 uintptr = uintptr(C.f7665)
|
var good7665 uintptr = uintptr(C.f7665)
|
||||||
|
|
||||||
|
|
@ -558,6 +539,17 @@ func test31891(t *testing.T) {
|
||||||
C.callIssue31891()
|
C.callIssue31891()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// issue 37033, check if cgo.Handle works properly
|
||||||
|
|
||||||
|
var issue37033 = 42
|
||||||
|
|
||||||
|
//export GoFunc37033
|
||||||
|
func GoFunc37033(handle C.uintptr_t) {
|
||||||
|
h := cgo.Handle(handle)
|
||||||
|
ch := h.Value().(chan int)
|
||||||
|
ch <- issue37033
|
||||||
|
}
|
||||||
|
|
||||||
// issue 38408
|
// issue 38408
|
||||||
// A typedef pointer can be used as the element type.
|
// A typedef pointer can be used as the element type.
|
||||||
// No runtime test; just make sure it compiles.
|
// No runtime test; just make sure it compiles.
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
@ -53,7 +52,7 @@ func testMain(m *testing.M) int {
|
||||||
// We need a writable GOPATH in which to run the tests.
|
// We need a writable GOPATH in which to run the tests.
|
||||||
// Construct one in a temporary directory.
|
// Construct one in a temporary directory.
|
||||||
var err error
|
var err error
|
||||||
GOPATH, err = ioutil.TempDir("", "carchive_test")
|
GOPATH, err = os.MkdirTemp("", "carchive_test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +73,7 @@ func testMain(m *testing.M) int {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
os.Setenv("PWD", modRoot)
|
os.Setenv("PWD", modRoot)
|
||||||
if err := ioutil.WriteFile("go.mod", []byte("module testcarchive\n"), 0666); err != nil {
|
if err := os.WriteFile("go.mod", []byte("module testcarchive\n"), 0666); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -176,7 +175,7 @@ func genHeader(t *testing.T, header, dir string) {
|
||||||
// The 'cgo' command generates a number of additional artifacts,
|
// The 'cgo' command generates a number of additional artifacts,
|
||||||
// but we're only interested in the header.
|
// but we're only interested in the header.
|
||||||
// Shunt the rest of the outputs to a temporary directory.
|
// Shunt the rest of the outputs to a temporary directory.
|
||||||
objDir, err := ioutil.TempDir(GOPATH, "_obj")
|
objDir, err := os.MkdirTemp(GOPATH, "_obj")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -252,7 +251,7 @@ var badLineRegexp = regexp.MustCompile(`(?m)^#line [0-9]+ "/.*$`)
|
||||||
// the user and make the files change based on details of the location
|
// the user and make the files change based on details of the location
|
||||||
// of GOPATH.
|
// of GOPATH.
|
||||||
func checkLineComments(t *testing.T, hdrname string) {
|
func checkLineComments(t *testing.T, hdrname string) {
|
||||||
hdr, err := ioutil.ReadFile(hdrname)
|
hdr, err := os.ReadFile(hdrname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
|
|
@ -618,7 +617,7 @@ func TestExtar(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
s := strings.Replace(testar, "PWD", dir, 1)
|
s := strings.Replace(testar, "PWD", dir, 1)
|
||||||
if err := ioutil.WriteFile("testar", []byte(s), 0777); err != nil {
|
if err := os.WriteFile("testar", []byte(s), 0777); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -776,7 +775,7 @@ func TestSIGPROF(t *testing.T) {
|
||||||
// tool with -buildmode=c-archive, it passes -shared to the compiler,
|
// tool with -buildmode=c-archive, it passes -shared to the compiler,
|
||||||
// so we override that. The go tool doesn't work this way, but Bazel
|
// so we override that. The go tool doesn't work this way, but Bazel
|
||||||
// will likely do it in the future. And it ought to work. This test
|
// will likely do it in the future. And it ought to work. This test
|
||||||
// was added because at one time it did not work on PPC GNU/Linux.
|
// was added because at one time it did not work on PPC Linux.
|
||||||
func TestCompileWithoutShared(t *testing.T) {
|
func TestCompileWithoutShared(t *testing.T) {
|
||||||
// For simplicity, reuse the signal forwarding test.
|
// For simplicity, reuse the signal forwarding test.
|
||||||
checkSignalForwardingTest(t)
|
checkSignalForwardingTest(t)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -13,7 +13,7 @@ import "C"
|
||||||
|
|
||||||
//export go_start_profile
|
//export go_start_profile
|
||||||
func go_start_profile() {
|
func go_start_profile() {
|
||||||
pprof.StartCPUProfile(ioutil.Discard)
|
pprof.StartCPUProfile(io.Discard)
|
||||||
}
|
}
|
||||||
|
|
||||||
//export go_stop_profile
|
//export go_stop_profile
|
||||||
|
|
|
||||||
2
misc/cgo/testcarchive/testdata/main_unix.c
vendored
2
misc/cgo/testcarchive/testdata/main_unix.c
vendored
|
|
@ -36,7 +36,7 @@ int install_handler() {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
// gccgo does not set SA_ONSTACK for SIGSEGV.
|
// gccgo does not set SA_ONSTACK for SIGSEGV.
|
||||||
if (getenv("GCCGO") == "" && (osa.sa_flags&SA_ONSTACK) == 0) {
|
if (getenv("GCCGO") == NULL && (osa.sa_flags&SA_ONSTACK) == 0) {
|
||||||
fprintf(stderr, "Go runtime did not install signal handler\n");
|
fprintf(stderr, "Go runtime did not install signal handler\n");
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
@ -125,7 +124,7 @@ func testMain(m *testing.M) int {
|
||||||
// Copy testdata into GOPATH/src/testcshared, along with a go.mod file
|
// Copy testdata into GOPATH/src/testcshared, along with a go.mod file
|
||||||
// declaring the same path.
|
// declaring the same path.
|
||||||
|
|
||||||
GOPATH, err := ioutil.TempDir("", "cshared_test")
|
GOPATH, err := os.MkdirTemp("", "cshared_test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -140,7 +139,7 @@ func testMain(m *testing.M) int {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
os.Setenv("PWD", modRoot)
|
os.Setenv("PWD", modRoot)
|
||||||
if err := ioutil.WriteFile("go.mod", []byte("module testcshared\n"), 0666); err != nil {
|
if err := os.WriteFile("go.mod", []byte("module testcshared\n"), 0666); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -260,7 +259,7 @@ func createHeaders() error {
|
||||||
// The 'cgo' command generates a number of additional artifacts,
|
// The 'cgo' command generates a number of additional artifacts,
|
||||||
// but we're only interested in the header.
|
// but we're only interested in the header.
|
||||||
// Shunt the rest of the outputs to a temporary directory.
|
// Shunt the rest of the outputs to a temporary directory.
|
||||||
objDir, err := ioutil.TempDir("", "testcshared_obj")
|
objDir, err := os.MkdirTemp("", "testcshared_obj")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -381,7 +380,7 @@ func main() {
|
||||||
|
|
||||||
srcfile := filepath.Join(tmpdir, "test.go")
|
srcfile := filepath.Join(tmpdir, "test.go")
|
||||||
objfile := filepath.Join(tmpdir, "test.dll")
|
objfile := filepath.Join(tmpdir, "test.dll")
|
||||||
if err := ioutil.WriteFile(srcfile, []byte(prog), 0666); err != nil {
|
if err := os.WriteFile(srcfile, []byte(prog), 0666); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
argv := []string{"build", "-buildmode=c-shared"}
|
argv := []string{"build", "-buildmode=c-shared"}
|
||||||
|
|
@ -643,7 +642,7 @@ func TestPIE(t *testing.T) {
|
||||||
|
|
||||||
// Test that installing a second time recreates the header file.
|
// Test that installing a second time recreates the header file.
|
||||||
func TestCachedInstall(t *testing.T) {
|
func TestCachedInstall(t *testing.T) {
|
||||||
tmpdir, err := ioutil.TempDir("", "cshared")
|
tmpdir, err := os.MkdirTemp("", "cshared")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -719,14 +718,14 @@ func TestCachedInstall(t *testing.T) {
|
||||||
// copyFile copies src to dst.
|
// copyFile copies src to dst.
|
||||||
func copyFile(t *testing.T, dst, src string) {
|
func copyFile(t *testing.T, dst, src string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
data, err := ioutil.ReadFile(src)
|
data, err := os.ReadFile(src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := os.MkdirAll(filepath.Dir(dst), 0777); err != nil {
|
if err := os.MkdirAll(filepath.Dir(dst), 0777); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(dst, data, 0666); err != nil {
|
if err := os.WriteFile(dst, data, 0666); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -743,7 +742,7 @@ func TestGo2C2Go(t *testing.T) {
|
||||||
|
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
tmpdir, err := ioutil.TempDir("", "cshared-TestGo2C2Go")
|
tmpdir, err := os.MkdirTemp("", "cshared-TestGo2C2Go")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ package testgodefs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -34,7 +33,7 @@ func TestGoDefs(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
gopath, err := ioutil.TempDir("", "testgodefs-gopath")
|
gopath, err := os.MkdirTemp("", "testgodefs-gopath")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -58,20 +57,20 @@ func TestGoDefs(t *testing.T) {
|
||||||
t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr)
|
t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ioutil.WriteFile(filepath.Join(dir, fp+"_defs.go"), out, 0644); err != nil {
|
if err := os.WriteFile(filepath.Join(dir, fp+"_defs.go"), out, 0644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
main, err := ioutil.ReadFile(filepath.Join("testdata", "main.go"))
|
main, err := os.ReadFile(filepath.Join("testdata", "main.go"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(dir, "main.go"), main, 0644); err != nil {
|
if err := os.WriteFile(filepath.Join(dir, "main.go"), main, 0644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ioutil.WriteFile(filepath.Join(dir, "go.mod"), []byte("module testgodefs\ngo 1.14\n"), 0644); err != nil {
|
if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module testgodefs\ngo 1.14\n"), 0644); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
@ -31,15 +30,28 @@ func TestMain(m *testing.M) {
|
||||||
os.Exit(testMain(m))
|
os.Exit(testMain(m))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tmpDir is used to cleanup logged commands -- s/tmpDir/$TMPDIR/
|
||||||
|
var tmpDir string
|
||||||
|
|
||||||
|
// prettyPrintf prints lines with tmpDir sanitized.
|
||||||
|
func prettyPrintf(format string, args ...interface{}) {
|
||||||
|
s := fmt.Sprintf(format, args...)
|
||||||
|
if tmpDir != "" {
|
||||||
|
s = strings.ReplaceAll(s, tmpDir, "$TMPDIR")
|
||||||
|
}
|
||||||
|
fmt.Print(s)
|
||||||
|
}
|
||||||
|
|
||||||
func testMain(m *testing.M) int {
|
func testMain(m *testing.M) int {
|
||||||
// Copy testdata into GOPATH/src/testplugin, along with a go.mod file
|
// Copy testdata into GOPATH/src/testplugin, along with a go.mod file
|
||||||
// declaring the same path.
|
// declaring the same path.
|
||||||
|
|
||||||
GOPATH, err := ioutil.TempDir("", "plugin_test")
|
GOPATH, err := os.MkdirTemp("", "plugin_test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(GOPATH)
|
defer os.RemoveAll(GOPATH)
|
||||||
|
tmpDir = GOPATH
|
||||||
|
|
||||||
modRoot := filepath.Join(GOPATH, "src", "testplugin")
|
modRoot := filepath.Join(GOPATH, "src", "testplugin")
|
||||||
altRoot := filepath.Join(GOPATH, "alt", "src", "testplugin")
|
altRoot := filepath.Join(GOPATH, "alt", "src", "testplugin")
|
||||||
|
|
@ -50,14 +62,20 @@ func testMain(m *testing.M) int {
|
||||||
if err := overlayDir(dstRoot, srcRoot); err != nil {
|
if err := overlayDir(dstRoot, srcRoot); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(dstRoot, "go.mod"), []byte("module testplugin\n"), 0666); err != nil {
|
prettyPrintf("mkdir -p %s\n", dstRoot)
|
||||||
|
prettyPrintf("rsync -a %s/ %s\n", srcRoot, dstRoot)
|
||||||
|
|
||||||
|
if err := os.WriteFile(filepath.Join(dstRoot, "go.mod"), []byte("module testplugin\n"), 0666); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
prettyPrintf("echo 'module testplugin' > %s/go.mod\n", dstRoot)
|
||||||
}
|
}
|
||||||
|
|
||||||
os.Setenv("GOPATH", filepath.Join(GOPATH, "alt"))
|
os.Setenv("GOPATH", filepath.Join(GOPATH, "alt"))
|
||||||
if err := os.Chdir(altRoot); err != nil {
|
if err := os.Chdir(altRoot); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
|
} else {
|
||||||
|
prettyPrintf("cd %s\n", altRoot)
|
||||||
}
|
}
|
||||||
os.Setenv("PWD", altRoot)
|
os.Setenv("PWD", altRoot)
|
||||||
goCmd(nil, "build", "-buildmode=plugin", "-o", filepath.Join(modRoot, "plugin-mismatch.so"), "./plugin-mismatch")
|
goCmd(nil, "build", "-buildmode=plugin", "-o", filepath.Join(modRoot, "plugin-mismatch.so"), "./plugin-mismatch")
|
||||||
|
|
@ -65,6 +83,8 @@ func testMain(m *testing.M) int {
|
||||||
os.Setenv("GOPATH", GOPATH)
|
os.Setenv("GOPATH", GOPATH)
|
||||||
if err := os.Chdir(modRoot); err != nil {
|
if err := os.Chdir(modRoot); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
|
} else {
|
||||||
|
prettyPrintf("cd %s\n", modRoot)
|
||||||
}
|
}
|
||||||
os.Setenv("PWD", modRoot)
|
os.Setenv("PWD", modRoot)
|
||||||
|
|
||||||
|
|
@ -72,13 +92,14 @@ func testMain(m *testing.M) int {
|
||||||
|
|
||||||
goCmd(nil, "build", "-buildmode=plugin", "./plugin1")
|
goCmd(nil, "build", "-buildmode=plugin", "./plugin1")
|
||||||
goCmd(nil, "build", "-buildmode=plugin", "./plugin2")
|
goCmd(nil, "build", "-buildmode=plugin", "./plugin2")
|
||||||
so, err := ioutil.ReadFile("plugin2.so")
|
so, err := os.ReadFile("plugin2.so")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile("plugin2-dup.so", so, 0444); err != nil {
|
if err := os.WriteFile("plugin2-dup.so", so, 0444); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
prettyPrintf("cp plugin2.so plugin2-dup.so\n")
|
||||||
|
|
||||||
goCmd(nil, "build", "-buildmode=plugin", "-o=sub/plugin1.so", "./sub/plugin1")
|
goCmd(nil, "build", "-buildmode=plugin", "-o=sub/plugin1.so", "./sub/plugin1")
|
||||||
goCmd(nil, "build", "-buildmode=plugin", "-o=unnamed1.so", "./unnamed1/main.go")
|
goCmd(nil, "build", "-buildmode=plugin", "-o=unnamed1.so", "./unnamed1/main.go")
|
||||||
|
|
@ -95,8 +116,53 @@ func goCmd(t *testing.T, op string, args ...string) {
|
||||||
run(t, "go", append([]string{op, "-gcflags", gcflags}, args...)...)
|
run(t, "go", append([]string{op, "-gcflags", gcflags}, args...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// escape converts a string to something suitable for a shell command line.
|
||||||
|
func escape(s string) string {
|
||||||
|
s = strings.Replace(s, "\\", "\\\\", -1)
|
||||||
|
s = strings.Replace(s, "'", "\\'", -1)
|
||||||
|
// Conservative guess at characters that will force quoting
|
||||||
|
if s == "" || strings.ContainsAny(s, "\\ ;#*&$~?!|[]()<>{}`") {
|
||||||
|
s = "'" + s + "'"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// asCommandLine renders cmd as something that could be copy-and-pasted into a command line
|
||||||
|
func asCommandLine(cwd string, cmd *exec.Cmd) string {
|
||||||
|
s := "("
|
||||||
|
if cmd.Dir != "" && cmd.Dir != cwd {
|
||||||
|
s += "cd" + escape(cmd.Dir) + ";"
|
||||||
|
}
|
||||||
|
for _, e := range cmd.Env {
|
||||||
|
if !strings.HasPrefix(e, "PATH=") &&
|
||||||
|
!strings.HasPrefix(e, "HOME=") &&
|
||||||
|
!strings.HasPrefix(e, "USER=") &&
|
||||||
|
!strings.HasPrefix(e, "SHELL=") {
|
||||||
|
s += " "
|
||||||
|
s += escape(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// These EVs are relevant to this test.
|
||||||
|
for _, e := range os.Environ() {
|
||||||
|
if strings.HasPrefix(e, "PWD=") ||
|
||||||
|
strings.HasPrefix(e, "GOPATH=") ||
|
||||||
|
strings.HasPrefix(e, "LD_LIBRARY_PATH=") {
|
||||||
|
s += " "
|
||||||
|
s += escape(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, a := range cmd.Args {
|
||||||
|
s += " "
|
||||||
|
s += escape(a)
|
||||||
|
}
|
||||||
|
s += " )"
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
func run(t *testing.T, bin string, args ...string) string {
|
func run(t *testing.T, bin string, args ...string) string {
|
||||||
cmd := exec.Command(bin, args...)
|
cmd := exec.Command(bin, args...)
|
||||||
|
cmdLine := asCommandLine(".", cmd)
|
||||||
|
prettyPrintf("%s\n", cmdLine)
|
||||||
cmd.Stderr = new(strings.Builder)
|
cmd.Stderr = new(strings.Builder)
|
||||||
out, err := cmd.Output()
|
out, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -201,12 +267,18 @@ func TestMethod(t *testing.T) {
|
||||||
// Exported symbol's method must be live.
|
// Exported symbol's method must be live.
|
||||||
goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./method/plugin.go")
|
goCmd(t, "build", "-buildmode=plugin", "-o", "plugin.so", "./method/plugin.go")
|
||||||
goCmd(t, "build", "-o", "method.exe", "./method/main.go")
|
goCmd(t, "build", "-o", "method.exe", "./method/main.go")
|
||||||
|
run(t, "./method.exe")
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
}
|
||||||
defer cancel()
|
|
||||||
cmd := exec.CommandContext(ctx, "./method.exe")
|
func TestMethod2(t *testing.T) {
|
||||||
out, err := cmd.CombinedOutput()
|
goCmd(t, "build", "-buildmode=plugin", "-o", "method2.so", "./method2/plugin.go")
|
||||||
if err != nil {
|
goCmd(t, "build", "-o", "method2.exe", "./method2/main.go")
|
||||||
t.Fatalf("%s: %v\n%s", strings.Join(cmd.Args, " "), err, out)
|
run(t, "./method2.exe")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIssue44956(t *testing.T) {
|
||||||
|
goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p1.so", "./issue44956/plugin1.go")
|
||||||
|
goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p2.so", "./issue44956/plugin2.go")
|
||||||
|
goCmd(t, "build", "-o", "issue44956.exe", "./issue44956/main.go")
|
||||||
|
run(t, "./issue44956.exe")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
7
misc/cgo/testplugin/testdata/issue44956/base/base.go
vendored
Normal file
7
misc/cgo/testplugin/testdata/issue44956/base/base.go
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package base
|
||||||
|
|
||||||
|
var X = &map[int]int{123: 456}
|
||||||
47
misc/cgo/testplugin/testdata/issue44956/main.go
vendored
Normal file
47
misc/cgo/testplugin/testdata/issue44956/main.go
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Issue 44956: writable static temp is not exported correctly.
|
||||||
|
// In the test below, package base is
|
||||||
|
//
|
||||||
|
// X = &map{...}
|
||||||
|
//
|
||||||
|
// which compiles to
|
||||||
|
//
|
||||||
|
// X = &stmp // static
|
||||||
|
// stmp = makemap(...) // in init function
|
||||||
|
//
|
||||||
|
// plugin1 and plugin2 both import base. plugin1 doesn't use
|
||||||
|
// base.X, so that symbol is deadcoded in plugin1.
|
||||||
|
//
|
||||||
|
// plugin1 is loaded first. base.init runs at that point, which
|
||||||
|
// initialize base.stmp.
|
||||||
|
//
|
||||||
|
// plugin2 is then loaded. base.init already ran, so it doesn't run
|
||||||
|
// again. When base.stmp is not exported, plugin2's base.X points to
|
||||||
|
// its own private base.stmp, which is not initialized, fail.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "plugin"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
_, err := plugin.Open("issue44956p1.so")
|
||||||
|
if err != nil {
|
||||||
|
panic("FAIL")
|
||||||
|
}
|
||||||
|
|
||||||
|
p2, err := plugin.Open("issue44956p2.so")
|
||||||
|
if err != nil {
|
||||||
|
panic("FAIL")
|
||||||
|
}
|
||||||
|
f, err := p2.Lookup("F")
|
||||||
|
if err != nil {
|
||||||
|
panic("FAIL")
|
||||||
|
}
|
||||||
|
x := f.(func() *map[int]int)()
|
||||||
|
if x == nil || (*x)[123] != 456 {
|
||||||
|
panic("FAIL")
|
||||||
|
}
|
||||||
|
}
|
||||||
9
misc/cgo/testplugin/testdata/issue44956/plugin1.go
vendored
Normal file
9
misc/cgo/testplugin/testdata/issue44956/plugin1.go
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import _ "testplugin/issue44956/base"
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
// runindir -gcflags=-c=1
|
|
||||||
// +build !windows
|
|
||||||
|
|
||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// TODO May delete or adapt this test once regabi is the default
|
package main
|
||||||
|
|
||||||
package ignore
|
import "testplugin/issue44956/base"
|
||||||
|
|
||||||
|
func F() *map[int]int { return base.X }
|
||||||
|
|
||||||
|
func main() {}
|
||||||
32
misc/cgo/testplugin/testdata/method2/main.go
vendored
Normal file
32
misc/cgo/testplugin/testdata/method2/main.go
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// A type can be passed to a plugin and converted to interface
|
||||||
|
// there. So its methods need to be live.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"plugin"
|
||||||
|
|
||||||
|
"testplugin/method2/p"
|
||||||
|
)
|
||||||
|
|
||||||
|
var t p.T
|
||||||
|
|
||||||
|
type I interface{ M() }
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
pl, err := plugin.Open("method2.so")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := pl.Lookup("F")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f.(func(p.T) interface{})(t).(I).M()
|
||||||
|
}
|
||||||
9
misc/cgo/testplugin/testdata/method2/p/p.go
vendored
Normal file
9
misc/cgo/testplugin/testdata/method2/p/p.go
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package p
|
||||||
|
|
||||||
|
type T int
|
||||||
|
|
||||||
|
func (T) M() { println("M") }
|
||||||
11
misc/cgo/testplugin/testdata/method2/plugin.go
vendored
Normal file
11
misc/cgo/testplugin/testdata/method2/plugin.go
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "testplugin/method2/p"
|
||||||
|
|
||||||
|
func main() {}
|
||||||
|
|
||||||
|
func F(t p.T) interface{} { return t }
|
||||||
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -36,7 +35,7 @@ func requireOvercommit(t *testing.T) {
|
||||||
|
|
||||||
overcommit.Once.Do(func() {
|
overcommit.Once.Do(func() {
|
||||||
var out []byte
|
var out []byte
|
||||||
out, overcommit.err = ioutil.ReadFile("/proc/sys/vm/overcommit_memory")
|
out, overcommit.err = os.ReadFile("/proc/sys/vm/overcommit_memory")
|
||||||
if overcommit.err != nil {
|
if overcommit.err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -313,14 +312,14 @@ int main() {
|
||||||
`)
|
`)
|
||||||
|
|
||||||
func (c *config) checkCSanitizer() (skip bool, err error) {
|
func (c *config) checkCSanitizer() (skip bool, err error) {
|
||||||
dir, err := ioutil.TempDir("", c.sanitizer)
|
dir, err := os.MkdirTemp("", c.sanitizer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("failed to create temp directory: %v", err)
|
return false, fmt.Errorf("failed to create temp directory: %v", err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(dir)
|
defer os.RemoveAll(dir)
|
||||||
|
|
||||||
src := filepath.Join(dir, "return0.c")
|
src := filepath.Join(dir, "return0.c")
|
||||||
if err := ioutil.WriteFile(src, cMain, 0600); err != nil {
|
if err := os.WriteFile(src, cMain, 0600); err != nil {
|
||||||
return false, fmt.Errorf("failed to write C source file: %v", err)
|
return false, fmt.Errorf("failed to write C source file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -418,7 +417,7 @@ func (d *tempDir) Join(name string) string {
|
||||||
|
|
||||||
func newTempDir(t *testing.T) *tempDir {
|
func newTempDir(t *testing.T) *tempDir {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
dir, err := ioutil.TempDir("", filepath.Dir(t.Name()))
|
dir, err := os.MkdirTemp("", filepath.Dir(t.Name()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to create temp dir: %v", err)
|
t.Fatalf("Failed to create temp dir: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -440,3 +439,14 @@ func hangProneCmd(name string, arg ...string) *exec.Cmd {
|
||||||
}
|
}
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mSanSupported is a copy of the function cmd/internal/sys.MSanSupported,
|
||||||
|
// because the internal pacakage can't be used here.
|
||||||
|
func mSanSupported(goos, goarch string) bool {
|
||||||
|
switch goos {
|
||||||
|
case "linux":
|
||||||
|
return goarch == "amd64" || goarch == "arm64"
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ package sanitizers_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
@ -19,6 +19,12 @@ func TestShared(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GOARCH, err := goEnv("GOARCH")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
libExt := "so"
|
libExt := "so"
|
||||||
if GOOS == "darwin" {
|
if GOOS == "darwin" {
|
||||||
libExt = "dylib"
|
libExt = "dylib"
|
||||||
|
|
@ -41,6 +47,11 @@ func TestShared(t *testing.T) {
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
tc := tc
|
tc := tc
|
||||||
name := strings.TrimSuffix(tc.src, ".go")
|
name := strings.TrimSuffix(tc.src, ".go")
|
||||||
|
//The memory sanitizer tests require support for the -msan option.
|
||||||
|
if tc.sanitizer == "memory" && !mSanSupported(GOOS, GOARCH) {
|
||||||
|
t.Logf("skipping %s test on %s/%s; -msan option is not supported.", name, GOOS, GOARCH)
|
||||||
|
continue
|
||||||
|
}
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
config := configure(tc.sanitizer)
|
config := configure(tc.sanitizer)
|
||||||
|
|
@ -53,7 +64,7 @@ func TestShared(t *testing.T) {
|
||||||
mustRun(t, config.goCmd("build", "-buildmode=c-shared", "-o", lib, srcPath(tc.src)))
|
mustRun(t, config.goCmd("build", "-buildmode=c-shared", "-o", lib, srcPath(tc.src)))
|
||||||
|
|
||||||
cSrc := dir.Join("main.c")
|
cSrc := dir.Join("main.c")
|
||||||
if err := ioutil.WriteFile(cSrc, cMain, 0600); err != nil {
|
if err := os.WriteFile(cSrc, cMain, 0600); err != nil {
|
||||||
t.Fatalf("failed to write C source file: %v", err)
|
t.Fatalf("failed to write C source file: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMSAN(t *testing.T) {
|
func TestMSAN(t *testing.T) {
|
||||||
|
goos, err := goEnv("GOOS")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
goarch, err := goEnv("GOARCH")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// The msan tests require support for the -msan option.
|
||||||
|
if !mSanSupported(goos, goarch) {
|
||||||
|
t.Skipf("skipping on %s/%s; -msan option is not supported.", goos, goarch)
|
||||||
|
}
|
||||||
|
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
requireOvercommit(t)
|
requireOvercommit(t)
|
||||||
config := configure("memory")
|
config := configure("memory")
|
||||||
|
|
|
||||||
4
misc/cgo/testsanitizers/testdata/tsan9.go
vendored
4
misc/cgo/testsanitizers/testdata/tsan9.go
vendored
|
|
@ -44,7 +44,7 @@ void spin() {
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -60,7 +60,7 @@ func goSpin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
pprof.StartCPUProfile(ioutil.Discard)
|
pprof.StartCPUProfile(io.Discard)
|
||||||
go C.spin()
|
go C.spin()
|
||||||
goSpin()
|
goSpin()
|
||||||
pprof.StopCPUProfile()
|
pprof.StopCPUProfile()
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
@ -90,7 +89,7 @@ func goCmd(t *testing.T, args ...string) string {
|
||||||
|
|
||||||
// TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit).
|
// TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit).
|
||||||
func testMain(m *testing.M) (int, error) {
|
func testMain(m *testing.M) (int, error) {
|
||||||
workDir, err := ioutil.TempDir("", "shared_test")
|
workDir, err := os.MkdirTemp("", "shared_test")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
@ -177,7 +176,7 @@ func cloneTestdataModule(gopath string) (string, error) {
|
||||||
if err := overlayDir(modRoot, "testdata"); err != nil {
|
if err := overlayDir(modRoot, "testdata"); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module testshared\n"), 0644); err != nil {
|
if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module testshared\n"), 0644); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return modRoot, nil
|
return modRoot, nil
|
||||||
|
|
@ -318,7 +317,7 @@ func TestShlibnameFiles(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, pkg := range pkgs {
|
for _, pkg := range pkgs {
|
||||||
shlibnamefile := filepath.Join(gorootInstallDir, pkg+".shlibname")
|
shlibnamefile := filepath.Join(gorootInstallDir, pkg+".shlibname")
|
||||||
contentsb, err := ioutil.ReadFile(shlibnamefile)
|
contentsb, err := os.ReadFile(shlibnamefile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("error reading shlibnamefile for %s: %v", pkg, err)
|
t.Errorf("error reading shlibnamefile for %s: %v", pkg, err)
|
||||||
continue
|
continue
|
||||||
|
|
@ -791,7 +790,7 @@ func resetFileStamps() {
|
||||||
// It also sets the time of the file, so that we can see if it is rewritten.
|
// It also sets the time of the file, so that we can see if it is rewritten.
|
||||||
func touch(t *testing.T, path string) (cleanup func()) {
|
func touch(t *testing.T, path string) (cleanup func()) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
data, err := ioutil.ReadFile(path)
|
data, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -837,14 +836,14 @@ func touch(t *testing.T, path string) (cleanup func()) {
|
||||||
// user-writable.
|
// user-writable.
|
||||||
perm := fi.Mode().Perm() | 0200
|
perm := fi.Mode().Perm() | 0200
|
||||||
|
|
||||||
if err := ioutil.WriteFile(path, data, perm); err != nil {
|
if err := os.WriteFile(path, data, perm); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := os.Chtimes(path, nearlyNew, nearlyNew); err != nil {
|
if err := os.Chtimes(path, nearlyNew, nearlyNew); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
return func() {
|
return func() {
|
||||||
if err := ioutil.WriteFile(path, old, perm); err != nil {
|
if err := os.WriteFile(path, old, perm); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
misc/cgo/testshared/testdata/depBase/asm.s
vendored
2
misc/cgo/testshared/testdata/depBase/asm.s
vendored
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !gccgo
|
// +build gc
|
||||||
|
|
||||||
#include "textflag.h"
|
#include "textflag.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// +build !gccgo
|
// +build gc
|
||||||
|
|
||||||
package depBase
|
package depBase
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
package so_test
|
package so_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
@ -37,7 +36,7 @@ func requireTestSOSupported(t *testing.T) {
|
||||||
func TestSO(t *testing.T) {
|
func TestSO(t *testing.T) {
|
||||||
requireTestSOSupported(t)
|
requireTestSOSupported(t)
|
||||||
|
|
||||||
GOPATH, err := ioutil.TempDir("", "cgosotest")
|
GOPATH, err := os.MkdirTemp("", "cgosotest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +46,7 @@ func TestSO(t *testing.T) {
|
||||||
if err := overlayDir(modRoot, "testdata"); err != nil {
|
if err := overlayDir(modRoot, "testdata"); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
|
if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,6 +79,10 @@ func TestSO(t *testing.T) {
|
||||||
case "windows":
|
case "windows":
|
||||||
ext = "dll"
|
ext = "dll"
|
||||||
args = append(args, "-DEXPORT_DLL")
|
args = append(args, "-DEXPORT_DLL")
|
||||||
|
// At least in mingw-clang it is not permitted to just name a .dll
|
||||||
|
// on the command line. You must name the corresponding import
|
||||||
|
// library instead, even though the dll is used when the executable is run.
|
||||||
|
args = append(args, "-Wl,-out-implib,libcgosotest.a")
|
||||||
case "aix":
|
case "aix":
|
||||||
ext = "so.1"
|
ext = "so.1"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
misc/cgo/testso/testdata/cgoso.go
vendored
2
misc/cgo/testso/testdata/cgoso.go
vendored
|
|
@ -14,7 +14,7 @@ package cgosotest
|
||||||
#cgo solaris LDFLAGS: -L. -lcgosotest
|
#cgo solaris LDFLAGS: -L. -lcgosotest
|
||||||
#cgo netbsd LDFLAGS: -L. libcgosotest.so
|
#cgo netbsd LDFLAGS: -L. libcgosotest.so
|
||||||
#cgo darwin LDFLAGS: -L. libcgosotest.dylib
|
#cgo darwin LDFLAGS: -L. libcgosotest.dylib
|
||||||
#cgo windows LDFLAGS: -L. libcgosotest.dll
|
#cgo windows LDFLAGS: -L. libcgosotest.a
|
||||||
#cgo aix LDFLAGS: -L. -l cgosotest
|
#cgo aix LDFLAGS: -L. -l cgosotest
|
||||||
|
|
||||||
void init(void);
|
void init(void);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
package so_test
|
package so_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
@ -37,7 +36,7 @@ func requireTestSOSupported(t *testing.T) {
|
||||||
func TestSO(t *testing.T) {
|
func TestSO(t *testing.T) {
|
||||||
requireTestSOSupported(t)
|
requireTestSOSupported(t)
|
||||||
|
|
||||||
GOPATH, err := ioutil.TempDir("", "cgosotest")
|
GOPATH, err := os.MkdirTemp("", "cgosotest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -47,7 +46,7 @@ func TestSO(t *testing.T) {
|
||||||
if err := overlayDir(modRoot, "testdata"); err != nil {
|
if err := overlayDir(modRoot, "testdata"); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
|
if err := os.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module cgosotest\n"), 0666); err != nil {
|
||||||
log.Panic(err)
|
log.Panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,6 +79,10 @@ func TestSO(t *testing.T) {
|
||||||
case "windows":
|
case "windows":
|
||||||
ext = "dll"
|
ext = "dll"
|
||||||
args = append(args, "-DEXPORT_DLL")
|
args = append(args, "-DEXPORT_DLL")
|
||||||
|
// At least in mingw-clang it is not permitted to just name a .dll
|
||||||
|
// on the command line. You must name the corresponding import
|
||||||
|
// library instead, even though the dll is used when the executable is run.
|
||||||
|
args = append(args, "-Wl,-out-implib,libcgosotest.a")
|
||||||
case "aix":
|
case "aix":
|
||||||
ext = "so.1"
|
ext = "so.1"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
misc/cgo/testsovar/testdata/cgoso.go
vendored
2
misc/cgo/testsovar/testdata/cgoso.go
vendored
|
|
@ -18,7 +18,7 @@ package cgosotest
|
||||||
#cgo solaris LDFLAGS: -L. -lcgosotest
|
#cgo solaris LDFLAGS: -L. -lcgosotest
|
||||||
#cgo netbsd LDFLAGS: -L. libcgosotest.so
|
#cgo netbsd LDFLAGS: -L. libcgosotest.so
|
||||||
#cgo darwin LDFLAGS: -L. libcgosotest.dylib
|
#cgo darwin LDFLAGS: -L. libcgosotest.dylib
|
||||||
#cgo windows LDFLAGS: -L. libcgosotest.dll
|
#cgo windows LDFLAGS: -L. libcgosotest.a
|
||||||
#cgo aix LDFLAGS: -L. -l cgosotest
|
#cgo aix LDFLAGS: -L. -l cgosotest
|
||||||
|
|
||||||
#include "cgoso_c.h"
|
#include "cgoso_c.h"
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
<a href="#" url="https://golang.org/pkg/">pkg</a> id/name:</small>
|
<a href="#" url="https://golang.org/pkg/">pkg</a> id/name:</small>
|
||||||
<form style='margin: 0' id='navform'><nobr><input id="inputbox" size=10 tabindex=1 /><input type="submit" value="go" /></nobr></form>
|
<form style='margin: 0' id='navform'><nobr><input id="inputbox" size=10 tabindex=1 /><input type="submit" value="go" /></nobr></form>
|
||||||
<small>Also: <a href="#" url="https://build.golang.org">buildbots</a>
|
<small>Also: <a href="#" url="https://build.golang.org">buildbots</a>
|
||||||
<a href="#" url="https://github.com/golang/go">Github</a>
|
<a href="#" url="https://github.com/golang/go">GitHub</a>
|
||||||
</small>
|
</small>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -38,7 +37,7 @@ func main() {
|
||||||
fmt.Println("# will be overwritten when running Go programs.")
|
fmt.Println("# will be overwritten when running Go programs.")
|
||||||
for _, mp := range mps {
|
for _, mp := range mps {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
f, err := ioutil.TempFile("", "go_ios_detect_")
|
f, err := os.CreateTemp("", "go_ios_detect_")
|
||||||
check(err)
|
check(err)
|
||||||
fname := f.Name()
|
fname := f.Name()
|
||||||
defer os.Remove(fname)
|
defer os.Remove(fname)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -79,7 +78,7 @@ func main() {
|
||||||
|
|
||||||
func runMain() (int, error) {
|
func runMain() (int, error) {
|
||||||
var err error
|
var err error
|
||||||
tmpdir, err = ioutil.TempDir("", "go_ios_exec_")
|
tmpdir, err = os.MkdirTemp("", "go_ios_exec_")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 1, err
|
return 1, err
|
||||||
}
|
}
|
||||||
|
|
@ -205,13 +204,13 @@ func assembleApp(appdir, bin string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
entitlementsPath := filepath.Join(tmpdir, "Entitlements.plist")
|
entitlementsPath := filepath.Join(tmpdir, "Entitlements.plist")
|
||||||
if err := ioutil.WriteFile(entitlementsPath, []byte(entitlementsPlist()), 0744); err != nil {
|
if err := os.WriteFile(entitlementsPath, []byte(entitlementsPlist()), 0744); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(appdir, "Info.plist"), []byte(infoPlist(pkgpath)), 0744); err != nil {
|
if err := os.WriteFile(filepath.Join(appdir, "Info.plist"), []byte(infoPlist(pkgpath)), 0744); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := ioutil.WriteFile(filepath.Join(appdir, "ResourceRules.plist"), []byte(resourceRules), 0744); err != nil {
|
if err := os.WriteFile(filepath.Join(appdir, "ResourceRules.plist"), []byte(resourceRules), 0744); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -144,7 +144,7 @@ func doCrawl(url string) error {
|
||||||
if res.StatusCode != 200 {
|
if res.StatusCode != 200 {
|
||||||
return errors.New(res.Status)
|
return errors.New(res.Status)
|
||||||
}
|
}
|
||||||
slurp, err := ioutil.ReadAll(res.Body)
|
slurp, err := io.ReadAll(res.Body)
|
||||||
res.Body.Close()
|
res.Body.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error reading %s body: %v", url, err)
|
log.Fatalf("Error reading %s body: %v", url, err)
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ package reboot_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -23,7 +22,7 @@ import (
|
||||||
|
|
||||||
func TestExperimentToolID(t *testing.T) {
|
func TestExperimentToolID(t *testing.T) {
|
||||||
// Set up GOROOT
|
// Set up GOROOT
|
||||||
goroot, err := ioutil.TempDir("", "experiment-goroot")
|
goroot, err := os.MkdirTemp("", "experiment-goroot")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -34,13 +33,13 @@ func TestExperimentToolID(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ioutil.WriteFile(filepath.Join(goroot, "VERSION"), []byte("go1.999"), 0666); err != nil {
|
if err := os.WriteFile(filepath.Join(goroot, "VERSION"), []byte("go1.999"), 0666); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
env := append(os.Environ(), "GOROOT=", "GOROOT_BOOTSTRAP="+runtime.GOROOT())
|
env := append(os.Environ(), "GOROOT=", "GOROOT_BOOTSTRAP="+runtime.GOROOT())
|
||||||
|
|
||||||
// Use a clean cache.
|
// Use a clean cache.
|
||||||
gocache, err := ioutil.TempDir("", "experiment-gocache")
|
gocache, err := os.MkdirTemp("", "experiment-gocache")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
package reboot_test
|
package reboot_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -16,7 +15,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRepeatBootstrap(t *testing.T) {
|
func TestRepeatBootstrap(t *testing.T) {
|
||||||
goroot, err := ioutil.TempDir("", "reboot-goroot")
|
goroot, err := os.MkdirTemp("", "reboot-goroot")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -27,7 +26,7 @@ func TestRepeatBootstrap(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ioutil.WriteFile(filepath.Join(goroot, "VERSION"), []byte(runtime.Version()), 0666); err != nil {
|
if err := os.WriteFile(filepath.Join(goroot, "VERSION"), []byte(runtime.Version()), 0666); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -993,13 +993,13 @@
|
||||||
</style>
|
</style>
|
||||||
<div style="padding-right: 200px">
|
<div style="padding-right: 200px">
|
||||||
<div style="float:right; border-style: solid; border-width: 1px; padding:20px">
|
<div style="float:right; border-style: solid; border-width: 1px; padding:20px">
|
||||||
X no feedback<br/>
|
X no feedback<br>
|
||||||
0 uninitialized<br/>
|
0 uninitialized<br>
|
||||||
. premonomorphic<br/>
|
. premonomorphic<br>
|
||||||
1 monomorphic<br/>
|
1 monomorphic<br>
|
||||||
^ recompute handler<br/>
|
^ recompute handler<br>
|
||||||
P polymorphic<br/>
|
P polymorphic<br>
|
||||||
N megamorphic<br/>
|
N megamorphic<br>
|
||||||
G generic
|
G generic
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -3596,7 +3596,7 @@
|
||||||
<div id="pipeline_per_frame_container">
|
<div id="pipeline_per_frame_container">
|
||||||
<div class="subtitle">Graphics Pipeline and Raster Tasks</div>
|
<div class="subtitle">Graphics Pipeline and Raster Tasks</div>
|
||||||
<div class="description">
|
<div class="description">
|
||||||
When raster tasks are completed in comparison to the rest of the graphics pipeline.<br/>
|
When raster tasks are completed in comparison to the rest of the graphics pipeline.<br>
|
||||||
Only pages where raster tasks are completed after beginFrame is issued are included.
|
Only pages where raster tasks are completed after beginFrame is issued are included.
|
||||||
</div>
|
</div>
|
||||||
<tr-v-ui-raster-visualization id="rasterVisualization">
|
<tr-v-ui-raster-visualization id="rasterVisualization">
|
||||||
|
|
|
||||||
|
|
@ -296,8 +296,8 @@
|
||||||
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
|
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
|
||||||
},
|
},
|
||||||
|
|
||||||
// func walltime1() (sec int64, nsec int32)
|
// func walltime() (sec int64, nsec int32)
|
||||||
"runtime.walltime1": (sp) => {
|
"runtime.walltime": (sp) => {
|
||||||
sp >>>= 0;
|
sp >>>= 0;
|
||||||
const msec = (new Date).getTime();
|
const msec = (new Date).getTime();
|
||||||
setInt64(sp + 8, msec / 1000);
|
setInt64(sp + 8, msec / 1000);
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
User-agent: *
|
|
||||||
Disallow: /
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build aix || linux || dragonfly || openbsd || solaris
|
||||||
// +build aix linux dragonfly openbsd solaris
|
// +build aix linux dragonfly openbsd solaris
|
||||||
|
|
||||||
package tar
|
package tar
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build darwin || freebsd || netbsd
|
||||||
// +build darwin freebsd netbsd
|
// +build darwin freebsd netbsd
|
||||||
|
|
||||||
package tar
|
package tar
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build aix || linux || darwin || dragonfly || freebsd || openbsd || netbsd || solaris
|
||||||
// +build aix linux darwin dragonfly freebsd openbsd netbsd solaris
|
// +build aix linux darwin dragonfly freebsd openbsd netbsd solaris
|
||||||
|
|
||||||
package tar
|
package tar
|
||||||
|
|
|
||||||
|
|
@ -262,16 +262,11 @@ func TestFileInfoHeaderDir(t *testing.T) {
|
||||||
func TestFileInfoHeaderSymlink(t *testing.T) {
|
func TestFileInfoHeaderSymlink(t *testing.T) {
|
||||||
testenv.MustHaveSymlink(t)
|
testenv.MustHaveSymlink(t)
|
||||||
|
|
||||||
tmpdir, err := os.MkdirTemp("", "TestFileInfoHeaderSymlink")
|
tmpdir := t.TempDir()
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer os.RemoveAll(tmpdir)
|
|
||||||
|
|
||||||
link := filepath.Join(tmpdir, "link")
|
link := filepath.Join(tmpdir, "link")
|
||||||
target := tmpdir
|
target := tmpdir
|
||||||
err = os.Symlink(target, link)
|
if err := os.Symlink(target, link); err != nil {
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
fi, err := os.Lstat(link)
|
fi, err := os.Lstat(link)
|
||||||
|
|
|
||||||
|
|
@ -52,12 +52,9 @@ type File struct {
|
||||||
FileHeader
|
FileHeader
|
||||||
zip *Reader
|
zip *Reader
|
||||||
zipr io.ReaderAt
|
zipr io.ReaderAt
|
||||||
zipsize int64
|
|
||||||
headerOffset int64
|
headerOffset int64
|
||||||
}
|
zip64 bool // zip64 extended information extra field presence
|
||||||
|
descErr error // error reading the data descriptor during init
|
||||||
func (f *File) hasDataDescriptor() bool {
|
|
||||||
return f.Flags&0x8 != 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenReader will open the Zip file specified by name and return a ReadCloser.
|
// OpenReader will open the Zip file specified by name and return a ReadCloser.
|
||||||
|
|
@ -112,7 +109,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
|
||||||
// a bad one, and then only report an ErrFormat or UnexpectedEOF if
|
// a bad one, and then only report an ErrFormat or UnexpectedEOF if
|
||||||
// the file count modulo 65536 is incorrect.
|
// the file count modulo 65536 is incorrect.
|
||||||
for {
|
for {
|
||||||
f := &File{zip: z, zipr: r, zipsize: size}
|
f := &File{zip: z, zipr: r}
|
||||||
err = readDirectoryHeader(f, buf)
|
err = readDirectoryHeader(f, buf)
|
||||||
if err == ErrFormat || err == io.ErrUnexpectedEOF {
|
if err == ErrFormat || err == io.ErrUnexpectedEOF {
|
||||||
break
|
break
|
||||||
|
|
@ -120,6 +117,7 @@ func (z *Reader) init(r io.ReaderAt, size int64) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
f.readDataDescriptor()
|
||||||
z.File = append(z.File, f)
|
z.File = append(z.File, f)
|
||||||
}
|
}
|
||||||
if uint16(len(z.File)) != uint16(end.directoryRecords) { // only compare 16 bits here
|
if uint16(len(z.File)) != uint16(end.directoryRecords) { // only compare 16 bits here
|
||||||
|
|
@ -180,26 +178,68 @@ func (f *File) Open() (io.ReadCloser, error) {
|
||||||
return nil, ErrAlgorithm
|
return nil, ErrAlgorithm
|
||||||
}
|
}
|
||||||
var rc io.ReadCloser = dcomp(r)
|
var rc io.ReadCloser = dcomp(r)
|
||||||
var desr io.Reader
|
|
||||||
if f.hasDataDescriptor() {
|
|
||||||
desr = io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, dataDescriptorLen)
|
|
||||||
}
|
|
||||||
rc = &checksumReader{
|
rc = &checksumReader{
|
||||||
rc: rc,
|
rc: rc,
|
||||||
hash: crc32.NewIEEE(),
|
hash: crc32.NewIEEE(),
|
||||||
f: f,
|
f: f,
|
||||||
desr: desr,
|
|
||||||
}
|
}
|
||||||
return rc, nil
|
return rc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OpenRaw returns a Reader that provides access to the File's contents without
|
||||||
|
// decompression.
|
||||||
|
func (f *File) OpenRaw() (io.Reader, error) {
|
||||||
|
bodyOffset, err := f.findBodyOffset()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset, int64(f.CompressedSize64))
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *File) readDataDescriptor() {
|
||||||
|
if !f.hasDataDescriptor() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
bodyOffset, err := f.findBodyOffset()
|
||||||
|
if err != nil {
|
||||||
|
f.descErr = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// In section 4.3.9.2 of the spec: "However ZIP64 format MAY be used
|
||||||
|
// regardless of the size of a file. When extracting, if the zip64
|
||||||
|
// extended information extra field is present for the file the
|
||||||
|
// compressed and uncompressed sizes will be 8 byte values."
|
||||||
|
//
|
||||||
|
// Historically, this package has used the compressed and uncompressed
|
||||||
|
// sizes from the central directory to determine if the package is
|
||||||
|
// zip64.
|
||||||
|
//
|
||||||
|
// For this case we allow either the extra field or sizes to determine
|
||||||
|
// the data descriptor length.
|
||||||
|
zip64 := f.zip64 || f.isZip64()
|
||||||
|
n := int64(dataDescriptorLen)
|
||||||
|
if zip64 {
|
||||||
|
n = dataDescriptor64Len
|
||||||
|
}
|
||||||
|
size := int64(f.CompressedSize64)
|
||||||
|
r := io.NewSectionReader(f.zipr, f.headerOffset+bodyOffset+size, n)
|
||||||
|
dd, err := readDataDescriptor(r, zip64)
|
||||||
|
if err != nil {
|
||||||
|
f.descErr = err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f.CRC32 = dd.crc32
|
||||||
|
}
|
||||||
|
|
||||||
type checksumReader struct {
|
type checksumReader struct {
|
||||||
rc io.ReadCloser
|
rc io.ReadCloser
|
||||||
hash hash.Hash32
|
hash hash.Hash32
|
||||||
nread uint64 // number of bytes read so far
|
nread uint64 // number of bytes read so far
|
||||||
f *File
|
f *File
|
||||||
desr io.Reader // if non-nil, where to read the data descriptor
|
err error // sticky error
|
||||||
err error // sticky error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *checksumReader) Stat() (fs.FileInfo, error) {
|
func (r *checksumReader) Stat() (fs.FileInfo, error) {
|
||||||
|
|
@ -220,12 +260,12 @@ func (r *checksumReader) Read(b []byte) (n int, err error) {
|
||||||
if r.nread != r.f.UncompressedSize64 {
|
if r.nread != r.f.UncompressedSize64 {
|
||||||
return 0, io.ErrUnexpectedEOF
|
return 0, io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
if r.desr != nil {
|
if r.f.hasDataDescriptor() {
|
||||||
if err1 := readDataDescriptor(r.desr, r.f); err1 != nil {
|
if r.f.descErr != nil {
|
||||||
if err1 == io.EOF {
|
if r.f.descErr == io.EOF {
|
||||||
err = io.ErrUnexpectedEOF
|
err = io.ErrUnexpectedEOF
|
||||||
} else {
|
} else {
|
||||||
err = err1
|
err = r.f.descErr
|
||||||
}
|
}
|
||||||
} else if r.hash.Sum32() != r.f.CRC32 {
|
} else if r.hash.Sum32() != r.f.CRC32 {
|
||||||
err = ErrChecksum
|
err = ErrChecksum
|
||||||
|
|
@ -336,6 +376,8 @@ parseExtras:
|
||||||
|
|
||||||
switch fieldTag {
|
switch fieldTag {
|
||||||
case zip64ExtraID:
|
case zip64ExtraID:
|
||||||
|
f.zip64 = true
|
||||||
|
|
||||||
// update directory values from the zip64 extra block.
|
// update directory values from the zip64 extra block.
|
||||||
// They should only be consulted if the sizes read earlier
|
// They should only be consulted if the sizes read earlier
|
||||||
// are maxed out.
|
// are maxed out.
|
||||||
|
|
@ -435,8 +477,9 @@ parseExtras:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readDataDescriptor(r io.Reader, f *File) error {
|
func readDataDescriptor(r io.Reader, zip64 bool) (*dataDescriptor, error) {
|
||||||
var buf [dataDescriptorLen]byte
|
// Create enough space for the largest possible size
|
||||||
|
var buf [dataDescriptor64Len]byte
|
||||||
|
|
||||||
// The spec says: "Although not originally assigned a
|
// The spec says: "Although not originally assigned a
|
||||||
// signature, the value 0x08074b50 has commonly been adopted
|
// signature, the value 0x08074b50 has commonly been adopted
|
||||||
|
|
@ -446,10 +489,9 @@ func readDataDescriptor(r io.Reader, f *File) error {
|
||||||
// descriptors and should account for either case when reading
|
// descriptors and should account for either case when reading
|
||||||
// ZIP files to ensure compatibility."
|
// ZIP files to ensure compatibility."
|
||||||
//
|
//
|
||||||
// dataDescriptorLen includes the size of the signature but
|
// First read just those 4 bytes to see if the signature exists.
|
||||||
// first read just those 4 bytes to see if it exists.
|
|
||||||
if _, err := io.ReadFull(r, buf[:4]); err != nil {
|
if _, err := io.ReadFull(r, buf[:4]); err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
off := 0
|
off := 0
|
||||||
maybeSig := readBuf(buf[:4])
|
maybeSig := readBuf(buf[:4])
|
||||||
|
|
@ -458,21 +500,28 @@ func readDataDescriptor(r io.Reader, f *File) error {
|
||||||
// bytes.
|
// bytes.
|
||||||
off += 4
|
off += 4
|
||||||
}
|
}
|
||||||
if _, err := io.ReadFull(r, buf[off:12]); err != nil {
|
|
||||||
return err
|
end := dataDescriptorLen - 4
|
||||||
|
if zip64 {
|
||||||
|
end = dataDescriptor64Len - 4
|
||||||
}
|
}
|
||||||
b := readBuf(buf[:12])
|
if _, err := io.ReadFull(r, buf[off:end]); err != nil {
|
||||||
if b.uint32() != f.CRC32 {
|
return nil, err
|
||||||
return ErrChecksum
|
}
|
||||||
|
b := readBuf(buf[:end])
|
||||||
|
|
||||||
|
out := &dataDescriptor{
|
||||||
|
crc32: b.uint32(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// The two sizes that follow here can be either 32 bits or 64 bits
|
if zip64 {
|
||||||
// but the spec is not very clear on this and different
|
out.compressedSize = b.uint64()
|
||||||
// interpretations has been made causing incompatibilities. We
|
out.uncompressedSize = b.uint64()
|
||||||
// already have the sizes from the central directory so we can
|
} else {
|
||||||
// just ignore these.
|
out.compressedSize = uint64(b.uint32())
|
||||||
|
out.uncompressedSize = uint64(b.uint32())
|
||||||
return nil
|
}
|
||||||
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) {
|
func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, err error) {
|
||||||
|
|
@ -628,10 +677,11 @@ func (b *readBuf) sub(n int) readBuf {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A fileListEntry is a File and its ename.
|
// A fileListEntry is a File and its ename.
|
||||||
// If file == nil, the fileListEntry describes a directory, without metadata.
|
// If file == nil, the fileListEntry describes a directory without metadata.
|
||||||
type fileListEntry struct {
|
type fileListEntry struct {
|
||||||
name string
|
name string
|
||||||
file *File // nil for directories
|
file *File
|
||||||
|
isDir bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type fileInfoDirEntry interface {
|
type fileInfoDirEntry interface {
|
||||||
|
|
@ -640,20 +690,26 @@ type fileInfoDirEntry interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *fileListEntry) stat() fileInfoDirEntry {
|
func (e *fileListEntry) stat() fileInfoDirEntry {
|
||||||
if e.file != nil {
|
if !e.isDir {
|
||||||
return headerFileInfo{&e.file.FileHeader}
|
return headerFileInfo{&e.file.FileHeader}
|
||||||
}
|
}
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only used for directories.
|
// Only used for directories.
|
||||||
func (f *fileListEntry) Name() string { _, elem, _ := split(f.name); return elem }
|
func (f *fileListEntry) Name() string { _, elem, _ := split(f.name); return elem }
|
||||||
func (f *fileListEntry) Size() int64 { return 0 }
|
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) Mode() fs.FileMode { return fs.ModeDir | 0555 }
|
func (f *fileListEntry) Type() fs.FileMode { return fs.ModeDir }
|
||||||
func (f *fileListEntry) Type() fs.FileMode { return fs.ModeDir }
|
func (f *fileListEntry) IsDir() bool { return true }
|
||||||
func (f *fileListEntry) IsDir() bool { return true }
|
func (f *fileListEntry) Sys() interface{} { return nil }
|
||||||
func (f *fileListEntry) Sys() interface{} { return nil }
|
|
||||||
|
func (f *fileListEntry) ModTime() time.Time {
|
||||||
|
if f.file == nil {
|
||||||
|
return time.Time{}
|
||||||
|
}
|
||||||
|
return f.file.FileHeader.Modified.UTC()
|
||||||
|
}
|
||||||
|
|
||||||
func (f *fileListEntry) Info() (fs.FileInfo, error) { return f, nil }
|
func (f *fileListEntry) Info() (fs.FileInfo, error) { return f, nil }
|
||||||
|
|
||||||
|
|
@ -664,7 +720,7 @@ func toValidName(name string) string {
|
||||||
if strings.HasPrefix(p, "/") {
|
if strings.HasPrefix(p, "/") {
|
||||||
p = p[len("/"):]
|
p = p[len("/"):]
|
||||||
}
|
}
|
||||||
for strings.HasPrefix(name, "../") {
|
for strings.HasPrefix(p, "../") {
|
||||||
p = p[len("../"):]
|
p = p[len("../"):]
|
||||||
}
|
}
|
||||||
return p
|
return p
|
||||||
|
|
@ -673,15 +729,32 @@ func toValidName(name string) string {
|
||||||
func (r *Reader) initFileList() {
|
func (r *Reader) initFileList() {
|
||||||
r.fileListOnce.Do(func() {
|
r.fileListOnce.Do(func() {
|
||||||
dirs := make(map[string]bool)
|
dirs := make(map[string]bool)
|
||||||
|
knownDirs := make(map[string]bool)
|
||||||
for _, file := range r.File {
|
for _, file := range r.File {
|
||||||
|
isDir := len(file.Name) > 0 && file.Name[len(file.Name)-1] == '/'
|
||||||
name := toValidName(file.Name)
|
name := toValidName(file.Name)
|
||||||
for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) {
|
for dir := path.Dir(name); dir != "."; dir = path.Dir(dir) {
|
||||||
dirs[dir] = true
|
dirs[dir] = true
|
||||||
}
|
}
|
||||||
r.fileList = append(r.fileList, fileListEntry{name, file})
|
entry := fileListEntry{
|
||||||
|
name: name,
|
||||||
|
file: file,
|
||||||
|
isDir: isDir,
|
||||||
|
}
|
||||||
|
r.fileList = append(r.fileList, entry)
|
||||||
|
if isDir {
|
||||||
|
knownDirs[name] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for dir := range dirs {
|
for dir := range dirs {
|
||||||
r.fileList = append(r.fileList, fileListEntry{dir + "/", nil})
|
if !knownDirs[dir] {
|
||||||
|
entry := fileListEntry{
|
||||||
|
name: dir,
|
||||||
|
file: nil,
|
||||||
|
isDir: true,
|
||||||
|
}
|
||||||
|
r.fileList = append(r.fileList, entry)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Slice(r.fileList, func(i, j int) bool { return fileEntryLess(r.fileList[i].name, r.fileList[j].name) })
|
sort.Slice(r.fileList, func(i, j int) bool { return fileEntryLess(r.fileList[i].name, r.fileList[j].name) })
|
||||||
|
|
@ -705,7 +778,7 @@ func (r *Reader) Open(name string) (fs.File, error) {
|
||||||
if e == nil || !fs.ValidPath(name) {
|
if e == nil || !fs.ValidPath(name) {
|
||||||
return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist}
|
return nil, &fs.PathError{Op: "open", Path: name, Err: fs.ErrNotExist}
|
||||||
}
|
}
|
||||||
if e.file == nil || strings.HasSuffix(e.file.Name, "/") {
|
if e.isDir {
|
||||||
return &openDir{e, r.openReadDir(name), 0}, nil
|
return &openDir{e, r.openReadDir(name), 0}, nil
|
||||||
}
|
}
|
||||||
rc, err := e.file.Open()
|
rc, err := e.file.Open()
|
||||||
|
|
@ -730,7 +803,7 @@ func split(name string) (dir, elem string, isDir bool) {
|
||||||
return name[:i], name[i+1:], isDir
|
return name[:i], name[i+1:], isDir
|
||||||
}
|
}
|
||||||
|
|
||||||
var dotFile = &fileListEntry{name: "./"}
|
var dotFile = &fileListEntry{name: "./", isDir: true}
|
||||||
|
|
||||||
func (r *Reader) openLookup(name string) *fileListEntry {
|
func (r *Reader) openLookup(name string) *fileListEntry {
|
||||||
if name == "." {
|
if name == "." {
|
||||||
|
|
|
||||||
|
|
@ -499,9 +499,15 @@ func TestReader(t *testing.T) {
|
||||||
func readTestZip(t *testing.T, zt ZipTest) {
|
func readTestZip(t *testing.T, zt ZipTest) {
|
||||||
var z *Reader
|
var z *Reader
|
||||||
var err error
|
var err error
|
||||||
|
var raw []byte
|
||||||
if zt.Source != nil {
|
if zt.Source != nil {
|
||||||
rat, size := zt.Source()
|
rat, size := zt.Source()
|
||||||
z, err = NewReader(rat, size)
|
z, err = NewReader(rat, size)
|
||||||
|
raw = make([]byte, size)
|
||||||
|
if _, err := rat.ReadAt(raw, 0); err != nil {
|
||||||
|
t.Errorf("ReadAt error=%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
path := filepath.Join("testdata", zt.Name)
|
path := filepath.Join("testdata", zt.Name)
|
||||||
if zt.Obscured {
|
if zt.Obscured {
|
||||||
|
|
@ -519,6 +525,12 @@ func readTestZip(t *testing.T, zt ZipTest) {
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
z = &rc.Reader
|
z = &rc.Reader
|
||||||
}
|
}
|
||||||
|
var err2 error
|
||||||
|
raw, err2 = os.ReadFile(path)
|
||||||
|
if err2 != nil {
|
||||||
|
t.Errorf("ReadFile(%s) error=%v", path, err2)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != zt.Error {
|
if err != zt.Error {
|
||||||
t.Errorf("error=%v, want %v", err, zt.Error)
|
t.Errorf("error=%v, want %v", err, zt.Error)
|
||||||
|
|
@ -545,7 +557,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
|
||||||
|
|
||||||
// test read of each file
|
// test read of each file
|
||||||
for i, ft := range zt.File {
|
for i, ft := range zt.File {
|
||||||
readTestFile(t, zt, ft, z.File[i])
|
readTestFile(t, zt, ft, z.File[i], raw)
|
||||||
}
|
}
|
||||||
if t.Failed() {
|
if t.Failed() {
|
||||||
return
|
return
|
||||||
|
|
@ -557,7 +569,7 @@ func readTestZip(t *testing.T, zt ZipTest) {
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
for j, ft := range zt.File {
|
for j, ft := range zt.File {
|
||||||
go func(j int, ft ZipTestFile) {
|
go func(j int, ft ZipTestFile) {
|
||||||
readTestFile(t, zt, ft, z.File[j])
|
readTestFile(t, zt, ft, z.File[j], raw)
|
||||||
done <- true
|
done <- true
|
||||||
}(j, ft)
|
}(j, ft)
|
||||||
n++
|
n++
|
||||||
|
|
@ -574,7 +586,7 @@ func equalTimeAndZone(t1, t2 time.Time) bool {
|
||||||
return t1.Equal(t2) && name1 == name2 && offset1 == offset2
|
return t1.Equal(t2) && name1 == name2 && offset1 == offset2
|
||||||
}
|
}
|
||||||
|
|
||||||
func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
|
func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File, raw []byte) {
|
||||||
if f.Name != ft.Name {
|
if f.Name != ft.Name {
|
||||||
t.Errorf("name=%q, want %q", f.Name, ft.Name)
|
t.Errorf("name=%q, want %q", f.Name, ft.Name)
|
||||||
}
|
}
|
||||||
|
|
@ -594,6 +606,31 @@ func readTestFile(t *testing.T, zt ZipTest, ft ZipTestFile, f *File) {
|
||||||
t.Errorf("%v: UncompressedSize=%#x does not match UncompressedSize64=%#x", f.Name, size, f.UncompressedSize64)
|
t.Errorf("%v: UncompressedSize=%#x does not match UncompressedSize64=%#x", f.Name, size, f.UncompressedSize64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that OpenRaw returns the correct byte segment
|
||||||
|
rw, err := f.OpenRaw()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%v: OpenRaw error=%v", f.Name, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
start, err := f.DataOffset()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%v: DataOffset error=%v", f.Name, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
got, err := io.ReadAll(rw)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%v: OpenRaw ReadAll error=%v", f.Name, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
end := uint64(start) + f.CompressedSize64
|
||||||
|
want := raw[start:end]
|
||||||
|
if !bytes.Equal(got, want) {
|
||||||
|
t.Logf("got %q", got)
|
||||||
|
t.Logf("want %q", want)
|
||||||
|
t.Errorf("%v: OpenRaw returned unexpected bytes", f.Name)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
r, err := f.Open()
|
r, err := f.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%v", err)
|
t.Errorf("%v", err)
|
||||||
|
|
@ -776,8 +813,8 @@ func returnRecursiveZip() (r io.ReaderAt, size int64) {
|
||||||
// "archive/zip"
|
// "archive/zip"
|
||||||
// "bytes"
|
// "bytes"
|
||||||
// "io"
|
// "io"
|
||||||
// "io/ioutil"
|
|
||||||
// "log"
|
// "log"
|
||||||
|
// "os"
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// type zeros struct{}
|
// type zeros struct{}
|
||||||
|
|
@ -1073,11 +1110,218 @@ func TestIssue12449(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFS(t *testing.T) {
|
func TestFS(t *testing.T) {
|
||||||
z, err := OpenReader("testdata/unix.zip")
|
for _, test := range []struct {
|
||||||
|
file string
|
||||||
|
want []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"testdata/unix.zip",
|
||||||
|
[]string{"hello", "dir/bar", "readonly"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"testdata/subdir.zip",
|
||||||
|
[]string{"a/b/c"},
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(test.file, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
z, err := OpenReader(test.file)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer z.Close()
|
||||||
|
if err := fstest.TestFS(z, test.want...); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFSModTime(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
z, err := OpenReader("testdata/subdir.zip")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if err := fstest.TestFS(z, "hello", "dir/bar", "dir/empty", "readonly"); err != nil {
|
defer z.Close()
|
||||||
t.Fatal(err)
|
|
||||||
|
for _, test := range []struct {
|
||||||
|
name string
|
||||||
|
want time.Time
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"a",
|
||||||
|
time.Date(2021, 4, 19, 12, 29, 56, 0, timeZone(-7*time.Hour)).UTC(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"a/b/c",
|
||||||
|
time.Date(2021, 4, 19, 12, 29, 59, 0, timeZone(-7*time.Hour)).UTC(),
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
fi, err := fs.Stat(z, test.name)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%s: %v", test.name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if got := fi.ModTime(); !got.Equal(test.want) {
|
||||||
|
t.Errorf("%s: got modtime %v, want %v", test.name, got, test.want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCVE202127919(t *testing.T) {
|
||||||
|
// Archive containing only the file "../test.txt"
|
||||||
|
data := []byte{
|
||||||
|
0x50, 0x4b, 0x03, 0x04, 0x14, 0x00, 0x08, 0x00,
|
||||||
|
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x2e, 0x2e,
|
||||||
|
0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74, 0x78,
|
||||||
|
0x74, 0x0a, 0xc9, 0xc8, 0x2c, 0x56, 0xc8, 0x2c,
|
||||||
|
0x56, 0x48, 0x54, 0x28, 0x49, 0x2d, 0x2e, 0x51,
|
||||||
|
0x28, 0x49, 0xad, 0x28, 0x51, 0x48, 0xcb, 0xcc,
|
||||||
|
0x49, 0xd5, 0xe3, 0x02, 0x04, 0x00, 0x00, 0xff,
|
||||||
|
0xff, 0x50, 0x4b, 0x07, 0x08, 0xc0, 0xd7, 0xed,
|
||||||
|
0xc3, 0x20, 0x00, 0x00, 0x00, 0x1a, 0x00, 0x00,
|
||||||
|
0x00, 0x50, 0x4b, 0x01, 0x02, 0x14, 0x00, 0x14,
|
||||||
|
0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xc0, 0xd7, 0xed, 0xc3, 0x20, 0x00, 0x00,
|
||||||
|
0x00, 0x1a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2e,
|
||||||
|
0x2e, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x74,
|
||||||
|
0x78, 0x74, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x39, 0x00,
|
||||||
|
0x00, 0x00, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
}
|
||||||
|
r, err := NewReader(bytes.NewReader([]byte(data)), int64(len(data)))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error reading the archive: %v", err)
|
||||||
|
}
|
||||||
|
_, err = r.Open("test.txt")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error reading file: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestReadDataDescriptor(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
desc string
|
||||||
|
in []byte
|
||||||
|
zip64 bool
|
||||||
|
want *dataDescriptor
|
||||||
|
wantErr error
|
||||||
|
}{{
|
||||||
|
desc: "valid 32 bit with signature",
|
||||||
|
in: []byte{
|
||||||
|
0x50, 0x4b, 0x07, 0x08, // signature
|
||||||
|
0x00, 0x01, 0x02, 0x03, // crc32
|
||||||
|
0x04, 0x05, 0x06, 0x07, // compressed size
|
||||||
|
0x08, 0x09, 0x0a, 0x0b, // uncompressed size
|
||||||
|
},
|
||||||
|
want: &dataDescriptor{
|
||||||
|
crc32: 0x03020100,
|
||||||
|
compressedSize: 0x07060504,
|
||||||
|
uncompressedSize: 0x0b0a0908,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
desc: "valid 32 bit without signature",
|
||||||
|
in: []byte{
|
||||||
|
0x00, 0x01, 0x02, 0x03, // crc32
|
||||||
|
0x04, 0x05, 0x06, 0x07, // compressed size
|
||||||
|
0x08, 0x09, 0x0a, 0x0b, // uncompressed size
|
||||||
|
},
|
||||||
|
want: &dataDescriptor{
|
||||||
|
crc32: 0x03020100,
|
||||||
|
compressedSize: 0x07060504,
|
||||||
|
uncompressedSize: 0x0b0a0908,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
desc: "valid 64 bit with signature",
|
||||||
|
in: []byte{
|
||||||
|
0x50, 0x4b, 0x07, 0x08, // signature
|
||||||
|
0x00, 0x01, 0x02, 0x03, // crc32
|
||||||
|
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size
|
||||||
|
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // uncompressed size
|
||||||
|
},
|
||||||
|
zip64: true,
|
||||||
|
want: &dataDescriptor{
|
||||||
|
crc32: 0x03020100,
|
||||||
|
compressedSize: 0x0b0a090807060504,
|
||||||
|
uncompressedSize: 0x131211100f0e0d0c,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
desc: "valid 64 bit without signature",
|
||||||
|
in: []byte{
|
||||||
|
0x00, 0x01, 0x02, 0x03, // crc32
|
||||||
|
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size
|
||||||
|
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, // uncompressed size
|
||||||
|
},
|
||||||
|
zip64: true,
|
||||||
|
want: &dataDescriptor{
|
||||||
|
crc32: 0x03020100,
|
||||||
|
compressedSize: 0x0b0a090807060504,
|
||||||
|
uncompressedSize: 0x131211100f0e0d0c,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
desc: "invalid 32 bit with signature",
|
||||||
|
in: []byte{
|
||||||
|
0x50, 0x4b, 0x07, 0x08, // signature
|
||||||
|
0x00, 0x01, 0x02, 0x03, // crc32
|
||||||
|
0x04, 0x05, // unexpected end
|
||||||
|
},
|
||||||
|
wantErr: io.ErrUnexpectedEOF,
|
||||||
|
}, {
|
||||||
|
desc: "invalid 32 bit without signature",
|
||||||
|
in: []byte{
|
||||||
|
0x00, 0x01, 0x02, 0x03, // crc32
|
||||||
|
0x04, 0x05, // unexpected end
|
||||||
|
},
|
||||||
|
wantErr: io.ErrUnexpectedEOF,
|
||||||
|
}, {
|
||||||
|
desc: "invalid 64 bit with signature",
|
||||||
|
in: []byte{
|
||||||
|
0x50, 0x4b, 0x07, 0x08, // signature
|
||||||
|
0x00, 0x01, 0x02, 0x03, // crc32
|
||||||
|
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size
|
||||||
|
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // unexpected end
|
||||||
|
},
|
||||||
|
zip64: true,
|
||||||
|
wantErr: io.ErrUnexpectedEOF,
|
||||||
|
}, {
|
||||||
|
desc: "invalid 64 bit without signature",
|
||||||
|
in: []byte{
|
||||||
|
0x00, 0x01, 0x02, 0x03, // crc32
|
||||||
|
0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, // compressed size
|
||||||
|
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, // unexpected end
|
||||||
|
},
|
||||||
|
zip64: true,
|
||||||
|
wantErr: io.ErrUnexpectedEOF,
|
||||||
|
}}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
|
r := bytes.NewReader(test.in)
|
||||||
|
|
||||||
|
desc, err := readDataDescriptor(r, test.zip64)
|
||||||
|
if err != test.wantErr {
|
||||||
|
t.Fatalf("got err %v; want nil", err)
|
||||||
|
}
|
||||||
|
if test.want == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if desc == nil {
|
||||||
|
t.Fatalf("got nil DataDescriptor; want non-nil")
|
||||||
|
}
|
||||||
|
if desc.crc32 != test.want.crc32 {
|
||||||
|
t.Errorf("got CRC32 %#x; want %#x", desc.crc32, test.want.crc32)
|
||||||
|
}
|
||||||
|
if desc.compressedSize != test.want.compressedSize {
|
||||||
|
t.Errorf("got CompressedSize %#x; want %#x", desc.compressedSize, test.want.compressedSize)
|
||||||
|
}
|
||||||
|
if desc.uncompressedSize != test.want.uncompressedSize {
|
||||||
|
t.Errorf("got UncompressedSize %#x; want %#x", desc.uncompressedSize, test.want.uncompressedSize)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ const (
|
||||||
directoryHeaderLen = 46 // + filename + extra + comment
|
directoryHeaderLen = 46 // + filename + extra + comment
|
||||||
directoryEndLen = 22 // + comment
|
directoryEndLen = 22 // + comment
|
||||||
dataDescriptorLen = 16 // four uint32: descriptor signature, crc32, compressed size, size
|
dataDescriptorLen = 16 // four uint32: descriptor signature, crc32, compressed size, size
|
||||||
dataDescriptor64Len = 24 // descriptor with 8 byte sizes
|
dataDescriptor64Len = 24 // two uint32: signature, crc32 | two uint64: compressed size, size
|
||||||
directory64LocLen = 20 //
|
directory64LocLen = 20 //
|
||||||
directory64EndLen = 56 // + extra
|
directory64EndLen = 56 // + extra
|
||||||
|
|
||||||
|
|
@ -315,6 +315,10 @@ func (h *FileHeader) isZip64() bool {
|
||||||
return h.CompressedSize64 >= uint32max || h.UncompressedSize64 >= uint32max
|
return h.CompressedSize64 >= uint32max || h.UncompressedSize64 >= uint32max
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FileHeader) hasDataDescriptor() bool {
|
||||||
|
return f.Flags&0x8 != 0
|
||||||
|
}
|
||||||
|
|
||||||
func msdosModeToFileMode(m uint32) (mode fs.FileMode) {
|
func msdosModeToFileMode(m uint32) (mode fs.FileMode) {
|
||||||
if m&msdosDir != 0 {
|
if m&msdosDir != 0 {
|
||||||
mode = fs.ModeDir | 0777
|
mode = fs.ModeDir | 0777
|
||||||
|
|
@ -341,11 +345,9 @@ func fileModeToUnixMode(mode fs.FileMode) uint32 {
|
||||||
case fs.ModeSocket:
|
case fs.ModeSocket:
|
||||||
m = s_IFSOCK
|
m = s_IFSOCK
|
||||||
case fs.ModeDevice:
|
case fs.ModeDevice:
|
||||||
if mode&fs.ModeCharDevice != 0 {
|
m = s_IFBLK
|
||||||
m = s_IFCHR
|
case fs.ModeDevice | fs.ModeCharDevice:
|
||||||
} else {
|
m = s_IFCHR
|
||||||
m = s_IFBLK
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if mode&fs.ModeSetuid != 0 {
|
if mode&fs.ModeSetuid != 0 {
|
||||||
m |= s_ISUID
|
m |= s_ISUID
|
||||||
|
|
@ -388,3 +390,11 @@ func unixModeToFileMode(m uint32) fs.FileMode {
|
||||||
}
|
}
|
||||||
return mode
|
return mode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dataDescriptor holds the data descriptor that optionally follows the file
|
||||||
|
// contents in the zip file.
|
||||||
|
type dataDescriptor struct {
|
||||||
|
crc32 uint32
|
||||||
|
compressedSize uint64
|
||||||
|
uncompressedSize uint64
|
||||||
|
}
|
||||||
|
|
|
||||||
BIN
src/archive/zip/testdata/subdir.zip
vendored
Normal file
BIN
src/archive/zip/testdata/subdir.zip
vendored
Normal file
Binary file not shown.
|
|
@ -37,6 +37,7 @@ type Writer struct {
|
||||||
type header struct {
|
type header struct {
|
||||||
*FileHeader
|
*FileHeader
|
||||||
offset uint64
|
offset uint64
|
||||||
|
raw bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWriter returns a new Writer writing a zip file to w.
|
// NewWriter returns a new Writer writing a zip file to w.
|
||||||
|
|
@ -245,22 +246,31 @@ func detectUTF8(s string) (valid, require bool) {
|
||||||
return true, require
|
return true, require
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepare performs the bookkeeping operations required at the start of
|
||||||
|
// CreateHeader and CreateRaw.
|
||||||
|
func (w *Writer) prepare(fh *FileHeader) error {
|
||||||
|
if w.last != nil && !w.last.closed {
|
||||||
|
if err := w.last.close(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(w.dir) > 0 && w.dir[len(w.dir)-1].FileHeader == fh {
|
||||||
|
// See https://golang.org/issue/11144 confusion.
|
||||||
|
return errors.New("archive/zip: invalid duplicate FileHeader")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// CreateHeader adds a file to the zip archive using the provided FileHeader
|
// CreateHeader adds a file to the zip archive using the provided FileHeader
|
||||||
// for the file metadata. Writer takes ownership of fh and may mutate
|
// for the file metadata. Writer takes ownership of fh and may mutate
|
||||||
// its fields. The caller must not modify fh after calling CreateHeader.
|
// its fields. The caller must not modify fh after calling CreateHeader.
|
||||||
//
|
//
|
||||||
// This returns a Writer to which the file contents should be written.
|
// This returns a Writer to which the file contents should be written.
|
||||||
// The file's contents must be written to the io.Writer before the next
|
// The file's contents must be written to the io.Writer before the next
|
||||||
// call to Create, CreateHeader, or Close.
|
// call to Create, CreateHeader, CreateRaw, or Close.
|
||||||
func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
|
func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
|
||||||
if w.last != nil && !w.last.closed {
|
if err := w.prepare(fh); err != nil {
|
||||||
if err := w.last.close(); err != nil {
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(w.dir) > 0 && w.dir[len(w.dir)-1].FileHeader == fh {
|
|
||||||
// See https://golang.org/issue/11144 confusion.
|
|
||||||
return nil, errors.New("archive/zip: invalid duplicate FileHeader")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The ZIP format has a sad state of affairs regarding character encoding.
|
// The ZIP format has a sad state of affairs regarding character encoding.
|
||||||
|
|
@ -365,7 +375,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
|
||||||
ow = fw
|
ow = fw
|
||||||
}
|
}
|
||||||
w.dir = append(w.dir, h)
|
w.dir = append(w.dir, h)
|
||||||
if err := writeHeader(w.cw, fh); err != nil {
|
if err := writeHeader(w.cw, h); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// If we're creating a directory, fw is nil.
|
// If we're creating a directory, fw is nil.
|
||||||
|
|
@ -373,7 +383,7 @@ func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error) {
|
||||||
return ow, nil
|
return ow, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeHeader(w io.Writer, h *FileHeader) error {
|
func writeHeader(w io.Writer, h *header) error {
|
||||||
const maxUint16 = 1<<16 - 1
|
const maxUint16 = 1<<16 - 1
|
||||||
if len(h.Name) > maxUint16 {
|
if len(h.Name) > maxUint16 {
|
||||||
return errLongName
|
return errLongName
|
||||||
|
|
@ -390,9 +400,20 @@ func writeHeader(w io.Writer, h *FileHeader) error {
|
||||||
b.uint16(h.Method)
|
b.uint16(h.Method)
|
||||||
b.uint16(h.ModifiedTime)
|
b.uint16(h.ModifiedTime)
|
||||||
b.uint16(h.ModifiedDate)
|
b.uint16(h.ModifiedDate)
|
||||||
b.uint32(0) // since we are writing a data descriptor crc32,
|
// In raw mode (caller does the compression), the values are either
|
||||||
b.uint32(0) // compressed size,
|
// written here or in the trailing data descriptor based on the header
|
||||||
b.uint32(0) // and uncompressed size should be zero
|
// flags.
|
||||||
|
if h.raw && !h.hasDataDescriptor() {
|
||||||
|
b.uint32(h.CRC32)
|
||||||
|
b.uint32(uint32(min64(h.CompressedSize64, uint32max)))
|
||||||
|
b.uint32(uint32(min64(h.UncompressedSize64, uint32max)))
|
||||||
|
} else {
|
||||||
|
// When this package handle the compression, these values are
|
||||||
|
// always written to the trailing data descriptor.
|
||||||
|
b.uint32(0) // crc32
|
||||||
|
b.uint32(0) // compressed size
|
||||||
|
b.uint32(0) // uncompressed size
|
||||||
|
}
|
||||||
b.uint16(uint16(len(h.Name)))
|
b.uint16(uint16(len(h.Name)))
|
||||||
b.uint16(uint16(len(h.Extra)))
|
b.uint16(uint16(len(h.Extra)))
|
||||||
if _, err := w.Write(buf[:]); err != nil {
|
if _, err := w.Write(buf[:]); err != nil {
|
||||||
|
|
@ -405,6 +426,65 @@ func writeHeader(w io.Writer, h *FileHeader) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func min64(x, y uint64) uint64 {
|
||||||
|
if x < y {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRaw adds a file to the zip archive using the provided FileHeader and
|
||||||
|
// returns a Writer to which the file contents should be written. The file's
|
||||||
|
// contents must be written to the io.Writer before the next call to Create,
|
||||||
|
// CreateHeader, CreateRaw, or Close.
|
||||||
|
//
|
||||||
|
// In contrast to CreateHeader, the bytes passed to Writer are not compressed.
|
||||||
|
func (w *Writer) CreateRaw(fh *FileHeader) (io.Writer, error) {
|
||||||
|
if err := w.prepare(fh); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fh.CompressedSize = uint32(min64(fh.CompressedSize64, uint32max))
|
||||||
|
fh.UncompressedSize = uint32(min64(fh.UncompressedSize64, uint32max))
|
||||||
|
|
||||||
|
h := &header{
|
||||||
|
FileHeader: fh,
|
||||||
|
offset: uint64(w.cw.count),
|
||||||
|
raw: true,
|
||||||
|
}
|
||||||
|
w.dir = append(w.dir, h)
|
||||||
|
if err := writeHeader(w.cw, h); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.HasSuffix(fh.Name, "/") {
|
||||||
|
w.last = nil
|
||||||
|
return dirWriter{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fw := &fileWriter{
|
||||||
|
header: h,
|
||||||
|
zipw: w.cw,
|
||||||
|
}
|
||||||
|
w.last = fw
|
||||||
|
return fw, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy copies the file f (obtained from a Reader) into w. It copies the raw
|
||||||
|
// form directly bypassing decompression, compression, and validation.
|
||||||
|
func (w *Writer) Copy(f *File) error {
|
||||||
|
r, err := f.OpenRaw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fw, err := w.CreateRaw(&f.FileHeader)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = io.Copy(fw, r)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// RegisterCompressor registers or overrides a custom compressor for a specific
|
// RegisterCompressor registers or overrides a custom compressor for a specific
|
||||||
// method ID. If a compressor for a given method is not found, Writer will
|
// method ID. If a compressor for a given method is not found, Writer will
|
||||||
// default to looking up the compressor at the package level.
|
// default to looking up the compressor at the package level.
|
||||||
|
|
@ -446,6 +526,9 @@ func (w *fileWriter) Write(p []byte) (int, error) {
|
||||||
if w.closed {
|
if w.closed {
|
||||||
return 0, errors.New("zip: write to closed file")
|
return 0, errors.New("zip: write to closed file")
|
||||||
}
|
}
|
||||||
|
if w.raw {
|
||||||
|
return w.zipw.Write(p)
|
||||||
|
}
|
||||||
w.crc32.Write(p)
|
w.crc32.Write(p)
|
||||||
return w.rawCount.Write(p)
|
return w.rawCount.Write(p)
|
||||||
}
|
}
|
||||||
|
|
@ -455,6 +538,9 @@ func (w *fileWriter) close() error {
|
||||||
return errors.New("zip: file closed twice")
|
return errors.New("zip: file closed twice")
|
||||||
}
|
}
|
||||||
w.closed = true
|
w.closed = true
|
||||||
|
if w.raw {
|
||||||
|
return w.writeDataDescriptor()
|
||||||
|
}
|
||||||
if err := w.comp.Close(); err != nil {
|
if err := w.comp.Close(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -474,26 +560,33 @@ func (w *fileWriter) close() error {
|
||||||
fh.UncompressedSize = uint32(fh.UncompressedSize64)
|
fh.UncompressedSize = uint32(fh.UncompressedSize64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return w.writeDataDescriptor()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *fileWriter) writeDataDescriptor() error {
|
||||||
|
if !w.hasDataDescriptor() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// Write data descriptor. This is more complicated than one would
|
// Write data descriptor. This is more complicated than one would
|
||||||
// think, see e.g. comments in zipfile.c:putextended() and
|
// think, see e.g. comments in zipfile.c:putextended() and
|
||||||
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073588.
|
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7073588.
|
||||||
// The approach here is to write 8 byte sizes if needed without
|
// The approach here is to write 8 byte sizes if needed without
|
||||||
// adding a zip64 extra in the local header (too late anyway).
|
// adding a zip64 extra in the local header (too late anyway).
|
||||||
var buf []byte
|
var buf []byte
|
||||||
if fh.isZip64() {
|
if w.isZip64() {
|
||||||
buf = make([]byte, dataDescriptor64Len)
|
buf = make([]byte, dataDescriptor64Len)
|
||||||
} else {
|
} else {
|
||||||
buf = make([]byte, dataDescriptorLen)
|
buf = make([]byte, dataDescriptorLen)
|
||||||
}
|
}
|
||||||
b := writeBuf(buf)
|
b := writeBuf(buf)
|
||||||
b.uint32(dataDescriptorSignature) // de-facto standard, required by OS X
|
b.uint32(dataDescriptorSignature) // de-facto standard, required by OS X
|
||||||
b.uint32(fh.CRC32)
|
b.uint32(w.CRC32)
|
||||||
if fh.isZip64() {
|
if w.isZip64() {
|
||||||
b.uint64(fh.CompressedSize64)
|
b.uint64(w.CompressedSize64)
|
||||||
b.uint64(fh.UncompressedSize64)
|
b.uint64(w.UncompressedSize64)
|
||||||
} else {
|
} else {
|
||||||
b.uint32(fh.CompressedSize)
|
b.uint32(w.CompressedSize)
|
||||||
b.uint32(fh.UncompressedSize)
|
b.uint32(w.UncompressedSize)
|
||||||
}
|
}
|
||||||
_, err := w.zipw.Write(buf)
|
_, err := w.zipw.Write(buf)
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,10 @@ package zip
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"compress/flate"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/crc32"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
|
@ -57,6 +59,18 @@ var writeTests = []WriteTest{
|
||||||
Method: Deflate,
|
Method: Deflate,
|
||||||
Mode: 0755 | fs.ModeSymlink,
|
Mode: 0755 | fs.ModeSymlink,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "device",
|
||||||
|
Data: []byte("device file"),
|
||||||
|
Method: Deflate,
|
||||||
|
Mode: 0755 | fs.ModeDevice,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "chardevice",
|
||||||
|
Data: []byte("char device file"),
|
||||||
|
Method: Deflate,
|
||||||
|
Mode: 0755 | fs.ModeDevice | fs.ModeCharDevice,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWriter(t *testing.T) {
|
func TestWriter(t *testing.T) {
|
||||||
|
|
@ -353,6 +367,171 @@ func TestWriterDirAttributes(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWriterCopy(t *testing.T) {
|
||||||
|
// make a zip file
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
w := NewWriter(buf)
|
||||||
|
for _, wt := range writeTests {
|
||||||
|
testCreate(t, w, &wt)
|
||||||
|
}
|
||||||
|
if err := w.Close(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read it back
|
||||||
|
src, err := NewReader(bytes.NewReader(buf.Bytes()), int64(buf.Len()))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, wt := range writeTests {
|
||||||
|
testReadFile(t, src.File[i], &wt)
|
||||||
|
}
|
||||||
|
|
||||||
|
// make a new zip file copying the old compressed data.
|
||||||
|
buf2 := new(bytes.Buffer)
|
||||||
|
dst := NewWriter(buf2)
|
||||||
|
for _, f := range src.File {
|
||||||
|
if err := dst.Copy(f); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := dst.Close(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the new one back
|
||||||
|
r, err := NewReader(bytes.NewReader(buf2.Bytes()), int64(buf2.Len()))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, wt := range writeTests {
|
||||||
|
testReadFile(t, r.File[i], &wt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWriterCreateRaw(t *testing.T) {
|
||||||
|
files := []struct {
|
||||||
|
name string
|
||||||
|
content []byte
|
||||||
|
method uint16
|
||||||
|
flags uint16
|
||||||
|
crc32 uint32
|
||||||
|
uncompressedSize uint64
|
||||||
|
compressedSize uint64
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "small store w desc",
|
||||||
|
content: []byte("gophers"),
|
||||||
|
method: Store,
|
||||||
|
flags: 0x8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "small deflate wo desc",
|
||||||
|
content: bytes.Repeat([]byte("abcdefg"), 2048),
|
||||||
|
method: Deflate,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// write a zip file
|
||||||
|
archive := new(bytes.Buffer)
|
||||||
|
w := NewWriter(archive)
|
||||||
|
|
||||||
|
for i := range files {
|
||||||
|
f := &files[i]
|
||||||
|
f.crc32 = crc32.ChecksumIEEE(f.content)
|
||||||
|
size := uint64(len(f.content))
|
||||||
|
f.uncompressedSize = size
|
||||||
|
f.compressedSize = size
|
||||||
|
|
||||||
|
var compressedContent []byte
|
||||||
|
if f.method == Deflate {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
w, err := flate.NewWriter(&buf, flate.BestSpeed)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("flate.NewWriter err = %v", err)
|
||||||
|
}
|
||||||
|
_, err = w.Write(f.content)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("flate Write err = %v", err)
|
||||||
|
}
|
||||||
|
err = w.Close()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("flate Writer.Close err = %v", err)
|
||||||
|
}
|
||||||
|
compressedContent = buf.Bytes()
|
||||||
|
f.compressedSize = uint64(len(compressedContent))
|
||||||
|
}
|
||||||
|
|
||||||
|
h := &FileHeader{
|
||||||
|
Name: f.name,
|
||||||
|
Method: f.method,
|
||||||
|
Flags: f.flags,
|
||||||
|
CRC32: f.crc32,
|
||||||
|
CompressedSize64: f.compressedSize,
|
||||||
|
UncompressedSize64: f.uncompressedSize,
|
||||||
|
}
|
||||||
|
w, err := w.CreateRaw(h)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if compressedContent != nil {
|
||||||
|
_, err = w.Write(compressedContent)
|
||||||
|
} else {
|
||||||
|
_, err = w.Write(f.content)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("%s Write got %v; want nil", f.name, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := w.Close(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// read it back
|
||||||
|
r, err := NewReader(bytes.NewReader(archive.Bytes()), int64(archive.Len()))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
for i, want := range files {
|
||||||
|
got := r.File[i]
|
||||||
|
if got.Name != want.name {
|
||||||
|
t.Errorf("got Name %s; want %s", got.Name, want.name)
|
||||||
|
}
|
||||||
|
if got.Method != want.method {
|
||||||
|
t.Errorf("%s: got Method %#x; want %#x", want.name, got.Method, want.method)
|
||||||
|
}
|
||||||
|
if got.Flags != want.flags {
|
||||||
|
t.Errorf("%s: got Flags %#x; want %#x", want.name, got.Flags, want.flags)
|
||||||
|
}
|
||||||
|
if got.CRC32 != want.crc32 {
|
||||||
|
t.Errorf("%s: got CRC32 %#x; want %#x", want.name, got.CRC32, want.crc32)
|
||||||
|
}
|
||||||
|
if got.CompressedSize64 != want.compressedSize {
|
||||||
|
t.Errorf("%s: got CompressedSize64 %d; want %d", want.name, got.CompressedSize64, want.compressedSize)
|
||||||
|
}
|
||||||
|
if got.UncompressedSize64 != want.uncompressedSize {
|
||||||
|
t.Errorf("%s: got UncompressedSize64 %d; want %d", want.name, got.UncompressedSize64, want.uncompressedSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
r, err := got.Open()
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%s: Open err = %v", got.Name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := io.ReadAll(r)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%s: ReadAll err = %v", got.Name, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !bytes.Equal(buf, want.content) {
|
||||||
|
t.Errorf("%v: ReadAll returned unexpected bytes", got.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testCreate(t *testing.T, w *Writer, wt *WriteTest) {
|
func testCreate(t *testing.T, w *Writer, wt *WriteTest) {
|
||||||
header := &FileHeader{
|
header := &FileHeader{
|
||||||
Name: wt.Name,
|
Name: wt.Name,
|
||||||
|
|
@ -378,15 +557,15 @@ func testReadFile(t *testing.T, f *File, wt *WriteTest) {
|
||||||
testFileMode(t, f, wt.Mode)
|
testFileMode(t, f, wt.Mode)
|
||||||
rc, err := f.Open()
|
rc, err := f.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("opening:", err)
|
t.Fatalf("opening %s: %v", f.Name, err)
|
||||||
}
|
}
|
||||||
b, err := io.ReadAll(rc)
|
b, err := io.ReadAll(rc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("reading:", err)
|
t.Fatalf("reading %s: %v", f.Name, err)
|
||||||
}
|
}
|
||||||
err = rc.Close()
|
err = rc.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("closing:", err)
|
t.Fatalf("closing %s: %v", f.Name, err)
|
||||||
}
|
}
|
||||||
if !bytes.Equal(b, wt.Data) {
|
if !bytes.Equal(b, wt.Data) {
|
||||||
t.Errorf("File contents %q, want %q", b, wt.Data)
|
t.Errorf("File contents %q, want %q", b, wt.Data)
|
||||||
|
|
|
||||||
|
|
@ -670,7 +670,8 @@ func (b *Writer) WriteByte(c byte) error {
|
||||||
// WriteRune writes a single Unicode code point, returning
|
// WriteRune writes a single Unicode code point, returning
|
||||||
// the number of bytes written and any error.
|
// the number of bytes written and any error.
|
||||||
func (b *Writer) WriteRune(r rune) (size int, err error) {
|
func (b *Writer) WriteRune(r rune) (size int, err error) {
|
||||||
if r < utf8.RuneSelf {
|
// Compare as uint32 to correctly handle negative runes.
|
||||||
|
if uint32(r) < utf8.RuneSelf {
|
||||||
err = b.WriteByte(byte(r))
|
err = b.WriteByte(byte(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
|
|
|
||||||
|
|
@ -534,6 +534,20 @@ func TestReadWriteRune(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWriteInvalidRune(t *testing.T) {
|
||||||
|
// Invalid runes, including negative ones, should be written as the
|
||||||
|
// replacement character.
|
||||||
|
for _, r := range []rune{-1, utf8.MaxRune + 1} {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
w := NewWriter(&buf)
|
||||||
|
w.WriteRune(r)
|
||||||
|
w.Flush()
|
||||||
|
if s := buf.String(); s != "\uFFFD" {
|
||||||
|
t.Errorf("WriteRune(%d) wrote %q, not replacement character", r, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestReadStringAllocs(t *testing.T) {
|
func TestReadStringAllocs(t *testing.T) {
|
||||||
r := strings.NewReader(" foo foo 42 42 42 42 42 42 42 42 4.2 4.2 4.2 4.2\n")
|
r := strings.NewReader(" foo foo 42 42 42 42 42 42 42 42 4.2 4.2 4.2 4.2\n")
|
||||||
buf := NewReader(r)
|
buf := NewReader(r)
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,8 @@ type Scanner struct {
|
||||||
// and the next token to return to the user, if any, plus an error, if any.
|
// and the next token to return to the user, if any, plus an error, if any.
|
||||||
//
|
//
|
||||||
// Scanning stops if the function returns an error, in which case some of
|
// Scanning stops if the function returns an error, in which case some of
|
||||||
// the input may be discarded.
|
// the input may be discarded. If that error is ErrFinalToken, scanning
|
||||||
|
// stops with no error.
|
||||||
//
|
//
|
||||||
// Otherwise, the Scanner advances the input. If the token is not nil,
|
// Otherwise, the Scanner advances the input. If the token is not nil,
|
||||||
// the Scanner returns it to the user. If the token is nil, the
|
// the Scanner returns it to the user. If the token is nil, the
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
//
|
//
|
||||||
|
//go:build linux
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package bytes_test
|
package bytes_test
|
||||||
|
|
|
||||||
|
|
@ -275,7 +275,8 @@ func (b *Buffer) WriteByte(c byte) error {
|
||||||
// included to match bufio.Writer's WriteRune. The buffer is grown as needed;
|
// included to match bufio.Writer's WriteRune. The buffer is grown as needed;
|
||||||
// if it becomes too large, WriteRune will panic with ErrTooLarge.
|
// if it becomes too large, WriteRune will panic with ErrTooLarge.
|
||||||
func (b *Buffer) WriteRune(r rune) (n int, err error) {
|
func (b *Buffer) WriteRune(r rune) (n int, err error) {
|
||||||
if r < utf8.RuneSelf {
|
// Compare as uint32 to correctly handle negative runes.
|
||||||
|
if uint32(r) < utf8.RuneSelf {
|
||||||
b.WriteByte(byte(r))
|
b.WriteByte(byte(r))
|
||||||
return 1, nil
|
return 1, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ package bytes_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
. "bytes"
|
. "bytes"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
@ -387,6 +388,16 @@ func TestRuneIO(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWriteInvalidRune(t *testing.T) {
|
||||||
|
// Invalid runes, including negative ones, should be written as
|
||||||
|
// utf8.RuneError.
|
||||||
|
for _, r := range []rune{-1, utf8.MaxRune + 1} {
|
||||||
|
var buf Buffer
|
||||||
|
buf.WriteRune(r)
|
||||||
|
check(t, fmt.Sprintf("TestWriteInvalidRune (%d)", r), &buf, "\uFFFD")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestNext(t *testing.T) {
|
func TestNext(t *testing.T) {
|
||||||
b := []byte{0, 1, 2, 3, 4}
|
b := []byte{0, 1, 2, 3, 4}
|
||||||
tmp := make([]byte, 5)
|
tmp := make([]byte, 5)
|
||||||
|
|
|
||||||
|
|
@ -215,8 +215,7 @@ func main() {
|
||||||
}
|
}
|
||||||
optional := fileFeatures(*nextFile)
|
optional := fileFeatures(*nextFile)
|
||||||
exception := fileFeatures(*exceptFile)
|
exception := fileFeatures(*exceptFile)
|
||||||
fail = !compareAPI(bw, features, required, optional, exception,
|
fail = !compareAPI(bw, features, required, optional, exception, *allowNew)
|
||||||
*allowNew && strings.Contains(runtime.Version(), "devel"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// export emits the exported package features.
|
// export emits the exported package features.
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
//go:build ignore
|
||||||
// +build ignore
|
// +build ignore
|
||||||
|
|
||||||
// The run program is invoked via the dist tool.
|
// The run program is invoked via the dist tool.
|
||||||
|
|
@ -9,8 +10,11 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
exec "internal/execabs"
|
exec "internal/execabs"
|
||||||
|
"internal/goversion"
|
||||||
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -42,6 +46,7 @@ func main() {
|
||||||
apiDir := filepath.Join(goroot, "api")
|
apiDir := filepath.Join(goroot, "api")
|
||||||
out, err := exec.Command(goCmd(), "tool", "api",
|
out, err := exec.Command(goCmd(), "tool", "api",
|
||||||
"-c", findAPIDirFiles(apiDir),
|
"-c", findAPIDirFiles(apiDir),
|
||||||
|
allowNew(apiDir),
|
||||||
"-next", filepath.Join(apiDir, "next.txt"),
|
"-next", filepath.Join(apiDir, "next.txt"),
|
||||||
"-except", filepath.Join(apiDir, "except.txt")).CombinedOutput()
|
"-except", filepath.Join(apiDir, "except.txt")).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -70,3 +75,35 @@ func findAPIDirFiles(apiDir string) string {
|
||||||
}
|
}
|
||||||
return strings.Join(apiFiles, ",")
|
return strings.Join(apiFiles, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allowNew returns the -allow_new flag to use for the 'go tool api' invocation.
|
||||||
|
func allowNew(apiDir string) string {
|
||||||
|
// Verify that the api/go1.n.txt for previous Go version exists.
|
||||||
|
// It definitely should, otherwise it's a signal that the logic below may be outdated.
|
||||||
|
if _, err := os.Stat(filepath.Join(apiDir, fmt.Sprintf("go1.%d.txt", goversion.Version-1))); err != nil {
|
||||||
|
log.Fatalln("Problem with api file for previous release:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// See whether the api/go1.n.txt for this Go version has been created.
|
||||||
|
// (As of April 2021, it gets created during the release of the first Beta.)
|
||||||
|
_, err := os.Stat(filepath.Join(apiDir, fmt.Sprintf("go1.%d.txt", goversion.Version)))
|
||||||
|
if errors.Is(err, fs.ErrNotExist) {
|
||||||
|
// It doesn't exist, so we're in development or before Beta 1.
|
||||||
|
// At this stage, unmentioned API additions are deemed okay.
|
||||||
|
// (They will be quietly shown in API check output, but the test won't fail).
|
||||||
|
return "-allow_new=true"
|
||||||
|
} else if err == nil {
|
||||||
|
// The api/go1.n.txt for this Go version has been created,
|
||||||
|
// so we're definitely past Beta 1 in the release cycle.
|
||||||
|
//
|
||||||
|
// From this point, enforce that api/go1.n.txt is an accurate and complete
|
||||||
|
// representation of what's going into the release by failing API check if
|
||||||
|
// there are API additions (a month into the freeze, there shouldn't be many).
|
||||||
|
//
|
||||||
|
// See golang.org/issue/43956.
|
||||||
|
return "-allow_new=false"
|
||||||
|
} else {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
panic("unreachable")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,16 @@ func arm64RegisterNumber(name string, n int16) (int16, bool) {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// ARM64RegisterExtension parses an ARM64 register with extension or arrangement.
|
// ARM64RegisterShift constructs an ARM64 register with shift operation.
|
||||||
|
func ARM64RegisterShift(reg, op, count int16) (int64, error) {
|
||||||
|
// the base register of shift operations must be general register.
|
||||||
|
if reg > arm64.REG_R31 || reg < arm64.REG_R0 {
|
||||||
|
return 0, errors.New("invalid register for shift operation")
|
||||||
|
}
|
||||||
|
return int64(reg&31)<<16 | int64(op)<<22 | int64(uint16(count)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ARM64RegisterExtension constructs an ARM64 register with extension or arrangement.
|
||||||
func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
|
func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, isIndex bool) error {
|
||||||
Rnum := (reg & 31) + int16(num<<5)
|
Rnum := (reg & 31) + int16(num<<5)
|
||||||
if isAmount {
|
if isAmount {
|
||||||
|
|
@ -155,154 +164,163 @@ func ARM64RegisterExtension(a *obj.Addr, ext string, reg, num int16, isAmount, i
|
||||||
return errors.New("index shift amount is out of range")
|
return errors.New("index shift amount is out of range")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch ext {
|
if reg <= arm64.REG_R31 && reg >= arm64.REG_R0 {
|
||||||
case "UXTB":
|
switch ext {
|
||||||
if !isAmount {
|
case "UXTB":
|
||||||
return errors.New("invalid register extension")
|
if !isAmount {
|
||||||
}
|
return errors.New("invalid register extension")
|
||||||
if a.Type == obj.TYPE_MEM {
|
}
|
||||||
return errors.New("invalid shift for the register offset addressing mode")
|
if a.Type == obj.TYPE_MEM {
|
||||||
}
|
return errors.New("invalid shift for the register offset addressing mode")
|
||||||
a.Reg = arm64.REG_UXTB + Rnum
|
}
|
||||||
case "UXTH":
|
a.Reg = arm64.REG_UXTB + Rnum
|
||||||
if !isAmount {
|
case "UXTH":
|
||||||
return errors.New("invalid register extension")
|
if !isAmount {
|
||||||
}
|
return errors.New("invalid register extension")
|
||||||
if a.Type == obj.TYPE_MEM {
|
}
|
||||||
return errors.New("invalid shift for the register offset addressing mode")
|
if a.Type == obj.TYPE_MEM {
|
||||||
}
|
return errors.New("invalid shift for the register offset addressing mode")
|
||||||
a.Reg = arm64.REG_UXTH + Rnum
|
}
|
||||||
case "UXTW":
|
a.Reg = arm64.REG_UXTH + Rnum
|
||||||
if !isAmount {
|
case "UXTW":
|
||||||
return errors.New("invalid register extension")
|
if !isAmount {
|
||||||
}
|
return errors.New("invalid register extension")
|
||||||
// effective address of memory is a base register value and an offset register value.
|
}
|
||||||
if a.Type == obj.TYPE_MEM {
|
// effective address of memory is a base register value and an offset register value.
|
||||||
a.Index = arm64.REG_UXTW + Rnum
|
if a.Type == obj.TYPE_MEM {
|
||||||
} else {
|
a.Index = arm64.REG_UXTW + Rnum
|
||||||
a.Reg = arm64.REG_UXTW + Rnum
|
} else {
|
||||||
}
|
a.Reg = arm64.REG_UXTW + Rnum
|
||||||
case "UXTX":
|
}
|
||||||
if !isAmount {
|
case "UXTX":
|
||||||
return errors.New("invalid register extension")
|
if !isAmount {
|
||||||
}
|
return errors.New("invalid register extension")
|
||||||
if a.Type == obj.TYPE_MEM {
|
}
|
||||||
return errors.New("invalid shift for the register offset addressing mode")
|
if a.Type == obj.TYPE_MEM {
|
||||||
}
|
return errors.New("invalid shift for the register offset addressing mode")
|
||||||
a.Reg = arm64.REG_UXTX + Rnum
|
}
|
||||||
case "SXTB":
|
a.Reg = arm64.REG_UXTX + Rnum
|
||||||
if !isAmount {
|
case "SXTB":
|
||||||
return errors.New("invalid register extension")
|
if !isAmount {
|
||||||
}
|
return errors.New("invalid register extension")
|
||||||
a.Reg = arm64.REG_SXTB + Rnum
|
}
|
||||||
case "SXTH":
|
a.Reg = arm64.REG_SXTB + Rnum
|
||||||
if !isAmount {
|
case "SXTH":
|
||||||
return errors.New("invalid register extension")
|
if !isAmount {
|
||||||
}
|
return errors.New("invalid register extension")
|
||||||
if a.Type == obj.TYPE_MEM {
|
}
|
||||||
return errors.New("invalid shift for the register offset addressing mode")
|
if a.Type == obj.TYPE_MEM {
|
||||||
}
|
return errors.New("invalid shift for the register offset addressing mode")
|
||||||
a.Reg = arm64.REG_SXTH + Rnum
|
}
|
||||||
case "SXTW":
|
a.Reg = arm64.REG_SXTH + Rnum
|
||||||
if !isAmount {
|
case "SXTW":
|
||||||
return errors.New("invalid register extension")
|
if !isAmount {
|
||||||
}
|
return errors.New("invalid register extension")
|
||||||
if a.Type == obj.TYPE_MEM {
|
}
|
||||||
a.Index = arm64.REG_SXTW + Rnum
|
if a.Type == obj.TYPE_MEM {
|
||||||
} else {
|
a.Index = arm64.REG_SXTW + Rnum
|
||||||
a.Reg = arm64.REG_SXTW + Rnum
|
} else {
|
||||||
}
|
a.Reg = arm64.REG_SXTW + Rnum
|
||||||
case "SXTX":
|
}
|
||||||
if !isAmount {
|
case "SXTX":
|
||||||
return errors.New("invalid register extension")
|
if !isAmount {
|
||||||
}
|
return errors.New("invalid register extension")
|
||||||
if a.Type == obj.TYPE_MEM {
|
}
|
||||||
a.Index = arm64.REG_SXTX + Rnum
|
if a.Type == obj.TYPE_MEM {
|
||||||
} else {
|
a.Index = arm64.REG_SXTX + Rnum
|
||||||
a.Reg = arm64.REG_SXTX + Rnum
|
} else {
|
||||||
}
|
a.Reg = arm64.REG_SXTX + Rnum
|
||||||
case "LSL":
|
}
|
||||||
if !isAmount {
|
case "LSL":
|
||||||
return errors.New("invalid register extension")
|
if !isAmount {
|
||||||
}
|
return errors.New("invalid register extension")
|
||||||
a.Index = arm64.REG_LSL + Rnum
|
}
|
||||||
case "B8":
|
a.Index = arm64.REG_LSL + Rnum
|
||||||
if isIndex {
|
default:
|
||||||
return errors.New("invalid register extension")
|
return errors.New("unsupported general register extension type: " + ext)
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_8B & 15) << 5)
|
|
||||||
case "B16":
|
|
||||||
if isIndex {
|
|
||||||
return errors.New("invalid register extension")
|
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_16B & 15) << 5)
|
|
||||||
case "H4":
|
|
||||||
if isIndex {
|
|
||||||
return errors.New("invalid register extension")
|
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_4H & 15) << 5)
|
|
||||||
case "H8":
|
|
||||||
if isIndex {
|
|
||||||
return errors.New("invalid register extension")
|
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_8H & 15) << 5)
|
|
||||||
case "S2":
|
|
||||||
if isIndex {
|
|
||||||
return errors.New("invalid register extension")
|
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_2S & 15) << 5)
|
|
||||||
case "S4":
|
|
||||||
if isIndex {
|
|
||||||
return errors.New("invalid register extension")
|
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_4S & 15) << 5)
|
|
||||||
case "D1":
|
|
||||||
if isIndex {
|
|
||||||
return errors.New("invalid register extension")
|
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_1D & 15) << 5)
|
|
||||||
case "D2":
|
|
||||||
if isIndex {
|
|
||||||
return errors.New("invalid register extension")
|
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_2D & 15) << 5)
|
|
||||||
case "Q1":
|
|
||||||
if isIndex {
|
|
||||||
return errors.New("invalid register extension")
|
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_1Q & 15) << 5)
|
|
||||||
case "B":
|
|
||||||
if !isIndex {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_B & 15) << 5)
|
|
||||||
a.Index = num
|
|
||||||
case "H":
|
|
||||||
if !isIndex {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_H & 15) << 5)
|
|
||||||
a.Index = num
|
|
||||||
case "S":
|
|
||||||
if !isIndex {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_S & 15) << 5)
|
|
||||||
a.Index = num
|
|
||||||
case "D":
|
|
||||||
if !isIndex {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_D & 15) << 5)
|
|
||||||
a.Index = num
|
|
||||||
default:
|
|
||||||
return errors.New("unsupported register extension type: " + ext)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
|
} else if reg <= arm64.REG_V31 && reg >= arm64.REG_V0 {
|
||||||
|
switch ext {
|
||||||
|
case "B8":
|
||||||
|
if isIndex {
|
||||||
|
return errors.New("invalid register extension")
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_8B & 15) << 5)
|
||||||
|
case "B16":
|
||||||
|
if isIndex {
|
||||||
|
return errors.New("invalid register extension")
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_16B & 15) << 5)
|
||||||
|
case "H4":
|
||||||
|
if isIndex {
|
||||||
|
return errors.New("invalid register extension")
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_4H & 15) << 5)
|
||||||
|
case "H8":
|
||||||
|
if isIndex {
|
||||||
|
return errors.New("invalid register extension")
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_8H & 15) << 5)
|
||||||
|
case "S2":
|
||||||
|
if isIndex {
|
||||||
|
return errors.New("invalid register extension")
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_2S & 15) << 5)
|
||||||
|
case "S4":
|
||||||
|
if isIndex {
|
||||||
|
return errors.New("invalid register extension")
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_4S & 15) << 5)
|
||||||
|
case "D1":
|
||||||
|
if isIndex {
|
||||||
|
return errors.New("invalid register extension")
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_1D & 15) << 5)
|
||||||
|
case "D2":
|
||||||
|
if isIndex {
|
||||||
|
return errors.New("invalid register extension")
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_2D & 15) << 5)
|
||||||
|
case "Q1":
|
||||||
|
if isIndex {
|
||||||
|
return errors.New("invalid register extension")
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ARNG + (reg & 31) + ((arm64.ARNG_1Q & 15) << 5)
|
||||||
|
case "B":
|
||||||
|
if !isIndex {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_B & 15) << 5)
|
||||||
|
a.Index = num
|
||||||
|
case "H":
|
||||||
|
if !isIndex {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_H & 15) << 5)
|
||||||
|
a.Index = num
|
||||||
|
case "S":
|
||||||
|
if !isIndex {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_S & 15) << 5)
|
||||||
|
a.Index = num
|
||||||
|
case "D":
|
||||||
|
if !isIndex {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
a.Reg = arm64.REG_ELEM + (reg & 31) + ((arm64.ARNG_D & 15) << 5)
|
||||||
|
a.Index = num
|
||||||
|
default:
|
||||||
|
return errors.New("unsupported simd register extension type: " + ext)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return errors.New("invalid register and extension combination")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ARM64RegisterArrangement parses an ARM64 vector register arrangement.
|
// ARM64RegisterArrangement constructs an ARM64 vector register arrangement.
|
||||||
func ARM64RegisterArrangement(reg int16, name, arng string) (int64, error) {
|
func ARM64RegisterArrangement(reg int16, name, arng string) (int64, error) {
|
||||||
var curQ, curSize uint16
|
var curQ, curSize uint16
|
||||||
if name[0] != 'V' {
|
if name[0] != 'V' {
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,14 @@ func (p *Parser) asmText(operands [][]lex.Token) {
|
||||||
next++
|
next++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Issue an error if we see a function defined as ABIInternal
|
||||||
|
// without NOSPLIT. In ABIInternal, obj needs to know the function
|
||||||
|
// signature in order to construct the morestack path, so this
|
||||||
|
// currently isn't supported for asm functions.
|
||||||
|
if nameAddr.Sym.ABI() == obj.ABIInternal && flag&obj.NOSPLIT == 0 {
|
||||||
|
p.errorf("TEXT %q: ABIInternal requires NOSPLIT", name)
|
||||||
|
}
|
||||||
|
|
||||||
// Next operand is the frame and arg size.
|
// Next operand is the frame and arg size.
|
||||||
// Bizarre syntax: $frameSize-argSize is two words, not subtraction.
|
// Bizarre syntax: $frameSize-argSize is two words, not subtraction.
|
||||||
// Both frameSize and argSize must be simple integers; only frameSize
|
// Both frameSize and argSize must be simple integers; only frameSize
|
||||||
|
|
@ -799,22 +807,11 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
||||||
p.errorf("can't handle %s instruction with 4 operands", op)
|
p.errorf("can't handle %s instruction with 4 operands", op)
|
||||||
return
|
return
|
||||||
case 5:
|
case 5:
|
||||||
if p.arch.Family == sys.PPC64 && arch.IsPPC64RLD(op) {
|
if p.arch.Family == sys.PPC64 {
|
||||||
// Always reg, reg, con, con, reg. (con, con is a 'mask').
|
|
||||||
prog.From = a[0]
|
prog.From = a[0]
|
||||||
|
// Second arg is always a register type on ppc64.
|
||||||
prog.Reg = p.getRegister(prog, op, &a[1])
|
prog.Reg = p.getRegister(prog, op, &a[1])
|
||||||
mask1 := p.getConstant(prog, op, &a[2])
|
prog.SetRestArgs([]obj.Addr{a[2], a[3]})
|
||||||
mask2 := p.getConstant(prog, op, &a[3])
|
|
||||||
var mask uint32
|
|
||||||
if mask1 < mask2 {
|
|
||||||
mask = (^uint32(0) >> uint(mask1)) & (^uint32(0) << uint(31-mask2))
|
|
||||||
} else {
|
|
||||||
mask = (^uint32(0) >> uint(mask2+1)) & (^uint32(0) << uint(31-(mask1-1)))
|
|
||||||
}
|
|
||||||
prog.SetFrom3(obj.Addr{
|
|
||||||
Type: obj.TYPE_CONST,
|
|
||||||
Offset: int64(mask),
|
|
||||||
})
|
|
||||||
prog.To = a[4]
|
prog.To = a[4]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"internal/buildcfg"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -19,7 +20,6 @@ import (
|
||||||
|
|
||||||
"cmd/asm/internal/lex"
|
"cmd/asm/internal/lex"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/objabi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// An end-to-end test for the assembler: Do we print what we parse?
|
// An end-to-end test for the assembler: Do we print what we parse?
|
||||||
|
|
@ -270,7 +270,7 @@ var (
|
||||||
errQuotesRE = regexp.MustCompile(`"([^"]*)"`)
|
errQuotesRE = regexp.MustCompile(`"([^"]*)"`)
|
||||||
)
|
)
|
||||||
|
|
||||||
func testErrors(t *testing.T, goarch, file string) {
|
func testErrors(t *testing.T, goarch, file string, flags ...string) {
|
||||||
input := filepath.Join("testdata", file+".s")
|
input := filepath.Join("testdata", file+".s")
|
||||||
architecture, ctxt := setArch(goarch)
|
architecture, ctxt := setArch(goarch)
|
||||||
lexer := lex.NewLexer(input)
|
lexer := lex.NewLexer(input)
|
||||||
|
|
@ -292,6 +292,14 @@ func testErrors(t *testing.T, goarch, file string) {
|
||||||
}
|
}
|
||||||
errBuf.WriteString(s)
|
errBuf.WriteString(s)
|
||||||
}
|
}
|
||||||
|
for _, flag := range flags {
|
||||||
|
switch flag {
|
||||||
|
case "dynlink":
|
||||||
|
ctxt.Flag_dynlink = true
|
||||||
|
default:
|
||||||
|
t.Errorf("unknown flag %s", flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
pList.Firstpc, ok = parser.Parse()
|
pList.Firstpc, ok = parser.Parse()
|
||||||
obj.Flushplist(ctxt, pList, nil, "")
|
obj.Flushplist(ctxt, pList, nil, "")
|
||||||
if ok && !failed {
|
if ok && !failed {
|
||||||
|
|
@ -360,10 +368,10 @@ func Test386EndToEnd(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestARMEndToEnd(t *testing.T) {
|
func TestARMEndToEnd(t *testing.T) {
|
||||||
defer func(old int) { objabi.GOARM = old }(objabi.GOARM)
|
defer func(old int) { buildcfg.GOARM = old }(buildcfg.GOARM)
|
||||||
for _, goarm := range []int{5, 6, 7} {
|
for _, goarm := range []int{5, 6, 7} {
|
||||||
t.Logf("GOARM=%d", goarm)
|
t.Logf("GOARM=%d", goarm)
|
||||||
objabi.GOARM = goarm
|
buildcfg.GOARM = goarm
|
||||||
testEndToEnd(t, "arm", "arm")
|
testEndToEnd(t, "arm", "arm")
|
||||||
if goarm == 6 {
|
if goarm == 6 {
|
||||||
testEndToEnd(t, "arm", "armv6")
|
testEndToEnd(t, "arm", "armv6")
|
||||||
|
|
@ -430,6 +438,10 @@ func TestAMD64Errors(t *testing.T) {
|
||||||
testErrors(t, "amd64", "amd64error")
|
testErrors(t, "amd64", "amd64error")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAMD64DynLinkErrors(t *testing.T) {
|
||||||
|
testErrors(t, "amd64", "amd64dynlinkerror", "dynlink")
|
||||||
|
}
|
||||||
|
|
||||||
func TestMIPSEndToEnd(t *testing.T) {
|
func TestMIPSEndToEnd(t *testing.T) {
|
||||||
testEndToEnd(t, "mips", "mips")
|
testEndToEnd(t, "mips", "mips")
|
||||||
testEndToEnd(t, "mips64", "mips64")
|
testEndToEnd(t, "mips64", "mips64")
|
||||||
|
|
@ -439,8 +451,12 @@ func TestPPC64EndToEnd(t *testing.T) {
|
||||||
testEndToEnd(t, "ppc64", "ppc64")
|
testEndToEnd(t, "ppc64", "ppc64")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRISCVEncoder(t *testing.T) {
|
func TestRISCVEndToEnd(t *testing.T) {
|
||||||
testEndToEnd(t, "riscv64", "riscvenc")
|
testEndToEnd(t, "riscv64", "riscv64")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRISCVErrors(t *testing.T) {
|
||||||
|
testErrors(t, "riscv64", "riscv64error")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestS390XEndToEnd(t *testing.T) {
|
func TestS390XEndToEnd(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,20 @@
|
||||||
package asm
|
package asm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"internal/buildcfg"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"cmd/asm/internal/arch"
|
"cmd/asm/internal/arch"
|
||||||
"cmd/asm/internal/lex"
|
"cmd/asm/internal/lex"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/objabi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// A simple in-out test: Do we print what we parse?
|
// A simple in-out test: Do we print what we parse?
|
||||||
|
|
||||||
func setArch(goarch string) (*arch.Arch, *obj.Link) {
|
func setArch(goarch string) (*arch.Arch, *obj.Link) {
|
||||||
objabi.GOOS = "linux" // obj can handle this OS for all architectures.
|
buildcfg.GOOS = "linux" // obj can handle this OS for all architectures.
|
||||||
objabi.GOARCH = goarch
|
buildcfg.GOARCH = goarch
|
||||||
architecture := arch.Set(goarch)
|
architecture := arch.Set(goarch)
|
||||||
if architecture == nil {
|
if architecture == nil {
|
||||||
panic("asm: unrecognized architecture " + goarch)
|
panic("asm: unrecognized architecture " + goarch)
|
||||||
|
|
|
||||||
|
|
@ -689,7 +689,11 @@ func (p *Parser) registerShift(name string, prefix rune) int64 {
|
||||||
p.errorf("unexpected %s in register shift", tok.String())
|
p.errorf("unexpected %s in register shift", tok.String())
|
||||||
}
|
}
|
||||||
if p.arch.Family == sys.ARM64 {
|
if p.arch.Family == sys.ARM64 {
|
||||||
return int64(r1&31)<<16 | int64(op)<<22 | int64(uint16(count))
|
off, err := arch.ARM64RegisterShift(r1, op, count)
|
||||||
|
if err != nil {
|
||||||
|
p.errorf(err.Error())
|
||||||
|
}
|
||||||
|
return off
|
||||||
} else {
|
} else {
|
||||||
return int64((r1 & 15) | op<<5 | count)
|
return int64((r1 & 15) | op<<5 | count)
|
||||||
}
|
}
|
||||||
|
|
@ -999,15 +1003,17 @@ func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) {
|
||||||
p.errorf("unimplemented two-register form")
|
p.errorf("unimplemented two-register form")
|
||||||
}
|
}
|
||||||
a.Index = r1
|
a.Index = r1
|
||||||
if scale == 0 && p.arch.Family == sys.ARM64 {
|
if scale != 0 && p.arch.Family == sys.ARM64 {
|
||||||
// scale is 1 by default for ARM64
|
p.errorf("arm64 doesn't support scaled register format")
|
||||||
a.Scale = 1
|
|
||||||
} else {
|
} else {
|
||||||
a.Scale = int16(scale)
|
a.Scale = int16(scale)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.get(')')
|
p.get(')')
|
||||||
} else if scale != 0 {
|
} else if scale != 0 {
|
||||||
|
if p.arch.Family == sys.ARM64 {
|
||||||
|
p.errorf("arm64 doesn't support scaled register format")
|
||||||
|
}
|
||||||
// First (R) was missing, all we have is (R*scale).
|
// First (R) was missing, all we have is (R*scale).
|
||||||
a.Reg = 0
|
a.Reg = 0
|
||||||
a.Index = r1
|
a.Index = r1
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,13 @@ func tokenize(s string) [][]lex.Token {
|
||||||
|
|
||||||
func TestErroneous(t *testing.T) {
|
func TestErroneous(t *testing.T) {
|
||||||
|
|
||||||
tests := []struct {
|
type errtest struct {
|
||||||
pseudo string
|
pseudo string
|
||||||
operands string
|
operands string
|
||||||
expected string
|
expected string
|
||||||
}{
|
}
|
||||||
|
|
||||||
|
nonRuntimeTests := []errtest{
|
||||||
{"TEXT", "", "expect two or three operands for TEXT"},
|
{"TEXT", "", "expect two or three operands for TEXT"},
|
||||||
{"TEXT", "%", "expect two or three operands for TEXT"},
|
{"TEXT", "%", "expect two or three operands for TEXT"},
|
||||||
{"TEXT", "1, 1", "TEXT symbol \"<erroneous symbol>\" must be a symbol(SB)"},
|
{"TEXT", "1, 1", "TEXT symbol \"<erroneous symbol>\" must be a symbol(SB)"},
|
||||||
|
|
@ -58,23 +60,44 @@ func TestErroneous(t *testing.T) {
|
||||||
{"PCDATA", "1", "expect two operands for PCDATA"},
|
{"PCDATA", "1", "expect two operands for PCDATA"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runtimeTests := []errtest{
|
||||||
|
{"TEXT", "foo<ABIInternal>(SB),0", "TEXT \"foo\": ABIInternal requires NOSPLIT"},
|
||||||
|
}
|
||||||
|
|
||||||
|
testcats := []struct {
|
||||||
|
compilingRuntime bool
|
||||||
|
tests []errtest
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
compilingRuntime: false,
|
||||||
|
tests: nonRuntimeTests,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
compilingRuntime: true,
|
||||||
|
tests: runtimeTests,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// Note these errors should be independent of the architecture.
|
// Note these errors should be independent of the architecture.
|
||||||
// Just run the test with amd64.
|
// Just run the test with amd64.
|
||||||
parser := newParser("amd64")
|
parser := newParser("amd64")
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
parser.errorWriter = &buf
|
parser.errorWriter = &buf
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, cat := range testcats {
|
||||||
parser.errorCount = 0
|
for _, test := range cat.tests {
|
||||||
parser.lineNum++
|
parser.compilingRuntime = cat.compilingRuntime
|
||||||
if !parser.pseudo(test.pseudo, tokenize(test.operands)) {
|
parser.errorCount = 0
|
||||||
t.Fatalf("Wrong pseudo-instruction: %s", test.pseudo)
|
parser.lineNum++
|
||||||
|
if !parser.pseudo(test.pseudo, tokenize(test.operands)) {
|
||||||
|
t.Fatalf("Wrong pseudo-instruction: %s", test.pseudo)
|
||||||
|
}
|
||||||
|
errorLine := buf.String()
|
||||||
|
if test.expected != errorLine {
|
||||||
|
t.Errorf("Unexpected error %q; expected %q", errorLine, test.expected)
|
||||||
|
}
|
||||||
|
buf.Reset()
|
||||||
}
|
}
|
||||||
errorLine := buf.String()
|
|
||||||
if test.expected != errorLine {
|
|
||||||
t.Errorf("Unexpected error %q; expected %q", errorLine, test.expected)
|
|
||||||
}
|
|
||||||
buf.Reset()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
68
src/cmd/asm/internal/asm/testdata/amd64dynlinkerror.s
vendored
Normal file
68
src/cmd/asm/internal/asm/testdata/amd64dynlinkerror.s
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Test to make sure that if we use R15 after it is clobbered by
|
||||||
|
// a global variable access while dynamic linking, we get an error.
|
||||||
|
// See issue 43661.
|
||||||
|
|
||||||
|
TEXT ·a1(SB), 0, $0-0
|
||||||
|
CMPL runtime·writeBarrier(SB), $0
|
||||||
|
MOVL $0, R15
|
||||||
|
RET
|
||||||
|
TEXT ·a2(SB), 0, $0-0
|
||||||
|
CMPL runtime·writeBarrier(SB), $0
|
||||||
|
MOVQ $0, R15
|
||||||
|
RET
|
||||||
|
TEXT ·a3(SB), 0, $0-0
|
||||||
|
CMPL runtime·writeBarrier(SB), $0
|
||||||
|
XORL R15, R15
|
||||||
|
RET
|
||||||
|
TEXT ·a4(SB), 0, $0-0
|
||||||
|
CMPL runtime·writeBarrier(SB), $0
|
||||||
|
XORQ R15, R15
|
||||||
|
RET
|
||||||
|
TEXT ·a5(SB), 0, $0-0
|
||||||
|
CMPL runtime·writeBarrier(SB), $0
|
||||||
|
XORL R15, R15
|
||||||
|
RET
|
||||||
|
TEXT ·a6(SB), 0, $0-0
|
||||||
|
CMPL runtime·writeBarrier(SB), $0
|
||||||
|
POPQ R15
|
||||||
|
PUSHQ R15
|
||||||
|
RET
|
||||||
|
TEXT ·a7(SB), 0, $0-0
|
||||||
|
CMPL runtime·writeBarrier(SB), $0
|
||||||
|
MOVQ R15, AX // ERROR "when dynamic linking, R15 is clobbered by a global variable access and is used here"
|
||||||
|
RET
|
||||||
|
TEXT ·a8(SB), 0, $0-0
|
||||||
|
CMPL runtime·writeBarrier(SB), $0
|
||||||
|
ADDQ AX, R15 // ERROR "when dynamic linking, R15 is clobbered by a global variable access and is used here"
|
||||||
|
RET
|
||||||
|
TEXT ·a9(SB), 0, $0-0
|
||||||
|
CMPL runtime·writeBarrier(SB), $0
|
||||||
|
ORQ R15, R15 // ERROR "when dynamic linking, R15 is clobbered by a global variable access and is used here"
|
||||||
|
RET
|
||||||
|
TEXT ·a10(SB), 0, $0-0
|
||||||
|
CMPL runtime·writeBarrier(SB), $0
|
||||||
|
JEQ one
|
||||||
|
ORQ R15, R15 // ERROR "when dynamic linking, R15 is clobbered by a global variable access and is used here"
|
||||||
|
one:
|
||||||
|
RET
|
||||||
|
TEXT ·a11(SB), 0, $0-0
|
||||||
|
CMPL runtime·writeBarrier(SB), $0
|
||||||
|
JEQ one
|
||||||
|
JMP two
|
||||||
|
one:
|
||||||
|
ORQ R15, R15 // ERROR "when dynamic linking, R15 is clobbered by a global variable access and is used here"
|
||||||
|
two:
|
||||||
|
RET
|
||||||
|
TEXT ·a12(SB), 0, $0-0
|
||||||
|
CMPL runtime·writeBarrier(SB), $0
|
||||||
|
JMP one
|
||||||
|
two:
|
||||||
|
ORQ R15, R15
|
||||||
|
RET
|
||||||
|
one:
|
||||||
|
MOVL $0, R15
|
||||||
|
JMP two
|
||||||
124
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
124
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
|
|
@ -64,6 +64,16 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
CMN R1.SXTX<<2, R10 // 5fe921ab
|
CMN R1.SXTX<<2, R10 // 5fe921ab
|
||||||
CMPW R2.UXTH<<3, R11 // 7f2d226b
|
CMPW R2.UXTH<<3, R11 // 7f2d226b
|
||||||
CMNW R1.SXTB, R9 // 3f81212b
|
CMNW R1.SXTB, R9 // 3f81212b
|
||||||
|
ADD R1<<1, RSP, R3 // e367218b
|
||||||
|
ADDW R1<<2, R3, RSP // 7f48210b
|
||||||
|
SUB R1<<3, RSP // ff6f21cb
|
||||||
|
SUBS R1<<4, RSP, R3 // e37321eb
|
||||||
|
ADDS R1<<1, RSP, R4 // e46721ab
|
||||||
|
CMP R1<<2, RSP // ff6b21eb
|
||||||
|
CMN R1<<3, RSP // ff6f21ab
|
||||||
|
ADDS R1<<1, ZR, R4 // e40701ab
|
||||||
|
ADD R3<<50, ZR, ZR // ffcb038b
|
||||||
|
CMP R4<<24, ZR // ff6304eb
|
||||||
CMPW $0x60060, R2 // CMPW $393312, R2 // 1b0c8052db00a0725f001b6b
|
CMPW $0x60060, R2 // CMPW $393312, R2 // 1b0c8052db00a0725f001b6b
|
||||||
CMPW $40960, R0 // 1f284071
|
CMPW $40960, R0 // 1f284071
|
||||||
CMPW $27745, R2 // 3b8c8d525f001b6b
|
CMPW $27745, R2 // 3b8c8d525f001b6b
|
||||||
|
|
@ -207,6 +217,18 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
VUADDW2 V9.B16, V12.H8, V14.H8 // 8e11296e
|
VUADDW2 V9.B16, V12.H8, V14.H8 // 8e11296e
|
||||||
VUADDW2 V13.H8, V20.S4, V30.S4 // 9e126d6e
|
VUADDW2 V13.H8, V20.S4, V30.S4 // 9e126d6e
|
||||||
VUADDW2 V21.S4, V24.D2, V29.D2 // 1d13b56e
|
VUADDW2 V21.S4, V24.D2, V29.D2 // 1d13b56e
|
||||||
|
VUMAX V3.B8, V2.B8, V1.B8 // 4164232e
|
||||||
|
VUMAX V3.B16, V2.B16, V1.B16 // 4164236e
|
||||||
|
VUMAX V3.H4, V2.H4, V1.H4 // 4164632e
|
||||||
|
VUMAX V3.H8, V2.H8, V1.H8 // 4164636e
|
||||||
|
VUMAX V3.S2, V2.S2, V1.S2 // 4164a32e
|
||||||
|
VUMAX V3.S4, V2.S4, V1.S4 // 4164a36e
|
||||||
|
VUMIN V3.B8, V2.B8, V1.B8 // 416c232e
|
||||||
|
VUMIN V3.B16, V2.B16, V1.B16 // 416c236e
|
||||||
|
VUMIN V3.H4, V2.H4, V1.H4 // 416c632e
|
||||||
|
VUMIN V3.H8, V2.H8, V1.H8 // 416c636e
|
||||||
|
VUMIN V3.S2, V2.S2, V1.S2 // 416ca32e
|
||||||
|
VUMIN V3.S4, V2.S4, V1.S4 // 416ca36e
|
||||||
FCCMPS LT, F1, F2, $1 // 41b4211e
|
FCCMPS LT, F1, F2, $1 // 41b4211e
|
||||||
FMADDS F1, F3, F2, F4 // 440c011f
|
FMADDS F1, F3, F2, F4 // 440c011f
|
||||||
FMADDD F4, F5, F4, F4 // 8414441f
|
FMADDD F4, F5, F4, F4 // 8414441f
|
||||||
|
|
@ -352,6 +374,9 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
MOVD $1, ZR
|
MOVD $1, ZR
|
||||||
MOVD $1, R1
|
MOVD $1, R1
|
||||||
MOVK $1, R1
|
MOVK $1, R1
|
||||||
|
MOVD $0x1000100010001000, RSP // MOVD $1152939097061330944, RSP // ff8304b2
|
||||||
|
MOVW $0x10001000, RSP // MOVW $268439552, RSP // ff830432
|
||||||
|
ADDW $0x10001000, R1 // ADDW $268439552, R1 // fb83043221001b0b
|
||||||
|
|
||||||
// move a large constant to a Vd.
|
// move a large constant to a Vd.
|
||||||
VMOVS $0x80402010, V11 // VMOVS $2151686160, V11
|
VMOVS $0x80402010, V11 // VMOVS $2151686160, V11
|
||||||
|
|
@ -380,13 +405,13 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
// LD1/ST1
|
// LD1/ST1
|
||||||
VLD1 (R8), [V1.B16, V2.B16] // 01a1404c
|
VLD1 (R8), [V1.B16, V2.B16] // 01a1404c
|
||||||
VLD1.P (R3), [V31.H8, V0.H8] // 7fa4df4c
|
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
|
VLD1.P (R8)(R20), [V21.B16, V22.B16] // 15a1d44c
|
||||||
VLD1.P 64(R1), [V5.B16, V6.B16, V7.B16, V8.B16] // 2520df4c
|
VLD1.P 64(R1), [V5.B16, V6.B16, V7.B16, V8.B16] // 2520df4c
|
||||||
VLD1.P 1(R0), V4.B[15] // 041cdf4d
|
VLD1.P 1(R0), V4.B[15] // 041cdf4d
|
||||||
VLD1.P 2(R0), V4.H[7] // 0458df4d
|
VLD1.P 2(R0), V4.H[7] // 0458df4d
|
||||||
VLD1.P 4(R0), V4.S[3] // 0490df4d
|
VLD1.P 4(R0), V4.S[3] // 0490df4d
|
||||||
VLD1.P 8(R0), V4.D[1] // 0484df4d
|
VLD1.P 8(R0), V4.D[1] // 0484df4d
|
||||||
VLD1.P (R0)(R1), V4.D[1] // VLD1.P (R0)(R1*1), V4.D[1] // 0484c14d
|
VLD1.P (R0)(R1), V4.D[1] // 0484c14d
|
||||||
VLD1 (R0), V4.D[1] // 0484404d
|
VLD1 (R0), V4.D[1] // 0484404d
|
||||||
VST1.P [V4.S4, V5.S4], 32(R1) // 24a89f4c
|
VST1.P [V4.S4, V5.S4], 32(R1) // 24a89f4c
|
||||||
VST1 [V0.S4, V1.S4], (R0) // 00a8004c
|
VST1 [V0.S4, V1.S4], (R0) // 00a8004c
|
||||||
|
|
@ -394,29 +419,29 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
VLD1.P 24(R30), [V3.S2,V4.S2,V5.S2] // c36bdf0c
|
VLD1.P 24(R30), [V3.S2,V4.S2,V5.S2] // c36bdf0c
|
||||||
VLD2 (R29), [V23.H8, V24.H8] // b787404c
|
VLD2 (R29), [V23.H8, V24.H8] // b787404c
|
||||||
VLD2.P 16(R0), [V18.B8, V19.B8] // 1280df0c
|
VLD2.P 16(R0), [V18.B8, V19.B8] // 1280df0c
|
||||||
VLD2.P (R1)(R2), [V15.S2, V16.S2] // VLD2.P (R1)(R2*1), [V15.S2,V16.S2] // 2f88c20c
|
VLD2.P (R1)(R2), [V15.S2, V16.S2] // 2f88c20c
|
||||||
VLD3 (R27), [V11.S4, V12.S4, V13.S4] // 6b4b404c
|
VLD3 (R27), [V11.S4, V12.S4, V13.S4] // 6b4b404c
|
||||||
VLD3.P 48(RSP), [V11.S4, V12.S4, V13.S4] // eb4bdf4c
|
VLD3.P 48(RSP), [V11.S4, V12.S4, V13.S4] // eb4bdf4c
|
||||||
VLD3.P (R30)(R2), [V14.D2, V15.D2, V16.D2] // VLD3.P (R30)(R2*1), [V14.D2,V15.D2,V16.D2] // ce4fc24c
|
VLD3.P (R30)(R2), [V14.D2, V15.D2, V16.D2] // ce4fc24c
|
||||||
VLD4 (R15), [V10.H4, V11.H4, V12.H4, V13.H4] // ea05400c
|
VLD4 (R15), [V10.H4, V11.H4, V12.H4, V13.H4] // ea05400c
|
||||||
VLD4.P 32(R24), [V31.B8, V0.B8, V1.B8, V2.B8] // 1f03df0c
|
VLD4.P 32(R24), [V31.B8, V0.B8, V1.B8, V2.B8] // 1f03df0c
|
||||||
VLD4.P (R13)(R9), [V14.S2, V15.S2, V16.S2, V17.S2] // VLD4.P (R13)(R9*1), [V14.S2,V15.S2,V16.S2,V17.S2] // ae09c90c
|
VLD4.P (R13)(R9), [V14.S2, V15.S2, V16.S2, V17.S2] // ae09c90c
|
||||||
VLD1R (R1), [V9.B8] // 29c0400d
|
VLD1R (R1), [V9.B8] // 29c0400d
|
||||||
VLD1R.P (R1), [V9.B8] // 29c0df0d
|
VLD1R.P (R1), [V9.B8] // 29c0df0d
|
||||||
VLD1R.P 1(R1), [V2.B8] // 22c0df0d
|
VLD1R.P 1(R1), [V2.B8] // 22c0df0d
|
||||||
VLD1R.P 2(R1), [V2.H4] // 22c4df0d
|
VLD1R.P 2(R1), [V2.H4] // 22c4df0d
|
||||||
VLD1R (R0), [V0.B16] // 00c0404d
|
VLD1R (R0), [V0.B16] // 00c0404d
|
||||||
VLD1R.P (R0), [V0.B16] // 00c0df4d
|
VLD1R.P (R0), [V0.B16] // 00c0df4d
|
||||||
VLD1R.P (R15)(R1), [V15.H4] // VLD1R.P (R15)(R1*1), [V15.H4] // efc5c10d
|
VLD1R.P (R15)(R1), [V15.H4] // efc5c10d
|
||||||
VLD2R (R15), [V15.H4, V16.H4] // efc5600d
|
VLD2R (R15), [V15.H4, V16.H4] // efc5600d
|
||||||
VLD2R.P 16(R0), [V0.D2, V1.D2] // 00ccff4d
|
VLD2R.P 16(R0), [V0.D2, V1.D2] // 00ccff4d
|
||||||
VLD2R.P (R0)(R5), [V31.D1, V0.D1] // VLD2R.P (R0)(R5*1), [V31.D1, V0.D1] // 1fcce50d
|
VLD2R.P (R0)(R5), [V31.D1, V0.D1] // 1fcce50d
|
||||||
VLD3R (RSP), [V31.S2, V0.S2, V1.S2] // ffeb400d
|
VLD3R (RSP), [V31.S2, V0.S2, V1.S2] // ffeb400d
|
||||||
VLD3R.P 6(R15), [V15.H4, V16.H4, V17.H4] // efe5df0d
|
VLD3R.P 6(R15), [V15.H4, V16.H4, V17.H4] // efe5df0d
|
||||||
VLD3R.P (R15)(R6), [V15.H8, V16.H8, V17.H8] // VLD3R.P (R15)(R6*1), [V15.H8, V16.H8, V17.H8] // efe5c64d
|
VLD3R.P (R15)(R6), [V15.H8, V16.H8, V17.H8] // efe5c64d
|
||||||
VLD4R (R0), [V0.B8, V1.B8, V2.B8, V3.B8] // 00e0600d
|
VLD4R (R0), [V0.B8, V1.B8, V2.B8, V3.B8] // 00e0600d
|
||||||
VLD4R.P 16(RSP), [V31.S4, V0.S4, V1.S4, V2.S4] // ffebff4d
|
VLD4R.P 16(RSP), [V31.S4, V0.S4, V1.S4, V2.S4] // ffebff4d
|
||||||
VLD4R.P (R15)(R9), [V15.H4, V16.H4, V17.H4, V18.H4] // VLD4R.P (R15)(R9*1), [V15.H4, V16.H4, V17.H4, V18.H4] // efe5e90d
|
VLD4R.P (R15)(R9), [V15.H4, V16.H4, V17.H4, V18.H4] // efe5e90d
|
||||||
VST1.P [V24.S2], 8(R2) // 58789f0c
|
VST1.P [V24.S2], 8(R2) // 58789f0c
|
||||||
VST1 [V29.S2, V30.S2], (R29) // bdab000c
|
VST1 [V29.S2, V30.S2], (R29) // bdab000c
|
||||||
VST1 [V14.H4, V15.H4, V16.H4], (R27) // 6e67000c
|
VST1 [V14.H4, V15.H4, V16.H4], (R27) // 6e67000c
|
||||||
|
|
@ -424,17 +449,17 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
VST1.P V4.H[7], 2(R0) // 04589f4d
|
VST1.P V4.H[7], 2(R0) // 04589f4d
|
||||||
VST1.P V4.S[3], 4(R0) // 04909f4d
|
VST1.P V4.S[3], 4(R0) // 04909f4d
|
||||||
VST1.P V4.D[1], 8(R0) // 04849f4d
|
VST1.P V4.D[1], 8(R0) // 04849f4d
|
||||||
VST1.P V4.D[1], (R0)(R1) // VST1.P V4.D[1], (R0)(R1*1) // 0484814d
|
VST1.P V4.D[1], (R0)(R1) // 0484814d
|
||||||
VST1 V4.D[1], (R0) // 0484004d
|
VST1 V4.D[1], (R0) // 0484004d
|
||||||
VST2 [V22.H8, V23.H8], (R23) // f686004c
|
VST2 [V22.H8, V23.H8], (R23) // f686004c
|
||||||
VST2.P [V14.H4, V15.H4], 16(R17) // 2e869f0c
|
VST2.P [V14.H4, V15.H4], 16(R17) // 2e869f0c
|
||||||
VST2.P [V14.H4, V15.H4], (R3)(R17) // VST2.P [V14.H4,V15.H4], (R3)(R17*1) // 6e84910c
|
VST2.P [V14.H4, V15.H4], (R3)(R17) // 6e84910c
|
||||||
VST3 [V1.D2, V2.D2, V3.D2], (R11) // 614d004c
|
VST3 [V1.D2, V2.D2, V3.D2], (R11) // 614d004c
|
||||||
VST3.P [V18.S4, V19.S4, V20.S4], 48(R25) // 324b9f4c
|
VST3.P [V18.S4, V19.S4, V20.S4], 48(R25) // 324b9f4c
|
||||||
VST3.P [V19.B8, V20.B8, V21.B8], (R3)(R7) // VST3.P [V19.B8, V20.B8, V21.B8], (R3)(R7*1) // 7340870c
|
VST3.P [V19.B8, V20.B8, V21.B8], (R3)(R7) // 7340870c
|
||||||
VST4 [V22.D2, V23.D2, V24.D2, V25.D2], (R3) // 760c004c
|
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 [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
|
VST4.P [V24.B8, V25.B8, V26.B8, V27.B8], (R3)(R23) // 7800970c
|
||||||
|
|
||||||
// pre/post-indexed
|
// pre/post-indexed
|
||||||
FMOVS.P F20, 4(R0) // 144400bc
|
FMOVS.P F20, 4(R0) // 144400bc
|
||||||
|
|
@ -521,29 +546,29 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
|
|
||||||
// shifted or extended register offset.
|
// shifted or extended register offset.
|
||||||
MOVD (R2)(R6.SXTW), R4 // 44c866f8
|
MOVD (R2)(R6.SXTW), R4 // 44c866f8
|
||||||
MOVD (R3)(R6), R5 // MOVD (R3)(R6*1), R5 // 656866f8
|
MOVD (R3)(R6), R5 // 656866f8
|
||||||
MOVD (R2)(R6), R4 // MOVD (R2)(R6*1), R4 // 446866f8
|
MOVD (R2)(R6), R4 // 446866f8
|
||||||
MOVWU (R19)(R20<<2), R20 // 747a74b8
|
MOVWU (R19)(R20<<2), R20 // 747a74b8
|
||||||
MOVD (R2)(R6<<3), R4 // 447866f8
|
MOVD (R2)(R6<<3), R4 // 447866f8
|
||||||
MOVD (R3)(R7.SXTX<<3), R8 // 68f867f8
|
MOVD (R3)(R7.SXTX<<3), R8 // 68f867f8
|
||||||
MOVWU (R5)(R4.UXTW), R10 // aa4864b8
|
MOVWU (R5)(R4.UXTW), R10 // aa4864b8
|
||||||
MOVBU (R3)(R9.UXTW), R8 // 68486938
|
MOVBU (R3)(R9.UXTW), R8 // 68486938
|
||||||
MOVBU (R5)(R8), R10 // MOVBU (R5)(R8*1), R10 // aa686838
|
MOVBU (R5)(R8), R10 // aa686838
|
||||||
MOVHU (R2)(R7.SXTW<<1), R11 // 4bd86778
|
MOVHU (R2)(R7.SXTW<<1), R11 // 4bd86778
|
||||||
MOVHU (R1)(R2<<1), R5 // 25786278
|
MOVHU (R1)(R2<<1), R5 // 25786278
|
||||||
MOVB (R9)(R3.UXTW), R6 // 2649a338
|
MOVB (R9)(R3.UXTW), R6 // 2649a338
|
||||||
MOVB (R10)(R6), R15 // MOVB (R10)(R6*1), R15 // 4f69a638
|
MOVB (R10)(R6), R15 // 4f69a638
|
||||||
MOVB (R29)(R30<<0), R14 // ae7bbe38
|
MOVB (R29)(R30<<0), R14 // ae7bbe38
|
||||||
MOVB (R29)(R30), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38
|
MOVB (R29)(R30), R14 // ae6bbe38
|
||||||
MOVH (R5)(R7.SXTX<<1), R19 // b3f8a778
|
MOVH (R5)(R7.SXTX<<1), R19 // b3f8a778
|
||||||
MOVH (R8)(R4<<1), R10 // 0a79a478
|
MOVH (R8)(R4<<1), R10 // 0a79a478
|
||||||
MOVW (R9)(R8.SXTW<<2), R19 // 33d9a8b8
|
MOVW (R9)(R8.SXTW<<2), R19 // 33d9a8b8
|
||||||
MOVW (R1)(R4.SXTX), R11 // 2be8a4b8
|
MOVW (R1)(R4.SXTX), R11 // 2be8a4b8
|
||||||
MOVW (R1)(R4.SXTX), ZR // 3fe8a4b8
|
MOVW (R1)(R4.SXTX), ZR // 3fe8a4b8
|
||||||
MOVW (R2)(R5), R12 // MOVW (R2)(R5*1), R12 // 4c68a5b8
|
MOVW (R2)(R5), R12 // 4c68a5b8
|
||||||
FMOVS (R2)(R6), F4 // FMOVS (R2)(R6*1), F4 // 446866bc
|
FMOVS (R2)(R6), F4 // 446866bc
|
||||||
FMOVS (R2)(R6<<2), F4 // 447866bc
|
FMOVS (R2)(R6<<2), F4 // 447866bc
|
||||||
FMOVD (R2)(R6), F4 // FMOVD (R2)(R6*1), F4 // 446866fc
|
FMOVD (R2)(R6), F4 // 446866fc
|
||||||
FMOVD (R2)(R6<<3), F4 // 447866fc
|
FMOVD (R2)(R6<<3), F4 // 447866fc
|
||||||
|
|
||||||
MOVD R5, (R2)(R6<<3) // 457826f8
|
MOVD R5, (R2)(R6<<3) // 457826f8
|
||||||
|
|
@ -553,15 +578,15 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
MOVW R7, (R3)(R4.SXTW) // 67c824b8
|
MOVW R7, (R3)(R4.SXTW) // 67c824b8
|
||||||
MOVB R4, (R2)(R6.SXTX) // 44e82638
|
MOVB R4, (R2)(R6.SXTX) // 44e82638
|
||||||
MOVB R8, (R3)(R9.UXTW) // 68482938
|
MOVB R8, (R3)(R9.UXTW) // 68482938
|
||||||
MOVB R10, (R5)(R8) // MOVB R10, (R5)(R8*1) // aa682838
|
MOVB R10, (R5)(R8) // aa682838
|
||||||
MOVH R11, (R2)(R7.SXTW<<1) // 4bd82778
|
MOVH R11, (R2)(R7.SXTW<<1) // 4bd82778
|
||||||
MOVH R5, (R1)(R2<<1) // 25782278
|
MOVH R5, (R1)(R2<<1) // 25782278
|
||||||
MOVH R7, (R2)(R5.SXTX<<1) // 47f82578
|
MOVH R7, (R2)(R5.SXTX<<1) // 47f82578
|
||||||
MOVH R8, (R3)(R6.UXTW) // 68482678
|
MOVH R8, (R3)(R6.UXTW) // 68482678
|
||||||
MOVB R4, (R2)(R6.SXTX) // 44e82638
|
MOVB R4, (R2)(R6.SXTX) // 44e82638
|
||||||
FMOVS F4, (R2)(R6) // FMOVS F4, (R2)(R6*1) // 446826bc
|
FMOVS F4, (R2)(R6) // 446826bc
|
||||||
FMOVS F4, (R2)(R6<<2) // 447826bc
|
FMOVS F4, (R2)(R6<<2) // 447826bc
|
||||||
FMOVD F4, (R2)(R6) // FMOVD F4, (R2)(R6*1) // 446826fc
|
FMOVD F4, (R2)(R6) // 446826fc
|
||||||
FMOVD F4, (R2)(R6<<3) // 447826fc
|
FMOVD F4, (R2)(R6<<3) // 447826fc
|
||||||
|
|
||||||
// vmov
|
// vmov
|
||||||
|
|
@ -571,9 +596,12 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
||||||
VMOV R20, V1.S[0] // 811e044e
|
VMOV R20, V1.S[0] // 811e044e
|
||||||
VMOV R20, V1.S[1] // 811e0c4e
|
VMOV R20, V1.S[1] // 811e0c4e
|
||||||
VMOV R1, V9.H4 // 290c020e
|
VMOV R1, V9.H4 // 290c020e
|
||||||
|
VDUP R1, V9.H4 // 290c020e
|
||||||
VMOV R22, V11.D2 // cb0e084e
|
VMOV R22, V11.D2 // cb0e084e
|
||||||
|
VDUP R22, V11.D2 // cb0e084e
|
||||||
VMOV V2.B16, V4.B16 // 441ca24e
|
VMOV V2.B16, V4.B16 // 441ca24e
|
||||||
VMOV V20.S[0], V20 // 9406045e
|
VMOV V20.S[0], V20 // 9406045e
|
||||||
|
VDUP V20.S[0], V20 // 9406045e
|
||||||
VMOV V12.D[0], V12.D[1] // 8c05186e
|
VMOV V12.D[0], V12.D[1] // 8c05186e
|
||||||
VMOV V10.S[0], V12.S[1] // 4c050c6e
|
VMOV V10.S[0], V12.S[1] // 4c050c6e
|
||||||
VMOV V9.H[0], V12.H[1] // 2c05066e
|
VMOV V9.H[0], V12.H[1] // 2c05066e
|
||||||
|
|
@ -982,6 +1010,54 @@ again:
|
||||||
FSTPS (F3, F4), x(SB)
|
FSTPS (F3, F4), x(SB)
|
||||||
FSTPS (F3, F4), x+8(SB)
|
FSTPS (F3, F4), x+8(SB)
|
||||||
|
|
||||||
|
// FLDPQ/FSTPQ
|
||||||
|
FLDPQ -4000(R0), (F1, F2) // 1b803ed1610b40ad
|
||||||
|
FLDPQ -1024(R0), (F1, F2) // 010860ad
|
||||||
|
FLDPQ (R0), (F1, F2) // 010840ad
|
||||||
|
FLDPQ 16(R0), (F1, F2) // 018840ad
|
||||||
|
FLDPQ -16(R0), (F1, F2) // 01887fad
|
||||||
|
FLDPQ.W 32(R0), (F1, F2) // 0108c1ad
|
||||||
|
FLDPQ.P 32(R0), (F1, F2) // 0108c1ac
|
||||||
|
FLDPQ 11(R0), (F1, F2) // 1b2c0091610b40ad
|
||||||
|
FLDPQ 1024(R0), (F1, F2) // 1b001091610b40ad
|
||||||
|
FLDPQ 4104(R0), (F1, F2)
|
||||||
|
FLDPQ -4000(RSP), (F1, F2) // fb833ed1610b40ad
|
||||||
|
FLDPQ -1024(RSP), (F1, F2) // e10b60ad
|
||||||
|
FLDPQ (RSP), (F1, F2) // e10b40ad
|
||||||
|
FLDPQ 16(RSP), (F1, F2) // e18b40ad
|
||||||
|
FLDPQ -16(RSP), (F1, F2) // e18b7fad
|
||||||
|
FLDPQ.W 32(RSP), (F1, F2) // e10bc1ad
|
||||||
|
FLDPQ.P 32(RSP), (F1, F2) // e10bc1ac
|
||||||
|
FLDPQ 11(RSP), (F1, F2) // fb2f0091610b40ad
|
||||||
|
FLDPQ 1024(RSP), (F1, F2) // fb031091610b40ad
|
||||||
|
FLDPQ 4104(RSP), (F1, F2)
|
||||||
|
FLDPQ -31(R0), (F1, F2) // 1b7c00d1610b40ad
|
||||||
|
FLDPQ -4(R0), (F1, F2) // 1b1000d1610b40ad
|
||||||
|
FLDPQ x(SB), (F1, F2)
|
||||||
|
FLDPQ x+8(SB), (F1, F2)
|
||||||
|
FSTPQ (F3, F4), -4000(R5) // bb803ed1631300ad
|
||||||
|
FSTPQ (F3, F4), -1024(R5) // a31020ad
|
||||||
|
FSTPQ (F3, F4), (R5) // a31000ad
|
||||||
|
FSTPQ (F3, F4), 16(R5) // a39000ad
|
||||||
|
FSTPQ (F3, F4), -16(R5) // a3903fad
|
||||||
|
FSTPQ.W (F3, F4), 32(R5) // a31081ad
|
||||||
|
FSTPQ.P (F3, F4), 32(R5) // a31081ac
|
||||||
|
FSTPQ (F3, F4), 11(R5) // bb2c0091631300ad
|
||||||
|
FSTPQ (F3, F4), 1024(R5) // bb001091631300ad
|
||||||
|
FSTPQ (F3, F4), 4104(R5)
|
||||||
|
FSTPQ (F3, F4), -4000(RSP) // fb833ed1631300ad
|
||||||
|
FSTPQ (F3, F4), -1024(RSP) // e31320ad
|
||||||
|
FSTPQ (F3, F4), (RSP) // e31300ad
|
||||||
|
FSTPQ (F3, F4), 16(RSP) // e39300ad
|
||||||
|
FSTPQ (F3, F4), -16(RSP) // e3933fad
|
||||||
|
FSTPQ.W (F3, F4), 32(RSP) // e31381ad
|
||||||
|
FSTPQ.P (F3, F4), 32(RSP) // e31381ac
|
||||||
|
FSTPQ (F3, F4), 11(RSP) // fb2f0091631300ad
|
||||||
|
FSTPQ (F3, F4), 1024(RSP) // fb031091631300ad
|
||||||
|
FSTPQ (F3, F4), 4104(RSP)
|
||||||
|
FSTPQ (F3, F4), x(SB)
|
||||||
|
FSTPQ (F3, F4), x+8(SB)
|
||||||
|
|
||||||
// System Register
|
// System Register
|
||||||
MSR $1, SPSel // bf4100d5
|
MSR $1, SPSel // bf4100d5
|
||||||
MSR $9, DAIFSet // df4903d5
|
MSR $9, DAIFSet // df4903d5
|
||||||
|
|
|
||||||
46
src/cmd/asm/internal/asm/testdata/arm64enc.s
vendored
46
src/cmd/asm/internal/asm/testdata/arm64enc.s
vendored
|
|
@ -188,7 +188,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
MOVBU 2916(R24), R3 // 03936d39
|
MOVBU 2916(R24), R3 // 03936d39
|
||||||
MOVBU (R19)(R14<<0), R23 // 777a6e38
|
MOVBU (R19)(R14<<0), R23 // 777a6e38
|
||||||
MOVBU (R2)(R8.SXTX), R19 // 53e86838
|
MOVBU (R2)(R8.SXTX), R19 // 53e86838
|
||||||
MOVBU (R27)(R23), R14 // MOVBU (R27)(R23*1), R14 // 6e6b7738
|
MOVBU (R27)(R23), R14 // 6e6b7738
|
||||||
MOVHU.P 107(R14), R13 // cdb54678
|
MOVHU.P 107(R14), R13 // cdb54678
|
||||||
MOVHU.W 192(R3), R2 // 620c4c78
|
MOVHU.W 192(R3), R2 // 620c4c78
|
||||||
MOVHU 6844(R4), R19 // 93787579
|
MOVHU 6844(R4), R19 // 93787579
|
||||||
|
|
@ -201,9 +201,9 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
MOVB 997(R9), R23 // 37958f39
|
MOVB 997(R9), R23 // 37958f39
|
||||||
//TODO MOVBW (R2<<1)(R21), R15 // af7ae238
|
//TODO MOVBW (R2<<1)(R21), R15 // af7ae238
|
||||||
//TODO MOVBW (R26)(R0), R21 // 1568fa38
|
//TODO MOVBW (R26)(R0), R21 // 1568fa38
|
||||||
MOVB (R5)(R15), R16 // MOVB (R5)(R15*1), R16 // b068af38
|
MOVB (R5)(R15), R16 // b068af38
|
||||||
MOVB (R19)(R26.SXTW), R19 // 73caba38
|
MOVB (R19)(R26.SXTW), R19 // 73caba38
|
||||||
MOVB (R29)(R30), R14 // MOVB (R29)(R30*1), R14 // ae6bbe38
|
MOVB (R29)(R30), R14 // ae6bbe38
|
||||||
//TODO MOVHW.P 218(R22), R25 // d9a6cd78
|
//TODO MOVHW.P 218(R22), R25 // d9a6cd78
|
||||||
MOVH.P 179(R23), R5 // e5368b78
|
MOVH.P 179(R23), R5 // e5368b78
|
||||||
//TODO MOVHW.W 136(R2), R27 // 5b8cc878
|
//TODO MOVHW.W 136(R2), R27 // 5b8cc878
|
||||||
|
|
@ -357,12 +357,12 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
MOVD R25, -137(R17) // 397217f8
|
MOVD R25, -137(R17) // 397217f8
|
||||||
MOVW R4, (R12)(R22.UXTW<<2) // 845936b8
|
MOVW R4, (R12)(R22.UXTW<<2) // 845936b8
|
||||||
MOVD R27, (R5)(R15.UXTW<<3) // bb582ff8
|
MOVD R27, (R5)(R15.UXTW<<3) // bb582ff8
|
||||||
MOVB R2, (R10)(R16) // MOVB R2, (R10)(R16*1) // 42693038
|
MOVB R2, (R10)(R16) // 42693038
|
||||||
MOVB R2, (R29)(R26) // MOVB R2, (R29)(R26*1) // a26b3a38
|
MOVB R2, (R29)(R26) // a26b3a38
|
||||||
MOVH R11, -80(R23) // eb021b78
|
MOVH R11, -80(R23) // eb021b78
|
||||||
MOVH R11, (R27)(R14.SXTW<<1) // 6bdb2e78
|
MOVH R11, (R27)(R14.SXTW<<1) // 6bdb2e78
|
||||||
MOVB R19, (R0)(R4) // MOVB R19, (R0)(R4*1) // 13682438
|
MOVB R19, (R0)(R4) // 13682438
|
||||||
MOVB R1, (R6)(R4) // MOVB R1, (R6)(R4*1) // c1682438
|
MOVB R1, (R6)(R4) // c1682438
|
||||||
MOVH R3, (R11)(R13<<1) // 63792d78
|
MOVH R3, (R11)(R13<<1) // 63792d78
|
||||||
//TODO STTR 55(R4), R29 // 9d7803b8
|
//TODO STTR 55(R4), R29 // 9d7803b8
|
||||||
//TODO STTR 124(R5), R25 // b9c807f8
|
//TODO STTR 124(R5), R25 // b9c807f8
|
||||||
|
|
@ -669,6 +669,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
VCMEQ V24.S4, V13.S4, V12.S4 // ac8db86e
|
VCMEQ V24.S4, V13.S4, V12.S4 // ac8db86e
|
||||||
VCNT V13.B8, V11.B8 // ab59200e
|
VCNT V13.B8, V11.B8 // ab59200e
|
||||||
VMOV V31.B[15], V18 // f2071f5e
|
VMOV V31.B[15], V18 // f2071f5e
|
||||||
|
VDUP V31.B[15], V18 // f2071f5e
|
||||||
VDUP V31.B[13], V20.B16 // f4071b4e
|
VDUP V31.B[13], V20.B16 // f4071b4e
|
||||||
VEOR V4.B8, V18.B8, V7.B8 // 471e242e
|
VEOR V4.B8, V18.B8, V7.B8 // 471e242e
|
||||||
VEXT $4, V2.B8, V1.B8, V3.B8 // 2320022e
|
VEXT $4, V2.B8, V1.B8, V3.B8 // 2320022e
|
||||||
|
|
@ -679,27 +680,28 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
VLD1 (R24), [V18.D1, V19.D1, V20.D1] // 126f400c
|
VLD1 (R24), [V18.D1, V19.D1, V20.D1] // 126f400c
|
||||||
VLD1 (R29), [V14.D1, V15.D1, V16.D1, V17.D1] // ae2f400c
|
VLD1 (R29), [V14.D1, V15.D1, V16.D1, V17.D1] // ae2f400c
|
||||||
VLD1.P 16(R23), [V1.B16] // e172df4c
|
VLD1.P 16(R23), [V1.B16] // e172df4c
|
||||||
VLD1.P (R6)(R11), [V31.D1] // VLD1.P (R6)(R11*1), [V31.D1] // df7ccb0c
|
VLD1.P (R6)(R11), [V31.D1] // df7ccb0c
|
||||||
VLD1.P 16(R7), [V31.D1, V0.D1] // ffacdf0c
|
VLD1.P 16(R7), [V31.D1, V0.D1] // ffacdf0c
|
||||||
VLD1.P (R19)(R4), [V24.B8, V25.B8] // VLD1.P (R19)(R4*1), [V24.B8, V25.B8] // 78a2c40c
|
VLD1.P (R19)(R4), [V24.B8, V25.B8] // 78a2c40c
|
||||||
VLD1.P (R20)(R8), [V7.H8, V8.H8, V9.H8] // VLD1.P (R20)(R8*1), [V7.H8, V8.H8, V9.H8] // 8766c84c
|
VLD1.P (R20)(R8), [V7.H8, V8.H8, V9.H8] // 8766c84c
|
||||||
VLD1.P 32(R30), [V5.B8, V6.B8, V7.B8, V8.B8] // c523df0c
|
VLD1.P 32(R30), [V5.B8, V6.B8, V7.B8, V8.B8] // c523df0c
|
||||||
VLD1 (R19), V14.B[15] // 6e1e404d
|
VLD1 (R19), V14.B[15] // 6e1e404d
|
||||||
VLD1 (R29), V0.H[1] // a04b400d
|
VLD1 (R29), V0.H[1] // a04b400d
|
||||||
VLD1 (R27), V2.S[0] // 6283400d
|
VLD1 (R27), V2.S[0] // 6283400d
|
||||||
VLD1 (R21), V5.D[1] // a586404d
|
VLD1 (R21), V5.D[1] // a586404d
|
||||||
VLD1.P 1(R19), V10.B[14] // 6a1adf4d
|
VLD1.P 1(R19), V10.B[14] // 6a1adf4d
|
||||||
VLD1.P (R3)(R14), V16.B[11] // VLD1.P (R3)(R14*1), V16.B[11] // 700cce4d
|
VLD1.P (R3)(R14), V16.B[11] // 700cce4d
|
||||||
VLD1.P 2(R1), V28.H[2] // 3c50df0d
|
VLD1.P 2(R1), V28.H[2] // 3c50df0d
|
||||||
VLD1.P (R13)(R20), V9.H[2] // VLD1.P (R13)(R20*1), V9.H[2] // a951d40d
|
VLD1.P (R13)(R20), V9.H[2] // a951d40d
|
||||||
VLD1.P 4(R17), V1.S[3] // 2192df4d
|
VLD1.P 4(R17), V1.S[3] // 2192df4d
|
||||||
VLD1.P (R14)(R2), V17.S[2] // VLD1.P (R14)(R2*1), V17.S[2] // d181c24d
|
VLD1.P (R14)(R2), V17.S[2] // d181c24d
|
||||||
VLD1.P 8(R5), V30.D[1] // be84df4d
|
VLD1.P 8(R5), V30.D[1] // be84df4d
|
||||||
VLD1.P (R27)(R13), V27.D[0] // VLD1.P (R27)(R13*1), V27.D[0] // 7b87cd0d
|
VLD1.P (R27)(R13), V27.D[0] // 7b87cd0d
|
||||||
//TODO FMOVS.P -29(RSP), F8 // e8375ebc
|
//TODO FMOVS.P -29(RSP), F8 // e8375ebc
|
||||||
//TODO FMOVS.W 71(R29), F28 // bc7f44bc
|
//TODO FMOVS.W 71(R29), F28 // bc7f44bc
|
||||||
FMOVS 6160(R4), F23 // 971058bd
|
FMOVS 6160(R4), F23 // 971058bd
|
||||||
VMOV V18.B[10], V27 // 5b06155e
|
VMOV V18.B[10], V27 // 5b06155e
|
||||||
|
VDUP V18.B[10], V27 // 5b06155e
|
||||||
VMOV V12.B[2], V28.B[12] // 9c15196e
|
VMOV V12.B[2], V28.B[12] // 9c15196e
|
||||||
VMOV R30, V4.B[13] // c41f1b4e
|
VMOV R30, V4.B[13] // c41f1b4e
|
||||||
VMOV V2.B16, V4.B16 // 441ca24e
|
VMOV V2.B16, V4.B16 // 441ca24e
|
||||||
|
|
@ -732,25 +734,25 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
|
||||||
VSHL $7, V22.D2, V25.D2 // d956474f
|
VSHL $7, V22.D2, V25.D2 // d956474f
|
||||||
VST1 [V14.H4, V15.H4, V16.H4], (R27) // 6e67000c
|
VST1 [V14.H4, V15.H4, V16.H4], (R27) // 6e67000c
|
||||||
VST1 [V2.S4, V3.S4, V4.S4, V5.S4], (R14) // c229004c
|
VST1 [V2.S4, V3.S4, V4.S4, V5.S4], (R14) // c229004c
|
||||||
VST1.P [V25.S4], (R7)(R29) // VST1.P [V25.S4], (R7)(R29*1) // f9789d4c
|
VST1.P [V25.S4], (R7)(R29) // f9789d4c
|
||||||
VST1.P [V25.D2, V26.D2], 32(R7) // f9ac9f4c
|
VST1.P [V25.D2, V26.D2], 32(R7) // f9ac9f4c
|
||||||
VST1.P [V14.D1, V15.D1], (R7)(R23) // VST1.P [V14.D1, V15.D1], (R7)(R23*1) // eeac970c
|
VST1.P [V14.D1, V15.D1], (R7)(R23) // eeac970c
|
||||||
VST1.P [V25.D2, V26.D2, V27.D2], 48(R27) // 796f9f4c
|
VST1.P [V25.D2, V26.D2, V27.D2], 48(R27) // 796f9f4c
|
||||||
VST1.P [V13.H8, V14.H8, V15.H8], (R3)(R14) // VST1.P [V13.H8, V14.H8, V15.H8], (R3)(R14*1) // 6d648e4c
|
VST1.P [V13.H8, V14.H8, V15.H8], (R3)(R14) // 6d648e4c
|
||||||
VST1.P [V16.S4, V17.S4, V18.S4, V19.S4], 64(R6) // d0289f4c
|
VST1.P [V16.S4, V17.S4, V18.S4, V19.S4], 64(R6) // d0289f4c
|
||||||
VST1.P [V19.H4, V20.H4, V21.H4, V22.H4], (R4)(R16) // VST1.P [V19.H4, V20.H4, V21.H4, V22.H4], (R4)(R16*1) // 9324900c
|
VST1.P [V19.H4, V20.H4, V21.H4, V22.H4], (R4)(R16) // 9324900c
|
||||||
VST1 V12.B[3], (R1) // 2c0c000d
|
VST1 V12.B[3], (R1) // 2c0c000d
|
||||||
VST1 V12.B[3], (R1) // 2c0c000d
|
VST1 V12.B[3], (R1) // 2c0c000d
|
||||||
VST1 V25.S[2], (R20) // 9982004d
|
VST1 V25.S[2], (R20) // 9982004d
|
||||||
VST1 V9.D[1], (RSP) // e987004d
|
VST1 V9.D[1], (RSP) // e987004d
|
||||||
VST1.P V30.B[6], 1(R3) // 7e189f0d
|
VST1.P V30.B[6], 1(R3) // 7e189f0d
|
||||||
VST1.P V8.B[0], (R3)(R21) // VST1.P V8.B[0], (R3)(R21*1) // 6800950d
|
VST1.P V8.B[0], (R3)(R21) // 6800950d
|
||||||
VST1.P V15.H[5], 2(R10) // 4f499f4d
|
VST1.P V15.H[5], 2(R10) // 4f499f4d
|
||||||
VST1.P V1.H[7], (R23)(R11) // VST1.P V1.H[7], (R23)(R11*1) // e15a8b4d
|
VST1.P V1.H[7], (R23)(R11) // e15a8b4d
|
||||||
VST1.P V26.S[0], 4(R11) // 7a819f0d
|
VST1.P V26.S[0], 4(R11) // 7a819f0d
|
||||||
VST1.P V9.S[1], (R16)(R21) // VST1.P V9.S[1], (R16)(R21*1) // 0992950d
|
VST1.P V9.S[1], (R16)(R21) // 0992950d
|
||||||
VST1.P V16.D[0], 8(R9) // 30859f0d
|
VST1.P V16.D[0], 8(R9) // 30859f0d
|
||||||
VST1.P V23.D[1], (R21)(R16) // VST1.P V23.D[1], (R21)(R16*1) // b786904d
|
VST1.P V23.D[1], (R21)(R16) // b786904d
|
||||||
VSUB V1, V12, V23 // 9785e17e
|
VSUB V1, V12, V23 // 9785e17e
|
||||||
VUADDLV V31.S4, V11 // eb3bb06e
|
VUADDLV V31.S4, V11 // eb3bb06e
|
||||||
UCVTFWS R11, F19 // 7301231e
|
UCVTFWS R11, F19 // 7301231e
|
||||||
|
|
|
||||||
66
src/cmd/asm/internal/asm/testdata/arm64error.s
vendored
66
src/cmd/asm/internal/asm/testdata/arm64error.s
vendored
|
|
@ -8,10 +8,48 @@ TEXT errors(SB),$0
|
||||||
ADDSW R7->32, R14, R13 // ERROR "shift amount out of range 0 to 31"
|
ADDSW R7->32, R14, R13 // ERROR "shift amount out of range 0 to 31"
|
||||||
ADD R1.UXTB<<5, R2, R3 // ERROR "shift amount out of range 0 to 4"
|
ADD R1.UXTB<<5, R2, R3 // ERROR "shift amount out of range 0 to 4"
|
||||||
ADDS R1.UXTX<<7, R2, R3 // ERROR "shift amount out of range 0 to 4"
|
ADDS R1.UXTX<<7, R2, R3 // ERROR "shift amount out of range 0 to 4"
|
||||||
|
ADDS R5, R6, RSP // ERROR "illegal destination register"
|
||||||
|
SUBS R5, R6, RSP // ERROR "illegal destination register"
|
||||||
|
ADDSW R5, R6, RSP // ERROR "illegal destination register"
|
||||||
|
SUBSW R5, R6, RSP // ERROR "illegal destination register"
|
||||||
|
ADDS $0xff, R6, RSP // ERROR "illegal destination register"
|
||||||
|
ADDS $0xffff0, R6, RSP // ERROR "illegal destination register"
|
||||||
|
ADDS $0x1000100010001000, R6, RSP // ERROR "illegal destination register"
|
||||||
|
ADDS $0x10001000100011, R6, RSP // ERROR "illegal destination register"
|
||||||
|
ADDSW $0xff, R6, RSP // ERROR "illegal destination register"
|
||||||
|
ADDSW $0xffff0, R6, RSP // ERROR "illegal destination register"
|
||||||
|
ADDSW $0x1000100010001000, R6, RSP // ERROR "illegal destination register"
|
||||||
|
ADDSW $0x10001000100011, R6, RSP // ERROR "illegal destination register"
|
||||||
|
SUBS $0xff, R6, RSP // ERROR "illegal destination register"
|
||||||
|
SUBS $0xffff0, R6, RSP // ERROR "illegal destination register"
|
||||||
|
SUBS $0x1000100010001000, R6, RSP // ERROR "illegal destination register"
|
||||||
|
SUBS $0x10001000100011, R6, RSP // ERROR "illegal destination register"
|
||||||
|
SUBSW $0xff, R6, RSP // ERROR "illegal destination register"
|
||||||
|
SUBSW $0xffff0, R6, RSP // ERROR "illegal destination register"
|
||||||
|
SUBSW $0x1000100010001000, R6, RSP // ERROR "illegal destination register"
|
||||||
|
SUBSW $0x10001000100011, R6, RSP // ERROR "illegal destination register"
|
||||||
AND $0x22220000, R2, RSP // ERROR "illegal combination"
|
AND $0x22220000, R2, RSP // ERROR "illegal combination"
|
||||||
ANDS $0x22220000, R2, RSP // ERROR "illegal combination"
|
ANDS $0x22220000, R2, RSP // ERROR "illegal combination"
|
||||||
ADD R1, R2, R3, R4 // ERROR "illegal combination"
|
ADD R1, R2, R3, R4 // ERROR "illegal combination"
|
||||||
BICW R7@>33, R5, R16 // ERROR "shift amount out of range 0 to 31"
|
BICW R7@>33, R5, R16 // ERROR "shift amount out of range 0 to 31"
|
||||||
|
NEGW R7<<33, R5 // ERROR "shift amount out of range 0 to 31"
|
||||||
|
NEGSW R7<<33, R5 // ERROR "shift amount out of range 0 to 31"
|
||||||
|
ADD R7@>2, R5, R16 // ERROR "unsupported shift operator"
|
||||||
|
ADDW R7@>2, R5, R16 // ERROR "unsupported shift operator"
|
||||||
|
ADDS R7@>2, R5, R16 // ERROR "unsupported shift operator"
|
||||||
|
ADDSW R7@>2, R5, R16 // ERROR "unsupported shift operator"
|
||||||
|
SUB R7@>2, R5, R16 // ERROR "unsupported shift operator"
|
||||||
|
SUBW R7@>2, R5, R16 // ERROR "unsupported shift operator"
|
||||||
|
SUBS R7@>2, R5, R16 // ERROR "unsupported shift operator"
|
||||||
|
SUBSW R7@>2, R5, R16 // ERROR "unsupported shift operator"
|
||||||
|
CMP R7@>2, R5 // ERROR "unsupported shift operator"
|
||||||
|
CMPW R7@>2, R5 // ERROR "unsupported shift operator"
|
||||||
|
CMN R7@>2, R5 // ERROR "unsupported shift operator"
|
||||||
|
CMNW R7@>2, R5 // ERROR "unsupported shift operator"
|
||||||
|
NEG R7@>2, R5 // ERROR "unsupported shift operator"
|
||||||
|
NEGW R7@>2, R5 // ERROR "unsupported shift operator"
|
||||||
|
NEGS R7@>2, R5 // ERROR "unsupported shift operator"
|
||||||
|
NEGSW R7@>2, R5 // ERROR "unsupported shift operator"
|
||||||
CINC CS, R2, R3, R4 // ERROR "illegal combination"
|
CINC CS, R2, R3, R4 // ERROR "illegal combination"
|
||||||
CSEL LT, R1, R2 // ERROR "illegal combination"
|
CSEL LT, R1, R2 // ERROR "illegal combination"
|
||||||
LDP.P 8(R2), (R2, R3) // ERROR "constrained unpredictable behavior"
|
LDP.P 8(R2), (R2, R3) // ERROR "constrained unpredictable behavior"
|
||||||
|
|
@ -21,8 +59,8 @@ TEXT errors(SB),$0
|
||||||
LDP (R0), (R3, ZR) // ERROR "invalid register pair"
|
LDP (R0), (R3, ZR) // ERROR "invalid register pair"
|
||||||
LDXPW (RSP), (R2, R2) // ERROR "constrained unpredictable behavior"
|
LDXPW (RSP), (R2, R2) // ERROR "constrained unpredictable behavior"
|
||||||
LDAXPW (R5), (R2, R2) // ERROR "constrained unpredictable behavior"
|
LDAXPW (R5), (R2, R2) // ERROR "constrained unpredictable behavior"
|
||||||
MOVD.P 300(R2), R3 // ERROR "offset out of range [-255,254]"
|
MOVD.P 300(R2), R3 // ERROR "offset out of range [-256,255]"
|
||||||
MOVD.P R3, 344(R2) // ERROR "offset out of range [-255,254]"
|
MOVD.P R3, 344(R2) // ERROR "offset out of range [-256,255]"
|
||||||
MOVD (R3)(R7.SXTX<<2), R8 // ERROR "invalid index shift amount"
|
MOVD (R3)(R7.SXTX<<2), R8 // ERROR "invalid index shift amount"
|
||||||
MOVWU (R5)(R4.UXTW<<3), R10 // ERROR "invalid index shift amount"
|
MOVWU (R5)(R4.UXTW<<3), R10 // ERROR "invalid index shift amount"
|
||||||
MOVWU (R5)(R4<<1), R10 // ERROR "invalid index shift amount"
|
MOVWU (R5)(R4<<1), R10 // ERROR "invalid index shift amount"
|
||||||
|
|
@ -58,13 +96,13 @@ TEXT errors(SB),$0
|
||||||
VMOV V8.H[9], R3 // ERROR "register element index out of range 0 to 7"
|
VMOV V8.H[9], R3 // ERROR "register element index out of range 0 to 7"
|
||||||
VMOV V8.S[4], R3 // ERROR "register element index out of range 0 to 3"
|
VMOV V8.S[4], R3 // ERROR "register element index out of range 0 to 3"
|
||||||
VMOV V8.D[2], R3 // ERROR "register element index out of range 0 to 1"
|
VMOV V8.D[2], R3 // ERROR "register element index out of range 0 to 1"
|
||||||
VDUP V8.B[16], R3.B16 // ERROR "register element index out of range 0 to 15"
|
VDUP V8.B[16], V3.B16 // ERROR "register element index out of range 0 to 15"
|
||||||
VDUP V8.B[17], R3.B8 // ERROR "register element index out of range 0 to 15"
|
VDUP V8.B[17], V3.B8 // ERROR "register element index out of range 0 to 15"
|
||||||
VDUP V8.H[9], R3.H4 // ERROR "register element index out of range 0 to 7"
|
VDUP V8.H[9], V3.H4 // ERROR "register element index out of range 0 to 7"
|
||||||
VDUP V8.H[9], R3.H8 // ERROR "register element index out of range 0 to 7"
|
VDUP V8.H[9], V3.H8 // ERROR "register element index out of range 0 to 7"
|
||||||
VDUP V8.S[4], R3.S2 // ERROR "register element index out of range 0 to 3"
|
VDUP V8.S[4], V3.S2 // ERROR "register element index out of range 0 to 3"
|
||||||
VDUP V8.S[4], R3.S4 // ERROR "register element index out of range 0 to 3"
|
VDUP V8.S[4], V3.S4 // ERROR "register element index out of range 0 to 3"
|
||||||
VDUP V8.D[2], R3.D2 // ERROR "register element index out of range 0 to 1"
|
VDUP V8.D[2], V3.D2 // ERROR "register element index out of range 0 to 1"
|
||||||
VFMLA V1.D2, V12.D2, V3.S2 // ERROR "operand mismatch"
|
VFMLA V1.D2, V12.D2, V3.S2 // ERROR "operand mismatch"
|
||||||
VFMLA V1.S2, V12.S2, V3.D2 // ERROR "operand mismatch"
|
VFMLA V1.S2, V12.S2, V3.D2 // ERROR "operand mismatch"
|
||||||
VFMLA V1.S4, V12.S2, V3.D2 // ERROR "operand mismatch"
|
VFMLA V1.S4, V12.S2, V3.D2 // ERROR "operand mismatch"
|
||||||
|
|
@ -109,6 +147,9 @@ TEXT errors(SB),$0
|
||||||
VREV16 V1.D1, V2.D1 // ERROR "invalid arrangement"
|
VREV16 V1.D1, V2.D1 // ERROR "invalid arrangement"
|
||||||
VREV16 V1.B8, V2.B16 // ERROR "invalid arrangement"
|
VREV16 V1.B8, V2.B16 // ERROR "invalid arrangement"
|
||||||
VREV16 V1.H4, V2.H4 // ERROR "invalid arrangement"
|
VREV16 V1.H4, V2.H4 // ERROR "invalid arrangement"
|
||||||
|
FLDPQ (R0), (R1, R2) // ERROR "invalid register pair"
|
||||||
|
FLDPQ (R1), (F2, F2) // ERROR "constrained unpredictable behavior"
|
||||||
|
FSTPQ (R1, R2), (R0) // ERROR "invalid register pair"
|
||||||
FLDPD (R0), (R1, R2) // ERROR "invalid register pair"
|
FLDPD (R0), (R1, R2) // ERROR "invalid register pair"
|
||||||
FLDPD (R1), (F2, F2) // ERROR "constrained unpredictable behavior"
|
FLDPD (R1), (F2, F2) // ERROR "constrained unpredictable behavior"
|
||||||
FLDPS (R2), (F3, F3) // ERROR "constrained unpredictable behavior"
|
FLDPS (R2), (F3, F3) // ERROR "constrained unpredictable behavior"
|
||||||
|
|
@ -355,10 +396,17 @@ TEXT errors(SB),$0
|
||||||
VBIF V0.D2, V1.D2, V2.D2 // ERROR "invalid arrangement"
|
VBIF V0.D2, V1.D2, V2.D2 // ERROR "invalid arrangement"
|
||||||
VUADDW V9.B8, V12.H8, V14.B8 // ERROR "invalid arrangement"
|
VUADDW V9.B8, V12.H8, V14.B8 // ERROR "invalid arrangement"
|
||||||
VUADDW2 V9.B8, V12.S4, V14.S4 // ERROR "operand mismatch"
|
VUADDW2 V9.B8, V12.S4, V14.S4 // ERROR "operand mismatch"
|
||||||
|
VUMAX V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement"
|
||||||
|
VUMIN V1.D2, V2.D2, V3.D2 // ERROR "invalid arrangement"
|
||||||
|
VUMAX V1.B8, V2.B8, V3.B16 // ERROR "operand mismatch"
|
||||||
|
VUMIN V1.H4, V2.S4, V3.H4 // ERROR "operand mismatch"
|
||||||
VSLI $64, V7.D2, V8.D2 // ERROR "shift out of range"
|
VSLI $64, V7.D2, V8.D2 // ERROR "shift out of range"
|
||||||
VUSRA $0, 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 (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, 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, R4), (R2), (R8, R9) // ERROR "source register pair must be contiguous"
|
||||||
CASPD (R2, R3), (R2), (R8, R10) // ERROR "destination register pair must be contiguous"
|
CASPD (R2, R3), (R2), (R8, R10) // ERROR "destination register pair must be contiguous"
|
||||||
|
ADD R1>>2, RSP, R3 // ERROR "illegal combination"
|
||||||
|
ADDS R2<<3, R3, RSP // ERROR "unexpected SP reference"
|
||||||
|
CMP R1<<5, RSP // ERROR "the left shift amount out of range 0 to 4"
|
||||||
RET
|
RET
|
||||||
|
|
|
||||||
8
src/cmd/asm/internal/asm/testdata/mips64.s
vendored
8
src/cmd/asm/internal/asm/testdata/mips64.s
vendored
|
|
@ -407,6 +407,8 @@ label4:
|
||||||
SRLV R27, R6, R17 // 03668816
|
SRLV R27, R6, R17 // 03668816
|
||||||
SRA R11, R19, R20 // 0173a007
|
SRA R11, R19, R20 // 0173a007
|
||||||
SRAV R20, R19, R19 // 02939817
|
SRAV R20, R19, R19 // 02939817
|
||||||
|
ROTR R19, R18, R20 // 0272a046
|
||||||
|
ROTRV R9, R13, R16 // 012d8056
|
||||||
|
|
||||||
// LSHW rreg ',' rreg
|
// LSHW rreg ',' rreg
|
||||||
// {
|
// {
|
||||||
|
|
@ -418,6 +420,8 @@ label4:
|
||||||
SRLV R27, R6 // 03663016
|
SRLV R27, R6 // 03663016
|
||||||
SRA R11, R19 // 01739807
|
SRA R11, R19 // 01739807
|
||||||
SRAV R20, R19 // 02939817
|
SRAV R20, R19 // 02939817
|
||||||
|
ROTR R20, R19 // 02939846
|
||||||
|
ROTRV R16, R9 // 02094856
|
||||||
|
|
||||||
// LSHW imm ',' sreg ',' rreg
|
// LSHW imm ',' sreg ',' rreg
|
||||||
// {
|
// {
|
||||||
|
|
@ -429,6 +433,8 @@ label4:
|
||||||
SRLV $31, R6, R17 // 00068ffa
|
SRLV $31, R6, R17 // 00068ffa
|
||||||
SRA $8, R8, R19 // 00089a03
|
SRA $8, R8, R19 // 00089a03
|
||||||
SRAV $19, R8, R7 // 00083cfb
|
SRAV $19, R8, R7 // 00083cfb
|
||||||
|
ROTR $12, R8, R3 // 00281b02
|
||||||
|
ROTRV $8, R22, R22 // 0036b23a
|
||||||
|
|
||||||
// LSHW imm ',' rreg
|
// LSHW imm ',' rreg
|
||||||
// {
|
// {
|
||||||
|
|
@ -440,6 +446,8 @@ label4:
|
||||||
SRLV $31, R17 // 00118ffa
|
SRLV $31, R17 // 00118ffa
|
||||||
SRA $3, R12 // 000c60c3
|
SRA $3, R12 // 000c60c3
|
||||||
SRAV $12, R3 // 00031b3b
|
SRAV $12, R3 // 00031b3b
|
||||||
|
ROTR $12, R8 // 00284302
|
||||||
|
ROTRV $63, R22 // 0036b7fe
|
||||||
|
|
||||||
|
|
||||||
// LAND/LXOR/LNOR/LOR rreg ',' rreg
|
// LAND/LXOR/LNOR/LOR rreg ',' rreg
|
||||||
|
|
|
||||||
19
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
19
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
|
|
@ -41,6 +41,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||||
MOVDBR (R3)(R4), R5 // 7ca41c28
|
MOVDBR (R3)(R4), R5 // 7ca41c28
|
||||||
MOVWBR (R3)(R4), R5 // 7ca41c2c
|
MOVWBR (R3)(R4), R5 // 7ca41c2c
|
||||||
MOVHBR (R3)(R4), R5 // 7ca41e2c
|
MOVHBR (R3)(R4), R5 // 7ca41e2c
|
||||||
|
MOVD $foo+4009806848(FP), R5 // 3fe1ef0138bfcc20
|
||||||
|
MOVD $foo(SB), R5 // 3fe0000038bf0000
|
||||||
|
|
||||||
MOVDU 8(R3), R4 // e8830009
|
MOVDU 8(R3), R4 // e8830009
|
||||||
MOVDU (R3)(R4), R5 // 7ca4186a
|
MOVDU (R3)(R4), R5 // 7ca4186a
|
||||||
|
|
@ -77,6 +79,15 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||||
MOVBU R4, 1(R3) // 9c830001
|
MOVBU R4, 1(R3) // 9c830001
|
||||||
MOVBU R5, (R3)(R4) // 7ca419ee
|
MOVBU R5, (R3)(R4) // 7ca419ee
|
||||||
|
|
||||||
|
MOVB $0, R4 // 38800000
|
||||||
|
MOVBZ $0, R4 // 38800000
|
||||||
|
MOVH $0, R4 // 38800000
|
||||||
|
MOVHZ $0, R4 // 38800000
|
||||||
|
MOVW $0, R4 // 38800000
|
||||||
|
MOVWZ $0, R4 // 38800000
|
||||||
|
MOVD $0, R4 // 38800000
|
||||||
|
MOVD $0, R0 // 38000000
|
||||||
|
|
||||||
ADD $1, R3 // 38630001
|
ADD $1, R3 // 38630001
|
||||||
ADD $1, R3, R4 // 38830001
|
ADD $1, R3, R4 // 38830001
|
||||||
ADD $-1, R4 // 3884ffff
|
ADD $-1, R4 // 3884ffff
|
||||||
|
|
@ -280,11 +291,17 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||||
ROTLW R3, R4, R5 // 5c85183e
|
ROTLW R3, R4, R5 // 5c85183e
|
||||||
EXTSWSLI $3, R4, R5 // 7c851ef4
|
EXTSWSLI $3, R4, R5 // 7c851ef4
|
||||||
RLWMI $7, R3, $65535, R6 // 50663c3e
|
RLWMI $7, R3, $65535, R6 // 50663c3e
|
||||||
|
RLWMI $7, R3, $16, $31, R6 // 50663c3e
|
||||||
RLWMICC $7, R3, $65535, R6 // 50663c3f
|
RLWMICC $7, R3, $65535, R6 // 50663c3f
|
||||||
|
RLWMICC $7, R3, $16, $31, R6 // 50663c3f
|
||||||
RLWNM $3, R4, $7, R6 // 54861f7e
|
RLWNM $3, R4, $7, R6 // 54861f7e
|
||||||
|
RLWNM $3, R4, $29, $31, R6 // 54861f7e
|
||||||
RLWNM R3, R4, $7, R6 // 5c861f7e
|
RLWNM R3, R4, $7, R6 // 5c861f7e
|
||||||
|
RLWNM R3, R4, $29, $31, R6 // 5c861f7e
|
||||||
RLWNMCC $3, R4, $7, R6 // 54861f7f
|
RLWNMCC $3, R4, $7, R6 // 54861f7f
|
||||||
|
RLWNMCC $3, R4, $29, $31, R6 // 54861f7f
|
||||||
RLWNMCC R3, R4, $7, R6 // 5c861f7f
|
RLWNMCC R3, R4, $7, R6 // 5c861f7f
|
||||||
|
RLWNMCC R3, R4, $29, $31, R6 // 5c861f7f
|
||||||
RLDMI $0, R4, $7, R6 // 7886076c
|
RLDMI $0, R4, $7, R6 // 7886076c
|
||||||
RLDMICC $0, R4, $7, R6 // 7886076d
|
RLDMICC $0, R4, $7, R6 // 7886076d
|
||||||
RLDIMI $0, R4, $7, R6 // 788601cc
|
RLDIMI $0, R4, $7, R6 // 788601cc
|
||||||
|
|
@ -303,6 +320,8 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
||||||
RLDICCC $0, R4, $15, R6 // 788603c9
|
RLDICCC $0, R4, $15, R6 // 788603c9
|
||||||
CLRLSLWI $16, R5, $8, R4 // 54a4422e
|
CLRLSLWI $16, R5, $8, R4 // 54a4422e
|
||||||
CLRLSLDI $24, R4, $2, R3 // 78831588
|
CLRLSLDI $24, R4, $2, R3 // 78831588
|
||||||
|
RLDCR $1, R1, $-16, R1 // 78210ee4
|
||||||
|
RLDCRCC $1, R1, $-16, R1 // 78210ee5
|
||||||
|
|
||||||
BEQ 0(PC) // 41820000
|
BEQ 0(PC) // 41820000
|
||||||
BEQ CR1,0(PC) // 41860000
|
BEQ CR1,0(PC) // 41860000
|
||||||
|
|
|
||||||
|
|
@ -280,6 +280,9 @@ start:
|
||||||
MOV $2047, X5 // 9b02f07f
|
MOV $2047, X5 // 9b02f07f
|
||||||
MOV $-2048, X5 // 9b020080
|
MOV $-2048, X5 // 9b020080
|
||||||
|
|
||||||
|
// Converted to load of symbol.
|
||||||
|
MOV $4294967296, X5 // 97020000
|
||||||
|
|
||||||
MOV (X5), X6 // 03b30200
|
MOV (X5), X6 // 03b30200
|
||||||
MOV 4(X5), X6 // 03b34200
|
MOV 4(X5), X6 // 03b34200
|
||||||
MOVB (X5), X6 // 03830200
|
MOVB (X5), X6 // 03830200
|
||||||
|
|
@ -325,7 +328,7 @@ start:
|
||||||
// These jumps can get printed as jumps to 2 because they go to the
|
// These jumps can get printed as jumps to 2 because they go to the
|
||||||
// second instruction in the function (the first instruction is an
|
// second instruction in the function (the first instruction is an
|
||||||
// invisible stack pointer adjustment).
|
// invisible stack pointer adjustment).
|
||||||
JMP start // JMP 2 // 6ff09fc2
|
JMP start // JMP 2 // 6ff01fc2
|
||||||
JMP (X5) // 67800200
|
JMP (X5) // 67800200
|
||||||
JMP 4(X5) // 67804200
|
JMP 4(X5) // 67804200
|
||||||
|
|
||||||
|
|
@ -338,16 +341,16 @@ start:
|
||||||
JMP asmtest(SB) // 970f0000
|
JMP asmtest(SB) // 970f0000
|
||||||
|
|
||||||
// Branch pseudo-instructions
|
// Branch pseudo-instructions
|
||||||
BEQZ X5, start // BEQZ X5, 2 // e38602c0
|
BEQZ X5, start // BEQZ X5, 2 // e38202c0
|
||||||
BGEZ X5, start // BGEZ X5, 2 // e3d402c0
|
BGEZ X5, start // BGEZ X5, 2 // e3d002c0
|
||||||
BGT X5, X6, start // BGT X5, X6, 2 // e34253c0
|
BGT X5, X6, start // BGT X5, X6, 2 // e34e53be
|
||||||
BGTU X5, X6, start // BGTU X5, X6, 2 // e36053c0
|
BGTU X5, X6, start // BGTU X5, X6, 2 // e36c53be
|
||||||
BGTZ X5, start // BGTZ X5, 2 // e34e50be
|
BGTZ X5, start // BGTZ X5, 2 // e34a50be
|
||||||
BLE X5, X6, start // BLE X5, X6, 2 // e35c53be
|
BLE X5, X6, start // BLE X5, X6, 2 // e35853be
|
||||||
BLEU X5, X6, start // BLEU X5, X6, 2 // e37a53be
|
BLEU X5, X6, start // BLEU X5, X6, 2 // e37653be
|
||||||
BLEZ X5, start // BLEZ X5, 2 // e35850be
|
BLEZ X5, start // BLEZ X5, 2 // e35450be
|
||||||
BLTZ X5, start // BLTZ X5, 2 // e3c602be
|
BLTZ X5, start // BLTZ X5, 2 // e3c202be
|
||||||
BNEZ X5, start // BNEZ X5, 2 // e39402be
|
BNEZ X5, start // BNEZ X5, 2 // e39002be
|
||||||
|
|
||||||
// Set pseudo-instructions
|
// Set pseudo-instructions
|
||||||
SEQZ X15, X15 // 93b71700
|
SEQZ X15, X15 // 93b71700
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue