mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.boringcrypto] all: merge master into dev.boringcrypto
Change-Id: I0f610a900fcd5575ca12b34bc74fa63c2146b10b
This commit is contained in:
commit
e48f228c9b
2657 changed files with 399109 additions and 114405 deletions
1
AUTHORS
1
AUTHORS
|
|
@ -928,6 +928,7 @@ Maxim Khitrov <max@mxcrypt.com>
|
|||
Maxime de Roucy <maxime.deroucy@gmail.com>
|
||||
Máximo Cuadros Ortiz <mcuadros@gmail.com>
|
||||
Maxwell Krohn <themax@gmail.com>
|
||||
Maya Rashish <maya@netbsd.org>
|
||||
Mayank Kumar <krmayankk@gmail.com>
|
||||
MediaMath, Inc
|
||||
Meir Fischer <meirfischer@gmail.com>
|
||||
|
|
|
|||
|
|
@ -458,3 +458,4 @@ pkg syscall (freebsd-arm-cgo), type Stat_t struct, Rdev uint32
|
|||
pkg syscall (freebsd-arm-cgo), type Statfs_t struct, Mntfromname [88]int8
|
||||
pkg syscall (freebsd-arm-cgo), type Statfs_t struct, Mntonname [88]int8
|
||||
pkg text/scanner, const GoTokens = 1012
|
||||
pkg unicode, const Version = "10.0.0"
|
||||
|
|
|
|||
8039
api/next.txt
8039
api/next.txt
File diff suppressed because it is too large
Load diff
85
doc/asm.html
85
doc/asm.html
|
|
@ -57,19 +57,32 @@ func main() {
|
|||
println(3)
|
||||
}
|
||||
$ GOOS=linux GOARCH=amd64 go tool compile -S x.go # or: go build -gcflags -S x.go
|
||||
|
||||
--- prog list "main" ---
|
||||
0000 (x.go:3) TEXT main+0(SB),$8-0
|
||||
0001 (x.go:3) FUNCDATA $0,gcargs·0+0(SB)
|
||||
0002 (x.go:3) FUNCDATA $1,gclocals·0+0(SB)
|
||||
0003 (x.go:4) MOVQ $3,(SP)
|
||||
0004 (x.go:4) PCDATA $0,$8
|
||||
0005 (x.go:4) CALL ,runtime.printint+0(SB)
|
||||
0006 (x.go:4) PCDATA $0,$-1
|
||||
0007 (x.go:4) PCDATA $0,$0
|
||||
0008 (x.go:4) CALL ,runtime.printnl+0(SB)
|
||||
0009 (x.go:4) PCDATA $0,$-1
|
||||
0010 (x.go:5) RET ,
|
||||
"".main STEXT size=74 args=0x0 locals=0x10
|
||||
0x0000 00000 (x.go:3) TEXT "".main(SB), $16-0
|
||||
0x0000 00000 (x.go:3) MOVQ (TLS), CX
|
||||
0x0009 00009 (x.go:3) CMPQ SP, 16(CX)
|
||||
0x000d 00013 (x.go:3) JLS 67
|
||||
0x000f 00015 (x.go:3) SUBQ $16, SP
|
||||
0x0013 00019 (x.go:3) MOVQ BP, 8(SP)
|
||||
0x0018 00024 (x.go:3) LEAQ 8(SP), BP
|
||||
0x001d 00029 (x.go:3) FUNCDATA $0, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
|
||||
0x001d 00029 (x.go:3) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
|
||||
0x001d 00029 (x.go:3) FUNCDATA $2, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
|
||||
0x001d 00029 (x.go:4) PCDATA $0, $0
|
||||
0x001d 00029 (x.go:4) PCDATA $1, $0
|
||||
0x001d 00029 (x.go:4) CALL runtime.printlock(SB)
|
||||
0x0022 00034 (x.go:4) MOVQ $3, (SP)
|
||||
0x002a 00042 (x.go:4) CALL runtime.printint(SB)
|
||||
0x002f 00047 (x.go:4) CALL runtime.printnl(SB)
|
||||
0x0034 00052 (x.go:4) CALL runtime.printunlock(SB)
|
||||
0x0039 00057 (x.go:5) MOVQ 8(SP), BP
|
||||
0x003e 00062 (x.go:5) ADDQ $16, SP
|
||||
0x0042 00066 (x.go:5) RET
|
||||
0x0043 00067 (x.go:5) NOP
|
||||
0x0043 00067 (x.go:3) PCDATA $1, $-1
|
||||
0x0043 00067 (x.go:3) PCDATA $0, $-1
|
||||
0x0043 00067 (x.go:3) CALL runtime.morestack_noctxt(SB)
|
||||
0x0048 00072 (x.go:3) JMP 0
|
||||
...
|
||||
</pre>
|
||||
|
||||
|
|
@ -78,38 +91,32 @@ The <code>FUNCDATA</code> and <code>PCDATA</code> directives contain information
|
|||
for use by the garbage collector; they are introduced by the compiler.
|
||||
</p>
|
||||
|
||||
<!-- Commenting out because the feature is gone but it's popular and may come back.
|
||||
|
||||
<p>
|
||||
To see what gets put in the binary after linking, add the <code>-a</code> flag to the linker:
|
||||
To see what gets put in the binary after linking, use <code>go tool objdump</code>:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
$ go tool 6l -a x.6 # or: go build -ldflags -a x.go
|
||||
codeblk [0x2000,0x1d059) at offset 0x1000
|
||||
002000 main.main | (3) TEXT main.main+0(SB),$8
|
||||
002000 65488b0c25a0080000 | (3) MOVQ 2208(GS),CX
|
||||
002009 483b21 | (3) CMPQ SP,(CX)
|
||||
00200c 7707 | (3) JHI ,2015
|
||||
00200e e83da20100 | (3) CALL ,1c250+runtime.morestack00
|
||||
002013 ebeb | (3) JMP ,2000
|
||||
002015 4883ec08 | (3) SUBQ $8,SP
|
||||
002019 | (3) FUNCDATA $0,main.gcargs·0+0(SB)
|
||||
002019 | (3) FUNCDATA $1,main.gclocals·0+0(SB)
|
||||
002019 48c7042403000000 | (4) MOVQ $3,(SP)
|
||||
002021 | (4) PCDATA $0,$8
|
||||
002021 e8aad20000 | (4) CALL ,f2d0+runtime.printint
|
||||
002026 | (4) PCDATA $0,$-1
|
||||
002026 | (4) PCDATA $0,$0
|
||||
002026 e865d40000 | (4) CALL ,f490+runtime.printnl
|
||||
00202b | (4) PCDATA $0,$-1
|
||||
00202b 4883c408 | (5) ADDQ $8,SP
|
||||
00202f c3 | (5) RET ,
|
||||
...
|
||||
$ go build -o x.exe x.go
|
||||
$ go tool objdump -s main.main x.exe
|
||||
TEXT main.main(SB) /tmp/x.go
|
||||
x.go:3 0x10501c0 65488b0c2530000000 MOVQ GS:0x30, CX
|
||||
x.go:3 0x10501c9 483b6110 CMPQ 0x10(CX), SP
|
||||
x.go:3 0x10501cd 7634 JBE 0x1050203
|
||||
x.go:3 0x10501cf 4883ec10 SUBQ $0x10, SP
|
||||
x.go:3 0x10501d3 48896c2408 MOVQ BP, 0x8(SP)
|
||||
x.go:3 0x10501d8 488d6c2408 LEAQ 0x8(SP), BP
|
||||
x.go:4 0x10501dd e86e45fdff CALL runtime.printlock(SB)
|
||||
x.go:4 0x10501e2 48c7042403000000 MOVQ $0x3, 0(SP)
|
||||
x.go:4 0x10501ea e8e14cfdff CALL runtime.printint(SB)
|
||||
x.go:4 0x10501ef e8ec47fdff CALL runtime.printnl(SB)
|
||||
x.go:4 0x10501f4 e8d745fdff CALL runtime.printunlock(SB)
|
||||
x.go:5 0x10501f9 488b6c2408 MOVQ 0x8(SP), BP
|
||||
x.go:5 0x10501fe 4883c410 ADDQ $0x10, SP
|
||||
x.go:5 0x1050202 c3 RET
|
||||
x.go:3 0x1050203 e83882ffff CALL runtime.morestack_noctxt(SB)
|
||||
x.go:3 0x1050208 ebb6 JMP main.main(SB)
|
||||
</pre>
|
||||
|
||||
-->
|
||||
|
||||
<h3 id="constants">Constants</h3>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -304,11 +304,11 @@ optional: you do not need to use source control to write Go code.
|
|||
<pre>
|
||||
$ <b>cd $GOPATH/src/github.com/user/hello</b>
|
||||
$ <b>git init</b>
|
||||
Initialized empty Git repository in /home/user/work/src/github.com/user/hello/.git/
|
||||
Initialized empty Git repository in /home/user/go/src/github.com/user/hello/.git/
|
||||
$ <b>git add hello.go</b>
|
||||
$ <b>git commit -m "initial commit"</b>
|
||||
[master (root-commit) 0b4507d] initial commit
|
||||
1 file changed, 1 insertion(+)
|
||||
1 file changed, 7 insertion(+)
|
||||
create mode 100644 hello.go
|
||||
</pre>
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ CLA (Contributor License Agreement).
|
|||
<li>
|
||||
<b>Step 2</b>: Configure authentication credentials for the Go Git repository.
|
||||
Visit <a href="https://go.googlesource.com/">go.googlesource.com</a>, click
|
||||
on "Generate Password" (top right), and follow the instructions.
|
||||
on the gear icon (top right), then on "Obtain password", and follow the
|
||||
instructions.
|
||||
</li>
|
||||
<li>
|
||||
<b>Step 3</b>: Register for Gerrit, the code review tool used by the Go team,
|
||||
|
|
|
|||
|
|
@ -149,6 +149,9 @@ Inspecting goroutines:
|
|||
(gdb) <b>help goroutine</b></pre>
|
||||
For example:
|
||||
<pre>(gdb) <b>goroutine 12 bt</b></pre>
|
||||
You can inspect all goroutines by passing <code>all</code> instead of a specific goroutine's ID.
|
||||
For example:
|
||||
<pre>(gdb) <b>goroutine all bt</b></pre>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,45 @@ Go 1.12 is a major release of Go.
|
|||
Read the <a href="/doc/go1.12">Go 1.12 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="go1.12.minor">Minor revisions</h3>
|
||||
|
||||
<p>
|
||||
go1.12.1 (released 2019/03/14) includes fixes to cgo, the compiler, the go
|
||||
command, and the <code>fmt</code>, <code>net/smtp</code>, <code>os</code>,
|
||||
<code>path/filepath</code>, <code>sync</code>, and <code>text/template</code>
|
||||
packages. See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.1">Go
|
||||
1.12.1 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.2 (released 2019/04/05) includes fixes to the compiler, the go
|
||||
command, the runtime, and the <code>doc</code>, <code>net</code>,
|
||||
<code>net/http/httputil</code>, and <code>os</code> packages. See the
|
||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.2">Go
|
||||
1.12.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.3 (released 2019/04/08) was accidentally released without its
|
||||
intended fix. It is identical to go1.12.2, except for its version
|
||||
number. The intended fix is in go1.12.4.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.4 (released 2019/04/11) fixes an issue where using the prebuilt binary
|
||||
releases on older versions of GNU/Linux
|
||||
<a href="https://golang.org/issues/31293">led to failures</a>
|
||||
when linking programs that used cgo.
|
||||
Only Linux users who hit this issue need to update.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.12.5 (released 2019/05/06) includes fixes to the compiler, the linker,
|
||||
the go command, the runtime, and the <code>os</code> package. See the
|
||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.12.5">Go
|
||||
1.12.5 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.11">go1.11 (released 2018/08/24)</h2>
|
||||
|
||||
<p>
|
||||
|
|
@ -73,6 +112,48 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.4+labe
|
|||
1.11.4 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.5 (released 2019/01/23) includes a security fix to the
|
||||
<code>crypto/elliptic</code> package. See
|
||||
the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.5">Go
|
||||
1.11.5 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.6 (released 2019/03/14) includes fixes to cgo, the compiler, linker,
|
||||
runtime, go command, and the <code>crypto/x509</code>, <code>encoding/json</code>,
|
||||
<code>net</code>, and <code>net/url</code> packages. See the
|
||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.6">Go
|
||||
1.11.6 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.7 (released 2019/04/05) includes fixes to the runtime and the
|
||||
<code>net</code> packages. See the
|
||||
<a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.7">Go
|
||||
1.11.7 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.8 (released 2019/04/08) was accidentally released without its
|
||||
intended fix. It is identical to go1.11.7, except for its version
|
||||
number. The intended fix is in go1.11.9.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.9 (released 2019/04/11) fixes an issue where using the prebuilt binary
|
||||
releases on older versions of GNU/Linux
|
||||
<a href="https://golang.org/issues/31293">led to failures</a>
|
||||
when linking programs that used cgo.
|
||||
Only Linux users who hit this issue need to update.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.11.10 (released 2019/05/06) includes fixes to the runtime and the linker.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.11.10">Go
|
||||
1.11.10 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.10">go1.10 (released 2018/02/16)</h2>
|
||||
|
||||
<p>
|
||||
|
|
@ -138,6 +219,13 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.7+labe
|
|||
Go 1.10.7 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.10.8 (released 2019/01/23) includes a security fix to the
|
||||
<code>crypto/elliptic</code> package. See
|
||||
the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.10.8">Go
|
||||
1.10.8 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.9">go1.9 (released 2017/08/24)</h2>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -1680,13 +1680,15 @@ maps. Here is a print statement for the time zone map defined in the previous s
|
|||
fmt.Printf("%v\n", timeZone) // or just fmt.Println(timeZone)
|
||||
</pre>
|
||||
<p>
|
||||
which gives output
|
||||
which gives output:
|
||||
</p>
|
||||
<pre>
|
||||
map[CST:-21600 PST:-28800 EST:-18000 UTC:0 MST:-25200]
|
||||
map[CST:-21600 EST:-18000 MST:-25200 PST:-28800 UTC:0]
|
||||
</pre>
|
||||
<p>
|
||||
For maps the keys may be output in any order, of course.
|
||||
For maps, <code>Printf</code> and friends sort the output lexicographically by key.
|
||||
</p>
|
||||
<p>
|
||||
When printing a struct, the modified format <code>%+v</code> annotates the
|
||||
fields of the structure with their names, and for any value the alternate
|
||||
format <code>%#v</code> prints the value in full Go syntax.
|
||||
|
|
@ -1710,7 +1712,7 @@ prints
|
|||
&{7 -2.35 abc def}
|
||||
&{a:7 b:-2.35 c:abc def}
|
||||
&main.T{a:7, b:-2.35, c:"abc\tdef"}
|
||||
map[string]int{"CST":-21600, "PST":-28800, "EST":-18000, "UTC":0, "MST":-25200}
|
||||
map[string]int{"CST":-21600, "EST":-18000, "MST":-25200, "PST":-28800, "UTC":0}
|
||||
</pre>
|
||||
<p>
|
||||
(Note the ampersands.)
|
||||
|
|
|
|||
|
|
@ -185,6 +185,17 @@ tour
|
|||
that build fails.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 147282, 147281 -->
|
||||
This changed use of the <code>go</code> directive means that if you
|
||||
use Go 1.12 to build a module, thus recording <code>go 1.12</code>
|
||||
in the <code>go.mod</code> file, you will get an error when
|
||||
attempting to build the same module with Go 1.11 through Go 1.11.3.
|
||||
Go 1.11.4 or later will work fine, as will releases older than Go 1.11.
|
||||
If you must use Go 1.11 through 1.11.3, you can avoid the problem by
|
||||
setting the language version to 1.11, using the Go 1.12 go tool,
|
||||
via <code>go mod edit -go=1.11</code>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 152739 -->
|
||||
When an import cannot be resolved using the active modules,
|
||||
the <code>go</code> command will now try to use the modules mentioned in the
|
||||
|
|
@ -600,17 +611,6 @@ for {
|
|||
|
||||
</dl><!-- io -->
|
||||
|
||||
<dl id="lib/time"><dt><a href="/pkg/lib/time/">lib/time</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 151299 -->
|
||||
The time zone database in <code>$GOROOT/lib/time/zoneinfo.zip</code>
|
||||
has been updated to version 2018i. Note that this ZIP file is
|
||||
only used if a time zone database is not provided by the operating
|
||||
system.
|
||||
</p>
|
||||
|
||||
</dl><!-- lib/time -->
|
||||
|
||||
<dl id="math"><dt><a href="/pkg/math/">math</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 153059 -->
|
||||
|
|
@ -791,7 +791,7 @@ for {
|
|||
A new <a href="/pkg/runtime/debug/#BuildInfo"><code>BuildInfo</code></a> type
|
||||
exposes the build information read from the running binary, available only in
|
||||
binaries built with module support. This includes the main package path, main
|
||||
module information, and the module dependencies. This type is given though the
|
||||
module information, and the module dependencies. This type is given through the
|
||||
<a href="/pkg/runtime/debug/#ReadBuildInfo"><code>ReadBuildInfo</code></a> function
|
||||
on <a href="/pkg/runtime/debug/#BuildInfo"><code>BuildInfo</code></a>.
|
||||
</p>
|
||||
|
|
@ -924,6 +924,17 @@ for {
|
|||
</p>
|
||||
</dl><!-- text/template -->
|
||||
|
||||
<dl id="time"><dt><a href="/pkg/time/">time</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 151299 -->
|
||||
The time zone database in <code>$GOROOT/lib/time/zoneinfo.zip</code>
|
||||
has been updated to version 2018i. Note that this ZIP file is
|
||||
only used if a time zone database is not provided by the operating
|
||||
system.
|
||||
</p>
|
||||
|
||||
</dl><!-- time -->
|
||||
|
||||
<dl id="unsafe"><dt><a href="/pkg/unsafe/">unsafe</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 146058 -->
|
||||
|
|
|
|||
97
doc/go1.13.html
Normal file
97
doc/go1.13.html
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
<!--{
|
||||
"Title": "Go 1.13 Release Notes",
|
||||
"Path": "/doc/go1.13",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<!--
|
||||
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>
|
||||
ul li { margin: 0.5em 0; }
|
||||
</style>
|
||||
|
||||
<h2 id="introduction">DRAFT RELEASE NOTES - Introduction to Go 1.13</h2>
|
||||
|
||||
<p>
|
||||
<strong>
|
||||
Go 1.13 is not yet released. These are work-in-progress
|
||||
release notes. Go 1.13 is expected to be released in August 2019.
|
||||
</strong>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
</p>
|
||||
|
||||
<h2 id="language">Changes to the language</h2>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
</p>
|
||||
|
||||
<h2 id="ports">Ports</h2>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
</p>
|
||||
|
||||
<h3 id="darwin">Darwin</h3>
|
||||
|
||||
<p>
|
||||
As <a href="go1.12#darwin">announced</a> in the Go 1.12 release notes,
|
||||
Go 1.13 now requires macOS 10.11 El Capitan or later;
|
||||
support for previous versions has been discontinued.
|
||||
</p>
|
||||
|
||||
<h3 id="freebsd">FreeBSD</h3>
|
||||
|
||||
<p>
|
||||
As <a href="go1.12#freebsd">announced</a> in the Go 1.12 release notes,
|
||||
Go 1.13 now requires FreeBSD 11.2 or later;
|
||||
support for previous versions has been discontinued.
|
||||
FreeBSD 12.0 or later requires a kernel with the COMPAT_FREEBSD11 option set (this is the default).
|
||||
</p>
|
||||
|
||||
<h2 id="tools">Tools</h2>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
</p>
|
||||
|
||||
<h2 id="runtime">Runtime</h2>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="library">Core library</h2>
|
||||
|
||||
<p>
|
||||
TODO generally
|
||||
</p>
|
||||
|
||||
<h3 id="tls_1_3">TLS 1.3</h3>
|
||||
|
||||
<p>
|
||||
TODO; link to <a href="/doc/go1.12#tls_1_3">Go 1.12 notes</a>.
|
||||
</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>
|
||||
|
||||
<p>
|
||||
TODO
|
||||
</p>
|
||||
|
||||
|
|
@ -2082,8 +2082,8 @@ At the beginning of the project we considered using LLVM for
|
|||
our performance goals.
|
||||
More important in retrospect, starting with LLVM would have made it
|
||||
harder to introduce some of the ABI and related changes, such as
|
||||
stack management, that Go requires but not are not part of the
|
||||
standard C setup.
|
||||
stack management, that Go requires but are not part of the standard
|
||||
C setup.
|
||||
A new <a href="https://go.googlesource.com/gollvm/">LLVM implementation</a>
|
||||
is starting to come together now, however.
|
||||
</p>
|
||||
|
|
|
|||
248
doc/go_spec.html
248
doc/go_spec.html
|
|
@ -1,6 +1,6 @@
|
|||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of February 16, 2019",
|
||||
"Subtitle": "Version of May 14, 2019",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
|
|
@ -118,6 +118,7 @@ The underscore character <code>_</code> (U+005F) is considered a letter.
|
|||
<pre class="ebnf">
|
||||
letter = unicode_letter | "_" .
|
||||
decimal_digit = "0" … "9" .
|
||||
binary_digit = "0" | "1" .
|
||||
octal_digit = "0" … "7" .
|
||||
hex_digit = "0" … "9" | "A" … "F" | "a" … "f" .
|
||||
</pre>
|
||||
|
|
@ -273,41 +274,96 @@ The following character sequences represent <a href="#Operators">operators</a>
|
|||
<p>
|
||||
An integer literal is a sequence of digits representing an
|
||||
<a href="#Constants">integer constant</a>.
|
||||
An optional prefix sets a non-decimal base: <code>0</code> for octal, <code>0x</code> or
|
||||
<code>0X</code> for hexadecimal. In hexadecimal literals, letters
|
||||
<code>a-f</code> and <code>A-F</code> represent values 10 through 15.
|
||||
An optional prefix sets a non-decimal base: <code>0b</code> or <code>0B</code>
|
||||
for binary, <code>0</code>, <code>0o</code>, or <code>0O</code> for octal,
|
||||
and <code>0x</code> or <code>0X</code> for hexadecimal.
|
||||
A single <code>0</code> is considered a decimal zero.
|
||||
In hexadecimal literals, letters <code>a</code> through <code>f</code>
|
||||
and <code>A</code> through <code>F</code> represent values 10 through 15.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For readability, an underscore character <code>_</code> may appear after
|
||||
a base prefix or between successive digits; such underscores do not change
|
||||
the literal's value.
|
||||
</p>
|
||||
<pre class="ebnf">
|
||||
int_lit = decimal_lit | octal_lit | hex_lit .
|
||||
decimal_lit = ( "1" … "9" ) { decimal_digit } .
|
||||
octal_lit = "0" { octal_digit } .
|
||||
hex_lit = "0" ( "x" | "X" ) hex_digit { hex_digit } .
|
||||
int_lit = decimal_lit | binary_lit | octal_lit | hex_lit .
|
||||
decimal_lit = "0" | ( "1" … "9" ) [ [ "_" ] decimal_digits ] .
|
||||
binary_lit = "0" ( "b" | "B" ) [ "_" ] binary_digits .
|
||||
octal_lit = "0" [ "o" | "O" ] [ "_" ] octal_digits .
|
||||
hex_lit = "0" ( "x" | "X" ) [ "_" ] hex_digits .
|
||||
|
||||
decimal_digits = decimal_digit { [ "_" ] decimal_digit } .
|
||||
binary_digits = binary_digit { [ "_" ] binary_digit } .
|
||||
octal_digits = octal_digit { [ "_" ] octal_digit } .
|
||||
hex_digits = hex_digit { [ "_" ] hex_digit } .
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
42
|
||||
4_2
|
||||
0600
|
||||
0_600
|
||||
0o600
|
||||
0O600 // second character is capital letter 'O'
|
||||
0xBadFace
|
||||
0xBad_Face
|
||||
0x_67_7a_2f_cc_40_c6
|
||||
170141183460469231731687303715884105727
|
||||
170_141183_460469_231731_687303_715884_105727
|
||||
|
||||
_42 // an identifier, not an integer literal
|
||||
42_ // invalid: _ must separate successive digits
|
||||
4__2 // invalid: only one _ at a time
|
||||
0_xBadFace // invalid: _ must separate successive digits
|
||||
</pre>
|
||||
|
||||
|
||||
<h3 id="Floating-point_literals">Floating-point literals</h3>
|
||||
|
||||
<p>
|
||||
A floating-point literal is a decimal representation of a
|
||||
A floating-point literal is a decimal or hexadecimal representation of a
|
||||
<a href="#Constants">floating-point constant</a>.
|
||||
It has an integer part, a decimal point, a fractional part,
|
||||
and an exponent part. The integer and fractional part comprise
|
||||
decimal digits; the exponent part is an <code>e</code> or <code>E</code>
|
||||
followed by an optionally signed decimal exponent. One of the
|
||||
integer part or the fractional part may be elided; one of the decimal
|
||||
point or the exponent may be elided.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A decimal floating-point literal consists of an integer part (decimal digits),
|
||||
a decimal point, a fractional part (decimal digits), and an exponent part
|
||||
(<code>e</code> or <code>E</code> followed by an optional sign and decimal digits).
|
||||
One of the integer part or the fractional part may be elided; one of the decimal point
|
||||
or the exponent part may be elided.
|
||||
An exponent value exp scales the mantissa (integer and fractional part) by 10<sup>exp</sup>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A hexadecimal floating-point literal consists of a <code>0x</code> or <code>0X</code>
|
||||
prefix, an integer part (hexadecimal digits), a radix point, a fractional part (hexadecimal digits),
|
||||
and an exponent part (<code>p</code> or <code>P</code> followed by an optional sign and decimal digits).
|
||||
One of the integer part or the fractional part may be elided; the radix point may be elided as well,
|
||||
but the exponent part is required. (This syntax matches the one given in IEEE 754-2008 §5.12.3.)
|
||||
An exponent value exp scales the mantissa (integer and fractional part) by 2<sup>exp</sup>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For readability, an underscore character <code>_</code> may appear after
|
||||
a base prefix or between successive digits; such underscores do not change
|
||||
the literal value.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
float_lit = decimals "." [ decimals ] [ exponent ] |
|
||||
decimals exponent |
|
||||
"." decimals [ exponent ] .
|
||||
decimals = decimal_digit { decimal_digit } .
|
||||
exponent = ( "e" | "E" ) [ "+" | "-" ] decimals .
|
||||
float_lit = decimal_float_lit | hex_float_lit .
|
||||
|
||||
decimal_float_lit = decimal_digits "." [ decimal_digits ] [ decimal_exponent ] |
|
||||
decimal_digits decimal_exponent |
|
||||
"." decimal_digits [ decimal_exponent ] .
|
||||
decimal_exponent = ( "e" | "E" ) [ "+" | "-" ] decimal_digits .
|
||||
|
||||
hex_float_lit = "0" ( "x" | "X" ) hex_mantissa hex_exponent .
|
||||
hex_mantissa = [ "_" ] hex_digits "." [ hex_digits ] |
|
||||
[ "_" ] hex_digits |
|
||||
"." hex_digits .
|
||||
hex_exponent = ( "p" | "P" ) [ "+" | "-" ] decimal_digits .
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
|
|
@ -320,24 +376,54 @@ exponent = ( "e" | "E" ) [ "+" | "-" ] decimals .
|
|||
1E6
|
||||
.25
|
||||
.12345E+5
|
||||
1_5. // == 15.0
|
||||
0.15e+0_2 // == 15.0
|
||||
|
||||
0x1p-2 // == 0.25
|
||||
0x2.p10 // == 2048.0
|
||||
0x1.Fp+0 // == 1.9375
|
||||
0X.8p-0 // == 0.5
|
||||
0X_1FFFP-16 // == 0.1249847412109375
|
||||
0x15e-2 // == 0x15e - 2 (integer subtraction)
|
||||
|
||||
0x.p1 // invalid: mantissa has no digits
|
||||
1p-2 // invalid: p exponent requires hexadecimal mantissa
|
||||
0x1.5e-2 // invalid: hexadecimal mantissa requires p exponent
|
||||
1_.5 // invalid: _ must separate successive digits
|
||||
1._5 // invalid: _ must separate successive digits
|
||||
1.5_e1 // invalid: _ must separate successive digits
|
||||
1.5e_1 // invalid: _ must separate successive digits
|
||||
1.5e1_ // invalid: _ must separate successive digits
|
||||
</pre>
|
||||
|
||||
|
||||
<h3 id="Imaginary_literals">Imaginary literals</h3>
|
||||
|
||||
<p>
|
||||
An imaginary literal is a decimal representation of the imaginary part of a
|
||||
An imaginary literal represents the imaginary part of a
|
||||
<a href="#Constants">complex constant</a>.
|
||||
It consists of a
|
||||
<a href="#Floating-point_literals">floating-point literal</a>
|
||||
or decimal integer followed
|
||||
by the lower-case letter <code>i</code>.
|
||||
It consists of an <a href="#Integer_literals">integer</a> or
|
||||
<a href="#Floating-point_literals">floating-point</a> literal
|
||||
followed by the lower-case letter <code>i</code>.
|
||||
The value of an imaginary literal is the value of the respective
|
||||
integer or floating-point literal multiplied by the imaginary unit <i>i</i>.
|
||||
</p>
|
||||
|
||||
<pre class="ebnf">
|
||||
imaginary_lit = (decimals | float_lit) "i" .
|
||||
imaginary_lit = (decimal_digits | int_lit | float_lit) "i" .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
For backward compatibility, an imaginary literal's integer part consisting
|
||||
entirely of decimal digits (and possibly underscores) is considered a decimal
|
||||
integer, even if it starts with a leading <code>0</code>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
0i
|
||||
011i // == 11i
|
||||
0123i // == 123i for backward-compatibility
|
||||
0o123i // == 0o123 * 1i == 83i
|
||||
0xabci // == 0xabc * 1i == 2748i
|
||||
0.i
|
||||
2.71828i
|
||||
1.e+0i
|
||||
|
|
@ -345,6 +431,7 @@ imaginary_lit = (decimals | float_lit) "i" .
|
|||
1E6i
|
||||
.25i
|
||||
.12345E+5i
|
||||
0x1p-2i // == 0x1p-2 * 1i == 0.25i
|
||||
</pre>
|
||||
|
||||
|
||||
|
|
@ -361,6 +448,7 @@ of the character itself,
|
|||
while multi-character sequences beginning with a backslash encode
|
||||
values in various formats.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The simplest form represents the single character within the quotes;
|
||||
since Go source text is Unicode characters encoded in UTF-8, multiple
|
||||
|
|
@ -370,6 +458,7 @@ a literal <code>a</code>, Unicode U+0061, value <code>0x61</code>, while
|
|||
<code>'ä'</code> holds two bytes (<code>0xc3</code> <code>0xa4</code>) representing
|
||||
a literal <code>a</code>-dieresis, U+00E4, value <code>0xe4</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Several backslash escapes allow arbitrary values to be encoded as
|
||||
ASCII text. There are four ways to represent the integer value
|
||||
|
|
@ -380,6 +469,7 @@ plain backslash <code>\</code> followed by exactly three octal digits.
|
|||
In each case the value of the literal is the value represented by
|
||||
the digits in the corresponding base.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Although these representations all result in an integer, they have
|
||||
different valid ranges. Octal escapes must represent a value between
|
||||
|
|
@ -388,9 +478,11 @@ by construction. The escapes <code>\u</code> and <code>\U</code>
|
|||
represent Unicode code points so within them some values are illegal,
|
||||
in particular those above <code>0x10FFFF</code> and surrogate halves.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
After a backslash, certain single-character escapes represent special values:
|
||||
</p>
|
||||
|
||||
<pre class="grammar">
|
||||
\a U+0007 alert or bell
|
||||
\b U+0008 backspace
|
||||
|
|
@ -403,6 +495,7 @@ After a backslash, certain single-character escapes represent special values:
|
|||
\' U+0027 single quote (valid escape only within rune literals)
|
||||
\" U+0022 double quote (valid escape only within string literals)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
All other sequences starting with a backslash are illegal inside rune literals.
|
||||
</p>
|
||||
|
|
@ -446,6 +539,7 @@ A string literal represents a <a href="#Constants">string constant</a>
|
|||
obtained from concatenating a sequence of characters. There are two forms:
|
||||
raw string literals and interpreted string literals.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Raw string literals are character sequences between back quotes, as in
|
||||
<code>`foo`</code>. Within the quotes, any character may appear except
|
||||
|
|
@ -457,6 +551,7 @@ contain newlines.
|
|||
Carriage return characters ('\r') inside raw string literals
|
||||
are discarded from the raw string value.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Interpreted string literals are character sequences between double
|
||||
quotes, as in <code>"bar"</code>.
|
||||
|
|
@ -596,6 +691,7 @@ precision in the language, a compiler may implement them using an
|
|||
internal representation with limited precision. That said, every
|
||||
implementation must:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Represent integer constants with at least 256 bits.</li>
|
||||
|
||||
|
|
@ -613,12 +709,14 @@ implementation must:
|
|||
represent a floating-point or complex constant due to limits
|
||||
on precision.</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
These requirements apply both to literal constants and to the result
|
||||
of evaluating <a href="#Constant_expressions">constant
|
||||
expressions</a>.
|
||||
</p>
|
||||
|
||||
|
||||
<h2 id="Variables">Variables</h2>
|
||||
|
||||
<p>
|
||||
|
|
@ -2415,10 +2513,24 @@ For array and slice literals the following rules apply:
|
|||
generates a pointer to a unique <a href="#Variables">variable</a> initialized
|
||||
with the literal's value.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var pointer *Point3D = &Point3D{y: 1000}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Note that the <a href="#The_zero_value">zero value</a> for a slice or map
|
||||
type is not the same as an initialized but empty value of the same type.
|
||||
Consequently, taking the address of an empty slice or map composite literal
|
||||
does not have the same effect as allocating a new slice or map value with
|
||||
<a href="#Allocation">new</a>.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
p1 := &[]int{} // p1 points to an initialized, empty slice with value []int{} and length 0
|
||||
p2 := new([]int) // p2 points to an uninitialized slice with value nil and length 0
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The length of an array literal is the length specified in the literal type.
|
||||
If fewer elements than the length are provided in the literal, the missing
|
||||
|
|
@ -3150,6 +3262,14 @@ is a <code>nil</code> slice. Otherwise, if the result is a slice, it shares its
|
|||
array with the operand.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var a [10]int
|
||||
s1 := a[3:7] // underlying array of s1 is array a; &s1[2] == &a[5]
|
||||
s2 := s1[1:4] // underlying array of s2 is underlying array of s1 which is array a; &s2[1] == &a[5]
|
||||
s2[1] = 42 // s2[1] == s1[2] == a[5] == 42; they all refer to the same underlying array element
|
||||
</pre>
|
||||
|
||||
|
||||
<h4>Full slice expressions</h4>
|
||||
|
||||
<p>
|
||||
|
|
@ -3386,7 +3506,7 @@ within <code>Greeting</code>, <code>who</code> will have the value
|
|||
</p>
|
||||
|
||||
<p>
|
||||
If the final argument is assignable to a slice type <code>[]T</code>, it may be
|
||||
If the final argument is assignable to a slice type <code>[]T</code>, it is
|
||||
passed unchanged as the value for a <code>...T</code> parameter if the argument
|
||||
is followed by <code>...</code>. In this case no new slice is created.
|
||||
</p>
|
||||
|
|
@ -6264,16 +6384,16 @@ var t T
|
|||
<h3 id="Package_initialization">Package initialization</h3>
|
||||
|
||||
<p>
|
||||
Within a package, package-level variables are initialized in
|
||||
<i>declaration order</i> but after any of the variables
|
||||
they <i>depend</i> on.
|
||||
Within a package, package-level variable initialization proceeds stepwise,
|
||||
with each step selecting the variable earliest in <i>declaration order</i>
|
||||
which has no dependencies on uninitialized variables.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
More precisely, a package-level variable is considered <i>ready for
|
||||
initialization</i> if it is not yet initialized and either has
|
||||
no <a href="#Variable_declarations">initialization expression</a> or
|
||||
its initialization expression has no dependencies on uninitialized variables.
|
||||
its initialization expression has no <i>dependencies</i> on uninitialized variables.
|
||||
Initialization proceeds by repeatedly initializing the next package-level
|
||||
variable that is earliest in declaration order and ready for initialization,
|
||||
until there are no variables ready for initialization.
|
||||
|
|
@ -6285,6 +6405,23 @@ process ends, those variables are part of one or more initialization cycles,
|
|||
and the program is not valid.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Multiple variables on the left-hand side of a variable declaration initialized
|
||||
by single (multi-valued) expression on the right-hand side are initialized
|
||||
together: If any of the variables on the left-hand side is initialized, all
|
||||
those variables are initialized in the same step.
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var x = a
|
||||
var a, b = f() // a and b are initialized together, before x is initialized
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
For the purpose of package initialization, <a href="#Blank_identifier">blank</a>
|
||||
variables are treated like any other variables in declarations.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The declaration order of variables declared in multiple files is determined
|
||||
by the order in which the files are presented to the compiler: Variables
|
||||
|
|
@ -6326,22 +6463,16 @@ or to a function or method that depends on <code>y</code>.
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
Dependency analysis is performed per package; only references referring
|
||||
to variables, functions, and methods declared in the current package
|
||||
are considered.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example, given the declarations
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var (
|
||||
a = c + b
|
||||
b = f()
|
||||
c = f()
|
||||
d = 3
|
||||
a = c + b // == 9
|
||||
b = f() // == 4
|
||||
c = f() // == 5
|
||||
d = 3 // == 5 after initialization has finished
|
||||
)
|
||||
|
||||
func f() int {
|
||||
|
|
@ -6352,6 +6483,39 @@ func f() int {
|
|||
|
||||
<p>
|
||||
the initialization order is <code>d</code>, <code>b</code>, <code>c</code>, <code>a</code>.
|
||||
Note that the order of subexpressions in initialization expressions is irrelevant:
|
||||
<code>a = c + b</code> and <code>a = b + c</code> result in the same initialization
|
||||
order in this example.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Dependency analysis is performed per package; only references referring
|
||||
to variables, functions, and (non-interface) methods declared in the current
|
||||
package are considered. If other, hidden, data dependencies exists between
|
||||
variables, the initialization order between those variables is unspecified.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For instance, given the declarations
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
var x = I(T{}).ab() // x has an undetected, hidden dependency on a and b
|
||||
var _ = sideEffect() // unrelated to x, a, or b
|
||||
var a = b
|
||||
var b = 42
|
||||
|
||||
type I interface { ab() []int }
|
||||
type T struct{}
|
||||
func (T) ab() []int { return []int{a, b} }
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
the variable <code>a</code> will be initialized after <code>b</code> but
|
||||
whether <code>x</code> is initialized before <code>b</code>, between
|
||||
<code>b</code> and <code>a</code>, or after <code>a</code>, and
|
||||
thus also the moment at which <code>sideEffect()</code> is called (before
|
||||
or after <code>x</code> is initialized) is not specified.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -627,6 +627,29 @@ contains further details regarding Go's ARM support.
|
|||
</p>
|
||||
</li>
|
||||
|
||||
<li><code>$GOPPC64</code> (for <code>ppc64</code> and <code>ppc64le</code> only)
|
||||
<p>
|
||||
This variable sets the processor level (i.e. Instruction Set Architecture version)
|
||||
for which the compiler will target. The default is <code>power8</code>.
|
||||
</p>
|
||||
<ul>
|
||||
<li><code>GOPPC64=power8</code>: generate ISA v2.07 instructions</li>
|
||||
<li><code>GOPPC64=power9</code>: generate ISA v3.00 instructions</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
||||
<li><code>$GOWASM</code> (for <code>wasm</code> only)
|
||||
<p>
|
||||
This variable is a comma separated list of <a href="https://github.com/WebAssembly/proposals">experimental WebAssembly features</a> that the compiled WebAssembly binary is allowed to use.
|
||||
The default is to use no experimental features.
|
||||
</p>
|
||||
<ul>
|
||||
<li><code>GOWASM=satconv</code>: generate <a href="https://github.com/WebAssembly/nontrapping-float-to-int-conversions/blob/master/proposals/nontrapping-float-to-int-conversion/Overview.md">saturating (non-trapping) float-to-int conversions</a></li>
|
||||
<li><code>GOWASM=signext</code>: generate <a href="https://github.com/WebAssembly/sign-extension-ops/blob/master/proposals/sign-extension-ops/Overview.md">sign-extension operators</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ If your OS or architecture is not on the list, you may be able to
|
|||
<tr><td>FreeBSD 10.3 or later</td> <td>amd64, 386</td> <td>Debian GNU/kFreeBSD not supported</td></tr>
|
||||
<tr valign='top'><td>Linux 2.6.23 or later with glibc</td> <td>amd64, 386, arm, arm64,<br>s390x, ppc64le</td> <td>CentOS/RHEL 5.x not supported.<br>Install from source for other libc.</td></tr>
|
||||
<tr><td>macOS 10.10 or later</td> <td>amd64</td> <td>use the clang or gcc<sup>†</sup> that comes with Xcode<sup>‡</sup> for <code>cgo</code> support</td></tr>
|
||||
<tr><td>Windows 7, Server 2008R2 or later</td> <td>amd64, 386</td> <td>use MinGW gcc<sup>†</sup>. No need for cygwin or msys.</td></tr>
|
||||
<tr valign='top'><td>Windows 7, Server 2008R2 or later</td> <td>amd64, 386</td> <td>use MinGW (<code>386</code>) or MinGW-W64 (<code>amd64</code>) gcc<sup>†</sup>.<br>No need for cygwin or msys.</td></tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
|
|
@ -204,7 +204,7 @@ you will need to <a href="https://golang.org/wiki/SettingGOPATH">set the <code>G
|
|||
</p>
|
||||
|
||||
<p>
|
||||
Next, make the directory <code>src/hello</code> inside your workspace,
|
||||
Next, make the directory <code class="testUnix">src/hello</code><code class="testWindows">src\hello</code> inside your workspace,
|
||||
and in that directory create a file named <code>hello.go</code> that looks like:
|
||||
</p>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ C compiler from the Android NDK. For example,
|
|||
CGO_ENABLED=1 \
|
||||
GOOS=android \
|
||||
GOARCH=arm64 \
|
||||
CC=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang \
|
||||
CC_FOR_TARGET=$NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang \
|
||||
./all.bash
|
||||
|
||||
To run tests on the Android device, add the bin directory to PATH so the
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ package main
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
|
|
@ -25,12 +26,9 @@ import (
|
|||
"syscall"
|
||||
)
|
||||
|
||||
func run(args ...string) string {
|
||||
if flags := os.Getenv("GOANDROID_ADB_FLAGS"); flags != "" {
|
||||
args = append(strings.Split(flags, " "), args...)
|
||||
}
|
||||
func run(args ...string) (string, error) {
|
||||
cmd := adbCmd(args...)
|
||||
buf := new(bytes.Buffer)
|
||||
cmd := exec.Command("adb", args...)
|
||||
cmd.Stdout = io.MultiWriter(os.Stdout, buf)
|
||||
// If the adb subprocess somehow hangs, go test will kill this wrapper
|
||||
// and wait for our os.Stderr (and os.Stdout) to close as a result.
|
||||
|
|
@ -42,69 +40,113 @@ func run(args ...string) string {
|
|||
// forcing cmd.Run to use another pipe and goroutine to pass
|
||||
// along stderr from adb.
|
||||
cmd.Stderr = struct{ io.Writer }{os.Stderr}
|
||||
log.Printf("adb %s", strings.Join(args, " "))
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatalf("adb %s: %v", strings.Join(args, " "), err)
|
||||
return "", fmt.Errorf("adb %s: %v", strings.Join(args, " "), err)
|
||||
}
|
||||
return buf.String()
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func adb(args ...string) error {
|
||||
if out, err := adbCmd(args...).CombinedOutput(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "adb %s\n%s", strings.Join(args, " "), out)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func adbCmd(args ...string) *exec.Cmd {
|
||||
if flags := os.Getenv("GOANDROID_ADB_FLAGS"); flags != "" {
|
||||
args = append(strings.Split(flags, " "), args...)
|
||||
}
|
||||
return exec.Command("adb", args...)
|
||||
}
|
||||
|
||||
const (
|
||||
// Directory structure on the target device androidtest.bash assumes.
|
||||
deviceGoroot = "/data/local/tmp/goroot"
|
||||
deviceGopath = "/data/local/tmp/gopath"
|
||||
deviceRoot = "/data/local/tmp/go_android_exec"
|
||||
deviceGoroot = deviceRoot + "/goroot"
|
||||
)
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
log.SetPrefix("go_android_exec: ")
|
||||
exitCode, err := runMain()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
func runMain() (int, error) {
|
||||
// Concurrent use of adb is flaky, so serialize adb commands.
|
||||
// See https://github.com/golang/go/issues/23795 or
|
||||
// https://issuetracker.google.com/issues/73230216.
|
||||
lockPath := filepath.Join(os.TempDir(), "go_android_exec-adb-lock")
|
||||
lock, err := os.OpenFile(lockPath, os.O_CREATE|os.O_RDWR, 0666)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return 0, err
|
||||
}
|
||||
defer lock.Close()
|
||||
if err := syscall.Flock(int(lock.Fd()), syscall.LOCK_EX); err != nil {
|
||||
log.Fatal(err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// In case we're booting a device or emulator alongside androidtest.bash
|
||||
// wait for it to be ready. adb wait-for-device is not enough, we have to
|
||||
// In case we're booting a device or emulator alongside all.bash, wait for
|
||||
// it to be ready. adb wait-for-device is not enough, we have to
|
||||
// wait for sys.boot_completed.
|
||||
run("wait-for-device", "shell", "while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done;")
|
||||
if err := adb("wait-for-device", "exec-out", "while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done;"); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Done once per make.bash.
|
||||
if err := adbCopyGoroot(); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Prepare a temporary directory that will be cleaned up at the end.
|
||||
deviceGotmp := fmt.Sprintf("/data/local/tmp/%s-%d",
|
||||
filepath.Base(os.Args[1]), os.Getpid())
|
||||
run("shell", "mkdir", "-p", deviceGotmp)
|
||||
// Binary names can conflict.
|
||||
// E.g. template.test from the {html,text}/template packages.
|
||||
binName := filepath.Base(os.Args[1])
|
||||
deviceGotmp := fmt.Sprintf(deviceRoot+"/%s-%d", binName, os.Getpid())
|
||||
deviceGopath := deviceGotmp + "/gopath"
|
||||
defer adb("exec-out", "rm", "-rf", deviceGotmp) // Clean up.
|
||||
|
||||
// Determine the package by examining the current working
|
||||
// directory, which will look something like
|
||||
// "$GOROOT/src/mime/multipart" or "$GOPATH/src/golang.org/x/mobile".
|
||||
// We extract everything after the $GOROOT or $GOPATH to run on the
|
||||
// same relative directory on the target device.
|
||||
subdir, inGoRoot := subdir()
|
||||
deviceCwd := filepath.Join(deviceGoroot, subdir)
|
||||
if !inGoRoot {
|
||||
deviceCwd = filepath.Join(deviceGopath, subdir)
|
||||
} else {
|
||||
adbSyncGoroot()
|
||||
subdir, inGoRoot, err := subdir()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
deviceCwd := filepath.Join(deviceGopath, subdir)
|
||||
if inGoRoot {
|
||||
deviceCwd = filepath.Join(deviceGoroot, subdir)
|
||||
} else {
|
||||
if err := adb("exec-out", "mkdir", "-p", deviceCwd); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err := adbCopyTree(deviceCwd, subdir); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Copy .go files from the package.
|
||||
goFiles, err := filepath.Glob("*.go")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if len(goFiles) > 0 {
|
||||
args := append(append([]string{"push"}, goFiles...), deviceCwd)
|
||||
if err := adb(args...); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
}
|
||||
run("shell", "mkdir", "-p", deviceCwd)
|
||||
|
||||
// Binary names can conflict.
|
||||
// E.g. template.test from the {html,text}/template packages.
|
||||
binName := fmt.Sprintf("%s-%d", filepath.Base(os.Args[1]), os.Getpid())
|
||||
deviceBin := fmt.Sprintf("%s/%s", deviceGotmp, binName)
|
||||
run("push", os.Args[1], deviceBin)
|
||||
|
||||
if _, err := os.Stat("testdata"); err == nil {
|
||||
run("push", "testdata", deviceCwd)
|
||||
if err := adb("push", os.Args[1], deviceBin); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Forward SIGQUIT from the go command to show backtraces from
|
||||
|
|
@ -115,108 +157,185 @@ func main() {
|
|||
for range quit {
|
||||
// We don't have the PID of the running process; use the
|
||||
// binary name instead.
|
||||
run("shell", "killall -QUIT "+binName)
|
||||
adb("exec-out", "killall -QUIT "+binName)
|
||||
}
|
||||
}()
|
||||
// The adb shell command will return an exit code of 0 regardless
|
||||
// of the command run. E.g.
|
||||
// $ adb shell false
|
||||
// $ echo $?
|
||||
// 0
|
||||
// In light of
|
||||
// https://code.google.com/p/android/issues/detail?id=3254
|
||||
// So we append the exitcode to the output and parse it from there.
|
||||
// dont trust the exitcode of adb. Instead, append the exitcode to
|
||||
// the output and parse it from there.
|
||||
const exitstr = "exitcode="
|
||||
cmd := `export TMPDIR="` + deviceGotmp + `"` +
|
||||
`; export GOROOT="` + deviceGoroot + `"` +
|
||||
`; export GOPATH="` + deviceGopath + `"` +
|
||||
`; export CGO_ENABLED=0` +
|
||||
`; export GOPROXY=` + os.Getenv("GOPROXY") +
|
||||
`; export GOCACHE="` + deviceRoot + `/gocache"` +
|
||||
`; export PATH=$PATH:"` + deviceGoroot + `/bin"` +
|
||||
`; cd "` + deviceCwd + `"` +
|
||||
"; '" + deviceBin + "' " + strings.Join(os.Args[2:], " ") +
|
||||
"; echo -n " + exitstr + "$?"
|
||||
output := run("shell", cmd)
|
||||
output, err := run("exec-out", cmd)
|
||||
signal.Reset(syscall.SIGQUIT)
|
||||
close(quit)
|
||||
|
||||
run("shell", "rm", "-rf", deviceGotmp) // Clean up.
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
exitIdx := strings.LastIndex(output, exitstr)
|
||||
if exitIdx == -1 {
|
||||
log.Fatalf("no exit code: %q", output)
|
||||
return 0, fmt.Errorf("no exit code: %q", output)
|
||||
}
|
||||
code, err := strconv.Atoi(output[exitIdx+len(exitstr):])
|
||||
if err != nil {
|
||||
log.Fatalf("bad exit code: %v", err)
|
||||
return 0, fmt.Errorf("bad exit code: %v", err)
|
||||
}
|
||||
os.Exit(code)
|
||||
return code, nil
|
||||
}
|
||||
|
||||
// subdir determines the package based on the current working directory,
|
||||
// and returns the path to the package source relative to $GOROOT (or $GOPATH).
|
||||
func subdir() (pkgpath string, underGoRoot bool) {
|
||||
func subdir() (pkgpath string, underGoRoot bool, err error) {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return "", false, err
|
||||
}
|
||||
if root := runtime.GOROOT(); strings.HasPrefix(cwd, root) {
|
||||
subdir, err := filepath.Rel(root, cwd)
|
||||
cwd, err = filepath.EvalSymlinks(cwd)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return "", false, err
|
||||
}
|
||||
goroot, err := filepath.EvalSymlinks(runtime.GOROOT())
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
if subdir, err := filepath.Rel(goroot, cwd); err == nil {
|
||||
if !strings.Contains(subdir, "..") {
|
||||
return subdir, true, nil
|
||||
}
|
||||
return subdir, true
|
||||
}
|
||||
|
||||
for _, p := range filepath.SplitList(build.Default.GOPATH) {
|
||||
if !strings.HasPrefix(cwd, p) {
|
||||
continue
|
||||
pabs, err := filepath.EvalSymlinks(p)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
subdir, err := filepath.Rel(p, cwd)
|
||||
if err == nil {
|
||||
return subdir, false
|
||||
if subdir, err := filepath.Rel(pabs, cwd); err == nil {
|
||||
if !strings.Contains(subdir, "..") {
|
||||
return subdir, false, nil
|
||||
}
|
||||
}
|
||||
log.Fatalf("the current path %q is not in either GOROOT(%q) or GOPATH(%q)",
|
||||
}
|
||||
return "", false, fmt.Errorf("the current path %q is not in either GOROOT(%q) or GOPATH(%q)",
|
||||
cwd, runtime.GOROOT(), build.Default.GOPATH)
|
||||
return "", false
|
||||
}
|
||||
|
||||
// adbSyncGoroot ensures that files necessary for testing the Go standard
|
||||
// packages are present on the attached device.
|
||||
func adbSyncGoroot() {
|
||||
// adbCopyTree copies testdata, go.mod, go.sum files from subdir
|
||||
// and from parent directories all the way up to the root of subdir.
|
||||
// go.mod and go.sum files are needed for the go tool modules queries,
|
||||
// and the testdata directories for tests. It is common for tests to
|
||||
// reach out into testdata from parent packages.
|
||||
func adbCopyTree(deviceCwd, subdir string) error {
|
||||
dir := ""
|
||||
for {
|
||||
for _, path := range []string{"testdata", "go.mod", "go.sum"} {
|
||||
path := filepath.Join(dir, path)
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
continue
|
||||
}
|
||||
devicePath := filepath.Join(deviceCwd, dir)
|
||||
if err := adb("exec-out", "mkdir", "-p", devicePath); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := adb("push", path, devicePath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if subdir == "." {
|
||||
break
|
||||
}
|
||||
subdir = filepath.Dir(subdir)
|
||||
dir = filepath.Join(dir, "..")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// adbCopyGoroot clears deviceRoot for previous versions of GOROOT, GOPATH
|
||||
// and temporary data. Then, it copies relevant parts of GOROOT to the device,
|
||||
// including the go tool built for android.
|
||||
// A lock file ensures this only happens once, even with concurrent exec
|
||||
// wrappers.
|
||||
func adbCopyGoroot() error {
|
||||
// Also known by cmd/dist. The bootstrap command deletes the file.
|
||||
statPath := filepath.Join(os.TempDir(), "go_android_exec-adb-sync-status")
|
||||
stat, err := os.OpenFile(statPath, os.O_CREATE|os.O_RDWR, 0666)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
defer stat.Close()
|
||||
// Serialize check and syncing.
|
||||
// Serialize check and copying.
|
||||
if err := syscall.Flock(int(stat.Fd()), syscall.LOCK_EX); err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
s, err := ioutil.ReadAll(stat)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
if string(s) == "done" {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
// Delete GOROOT, GOPATH and any leftover test data.
|
||||
if err := adb("exec-out", "rm", "-rf", deviceRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
deviceBin := filepath.Join(deviceGoroot, "bin")
|
||||
if err := adb("exec-out", "mkdir", "-p", deviceBin); err != nil {
|
||||
return err
|
||||
}
|
||||
devRoot := "/data/local/tmp/goroot"
|
||||
run("shell", "rm", "-rf", devRoot)
|
||||
run("shell", "mkdir", "-p", devRoot+"/pkg")
|
||||
goroot := runtime.GOROOT()
|
||||
// Build go for android.
|
||||
goCmd := filepath.Join(goroot, "bin", "go")
|
||||
runtimea, err := exec.Command(goCmd, "list", "-f", "{{.Target}}", "runtime").Output()
|
||||
tmpGo, err := ioutil.TempFile("", "go_android_exec-cmd-go-*")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
tmpGo.Close()
|
||||
defer os.Remove(tmpGo.Name())
|
||||
|
||||
if out, err := exec.Command(goCmd, "build", "-o", tmpGo.Name(), "cmd/go").CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("failed to build go tool for device: %s\n%v", out, err)
|
||||
}
|
||||
deviceGo := filepath.Join(deviceBin, "go")
|
||||
if err := adb("push", tmpGo.Name(), deviceGo); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, dir := range []string{"src", "test", "lib", "api"} {
|
||||
if err := adb("push", filepath.Join(goroot, dir), filepath.Join(deviceGoroot)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Copy only the relevant from pkg.
|
||||
if err := adb("exec-out", "mkdir", "-p", filepath.Join(deviceGoroot, "pkg", "tool")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := adb("push", filepath.Join(goroot, "pkg", "include"), filepath.Join(deviceGoroot, "pkg")); err != nil {
|
||||
return err
|
||||
}
|
||||
runtimea, err := exec.Command(goCmd, "list", "-f", "{{.Target}}", "runtime").Output()
|
||||
pkgdir := filepath.Dir(string(runtimea))
|
||||
if pkgdir == "" {
|
||||
log.Fatal("could not find android pkg dir")
|
||||
return errors.New("could not find android pkg dir")
|
||||
}
|
||||
for _, dir := range []string{"src", "test", "lib"} {
|
||||
run("push", filepath.Join(goroot, dir), filepath.Join(devRoot))
|
||||
if err := adb("push", pkgdir, filepath.Join(deviceGoroot, "pkg")); err != nil {
|
||||
return err
|
||||
}
|
||||
run("push", filepath.Join(pkgdir), filepath.Join(devRoot, "pkg/"))
|
||||
tooldir := filepath.Join(goroot, "pkg", "tool", filepath.Base(pkgdir))
|
||||
if err := adb("push", tooldir, filepath.Join(deviceGoroot, "pkg", "tool")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := stat.Write([]byte("done")); err != nil {
|
||||
log.Fatal(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,17 @@ goos=$(go env GOOS)
|
|||
libext="so"
|
||||
if [ "$goos" = "darwin" ]; then
|
||||
libext="dylib"
|
||||
elif [ "$goos" = "aix" ]; then
|
||||
libtext="a"
|
||||
fi
|
||||
|
||||
case "$FC" in
|
||||
*gfortran*)
|
||||
libpath=$(dirname $($FC -print-file-name=libgfortran.$libext))
|
||||
export CGO_LDFLAGS="$CGO_LDFLAGS -Wl,-rpath,$libpath -L $libpath"
|
||||
if [ "$goos" != "aix" ]; then
|
||||
RPATH_FLAG="-Wl,-rpath,$libpath"
|
||||
fi
|
||||
export CGO_LDFLAGS="$CGO_LDFLAGS $RPATH_FLAG -L $libpath"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ func testMain(m *testing.M) int {
|
|||
}
|
||||
|
||||
func TestTestRun(t *testing.T) {
|
||||
if os.Getenv("GOOS") == "android" {
|
||||
t.Skip("the go tool runs with CGO_ENABLED=0 on the android device")
|
||||
}
|
||||
out, err := exec.Command("go", "env", "GOROOT").Output()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ func testMain(m *testing.M) int {
|
|||
}
|
||||
|
||||
func TestTestRun(t *testing.T) {
|
||||
if os.Getenv("GOOS") == "android" {
|
||||
t.Skip("subpackage stdio is not available on android")
|
||||
}
|
||||
out, err := exec.Command("go", "env", "GOROOT").Output()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
|||
|
|
@ -199,7 +199,7 @@ func testCallbackCallers(t *testing.T) {
|
|||
t.Errorf("expected %d frames, got %d", len(name), n)
|
||||
}
|
||||
for i := 0; i < n; i++ {
|
||||
f := runtime.FuncForPC(pc[i])
|
||||
f := runtime.FuncForPC(pc[i] - 1) // TODO: use runtime.CallersFrames
|
||||
if f == nil {
|
||||
t.Fatalf("expected non-nil Func for pc %d", pc[i])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,16 @@
|
|||
|
||||
package cgotest
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSetgid(t *testing.T) { testSetgid(t) }
|
||||
func TestSetgid(t *testing.T) {
|
||||
if runtime.GOOS == "android" {
|
||||
t.Skip("unsupported on Android")
|
||||
}
|
||||
testSetgid(t)
|
||||
}
|
||||
func Test6997(t *testing.T) { test6997(t) }
|
||||
func TestBuildID(t *testing.T) { testBuildID(t) }
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ func Test25143(t *testing.T) { test25143(t) }
|
|||
func Test26066(t *testing.T) { test26066(t) }
|
||||
func Test27660(t *testing.T) { test27660(t) }
|
||||
func Test28896(t *testing.T) { test28896(t) }
|
||||
func Test29878(t *testing.T) { test29878(t) }
|
||||
func Test30065(t *testing.T) { test30065(t) }
|
||||
func TestAlign(t *testing.T) { testAlign(t) }
|
||||
func TestAtol(t *testing.T) { testAtol(t) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||
|
||||
#include <pthread.h>
|
||||
#include "_cgo_export.h"
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ import (
|
|||
// This is really an os package test but here for convenience.
|
||||
func testSetEnv(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
// Go uses SetEnvironmentVariable on windows. Howerver,
|
||||
// C runtime takes a *copy* at process startup of thei
|
||||
// Go uses SetEnvironmentVariable on windows. However,
|
||||
// C runtime takes a *copy* at process startup of the
|
||||
// OS environment, and stores it in environ/envp.
|
||||
// It is this copy that getenv/putenv manipulate.
|
||||
t.Logf("skipping test")
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ func test18146(t *testing.T) {
|
|||
switch runtime.GOOS {
|
||||
default:
|
||||
setNproc = false
|
||||
case "aix":
|
||||
nproc = 9
|
||||
case "linux":
|
||||
nproc = 6
|
||||
case "darwin", "dragonfly", "freebsd", "netbsd", "openbsd":
|
||||
|
|
|
|||
|
|
@ -11,7 +11,18 @@ package cgotest
|
|||
// #define ISSUE29781C 0
|
||||
import "C"
|
||||
|
||||
var issue29781X struct{ X int }
|
||||
|
||||
func issue29781F(...int) int { return 0 }
|
||||
|
||||
func issue29781G() {
|
||||
var p *C.char
|
||||
C.issue29781F(&p, C.ISSUE29781C+1)
|
||||
C.issue29781F(nil, (C.int)(
|
||||
0))
|
||||
C.issue29781F(&p, (C.int)(0))
|
||||
C.issue29781F(&p, (C.int)(
|
||||
0))
|
||||
C.issue29781F(&p, (C.int)(issue29781X.
|
||||
X))
|
||||
}
|
||||
|
|
|
|||
20
misc/cgo/test/issue29878.go
Normal file
20
misc/cgo/test/issue29878.go
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cgotest
|
||||
|
||||
// #include <stdint.h>
|
||||
// uint64_t issue29878exported(int8_t); // prototype must match
|
||||
// int16_t issue29878function(uint32_t arg) { return issue29878exported(arg); }
|
||||
import "C"
|
||||
|
||||
import "testing"
|
||||
|
||||
func test29878(t *testing.T) {
|
||||
const arg uint32 = 123 // fits into all integer types
|
||||
var ret int16 = C.issue29878function(arg) // no conversions needed
|
||||
if int64(ret) != int64(arg) {
|
||||
t.Errorf("return value unexpected: got %d, want %d", ret, arg)
|
||||
}
|
||||
}
|
||||
12
misc/cgo/test/issue29878export.go
Normal file
12
misc/cgo/test/issue29878export.go
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cgotest
|
||||
|
||||
import "C"
|
||||
|
||||
//export issue29878exported
|
||||
func issue29878exported(arg int8) uint64 {
|
||||
return uint64(arg)
|
||||
}
|
||||
|
|
@ -27,7 +27,10 @@ import (
|
|||
// this shim and move the tests currently located in testdata back into the
|
||||
// parent directory.
|
||||
func TestCrossPackageTests(t *testing.T) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
switch runtime.GOOS {
|
||||
case "android":
|
||||
t.Skip("Can't exec cmd/go subprocess on Android.")
|
||||
case "darwin":
|
||||
switch runtime.GOARCH {
|
||||
case "arm", "arm64":
|
||||
t.Skip("Can't exec cmd/go subprocess on iOS.")
|
||||
|
|
@ -56,7 +59,7 @@ func TestCrossPackageTests(t *testing.T) {
|
|||
cmd.Args = append(cmd.Args, "-short")
|
||||
}
|
||||
cmd.Dir = modRoot
|
||||
cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
|
||||
cmd.Env = append(os.Environ(), "GOPATH="+GOPATH, "PWD="+cmd.Dir)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err == nil {
|
||||
t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ import (
|
|||
|
||||
func testSigaltstack(t *testing.T) {
|
||||
switch {
|
||||
case runtime.GOOS == "solaris", runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64"):
|
||||
case runtime.GOOS == "solaris", runtime.GOOS == "illumos", runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64"):
|
||||
t.Skipf("switching signal stack not implemented on %s/%s", runtime.GOOS, runtime.GOARCH)
|
||||
case runtime.GOOS == "darwin" && runtime.GOARCH == "386":
|
||||
t.Skipf("sigaltstack fails on darwin/386")
|
||||
|
|
|
|||
12
misc/cgo/test/testdata/issue29563.go
vendored
Normal file
12
misc/cgo/test/testdata/issue29563.go
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build !windows
|
||||
|
||||
// Issue 29563: internal linker fails on duplicate weak symbols.
|
||||
// No runtime test; just make sure it compiles.
|
||||
|
||||
package cgotest
|
||||
|
||||
import _ "cgotest/issue29563"
|
||||
13
misc/cgo/test/testdata/issue29563/weak.go
vendored
Normal file
13
misc/cgo/test/testdata/issue29563/weak.go
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package issue29563
|
||||
|
||||
//int foo1();
|
||||
//int foo2();
|
||||
import "C"
|
||||
|
||||
func Bar() int {
|
||||
return int(C.foo1()) + int(C.foo2())
|
||||
}
|
||||
11
misc/cgo/test/testdata/issue29563/weak1.c
vendored
Normal file
11
misc/cgo/test/testdata/issue29563/weak1.c
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
extern int weaksym __attribute__((__weak__));
|
||||
int weaksym = 42;
|
||||
|
||||
int foo1()
|
||||
{
|
||||
return weaksym;
|
||||
}
|
||||
11
misc/cgo/test/testdata/issue29563/weak2.c
vendored
Normal file
11
misc/cgo/test/testdata/issue29563/weak2.c
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
extern int weaksym __attribute__((__weak__));
|
||||
int weaksym = 42;
|
||||
|
||||
int foo2()
|
||||
{
|
||||
return weaksym;
|
||||
}
|
||||
14
misc/cgo/test/testdata/issue30527.go
vendored
Normal file
14
misc/cgo/test/testdata/issue30527.go
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Issue 30527: function call rewriting casts untyped
|
||||
// constants to int because of ":=" usage.
|
||||
|
||||
package cgotest
|
||||
|
||||
import "cgotest/issue30527"
|
||||
|
||||
func issue30527G() {
|
||||
issue30527.G(nil)
|
||||
}
|
||||
19
misc/cgo/test/testdata/issue30527/a.go
vendored
Normal file
19
misc/cgo/test/testdata/issue30527/a.go
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package issue30527
|
||||
|
||||
import "math"
|
||||
|
||||
/*
|
||||
#include <inttypes.h>
|
||||
|
||||
static void issue30527F(char **p, uint64_t mod, uint32_t unused) {}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func G(p **C.char) {
|
||||
C.issue30527F(p, math.MaxUint64, 1)
|
||||
C.issue30527F(p, 1<<64-1, Z)
|
||||
}
|
||||
11
misc/cgo/test/testdata/issue30527/b.go
vendored
Normal file
11
misc/cgo/test/testdata/issue30527/b.go
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package issue30527
|
||||
|
||||
const (
|
||||
X = 1 << iota
|
||||
Y
|
||||
Z
|
||||
)
|
||||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"bufio"
|
||||
"bytes"
|
||||
"debug/elf"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
|
@ -36,6 +37,11 @@ var GOOS, GOARCH, GOPATH string
|
|||
var libgodir string
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
|
||||
fmt.Printf("SKIP - short mode and $GO_BUILDER_NAME not set\n")
|
||||
os.Exit(0)
|
||||
}
|
||||
log.SetFlags(log.Lshortfile)
|
||||
os.Exit(testMain(m))
|
||||
}
|
||||
|
|
@ -110,6 +116,11 @@ func testMain(m *testing.M) int {
|
|||
// TODO(crawshaw): can we do better?
|
||||
cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...)
|
||||
}
|
||||
if GOOS == "aix" {
|
||||
// -Wl,-bnoobjreorder is mandatory to keep the same layout
|
||||
// in .text section.
|
||||
cc = append(cc, "-Wl,-bnoobjreorder")
|
||||
}
|
||||
libbase := GOOS + "_" + GOARCH
|
||||
if runtime.Compiler == "gccgo" {
|
||||
libbase = "gccgo_" + libgodir + "_fPIC"
|
||||
|
|
@ -119,7 +130,7 @@ func testMain(m *testing.M) int {
|
|||
if GOARCH == "arm" || GOARCH == "arm64" {
|
||||
libbase += "_shared"
|
||||
}
|
||||
case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
|
||||
case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris", "illumos":
|
||||
libbase += "_shared"
|
||||
}
|
||||
}
|
||||
|
|
@ -318,8 +329,10 @@ func TestSignalForwarding(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSignalForwardingExternal(t *testing.T) {
|
||||
if GOOS == "freebsd" {
|
||||
if GOOS == "freebsd" || GOOS == "aix" {
|
||||
t.Skipf("skipping on %s/%s; signal always goes to the Go runtime", GOOS, GOARCH)
|
||||
} else if GOOS == "darwin" && GOARCH == "amd64" {
|
||||
t.Skipf("skipping on %s/%s: runtime does not permit SI_USER SIGSEGV", GOOS, GOARCH)
|
||||
}
|
||||
checkSignalForwardingTest(t)
|
||||
|
||||
|
|
@ -518,6 +531,9 @@ func TestExtar(t *testing.T) {
|
|||
if runtime.Compiler == "gccgo" {
|
||||
t.Skip("skipping -extar test when using gccgo")
|
||||
}
|
||||
if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
|
||||
t.Skip("shell scripts are not executable on iOS hosts")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
os.Remove("libgo4.a")
|
||||
|
|
@ -594,6 +610,7 @@ func TestPIE(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if GOOS != "aix" {
|
||||
f, err := elf.Open("testp" + exeSuffix)
|
||||
if err != nil {
|
||||
t.Fatal("elf.Open failed: ", err)
|
||||
|
|
@ -602,6 +619,7 @@ func TestPIE(t *testing.T) {
|
|||
if hasDynTag(t, f, elf.DT_TEXTREL) {
|
||||
t.Errorf("%s has DT_TEXTREL flag", "testp"+exeSuffix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func hasDynTag(t *testing.T, f *elf.File, tag elf.DynTag) bool {
|
||||
|
|
|
|||
19
misc/cgo/testcarchive/testdata/main4.c
vendored
19
misc/cgo/testcarchive/testdata/main4.c
vendored
|
|
@ -14,6 +14,13 @@
|
|||
|
||||
#include "libgo4.h"
|
||||
|
||||
#ifdef _AIX
|
||||
// On AIX, CSIGSTKSZ is too small to handle Go sighandler.
|
||||
#define CSIGSTKSZ 0x4000
|
||||
#else
|
||||
#define CSIGSTKSZ SIGSTKSZ
|
||||
#endif
|
||||
|
||||
static void die(const char* msg) {
|
||||
perror(msg);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -53,12 +60,12 @@ static void* thread1(void* arg __attribute__ ((unused))) {
|
|||
|
||||
// Set up an alternate signal stack for this thread.
|
||||
memset(&ss, 0, sizeof ss);
|
||||
ss.ss_sp = malloc(SIGSTKSZ);
|
||||
ss.ss_sp = malloc(CSIGSTKSZ);
|
||||
if (ss.ss_sp == NULL) {
|
||||
die("malloc");
|
||||
}
|
||||
ss.ss_flags = 0;
|
||||
ss.ss_size = SIGSTKSZ;
|
||||
ss.ss_size = CSIGSTKSZ;
|
||||
if (sigaltstack(&ss, NULL) < 0) {
|
||||
die("sigaltstack");
|
||||
}
|
||||
|
|
@ -93,7 +100,7 @@ static void* thread1(void* arg __attribute__ ((unused))) {
|
|||
fprintf(stderr, "sigaltstack disabled on return from Go\n");
|
||||
ok = 0;
|
||||
} else if (nss.ss_sp != ss.ss_sp) {
|
||||
fprintf(stderr, "sigalstack changed on return from Go\n");
|
||||
fprintf(stderr, "sigaltstack changed on return from Go\n");
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
|
|
@ -112,12 +119,12 @@ static void* thread2(void* arg __attribute__ ((unused))) {
|
|||
|
||||
// Set up an alternate signal stack for this thread.
|
||||
memset(&ss, 0, sizeof ss);
|
||||
ss.ss_sp = malloc(SIGSTKSZ);
|
||||
ss.ss_sp = malloc(CSIGSTKSZ);
|
||||
if (ss.ss_sp == NULL) {
|
||||
die("malloc");
|
||||
}
|
||||
ss.ss_flags = 0;
|
||||
ss.ss_size = SIGSTKSZ;
|
||||
ss.ss_size = CSIGSTKSZ;
|
||||
if (sigaltstack(&ss, NULL) < 0) {
|
||||
die("sigaltstack");
|
||||
}
|
||||
|
|
@ -150,7 +157,7 @@ static void* thread2(void* arg __attribute__ ((unused))) {
|
|||
fprintf(stderr, "sigaltstack disabled on return from Go\n");
|
||||
ok = 0;
|
||||
} else if (nss.ss_sp != ss.ss_sp) {
|
||||
fprintf(stderr, "sigalstack changed on return from Go\n");
|
||||
fprintf(stderr, "sigaltstack changed on return from Go\n");
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
6
misc/cgo/testcarchive/testdata/main5.c
vendored
6
misc/cgo/testcarchive/testdata/main5.c
vendored
|
|
@ -14,6 +14,8 @@
|
|||
|
||||
#include "libgo2.h"
|
||||
|
||||
int *nilp;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int verbose;
|
||||
int test;
|
||||
|
|
@ -39,7 +41,7 @@ int main(int argc, char** argv) {
|
|||
printf("attempting segfault\n");
|
||||
}
|
||||
|
||||
volatile int crash = *(int *) 0;
|
||||
*nilp = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +87,7 @@ int main(int argc, char** argv) {
|
|||
printf("write(2) unexpectedly succeeded\n");
|
||||
return 0;
|
||||
}
|
||||
printf("did not receieve SIGPIPE\n");
|
||||
printf("did not receive SIGPIPE\n");
|
||||
return 0;
|
||||
}
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -7,12 +7,14 @@ package cshared_test
|
|||
import (
|
||||
"bytes"
|
||||
"debug/elf"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
|
@ -35,6 +37,11 @@ func TestMain(m *testing.M) {
|
|||
|
||||
func testMain(m *testing.M) int {
|
||||
log.SetFlags(log.Lshortfile)
|
||||
flag.Parse()
|
||||
if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
|
||||
fmt.Printf("SKIP - short mode and $GO_BUILDER_NAME not set\n")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
GOOS = goEnv("GOOS")
|
||||
GOARCH = goEnv("GOARCH")
|
||||
|
|
@ -45,8 +52,8 @@ func testMain(m *testing.M) int {
|
|||
}
|
||||
|
||||
androiddir = fmt.Sprintf("/data/local/tmp/testcshared-%d", os.Getpid())
|
||||
if GOOS == "android" {
|
||||
args := append(adbCmd(), "shell", "mkdir", "-p", androiddir)
|
||||
if runtime.GOOS != GOOS && GOOS == "android" {
|
||||
args := append(adbCmd(), "exec-out", "mkdir", "-p", androiddir)
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
|
|
@ -104,7 +111,7 @@ func testMain(m *testing.M) int {
|
|||
if GOARCH == "arm" || GOARCH == "arm64" {
|
||||
libgodir += "_shared"
|
||||
}
|
||||
case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
|
||||
case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris", "illumos":
|
||||
libgodir += "_shared"
|
||||
}
|
||||
cc = append(cc, "-I", filepath.Join("pkg", libgodir))
|
||||
|
|
@ -177,7 +184,7 @@ func adbCmd() []string {
|
|||
}
|
||||
|
||||
func adbPush(t *testing.T, filename string) {
|
||||
if GOOS != "android" {
|
||||
if runtime.GOOS == GOOS || GOOS != "android" {
|
||||
return
|
||||
}
|
||||
args := append(adbCmd(), "push", filename, fmt.Sprintf("%s/%s", androiddir, filename))
|
||||
|
|
@ -191,7 +198,7 @@ func adbRun(t *testing.T, env []string, adbargs ...string) string {
|
|||
if GOOS != "android" {
|
||||
t.Fatalf("trying to run adb command when operating system is not android.")
|
||||
}
|
||||
args := append(adbCmd(), "shell")
|
||||
args := append(adbCmd(), "exec-out")
|
||||
// Propagate LD_LIBRARY_PATH to the adb shell invocation.
|
||||
for _, e := range env {
|
||||
if strings.Index(e, "LD_LIBRARY_PATH=") != -1 {
|
||||
|
|
@ -236,7 +243,7 @@ func run(t *testing.T, extraEnv []string, args ...string) string {
|
|||
|
||||
func runExe(t *testing.T, extraEnv []string, args ...string) string {
|
||||
t.Helper()
|
||||
if GOOS == "android" {
|
||||
if runtime.GOOS != GOOS && GOOS == "android" {
|
||||
return adbRun(t, append(os.Environ(), extraEnv...), args...)
|
||||
}
|
||||
return run(t, extraEnv, args...)
|
||||
|
|
@ -268,7 +275,7 @@ func createHeaders() error {
|
|||
return fmt.Errorf("command failed: %v\n%v\n%s\n", args, err, out)
|
||||
}
|
||||
|
||||
if GOOS == "android" {
|
||||
if runtime.GOOS != GOOS && GOOS == "android" {
|
||||
args = append(adbCmd(), "push", libgoname, fmt.Sprintf("%s/%s", androiddir, libgoname))
|
||||
cmd = exec.Command(args[0], args[1:]...)
|
||||
out, err = cmd.CombinedOutput()
|
||||
|
|
@ -298,7 +305,7 @@ func cleanupAndroid() {
|
|||
if GOOS != "android" {
|
||||
return
|
||||
}
|
||||
args := append(adbCmd(), "shell", "rm", "-rf", androiddir)
|
||||
args := append(adbCmd(), "exec-out", "rm", "-rf", androiddir)
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
|
|
@ -521,7 +528,7 @@ func TestCachedInstall(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// defer os.RemoveAll(tmpdir)
|
||||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
copyFile(t, filepath.Join(tmpdir, "src", "testcshared", "go.mod"), "go.mod")
|
||||
copyFile(t, filepath.Join(tmpdir, "src", "testcshared", "libgo", "libgo.go"), filepath.Join("libgo", "libgo.go"))
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package plugin_test
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
|
@ -22,8 +23,16 @@ import (
|
|||
var gcflags string = os.Getenv("GO_GCFLAGS")
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Parse()
|
||||
if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
|
||||
fmt.Printf("SKIP - short mode and $GO_BUILDER_NAME not set\n")
|
||||
os.Exit(0)
|
||||
}
|
||||
log.SetFlags(log.Lshortfile)
|
||||
os.Exit(testMain(m))
|
||||
}
|
||||
|
||||
func testMain(m *testing.M) int {
|
||||
// Copy testdata into GOPATH/src/testarchive, along with a go.mod file
|
||||
// declaring the same path.
|
||||
|
||||
|
|
@ -77,7 +86,7 @@ func TestMain(m *testing.M) {
|
|||
goCmd(nil, "build", "-buildmode=plugin", "-o=unnamed2.so", "./unnamed2/main.go")
|
||||
goCmd(nil, "build", "-o", "host.exe", "./host")
|
||||
|
||||
os.Exit(m.Run())
|
||||
return m.Run()
|
||||
}
|
||||
|
||||
func goCmd(t *testing.T, op string, args ...string) {
|
||||
|
|
|
|||
3
misc/cgo/testplugin/testdata/iface/main.go
vendored
3
misc/cgo/testplugin/testdata/iface/main.go
vendored
|
|
@ -5,9 +5,10 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testplugin/iface_i"
|
||||
"log"
|
||||
"plugin"
|
||||
|
||||
"testplugin/iface_i"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@ package main
|
|||
import "C"
|
||||
|
||||
import (
|
||||
"testplugin/common"
|
||||
"reflect"
|
||||
|
||||
"testplugin/common"
|
||||
)
|
||||
|
||||
func F() int {
|
||||
|
|
|
|||
|
|
@ -12,9 +12,10 @@ import "C"
|
|||
// void cfunc() {} // uses cgo_topofstack
|
||||
|
||||
import (
|
||||
"testplugin/common"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"testplugin/common"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
|||
3
misc/cgo/testshared/testdata/exe/exe.go
vendored
3
misc/cgo/testshared/testdata/exe/exe.go
vendored
|
|
@ -1,10 +1,11 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testshared/depBase"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime"
|
||||
|
||||
"testshared/depBase"
|
||||
)
|
||||
|
||||
// Having a function declared in the main package triggered
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ func requireTestSOSupported(t *testing.T) {
|
|||
t.Skip("No exec facility on iOS.")
|
||||
}
|
||||
case "ppc64":
|
||||
t.Skip("External linking not implemented on ppc64 (issue #8912).")
|
||||
if runtime.GOOS == "linux" {
|
||||
t.Skip("External linking not implemented on aix/ppc64 (issue #8912).")
|
||||
}
|
||||
case "mips64le", "mips64":
|
||||
t.Skip("External linking not implemented on mips64.")
|
||||
}
|
||||
|
|
@ -80,6 +82,8 @@ func TestSO(t *testing.T) {
|
|||
case "windows":
|
||||
ext = "dll"
|
||||
args = append(args, "-DEXPORT_DLL")
|
||||
case "aix":
|
||||
ext = "so.1"
|
||||
}
|
||||
sofname := "libcgosotest." + ext
|
||||
args = append(args, "-o", sofname, "cgoso_c.c")
|
||||
|
|
@ -93,6 +97,16 @@ func TestSO(t *testing.T) {
|
|||
}
|
||||
t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
|
||||
|
||||
if runtime.GOOS == "aix" {
|
||||
// Shared object must be wrapped by an archive
|
||||
cmd = exec.Command("ar", "-X64", "-q", "libcgosotest.a", "libcgosotest.so.1")
|
||||
cmd.Dir = modRoot
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
|
||||
}
|
||||
}
|
||||
|
||||
cmd = exec.Command("go", "build", "-o", "main.exe", "main.go")
|
||||
cmd.Dir = modRoot
|
||||
cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
|
||||
|
|
|
|||
2
misc/cgo/testso/testdata/cgoso.c
vendored
2
misc/cgo/testso/testdata/cgoso.c
vendored
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include "_cgo_export.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#if defined(WIN32) || defined(_AIX)
|
||||
extern void setCallback(void *);
|
||||
void init() {
|
||||
setCallback(goCallback);
|
||||
|
|
|
|||
1
misc/cgo/testso/testdata/cgoso.go
vendored
1
misc/cgo/testso/testdata/cgoso.go
vendored
|
|
@ -15,6 +15,7 @@ package cgosotest
|
|||
#cgo netbsd LDFLAGS: -L. libcgosotest.so
|
||||
#cgo darwin LDFLAGS: -L. libcgosotest.dylib
|
||||
#cgo windows LDFLAGS: -L. libcgosotest.dll
|
||||
#cgo aix LDFLAGS: -L. -l cgosotest
|
||||
|
||||
void init(void);
|
||||
void sofunc(void);
|
||||
|
|
|
|||
9
misc/cgo/testso/testdata/cgoso_c.c
vendored
9
misc/cgo/testso/testdata/cgoso_c.c
vendored
|
|
@ -14,6 +14,15 @@ __declspec(dllexport) void setCallback(void *f)
|
|||
goCallback = (void (*)())f;
|
||||
}
|
||||
__declspec(dllexport) void sofunc(void);
|
||||
#elif defined(_AIX)
|
||||
// AIX doesn't allow the creation of a shared object with an
|
||||
// undefined symbol. It's possible to bypass this problem by
|
||||
// using -Wl,-G and -Wl,-brtl option which allows run-time linking.
|
||||
// However, that's not how most of AIX shared object works.
|
||||
// Therefore, it's better to consider goCallback as a pointer and
|
||||
// to set up during an init function.
|
||||
void (*goCallback)(void);
|
||||
void setCallback(void *f) { goCallback = f; }
|
||||
#else
|
||||
extern void goCallback(void);
|
||||
void setCallback(void *f) { (void)f; }
|
||||
|
|
|
|||
2
misc/cgo/testso/testdata/cgoso_unix.go
vendored
2
misc/cgo/testso/testdata/cgoso_unix.go
vendored
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build dragonfly freebsd linux netbsd solaris
|
||||
// +build aix dragonfly freebsd linux netbsd solaris
|
||||
|
||||
package cgosotest
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ func requireTestSOSupported(t *testing.T) {
|
|||
t.Skip("No exec facility on iOS.")
|
||||
}
|
||||
case "ppc64":
|
||||
t.Skip("External linking not implemented on ppc64 (issue #8912).")
|
||||
if runtime.GOOS == "linux" {
|
||||
t.Skip("External linking not implemented on aix/ppc64 (issue #8912).")
|
||||
}
|
||||
case "mips64le", "mips64":
|
||||
t.Skip("External linking not implemented on mips64.")
|
||||
}
|
||||
|
|
@ -80,6 +82,8 @@ func TestSO(t *testing.T) {
|
|||
case "windows":
|
||||
ext = "dll"
|
||||
args = append(args, "-DEXPORT_DLL")
|
||||
case "aix":
|
||||
ext = "so.1"
|
||||
}
|
||||
sofname := "libcgosotest." + ext
|
||||
args = append(args, "-o", sofname, "cgoso_c.c")
|
||||
|
|
@ -93,6 +97,16 @@ func TestSO(t *testing.T) {
|
|||
}
|
||||
t.Logf("%s:\n%s", strings.Join(cmd.Args, " "), out)
|
||||
|
||||
if runtime.GOOS == "aix" {
|
||||
// Shared object must be wrapped by an archive
|
||||
cmd = exec.Command("ar", "-X64", "-q", "libcgosotest.a", "libcgosotest.so.1")
|
||||
cmd.Dir = modRoot
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: %s\n%s", strings.Join(cmd.Args, " "), err, out)
|
||||
}
|
||||
}
|
||||
|
||||
cmd = exec.Command("go", "build", "-o", "main.exe", "main.go")
|
||||
cmd.Dir = modRoot
|
||||
cmd.Env = append(os.Environ(), "GOPATH="+GOPATH)
|
||||
|
|
|
|||
1
misc/cgo/testsovar/testdata/cgoso.go
vendored
1
misc/cgo/testsovar/testdata/cgoso.go
vendored
|
|
@ -19,6 +19,7 @@ package cgosotest
|
|||
#cgo netbsd LDFLAGS: -L. libcgosotest.so
|
||||
#cgo darwin LDFLAGS: -L. libcgosotest.dylib
|
||||
#cgo windows LDFLAGS: -L. libcgosotest.dll
|
||||
#cgo aix LDFLAGS: -L. -l cgosotest
|
||||
|
||||
#include "cgoso_c.h"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
#!/bin/sh
|
||||
# Copyright 2012 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.
|
||||
|
||||
# git gofmt pre-commit hook
|
||||
#
|
||||
# To use, store as .git/hooks/pre-commit inside your repository and make sure
|
||||
# it has execute permissions.
|
||||
#
|
||||
# This script does not handle file names that contain spaces.
|
||||
|
||||
gofiles=$(git diff --cached --name-only --diff-filter=ACM | grep '\.go$')
|
||||
[ -z "$gofiles" ] && exit 0
|
||||
|
||||
unformatted=$(gofmt -l $gofiles)
|
||||
[ -z "$unformatted" ] && exit 0
|
||||
|
||||
# Some files are not gofmt'd. Print message and fail.
|
||||
|
||||
echo >&2 "Go files must be formatted with gofmt. Please run:"
|
||||
for fn in $unformatted; do
|
||||
echo >&2 " gofmt -w $PWD/$fn"
|
||||
done
|
||||
|
||||
exit 1
|
||||
11
misc/go.mod
Normal file
11
misc/go.mod
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
// Module misc contains tests and binaries that pertain to specific build modes
|
||||
// (cgo) and platforms (Android and iOS).
|
||||
//
|
||||
// The 'run' scripts in ../src execute these tests and binaries, which need to
|
||||
// be in a module in order to build and run successfully in module mode.
|
||||
// (Otherwise, they lack well-defined import paths, and module mode — unlike
|
||||
// GOPATH mode — does not synthesize import paths from the absolute working
|
||||
// directory.)
|
||||
module misc
|
||||
|
||||
go 1.12
|
||||
|
|
@ -31,9 +31,10 @@ which will output something similar to
|
|||
If you have multiple devices connected, specify the device UDID with the GOIOS_DEVICE_ID
|
||||
variable. Use `idevice_id -l` to list all available UDIDs.
|
||||
|
||||
Finally, to run the standard library tests, run iostest.bash with GOARCH set. For example,
|
||||
Finally, to run the standard library tests, run all.bash as usual, but with the compiler
|
||||
set to the clang wrapper that invokes clang for iOS. For example,
|
||||
|
||||
GOARCH=arm64 ./iostest.bash
|
||||
GOARCH=arm64 CGO_ENABLED=1 CC_FOR_TARGET=$(pwd)/../misc/ios/clangwrap.sh ./all.bash
|
||||
|
||||
To use the go tool directly to run programs and tests, put $GOROOT/bin into PATH to ensure
|
||||
the go_darwin_$GOARCH_exec wrapper is found. For example, to run the archive/tar tests
|
||||
|
|
|
|||
|
|
@ -467,8 +467,8 @@ func idevCmd(cmd *exec.Cmd) *exec.Cmd {
|
|||
func run(appdir, bundleID string, args []string) error {
|
||||
var env []string
|
||||
for _, e := range os.Environ() {
|
||||
// Don't override TMPDIR on the device.
|
||||
if strings.HasPrefix(e, "TMPDIR=") {
|
||||
// Don't override TMPDIR, HOME, GOCACHE on the device.
|
||||
if strings.HasPrefix(e, "TMPDIR=") || strings.HasPrefix(e, "HOME=") || strings.HasPrefix(e, "GOCACHE=") {
|
||||
continue
|
||||
}
|
||||
env = append(env, e)
|
||||
|
|
@ -633,8 +633,16 @@ func subdir() (pkgpath string, underGoRoot bool, err error) {
|
|||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
if root := runtime.GOROOT(); strings.HasPrefix(cwd, root) {
|
||||
subdir, err := filepath.Rel(root, cwd)
|
||||
cwd, err = filepath.EvalSymlinks(cwd)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
goroot, err := filepath.EvalSymlinks(runtime.GOROOT())
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
if strings.HasPrefix(cwd, goroot) {
|
||||
subdir, err := filepath.Rel(goroot, cwd)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
|
|
@ -642,10 +650,14 @@ func subdir() (pkgpath string, underGoRoot bool, err error) {
|
|||
}
|
||||
|
||||
for _, p := range filepath.SplitList(build.Default.GOPATH) {
|
||||
if !strings.HasPrefix(cwd, p) {
|
||||
pabs, err := filepath.EvalSymlinks(p)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
if !strings.HasPrefix(cwd, pabs) {
|
||||
continue
|
||||
}
|
||||
subdir, err := filepath.Rel(p, cwd)
|
||||
subdir, err := filepath.Rel(pabs, cwd)
|
||||
if err == nil {
|
||||
return subdir, false, nil
|
||||
}
|
||||
|
|
|
|||
2
misc/nacl/testdata/mime.types
vendored
2
misc/nacl/testdata/mime.types
vendored
|
|
@ -1,6 +1,6 @@
|
|||
# This file maps Internet media types to unique file extension(s).
|
||||
# Although created for httpd, this file is used by many software systems
|
||||
# and has been placed in the public domain for unlimited redisribution.
|
||||
# and has been placed in the public domain for unlimited redistribution.
|
||||
#
|
||||
# The table below contains both registered and (common) unregistered types.
|
||||
# A type that has no unique extension can be ignored -- they are listed
|
||||
|
|
|
|||
|
|
@ -48,42 +48,32 @@ go src=..
|
|||
pprof
|
||||
internal
|
||||
binutils
|
||||
testdata
|
||||
+
|
||||
driver
|
||||
testdata
|
||||
+
|
||||
graph
|
||||
testdata
|
||||
+
|
||||
report
|
||||
testdata
|
||||
+
|
||||
profile
|
||||
testdata
|
||||
+
|
||||
ianlancetaylor
|
||||
demangle
|
||||
testdata
|
||||
+
|
||||
golang.org
|
||||
x
|
||||
arch
|
||||
arm
|
||||
armasm
|
||||
testdata
|
||||
+
|
||||
arm64
|
||||
arm64asm
|
||||
testdata
|
||||
+
|
||||
x86
|
||||
x86asm
|
||||
testdata
|
||||
+
|
||||
ppc64
|
||||
ppc64asm
|
||||
testdata
|
||||
+
|
||||
archive
|
||||
tar
|
||||
|
|
@ -107,6 +97,9 @@ go src=..
|
|||
+
|
||||
zlib
|
||||
crypto
|
||||
ed25519
|
||||
testdata
|
||||
+
|
||||
rsa
|
||||
testdata
|
||||
+
|
||||
|
|
|
|||
80
misc/reboot/overlaydir_test.go
Normal file
80
misc/reboot/overlaydir_test.go
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package reboot_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added.
|
||||
//
|
||||
// TODO: Once we no longer need to support the misc module in GOPATH mode,
|
||||
// factor this function out into a package to reduce duplication.
|
||||
func overlayDir(dstRoot, srcRoot string) error {
|
||||
dstRoot = filepath.Clean(dstRoot)
|
||||
if err := os.MkdirAll(dstRoot, 0777); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If we don't use the absolute path here, exec'ing make.bash fails with
|
||||
// “too many levels of symbolic links”.
|
||||
symBase, err := filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
|
||||
if err != nil || srcPath == srcRoot {
|
||||
return err
|
||||
}
|
||||
|
||||
suffix := strings.TrimPrefix(srcPath, srcRoot)
|
||||
for len(suffix) > 0 && suffix[0] == filepath.Separator {
|
||||
suffix = suffix[1:]
|
||||
}
|
||||
dstPath := filepath.Join(dstRoot, suffix)
|
||||
|
||||
perm := info.Mode() & os.ModePerm
|
||||
if info.Mode()&os.ModeSymlink != 0 {
|
||||
info, err = os.Stat(srcPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
perm = info.Mode() & os.ModePerm
|
||||
}
|
||||
|
||||
// Always copy directories (don't symlink them).
|
||||
// If we add a file in the overlay, we don't want to add it in the original.
|
||||
if info.IsDir() {
|
||||
return os.Mkdir(dstPath, perm)
|
||||
}
|
||||
|
||||
// If the OS supports symlinks, use them instead of copying bytes.
|
||||
if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Otherwise, copy the bytes.
|
||||
src, err := os.Open(srcPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = io.Copy(dst, src)
|
||||
if closeErr := dst.Close(); err == nil {
|
||||
err = closeErr
|
||||
}
|
||||
return err
|
||||
})
|
||||
}
|
||||
52
misc/reboot/reboot_test.go
Normal file
52
misc/reboot/reboot_test.go
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package reboot_test verifies that the current GOROOT can be used to bootstrap
|
||||
// itself.
|
||||
package reboot_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRepeatBootstrap(t *testing.T) {
|
||||
goroot, err := ioutil.TempDir("", "reboot-goroot")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(goroot)
|
||||
|
||||
gorootSrc := filepath.Join(goroot, "src")
|
||||
if err := overlayDir(gorootSrc, filepath.Join(runtime.GOROOT(), "src")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(filepath.Join(goroot, "VERSION"), []byte(runtime.Version()), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var makeScript string
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
makeScript = "make.bat"
|
||||
case "plan9":
|
||||
makeScript = "make.rc"
|
||||
default:
|
||||
makeScript = "make.bash"
|
||||
}
|
||||
|
||||
cmd := exec.Command(filepath.Join(runtime.GOROOT(), "src", makeScript))
|
||||
cmd.Dir = gorootSrc
|
||||
cmd.Env = append(os.Environ(), "GOROOT=", "GOROOT_BOOTSTRAP="+runtime.GOROOT())
|
||||
cmd.Stderr = os.Stderr
|
||||
cmd.Stdout = os.Stdout
|
||||
if err := cmd.Run(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
@ -3,6 +3,15 @@
|
|||
// license that can be found in the LICENSE file.
|
||||
|
||||
(() => {
|
||||
// Map multiple JavaScript environments to a single common API,
|
||||
// preferring web standards over Node.js API.
|
||||
//
|
||||
// Environments considered:
|
||||
// - Browsers
|
||||
// - Node.js
|
||||
// - Electron
|
||||
// - Parcel
|
||||
|
||||
if (typeof global !== "undefined") {
|
||||
// global already exists
|
||||
} else if (typeof window !== "undefined") {
|
||||
|
|
@ -13,30 +22,15 @@
|
|||
throw new Error("cannot export Go (neither global, window nor self is defined)");
|
||||
}
|
||||
|
||||
// Map web browser API and Node.js API to a single common API (preferring web standards over Node.js API).
|
||||
const isNodeJS = global.process && global.process.title === "node";
|
||||
if (isNodeJS) {
|
||||
if (!global.require && typeof require !== "undefined") {
|
||||
global.require = require;
|
||||
}
|
||||
|
||||
if (!global.fs && global.require) {
|
||||
global.fs = require("fs");
|
||||
}
|
||||
|
||||
const nodeCrypto = require("crypto");
|
||||
global.crypto = {
|
||||
getRandomValues(b) {
|
||||
nodeCrypto.randomFillSync(b);
|
||||
},
|
||||
};
|
||||
|
||||
global.performance = {
|
||||
now() {
|
||||
const [sec, nsec] = process.hrtime();
|
||||
return sec * 1000 + nsec / 1000000;
|
||||
},
|
||||
};
|
||||
|
||||
const util = require("util");
|
||||
global.TextEncoder = util.TextEncoder;
|
||||
global.TextDecoder = util.TextDecoder;
|
||||
} else {
|
||||
if (!global.fs) {
|
||||
let outputBuf = "";
|
||||
global.fs = {
|
||||
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
|
||||
|
|
@ -72,6 +66,34 @@
|
|||
};
|
||||
}
|
||||
|
||||
if (!global.crypto) {
|
||||
const nodeCrypto = require("crypto");
|
||||
global.crypto = {
|
||||
getRandomValues(b) {
|
||||
nodeCrypto.randomFillSync(b);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (!global.performance) {
|
||||
global.performance = {
|
||||
now() {
|
||||
const [sec, nsec] = process.hrtime();
|
||||
return sec * 1000 + nsec / 1000000;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
if (!global.TextEncoder) {
|
||||
global.TextEncoder = require("util").TextEncoder;
|
||||
}
|
||||
|
||||
if (!global.TextDecoder) {
|
||||
global.TextDecoder = require("util").TextDecoder;
|
||||
}
|
||||
|
||||
// End of polyfills for common API.
|
||||
|
||||
const encoder = new TextEncoder("utf-8");
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
|
||||
|
|
@ -243,7 +265,15 @@
|
|||
const id = this._nextCallbackTimeoutID;
|
||||
this._nextCallbackTimeoutID++;
|
||||
this._scheduledTimeouts.set(id, setTimeout(
|
||||
() => { this._resume(); },
|
||||
() => {
|
||||
this._resume();
|
||||
while (this._scheduledTimeouts.has(id)) {
|
||||
// for some reason Go failed to register the timeout event, log and try again
|
||||
// (temporary workaround for https://github.com/golang/go/issues/28975)
|
||||
console.warn("scheduleTimeoutEvent: missed timeout event");
|
||||
this._resume();
|
||||
}
|
||||
},
|
||||
getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
|
||||
));
|
||||
mem().setInt32(sp + 16, id, true);
|
||||
|
|
@ -385,9 +415,13 @@
|
|||
let offset = 4096;
|
||||
|
||||
const strPtr = (str) => {
|
||||
let ptr = offset;
|
||||
new Uint8Array(mem.buffer, offset, str.length + 1).set(encoder.encode(str + "\0"));
|
||||
offset += str.length + (8 - (str.length % 8));
|
||||
const ptr = offset;
|
||||
const bytes = encoder.encode(str + "\0");
|
||||
new Uint8Array(mem.buffer, offset, bytes.length).set(bytes);
|
||||
offset += bytes.length;
|
||||
if (offset % 8 !== 0) {
|
||||
offset += 8 - (offset % 8);
|
||||
}
|
||||
return ptr;
|
||||
};
|
||||
|
||||
|
|
@ -439,9 +473,15 @@
|
|||
}
|
||||
}
|
||||
|
||||
if (isNodeJS) {
|
||||
if (
|
||||
global.require &&
|
||||
global.require.main === module &&
|
||||
global.process &&
|
||||
global.process.versions &&
|
||||
!global.process.versions.electron
|
||||
) {
|
||||
if (process.argv.length < 3) {
|
||||
process.stderr.write("usage: go_js_wasm_exec [wasm binary] [arguments]\n");
|
||||
console.error("usage: go_js_wasm_exec [wasm binary] [arguments]");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -459,7 +499,8 @@
|
|||
});
|
||||
return go.run(result.instance);
|
||||
}).catch((err) => {
|
||||
throw err;
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
|
|
|||
54
src/README.vendor
Normal file
54
src/README.vendor
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
Vendoring in std and cmd
|
||||
========================
|
||||
|
||||
The Go command maintains copies of external packages needed by the
|
||||
standard library in the src/vendor and src/cmd/vendor directories.
|
||||
|
||||
In GOPATH mode, imports of vendored packages are resolved to these
|
||||
directories following normal vendor directory logic
|
||||
(see golang.org/s/go15vendor).
|
||||
|
||||
In module mode, std and cmd are modules (defined in src/go.mod and
|
||||
src/cmd/go.mod). When a package outside std or cmd is imported
|
||||
by a package inside std or cmd, the import path is interpreted
|
||||
as if it had a "vendor/" prefix. For example, within "crypto/tls",
|
||||
an import of "golang.org/x/crypto/cryptobyte" resolves to
|
||||
"vendor/golang.org/x/crypto/cryptobyte". When a package with the
|
||||
same path is imported from a package outside std or cmd, it will
|
||||
be resolved normally. Consequently, a binary may be built with two
|
||||
copies of a package at different versions if the package is
|
||||
imported normally and vendored by the standard library.
|
||||
|
||||
Vendored packages are internally renamed with a "vendor/" prefix
|
||||
to preserve the invariant that all packages have distinct paths.
|
||||
This is necessary to avoid compiler and linker conflicts. Adding
|
||||
a "vendor/" prefix also maintains the invariant that standard
|
||||
library packages begin with a dotless path element.
|
||||
|
||||
The module requirements of std and cmd do not influence version
|
||||
selection in other modules. They are only considered when running
|
||||
module commands like 'go get' and 'go mod vendor' from a directory
|
||||
in GOROOT/src.
|
||||
|
||||
Maintaining vendor directories
|
||||
==============================
|
||||
|
||||
Before updating vendor directories, ensure that module mode is enabled.
|
||||
Make sure GO111MODULE=off is not set ('on' or 'auto' should work).
|
||||
|
||||
Requirements may be added, updated, and removed with 'go get'.
|
||||
The vendor directory may be updated with 'go mod vendor'.
|
||||
A typical sequence might be:
|
||||
|
||||
cd src
|
||||
go get -m golang.org/x/net@latest
|
||||
go mod tidy
|
||||
go mod vendor
|
||||
|
||||
Use caution when passing '-u' to 'go get'. The '-u' flag updates
|
||||
modules providing all transitively imported packages, not just
|
||||
the target module.
|
||||
|
||||
Note that 'go mod vendor' only copies packages that are transitively
|
||||
imported by packages in the current module. If a new package is needed,
|
||||
it should be imported before running 'go mod vendor'.
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# 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.
|
||||
|
||||
# For testing Android.
|
||||
|
||||
set -e
|
||||
ulimit -c 0 # no core files
|
||||
|
||||
if [ ! -f make.bash ]; then
|
||||
echo 'androidtest.bash must be run from $GOROOT/src' 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z $GOOS ]; then
|
||||
export GOOS=android
|
||||
fi
|
||||
if [ "$GOOS" != "android" ]; then
|
||||
echo "androidtest.bash requires GOOS=android, got GOOS=$GOOS" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "$GOARM" ] && [ "$GOARM" != "7" ]; then
|
||||
echo "android only supports GOARM=7, got GOARM=$GOARM" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export CGO_ENABLED=1
|
||||
unset GOBIN
|
||||
|
||||
export GOROOT=$(dirname $(pwd))
|
||||
# Put the exec wrapper into PATH
|
||||
export PATH=$GOROOT/bin:$PATH
|
||||
|
||||
# Run standard tests.
|
||||
bash all.bash
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux dragonfly openbsd solaris
|
||||
// +build aix linux dragonfly openbsd solaris
|
||||
|
||||
package tar
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// +build linux darwin dragonfly freebsd openbsd netbsd solaris
|
||||
// +build aix linux darwin dragonfly freebsd openbsd netbsd solaris
|
||||
|
||||
package tar
|
||||
|
||||
|
|
@ -54,6 +54,11 @@ func statUnix(fi os.FileInfo, h *Header) error {
|
|||
if h.Typeflag == TypeChar || h.Typeflag == TypeBlock {
|
||||
dev := uint64(sys.Rdev) // May be int32 or uint32
|
||||
switch runtime.GOOS {
|
||||
case "aix":
|
||||
var major, minor uint32
|
||||
major = uint32((dev & 0x3fffffff00000000) >> 32)
|
||||
minor = uint32((dev & 0x00000000ffffffff) >> 0)
|
||||
h.Devmajor, h.Devminor = int64(major), int64(minor)
|
||||
case "linux":
|
||||
// Copied from golang.org/x/sys/unix/dev_linux.go.
|
||||
major := uint32((dev & 0x00000000000fff00) >> 8)
|
||||
|
|
|
|||
|
|
@ -155,7 +155,12 @@ func (fi headerFileInfo) Size() int64 {
|
|||
return int64(fi.fh.UncompressedSize)
|
||||
}
|
||||
func (fi headerFileInfo) IsDir() bool { return fi.Mode().IsDir() }
|
||||
func (fi headerFileInfo) ModTime() time.Time { return fi.fh.ModTime() }
|
||||
func (fi headerFileInfo) ModTime() time.Time {
|
||||
if fi.fh.Modified.IsZero() {
|
||||
return fi.fh.ModTime()
|
||||
}
|
||||
return fi.fh.Modified.UTC()
|
||||
}
|
||||
func (fi headerFileInfo) Mode() os.FileMode { return fi.fh.Mode() }
|
||||
func (fi headerFileInfo) Sys() interface{} { return fi.fh }
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,47 @@ func TestFileHeaderRoundTrip64(t *testing.T) {
|
|||
testHeaderRoundTrip(fh, uint32max, fh.UncompressedSize64, t)
|
||||
}
|
||||
|
||||
func TestFileHeaderRoundTripModified(t *testing.T) {
|
||||
fh := &FileHeader{
|
||||
Name: "foo.txt",
|
||||
UncompressedSize: 987654321,
|
||||
Modified: time.Now().Local(),
|
||||
ModifiedTime: 1234,
|
||||
ModifiedDate: 5678,
|
||||
}
|
||||
fi := fh.FileInfo()
|
||||
fh2, err := FileInfoHeader(fi)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, want := fh2.Modified, fh.Modified.UTC(); got != want {
|
||||
t.Errorf("Modified: got %s, want %s\n", got, want)
|
||||
}
|
||||
if got, want := fi.ModTime(), fh.Modified.UTC(); got != want {
|
||||
t.Errorf("Modified: got %s, want %s\n", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileHeaderRoundTripWithoutModified(t *testing.T) {
|
||||
fh := &FileHeader{
|
||||
Name: "foo.txt",
|
||||
UncompressedSize: 987654321,
|
||||
ModifiedTime: 1234,
|
||||
ModifiedDate: 5678,
|
||||
}
|
||||
fi := fh.FileInfo()
|
||||
fh2, err := FileInfoHeader(fi)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got, want := fh2.ModTime(), fh.ModTime(); got != want {
|
||||
t.Errorf("Modified: got %s, want %s\n", got, want)
|
||||
}
|
||||
if got, want := fi.ModTime(), fh.ModTime(); got != want {
|
||||
t.Errorf("Modified: got %s, want %s\n", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
type repeatedByte struct {
|
||||
off int64
|
||||
b byte
|
||||
|
|
|
|||
|
|
@ -45,10 +45,11 @@ fi
|
|||
unset GOROOT
|
||||
src=$(cd .. && pwd)
|
||||
echo "#### Copying to $targ"
|
||||
cp -R "$src" "$targ"
|
||||
cp -Rp "$src" "$targ"
|
||||
cd "$targ"
|
||||
echo
|
||||
echo "#### Cleaning $targ"
|
||||
chmod -R +w .
|
||||
rm -f .gitignore
|
||||
if [ -e .git ]; then
|
||||
git clean -f -d
|
||||
|
|
@ -72,6 +73,7 @@ if [ "$goos" = "$gohostos" -a "$goarch" = "$gohostarch" ]; then
|
|||
# prepare a clean toolchain for others.
|
||||
true
|
||||
else
|
||||
rm -f bin/go_${goos}_${goarch}_exec
|
||||
mv bin/*_*/* bin
|
||||
rmdir bin/*_*
|
||||
rm -rf "pkg/${gohostos}_${gohostarch}" "pkg/tool/${gohostos}_${gohostarch}"
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@ func ExampleScanner_emptyFinalToken() {
|
|||
return i + 1, data[:i], nil
|
||||
}
|
||||
}
|
||||
if !atEOF {
|
||||
return 0, nil, nil
|
||||
}
|
||||
// There is one final token to be delivered, which may be the empty string.
|
||||
// Returning bufio.ErrFinalToken here tells Scan there are no more tokens after this
|
||||
// but does not trigger an error to be returned from Scan itself.
|
||||
|
|
|
|||
|
|
@ -73,7 +73,11 @@ do
|
|||
export GOARCH=386
|
||||
export GO386=387
|
||||
fi
|
||||
if ! "$GOROOT/bin/go" build -a std cmd; then
|
||||
|
||||
# Build and vet everything.
|
||||
# cmd/go/internal/work/exec.go enables the same vet flags during go test of std cmd
|
||||
# and should be kept in sync with any vet flag changes here.
|
||||
if ! "$GOROOT/bin/go" build std cmd || ! "$GOROOT/bin/go" vet -unsafeptr=false std cmd; then
|
||||
failed=true
|
||||
if $sete; then
|
||||
exit 1
|
||||
|
|
|
|||
|
|
@ -226,10 +226,9 @@ func close(c chan<- Type)
|
|||
// invocation of F then behaves like a call to panic, terminating G's
|
||||
// execution and running any deferred functions. This continues until all
|
||||
// functions in the executing goroutine have stopped, in reverse order. At
|
||||
// that point, the program is terminated and the error condition is reported,
|
||||
// including the value of the argument to panic. This termination sequence
|
||||
// is called panicking and can be controlled by the built-in function
|
||||
// recover.
|
||||
// that point, the program is terminated with a non-zero exit code. This
|
||||
// termination sequence is called panicking and can be controlled by the
|
||||
// built-in function recover.
|
||||
func panic(v interface{})
|
||||
|
||||
// The recover built-in function allows a program to manage behavior of a
|
||||
|
|
|
|||
|
|
@ -12,23 +12,12 @@ import (
|
|||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Equal returns a boolean reporting whether a and b
|
||||
// Equal reports whether a and b
|
||||
// are the same length and contain the same bytes.
|
||||
// A nil argument is equivalent to an empty slice.
|
||||
func Equal(a, b []byte) bool {
|
||||
return bytealg.Equal(a, b)
|
||||
}
|
||||
|
||||
func equalPortable(a, b []byte) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i, c := range a {
|
||||
if c != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
// Neither cmd/compile nor gccgo allocates for these string conversions.
|
||||
return string(a) == string(b)
|
||||
}
|
||||
|
||||
// Compare returns an integer comparing two byte slices lexicographically.
|
||||
|
|
@ -114,12 +103,34 @@ func indexBytePortable(s []byte, c byte) int {
|
|||
// LastIndex returns the index of the last instance of sep in s, or -1 if sep is not present in s.
|
||||
func LastIndex(s, sep []byte) int {
|
||||
n := len(sep)
|
||||
if n == 0 {
|
||||
switch {
|
||||
case n == 0:
|
||||
return len(s)
|
||||
case n == 1:
|
||||
return LastIndexByte(s, sep[0])
|
||||
case n == len(s):
|
||||
if Equal(s, sep) {
|
||||
return 0
|
||||
}
|
||||
c := sep[0]
|
||||
for i := len(s) - n; i >= 0; i-- {
|
||||
if s[i] == c && (n == 1 || Equal(s[i:i+n], sep)) {
|
||||
return -1
|
||||
case n > len(s):
|
||||
return -1
|
||||
}
|
||||
// Rabin-Karp search from the end of the string
|
||||
hashss, pow := hashStrRev(sep)
|
||||
last := len(s) - n
|
||||
var h uint32
|
||||
for i := len(s) - 1; i >= last; i-- {
|
||||
h = h*primeRK + uint32(s[i])
|
||||
}
|
||||
if h == hashss && Equal(s[last:], sep) {
|
||||
return last
|
||||
}
|
||||
for i := last - 1; i >= 0; i-- {
|
||||
h *= primeRK
|
||||
h += uint32(s[i])
|
||||
h -= pow * uint32(s[i+n])
|
||||
if h == hashss && Equal(s[i:i+n], sep) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
|
|
@ -477,13 +488,16 @@ func Map(mapping func(r rune) rune, s []byte) []byte {
|
|||
// It panics if count is negative or if
|
||||
// the result of (len(b) * count) overflows.
|
||||
func Repeat(b []byte, count int) []byte {
|
||||
if count == 0 {
|
||||
return []byte{}
|
||||
}
|
||||
// Since we cannot return an error on overflow,
|
||||
// we should panic if the repeat will generate
|
||||
// an overflow.
|
||||
// See Issue golang.org/issue/16237.
|
||||
if count < 0 {
|
||||
panic("bytes: negative Repeat count")
|
||||
} else if count > 0 && len(b)*count/count != len(b) {
|
||||
} else if len(b)*count/count != len(b) {
|
||||
panic("bytes: Repeat count causes overflow")
|
||||
}
|
||||
|
||||
|
|
@ -496,11 +510,66 @@ func Repeat(b []byte, count int) []byte {
|
|||
return nb
|
||||
}
|
||||
|
||||
// ToUpper treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters within it mapped to their upper case.
|
||||
func ToUpper(s []byte) []byte { return Map(unicode.ToUpper, s) }
|
||||
// ToUpper returns a copy of the byte slice s with all Unicode letters mapped to
|
||||
// their upper case.
|
||||
func ToUpper(s []byte) []byte {
|
||||
isASCII, hasLower := true, false
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if c >= utf8.RuneSelf {
|
||||
isASCII = false
|
||||
break
|
||||
}
|
||||
hasLower = hasLower || ('a' <= c && c <= 'z')
|
||||
}
|
||||
|
||||
// ToLower treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their lower case.
|
||||
func ToLower(s []byte) []byte { return Map(unicode.ToLower, s) }
|
||||
if isASCII { // optimize for ASCII-only byte slices.
|
||||
if !hasLower {
|
||||
// Just return a copy.
|
||||
return append([]byte(""), s...)
|
||||
}
|
||||
b := make([]byte, len(s))
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if 'a' <= c && c <= 'z' {
|
||||
c -= 'a' - 'A'
|
||||
}
|
||||
b[i] = c
|
||||
}
|
||||
return b
|
||||
}
|
||||
return Map(unicode.ToUpper, s)
|
||||
}
|
||||
|
||||
// ToLower returns a copy of the byte slice s with all Unicode letters mapped to
|
||||
// their lower case.
|
||||
func ToLower(s []byte) []byte {
|
||||
isASCII, hasUpper := true, false
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if c >= utf8.RuneSelf {
|
||||
isASCII = false
|
||||
break
|
||||
}
|
||||
hasUpper = hasUpper || ('A' <= c && c <= 'Z')
|
||||
}
|
||||
|
||||
if isASCII { // optimize for ASCII-only byte slices.
|
||||
if !hasUpper {
|
||||
return append([]byte(""), s...)
|
||||
}
|
||||
b := make([]byte, len(s))
|
||||
for i := 0; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if 'A' <= c && c <= 'Z' {
|
||||
c += 'a' - 'A'
|
||||
}
|
||||
b[i] = c
|
||||
}
|
||||
return b
|
||||
}
|
||||
return Map(unicode.ToLower, s)
|
||||
}
|
||||
|
||||
// ToTitle treats s as UTF-8-encoded bytes and returns a copy with all the Unicode letters mapped to their title case.
|
||||
func ToTitle(s []byte) []byte { return Map(unicode.ToTitle, s) }
|
||||
|
|
@ -523,6 +592,35 @@ func ToTitleSpecial(c unicode.SpecialCase, s []byte) []byte {
|
|||
return Map(c.ToTitle, s)
|
||||
}
|
||||
|
||||
// ToValidUTF8 treats s as UTF-8-encoded bytes and returns a copy with each run of bytes
|
||||
// representing invalid UTF-8 replaced with the bytes in replacement, which may be empty.
|
||||
func ToValidUTF8(s, replacement []byte) []byte {
|
||||
b := make([]byte, 0, len(s)+len(replacement))
|
||||
invalid := false // previous byte was from an invalid UTF-8 sequence
|
||||
for i := 0; i < len(s); {
|
||||
c := s[i]
|
||||
if c < utf8.RuneSelf {
|
||||
i++
|
||||
invalid = false
|
||||
b = append(b, byte(c))
|
||||
continue
|
||||
}
|
||||
_, wid := utf8.DecodeRune(s[i:])
|
||||
if wid == 1 {
|
||||
i++
|
||||
if !invalid {
|
||||
invalid = true
|
||||
b = append(b, replacement...)
|
||||
}
|
||||
continue
|
||||
}
|
||||
invalid = false
|
||||
b = append(b, s[i:i+wid]...)
|
||||
i += wid
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// isSeparator reports whether the rune could mark a word boundary.
|
||||
// TODO: update when package unicode captures more of the properties.
|
||||
func isSeparator(r rune) bool {
|
||||
|
|
@ -734,7 +832,41 @@ func TrimRight(s []byte, cutset string) []byte {
|
|||
// TrimSpace returns a subslice of s by slicing off all leading and
|
||||
// trailing white space, as defined by Unicode.
|
||||
func TrimSpace(s []byte) []byte {
|
||||
return TrimFunc(s, unicode.IsSpace)
|
||||
// Fast path for ASCII: look for the first ASCII non-space byte
|
||||
start := 0
|
||||
for ; start < len(s); start++ {
|
||||
c := s[start]
|
||||
if c >= utf8.RuneSelf {
|
||||
// If we run into a non-ASCII byte, fall back to the
|
||||
// slower unicode-aware method on the remaining bytes
|
||||
return TrimFunc(s[start:], unicode.IsSpace)
|
||||
}
|
||||
if asciiSpace[c] == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Now look for the first ASCII non-space byte from the end
|
||||
stop := len(s)
|
||||
for ; stop > start; stop-- {
|
||||
c := s[stop-1]
|
||||
if c >= utf8.RuneSelf {
|
||||
return TrimFunc(s[start:stop], unicode.IsSpace)
|
||||
}
|
||||
if asciiSpace[c] == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// At this point s[start:stop] starts and ends with an ASCII
|
||||
// non-space bytes, so we're done. Non-ASCII cases have already
|
||||
// been handled above.
|
||||
if start == stop {
|
||||
// Special case to preserve previous TrimLeftFunc behavior,
|
||||
// returning nil instead of empty slice if all spaces.
|
||||
return nil
|
||||
}
|
||||
return s[start:stop]
|
||||
}
|
||||
|
||||
// Runes interprets s as a sequence of UTF-8-encoded code points.
|
||||
|
|
@ -987,3 +1119,20 @@ func hashStr(sep []byte) (uint32, uint32) {
|
|||
}
|
||||
return hash, pow
|
||||
}
|
||||
|
||||
// hashStrRev returns the hash of the reverse of sep and the
|
||||
// appropriate multiplicative factor for use in Rabin-Karp algorithm.
|
||||
func hashStrRev(sep []byte) (uint32, uint32) {
|
||||
hash := uint32(0)
|
||||
for i := len(sep) - 1; i >= 0; i-- {
|
||||
hash = hash*primeRK + uint32(sep[i])
|
||||
}
|
||||
var pow, sq uint32 = 1, primeRK
|
||||
for i := len(sep); i > 0; i >>= 1 {
|
||||
if i&1 != 0 {
|
||||
pow *= sq
|
||||
}
|
||||
sq *= sq
|
||||
}
|
||||
return hash, pow
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,15 +51,17 @@ type BinOpTest struct {
|
|||
}
|
||||
|
||||
func TestEqual(t *testing.T) {
|
||||
// Run the tests and check for allocation at the same time.
|
||||
allocs := testing.AllocsPerRun(10, func() {
|
||||
for _, tt := range compareTests {
|
||||
eql := Equal(tt.a, tt.b)
|
||||
if eql != (tt.i == 0) {
|
||||
t.Errorf(`Equal(%q, %q) = %v`, tt.a, tt.b, eql)
|
||||
}
|
||||
eql = EqualPortable(tt.a, tt.b)
|
||||
if eql != (tt.i == 0) {
|
||||
t.Errorf(`EqualPortable(%q, %q) = %v`, tt.a, tt.b, eql)
|
||||
}
|
||||
})
|
||||
if allocs > 0 {
|
||||
t.Errorf("Equal allocated %v times", allocs)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -572,11 +574,6 @@ func BenchmarkEqual(b *testing.B) {
|
|||
benchBytes(b, sizes, bmEqual(Equal))
|
||||
}
|
||||
|
||||
func BenchmarkEqualPort(b *testing.B) {
|
||||
sizes := []int{1, 6, 32, 4 << 10, 4 << 20, 64 << 20}
|
||||
benchBytes(b, sizes, bmEqual(EqualPortable))
|
||||
}
|
||||
|
||||
func bmEqual(equal func([]byte, []byte) bool) func(b *testing.B, n int) {
|
||||
return func(b *testing.B, n int) {
|
||||
if len(bmbuf) < 2*n {
|
||||
|
|
@ -677,34 +674,6 @@ func BenchmarkCountSingle(b *testing.B) {
|
|||
})
|
||||
}
|
||||
|
||||
type ExplodeTest struct {
|
||||
s string
|
||||
n int
|
||||
a []string
|
||||
}
|
||||
|
||||
var explodetests = []ExplodeTest{
|
||||
{"", -1, []string{}},
|
||||
{abcd, -1, []string{"a", "b", "c", "d"}},
|
||||
{faces, -1, []string{"☺", "☻", "☹"}},
|
||||
{abcd, 2, []string{"a", "bcd"}},
|
||||
}
|
||||
|
||||
func TestExplode(t *testing.T) {
|
||||
for _, tt := range explodetests {
|
||||
a := SplitN([]byte(tt.s), nil, tt.n)
|
||||
result := sliceOfString(a)
|
||||
if !eq(result, tt.a) {
|
||||
t.Errorf(`Explode("%s", %d) = %v; want %v`, tt.s, tt.n, result, tt.a)
|
||||
continue
|
||||
}
|
||||
s := Join(a, []byte{})
|
||||
if string(s) != tt.s {
|
||||
t.Errorf(`Join(Explode("%s", %d), "") = "%s"`, tt.s, tt.n, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type SplitTest struct {
|
||||
s string
|
||||
sep string
|
||||
|
|
@ -713,7 +682,9 @@ type SplitTest struct {
|
|||
}
|
||||
|
||||
var splittests = []SplitTest{
|
||||
{"", "", -1, []string{}},
|
||||
{abcd, "a", 0, nil},
|
||||
{abcd, "", 2, []string{"a", "bcd"}},
|
||||
{abcd, "a", -1, []string{"", "bcd"}},
|
||||
{abcd, "z", -1, []string{"abcd"}},
|
||||
{abcd, "", -1, []string{"a", "b", "c", "d"}},
|
||||
|
|
@ -743,7 +714,7 @@ func TestSplit(t *testing.T) {
|
|||
t.Errorf(`Split(%q, %q, %d) = %v; want %v`, tt.s, tt.sep, tt.n, result, tt.a)
|
||||
continue
|
||||
}
|
||||
if tt.n == 0 {
|
||||
if tt.n == 0 || len(a) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -909,54 +880,72 @@ func TestFieldsFunc(t *testing.T) {
|
|||
}
|
||||
|
||||
// Test case for any function which accepts and returns a byte slice.
|
||||
// For ease of creation, we write the byte slices as strings.
|
||||
// For ease of creation, we write the input byte slice as a string.
|
||||
type StringTest struct {
|
||||
in, out string
|
||||
in string
|
||||
out []byte
|
||||
}
|
||||
|
||||
var upperTests = []StringTest{
|
||||
{"", ""},
|
||||
{"abc", "ABC"},
|
||||
{"AbC123", "ABC123"},
|
||||
{"azAZ09_", "AZAZ09_"},
|
||||
{"\u0250\u0250\u0250\u0250\u0250", "\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F"}, // grows one byte per char
|
||||
{"", []byte("")},
|
||||
{"ONLYUPPER", []byte("ONLYUPPER")},
|
||||
{"abc", []byte("ABC")},
|
||||
{"AbC123", []byte("ABC123")},
|
||||
{"azAZ09_", []byte("AZAZ09_")},
|
||||
{"longStrinGwitHmixofsmaLLandcAps", []byte("LONGSTRINGWITHMIXOFSMALLANDCAPS")},
|
||||
{"long\u0250string\u0250with\u0250nonascii\u2C6Fchars", []byte("LONG\u2C6FSTRING\u2C6FWITH\u2C6FNONASCII\u2C6FCHARS")},
|
||||
{"\u0250\u0250\u0250\u0250\u0250", []byte("\u2C6F\u2C6F\u2C6F\u2C6F\u2C6F")}, // grows one byte per char
|
||||
{"a\u0080\U0010FFFF", []byte("A\u0080\U0010FFFF")}, // test utf8.RuneSelf and utf8.MaxRune
|
||||
}
|
||||
|
||||
var lowerTests = []StringTest{
|
||||
{"", ""},
|
||||
{"abc", "abc"},
|
||||
{"AbC123", "abc123"},
|
||||
{"azAZ09_", "azaz09_"},
|
||||
{"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", "\u0251\u0251\u0251\u0251\u0251"}, // shrinks one byte per char
|
||||
{"", []byte("")},
|
||||
{"abc", []byte("abc")},
|
||||
{"AbC123", []byte("abc123")},
|
||||
{"azAZ09_", []byte("azaz09_")},
|
||||
{"longStrinGwitHmixofsmaLLandcAps", []byte("longstringwithmixofsmallandcaps")},
|
||||
{"LONG\u2C6FSTRING\u2C6FWITH\u2C6FNONASCII\u2C6FCHARS", []byte("long\u0250string\u0250with\u0250nonascii\u0250chars")},
|
||||
{"\u2C6D\u2C6D\u2C6D\u2C6D\u2C6D", []byte("\u0251\u0251\u0251\u0251\u0251")}, // shrinks one byte per char
|
||||
{"A\u0080\U0010FFFF", []byte("a\u0080\U0010FFFF")}, // test utf8.RuneSelf and utf8.MaxRune
|
||||
}
|
||||
|
||||
const space = "\t\v\r\f\n\u0085\u00a0\u2000\u3000"
|
||||
|
||||
var trimSpaceTests = []StringTest{
|
||||
{"", ""},
|
||||
{"abc", "abc"},
|
||||
{space + "abc" + space, "abc"},
|
||||
{" ", ""},
|
||||
{" \t\r\n \t\t\r\r\n\n ", ""},
|
||||
{" \t\r\n x\t\t\r\r\n\n ", "x"},
|
||||
{" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", "x\t\t\r\r\ny"},
|
||||
{"1 \t\r\n2", "1 \t\r\n2"},
|
||||
{" x\x80", "x\x80"},
|
||||
{" x\xc0", "x\xc0"},
|
||||
{"x \xc0\xc0 ", "x \xc0\xc0"},
|
||||
{"x \xc0", "x \xc0"},
|
||||
{"x \xc0 ", "x \xc0"},
|
||||
{"x \xc0\xc0 ", "x \xc0\xc0"},
|
||||
{"x ☺\xc0\xc0 ", "x ☺\xc0\xc0"},
|
||||
{"x ☺ ", "x ☺"},
|
||||
{"", nil},
|
||||
{" a", []byte("a")},
|
||||
{"b ", []byte("b")},
|
||||
{"abc", []byte("abc")},
|
||||
{space + "abc" + space, []byte("abc")},
|
||||
{" ", nil},
|
||||
{"\u3000 ", nil},
|
||||
{" \u3000", nil},
|
||||
{" \t\r\n \t\t\r\r\n\n ", nil},
|
||||
{" \t\r\n x\t\t\r\r\n\n ", []byte("x")},
|
||||
{" \u2000\t\r\n x\t\t\r\r\ny\n \u3000", []byte("x\t\t\r\r\ny")},
|
||||
{"1 \t\r\n2", []byte("1 \t\r\n2")},
|
||||
{" x\x80", []byte("x\x80")},
|
||||
{" x\xc0", []byte("x\xc0")},
|
||||
{"x \xc0\xc0 ", []byte("x \xc0\xc0")},
|
||||
{"x \xc0", []byte("x \xc0")},
|
||||
{"x \xc0 ", []byte("x \xc0")},
|
||||
{"x \xc0\xc0 ", []byte("x \xc0\xc0")},
|
||||
{"x ☺\xc0\xc0 ", []byte("x ☺\xc0\xc0")},
|
||||
{"x ☺ ", []byte("x ☺")},
|
||||
}
|
||||
|
||||
// Execute f on each test case. funcName should be the name of f; it's used
|
||||
// in failure reports.
|
||||
func runStringTests(t *testing.T, f func([]byte) []byte, funcName string, testCases []StringTest) {
|
||||
for _, tc := range testCases {
|
||||
actual := string(f([]byte(tc.in)))
|
||||
if actual != tc.out {
|
||||
actual := f([]byte(tc.in))
|
||||
if actual == nil && tc.out != nil {
|
||||
t.Errorf("%s(%q) = nil; want %q", funcName, tc.in, tc.out)
|
||||
}
|
||||
if actual != nil && tc.out == nil {
|
||||
t.Errorf("%s(%q) = %q; want nil", funcName, tc.in, actual)
|
||||
}
|
||||
if !Equal(actual, tc.out) {
|
||||
t.Errorf("%s(%q) = %q; want %q", funcName, tc.in, actual, tc.out)
|
||||
}
|
||||
}
|
||||
|
|
@ -1044,6 +1033,64 @@ func TestToUpper(t *testing.T) { runStringTests(t, ToUpper, "ToUpper", upperTest
|
|||
|
||||
func TestToLower(t *testing.T) { runStringTests(t, ToLower, "ToLower", lowerTests) }
|
||||
|
||||
func BenchmarkToUpper(b *testing.B) {
|
||||
for _, tc := range upperTests {
|
||||
tin := []byte(tc.in)
|
||||
b.Run(tc.in, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
actual := ToUpper(tin)
|
||||
if !Equal(actual, tc.out) {
|
||||
b.Errorf("ToUpper(%q) = %q; want %q", tc.in, actual, tc.out)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkToLower(b *testing.B) {
|
||||
for _, tc := range lowerTests {
|
||||
tin := []byte(tc.in)
|
||||
b.Run(tc.in, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
actual := ToLower(tin)
|
||||
if !Equal(actual, tc.out) {
|
||||
b.Errorf("ToLower(%q) = %q; want %q", tc.in, actual, tc.out)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var toValidUTF8Tests = []struct {
|
||||
in string
|
||||
repl string
|
||||
out string
|
||||
}{
|
||||
{"", "\uFFFD", ""},
|
||||
{"abc", "\uFFFD", "abc"},
|
||||
{"\uFDDD", "\uFFFD", "\uFDDD"},
|
||||
{"a\xffb", "\uFFFD", "a\uFFFDb"},
|
||||
{"a\xffb\uFFFD", "X", "aXb\uFFFD"},
|
||||
{"a☺\xffb☺\xC0\xAFc☺\xff", "", "a☺b☺c☺"},
|
||||
{"a☺\xffb☺\xC0\xAFc☺\xff", "日本語", "a☺日本語b☺日本語c☺日本語"},
|
||||
{"\xC0\xAF", "\uFFFD", "\uFFFD"},
|
||||
{"\xE0\x80\xAF", "\uFFFD", "\uFFFD"},
|
||||
{"\xed\xa0\x80", "abc", "abc"},
|
||||
{"\xed\xbf\xbf", "\uFFFD", "\uFFFD"},
|
||||
{"\xF0\x80\x80\xaf", "☺", "☺"},
|
||||
{"\xF8\x80\x80\x80\xAF", "\uFFFD", "\uFFFD"},
|
||||
{"\xFC\x80\x80\x80\x80\xAF", "\uFFFD", "\uFFFD"},
|
||||
}
|
||||
|
||||
func TestToValidUTF8(t *testing.T) {
|
||||
for _, tc := range toValidUTF8Tests {
|
||||
got := ToValidUTF8([]byte(tc.in), []byte(tc.repl))
|
||||
if !Equal(got, []byte(tc.out)) {
|
||||
t.Errorf("ToValidUTF8(%q, %q) = %q; want %q", tc.in, tc.repl, got, tc.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTrimSpace(t *testing.T) { runStringTests(t, TrimSpace, "TrimSpace", trimSpaceTests) }
|
||||
|
||||
type RepeatTest struct {
|
||||
|
|
@ -1251,7 +1298,10 @@ var isValidRune = predicate{
|
|||
|
||||
type TrimFuncTest struct {
|
||||
f predicate
|
||||
in, out string
|
||||
in string
|
||||
trimOut []byte
|
||||
leftOut []byte
|
||||
rightOut []byte
|
||||
}
|
||||
|
||||
func not(p predicate) predicate {
|
||||
|
|
@ -1264,20 +1314,68 @@ func not(p predicate) predicate {
|
|||
}
|
||||
|
||||
var trimFuncTests = []TrimFuncTest{
|
||||
{isSpace, space + " hello " + space, "hello"},
|
||||
{isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51", "hello"},
|
||||
{isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F", "hello"},
|
||||
{not(isSpace), "hello" + space + "hello", space},
|
||||
{not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo", "\u0e50\u0e521234\u0e50\u0e51"},
|
||||
{isValidRune, "ab\xc0a\xc0cd", "\xc0a\xc0"},
|
||||
{not(isValidRune), "\xc0a\xc0", "a"},
|
||||
{isSpace, space + " hello " + space,
|
||||
[]byte("hello"),
|
||||
[]byte("hello " + space),
|
||||
[]byte(space + " hello")},
|
||||
{isDigit, "\u0e50\u0e5212hello34\u0e50\u0e51",
|
||||
[]byte("hello"),
|
||||
[]byte("hello34\u0e50\u0e51"),
|
||||
[]byte("\u0e50\u0e5212hello")},
|
||||
{isUpper, "\u2C6F\u2C6F\u2C6F\u2C6FABCDhelloEF\u2C6F\u2C6FGH\u2C6F\u2C6F",
|
||||
[]byte("hello"),
|
||||
[]byte("helloEF\u2C6F\u2C6FGH\u2C6F\u2C6F"),
|
||||
[]byte("\u2C6F\u2C6F\u2C6F\u2C6FABCDhello")},
|
||||
{not(isSpace), "hello" + space + "hello",
|
||||
[]byte(space),
|
||||
[]byte(space + "hello"),
|
||||
[]byte("hello" + space)},
|
||||
{not(isDigit), "hello\u0e50\u0e521234\u0e50\u0e51helo",
|
||||
[]byte("\u0e50\u0e521234\u0e50\u0e51"),
|
||||
[]byte("\u0e50\u0e521234\u0e50\u0e51helo"),
|
||||
[]byte("hello\u0e50\u0e521234\u0e50\u0e51")},
|
||||
{isValidRune, "ab\xc0a\xc0cd",
|
||||
[]byte("\xc0a\xc0"),
|
||||
[]byte("\xc0a\xc0cd"),
|
||||
[]byte("ab\xc0a\xc0")},
|
||||
{not(isValidRune), "\xc0a\xc0",
|
||||
[]byte("a"),
|
||||
[]byte("a\xc0"),
|
||||
[]byte("\xc0a")},
|
||||
// The nils returned by TrimLeftFunc are odd behavior, but we need
|
||||
// to preserve backwards compatibility.
|
||||
{isSpace, "",
|
||||
nil,
|
||||
nil,
|
||||
[]byte("")},
|
||||
{isSpace, " ",
|
||||
nil,
|
||||
nil,
|
||||
[]byte("")},
|
||||
}
|
||||
|
||||
func TestTrimFunc(t *testing.T) {
|
||||
for _, tc := range trimFuncTests {
|
||||
actual := string(TrimFunc([]byte(tc.in), tc.f.f))
|
||||
if actual != tc.out {
|
||||
t.Errorf("TrimFunc(%q, %q) = %q; want %q", tc.in, tc.f.name, actual, tc.out)
|
||||
trimmers := []struct {
|
||||
name string
|
||||
trim func(s []byte, f func(r rune) bool) []byte
|
||||
out []byte
|
||||
}{
|
||||
{"TrimFunc", TrimFunc, tc.trimOut},
|
||||
{"TrimLeftFunc", TrimLeftFunc, tc.leftOut},
|
||||
{"TrimRightFunc", TrimRightFunc, tc.rightOut},
|
||||
}
|
||||
for _, trimmer := range trimmers {
|
||||
actual := trimmer.trim([]byte(tc.in), tc.f.f)
|
||||
if actual == nil && trimmer.out != nil {
|
||||
t.Errorf("%s(%q, %q) = nil; want %q", trimmer.name, tc.in, tc.f.name, trimmer.out)
|
||||
}
|
||||
if actual != nil && trimmer.out == nil {
|
||||
t.Errorf("%s(%q, %q) = %q; want nil", trimmer.name, tc.in, tc.f.name, actual)
|
||||
}
|
||||
if !Equal(actual, trimmer.out) {
|
||||
t.Errorf("%s(%q, %q) = %q; want %q", trimmer.name, tc.in, tc.f.name, actual, trimmer.out)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1617,9 +1715,41 @@ func BenchmarkFieldsFunc(b *testing.B) {
|
|||
}
|
||||
|
||||
func BenchmarkTrimSpace(b *testing.B) {
|
||||
s := []byte(" Some text. \n")
|
||||
tests := []struct {
|
||||
name string
|
||||
input []byte
|
||||
}{
|
||||
{"NoTrim", []byte("typical")},
|
||||
{"ASCII", []byte(" foo bar ")},
|
||||
{"SomeNonASCII", []byte(" \u2000\t\r\n x\t\t\r\r\ny\n \u3000 ")},
|
||||
{"JustNonASCII", []byte("\u2000\u2000\u2000☺☺☺☺\u3000\u3000\u3000")},
|
||||
}
|
||||
for _, test := range tests {
|
||||
b.Run(test.name, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
TrimSpace(s)
|
||||
TrimSpace(test.input)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkToValidUTF8(b *testing.B) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []byte
|
||||
}{
|
||||
{"Valid", []byte("typical")},
|
||||
{"InvalidASCII", []byte("foo\xffbar")},
|
||||
{"InvalidNonASCII", []byte("日本語\xff日本語")},
|
||||
}
|
||||
replacement := []byte("\uFFFD")
|
||||
b.ResetTimer()
|
||||
for _, test := range tests {
|
||||
b.Run(test.name, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ToValidUTF8(test.input, replacement)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1642,6 +1772,39 @@ func makeBenchInputHard() []byte {
|
|||
|
||||
var benchInputHard = makeBenchInputHard()
|
||||
|
||||
func benchmarkIndexHard(b *testing.B, sep []byte) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Index(benchInputHard, sep)
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkLastIndexHard(b *testing.B, sep []byte) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
LastIndex(benchInputHard, sep)
|
||||
}
|
||||
}
|
||||
|
||||
func benchmarkCountHard(b *testing.B, sep []byte) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Count(benchInputHard, sep)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexHard1(b *testing.B) { benchmarkIndexHard(b, []byte("<>")) }
|
||||
func BenchmarkIndexHard2(b *testing.B) { benchmarkIndexHard(b, []byte("</pre>")) }
|
||||
func BenchmarkIndexHard3(b *testing.B) { benchmarkIndexHard(b, []byte("<b>hello world</b>")) }
|
||||
func BenchmarkIndexHard4(b *testing.B) {
|
||||
benchmarkIndexHard(b, []byte("<pre><b>hello</b><strong>world</strong></pre>"))
|
||||
}
|
||||
|
||||
func BenchmarkLastIndexHard1(b *testing.B) { benchmarkLastIndexHard(b, []byte("<>")) }
|
||||
func BenchmarkLastIndexHard2(b *testing.B) { benchmarkLastIndexHard(b, []byte("</pre>")) }
|
||||
func BenchmarkLastIndexHard3(b *testing.B) { benchmarkLastIndexHard(b, []byte("<b>hello world</b>")) }
|
||||
|
||||
func BenchmarkCountHard1(b *testing.B) { benchmarkCountHard(b, []byte("<>")) }
|
||||
func BenchmarkCountHard2(b *testing.B) { benchmarkCountHard(b, []byte("</pre>")) }
|
||||
func BenchmarkCountHard3(b *testing.B) { benchmarkCountHard(b, []byte("<b>hello world</b>")) }
|
||||
|
||||
func BenchmarkSplitEmptySeparator(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
Split(benchInputHard, nil)
|
||||
|
|
|
|||
|
|
@ -365,6 +365,16 @@ func ExampleToTitle() {
|
|||
// ХЛЕБ
|
||||
}
|
||||
|
||||
func ExampleToTitleSpecial() {
|
||||
str := []byte("ahoj vývojári golang")
|
||||
totitle := bytes.ToTitleSpecial(unicode.AzeriCase, str)
|
||||
fmt.Println("Original : " + string(str))
|
||||
fmt.Println("ToTitle : " + string(totitle))
|
||||
// Output:
|
||||
// Original : ahoj vývojári golang
|
||||
// ToTitle : AHOJ VÝVOJÁRİ GOLANG
|
||||
}
|
||||
|
||||
func ExampleTrim() {
|
||||
fmt.Printf("[%q]", bytes.Trim([]byte(" !!! Achtung! Achtung! !!! "), "! "))
|
||||
// Output: ["Achtung! Achtung"]
|
||||
|
|
@ -438,11 +448,31 @@ func ExampleToUpper() {
|
|||
// Output: GOPHER
|
||||
}
|
||||
|
||||
func ExampleToUpperSpecial() {
|
||||
str := []byte("ahoj vývojári golang")
|
||||
totitle := bytes.ToUpperSpecial(unicode.AzeriCase, str)
|
||||
fmt.Println("Original : " + string(str))
|
||||
fmt.Println("ToUpper : " + string(totitle))
|
||||
// Output:
|
||||
// Original : ahoj vývojári golang
|
||||
// ToUpper : AHOJ VÝVOJÁRİ GOLANG
|
||||
}
|
||||
|
||||
func ExampleToLower() {
|
||||
fmt.Printf("%s", bytes.ToLower([]byte("Gopher")))
|
||||
// Output: gopher
|
||||
}
|
||||
|
||||
func ExampleToLowerSpecial() {
|
||||
str := []byte("AHOJ VÝVOJÁRİ GOLANG")
|
||||
totitle := bytes.ToLowerSpecial(unicode.AzeriCase, str)
|
||||
fmt.Println("Original : " + string(str))
|
||||
fmt.Println("ToLower : " + string(totitle))
|
||||
// Output:
|
||||
// Original : AHOJ VÝVOJÁRİ GOLANG
|
||||
// ToLower : ahoj vývojári golang
|
||||
}
|
||||
|
||||
func ExampleReader_Len() {
|
||||
fmt.Println(bytes.NewReader([]byte("Hi!")).Len())
|
||||
fmt.Println(bytes.NewReader([]byte("こんにちは!")).Len())
|
||||
|
|
|
|||
|
|
@ -6,4 +6,3 @@ package bytes
|
|||
|
||||
// Export func for testing
|
||||
var IndexBytePortable = indexBytePortable
|
||||
var EqualPortable = equalPortable
|
||||
|
|
|
|||
2
src/cmd/README.vendor
Normal file
2
src/cmd/README.vendor
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
See src/README.vendor for information on loading vendored packages
|
||||
and updating the vendor directory.
|
||||
|
|
@ -8,6 +8,7 @@ package main
|
|||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
|
|
@ -76,6 +77,8 @@ var contexts = []*build.Context{
|
|||
{GOOS: "netbsd", GOARCH: "amd64"},
|
||||
{GOOS: "netbsd", GOARCH: "arm", CgoEnabled: true},
|
||||
{GOOS: "netbsd", GOARCH: "arm"},
|
||||
{GOOS: "netbsd", GOARCH: "arm64", CgoEnabled: true},
|
||||
{GOOS: "netbsd", GOARCH: "arm64"},
|
||||
{GOOS: "openbsd", GOARCH: "386", CgoEnabled: true},
|
||||
{GOOS: "openbsd", GOARCH: "386"},
|
||||
{GOOS: "openbsd", GOARCH: "amd64", CgoEnabled: true},
|
||||
|
|
@ -153,6 +156,7 @@ func main() {
|
|||
var featureCtx = make(map[string]map[string]bool) // feature -> context name -> true
|
||||
for _, context := range contexts {
|
||||
w := NewWalker(context, filepath.Join(build.Default.GOROOT, "src"))
|
||||
w.loadImports(pkgNames, w.context)
|
||||
|
||||
for _, name := range pkgNames {
|
||||
// Vendored packages do not contribute to our
|
||||
|
|
@ -169,7 +173,13 @@ func main() {
|
|||
// w.Import(name) will return nil
|
||||
continue
|
||||
}
|
||||
pkg, _ := w.Import(name)
|
||||
pkg, err := w.Import(name)
|
||||
if _, nogo := err.(*build.NoGoError); nogo {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatalf("Import(%q): %v", name, err)
|
||||
}
|
||||
w.export(pkg)
|
||||
}
|
||||
}
|
||||
|
|
@ -233,7 +243,7 @@ func (w *Walker) export(pkg *types.Package) {
|
|||
w.current = pkg
|
||||
scope := pkg.Scope()
|
||||
for _, name := range scope.Names() {
|
||||
if ast.IsExported(name) {
|
||||
if token.IsExported(name) {
|
||||
w.emitObj(scope.Lookup(name))
|
||||
}
|
||||
}
|
||||
|
|
@ -349,6 +359,8 @@ type Walker struct {
|
|||
current *types.Package
|
||||
features map[string]bool // set
|
||||
imported map[string]*types.Package // packages already imported
|
||||
importMap map[string]map[string]string // importer dir -> import path -> canonical path
|
||||
importDir map[string]string // canonical import path -> dir
|
||||
}
|
||||
|
||||
func NewWalker(context *build.Context, root string) *Walker {
|
||||
|
|
@ -428,11 +440,74 @@ func tagKey(dir string, context *build.Context, tags []string) string {
|
|||
return key
|
||||
}
|
||||
|
||||
func (w *Walker) loadImports(paths []string, context *build.Context) {
|
||||
if context == nil {
|
||||
context = &build.Default
|
||||
}
|
||||
|
||||
var (
|
||||
tags = context.BuildTags
|
||||
cgoEnabled = "0"
|
||||
)
|
||||
if context.CgoEnabled {
|
||||
tags = append(tags[:len(tags):len(tags)], "cgo")
|
||||
cgoEnabled = "1"
|
||||
}
|
||||
|
||||
// TODO(golang.org/issue/29666): Request only the fields that we need.
|
||||
cmd := exec.Command(goCmd(), "list", "-e", "-deps", "-json")
|
||||
if len(tags) > 0 {
|
||||
cmd.Args = append(cmd.Args, "-tags", strings.Join(tags, " "))
|
||||
}
|
||||
cmd.Args = append(cmd.Args, paths...)
|
||||
|
||||
cmd.Env = append(os.Environ(),
|
||||
"GOOS="+context.GOOS,
|
||||
"GOARCH="+context.GOARCH,
|
||||
"CGO_ENABLED="+cgoEnabled,
|
||||
)
|
||||
|
||||
stdout := new(bytes.Buffer)
|
||||
cmd.Stdout = stdout
|
||||
cmd.Stderr = new(strings.Builder)
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
log.Fatalf("%s failed: %v\n%s", strings.Join(cmd.Args, " "), err, cmd.Stderr)
|
||||
}
|
||||
|
||||
w.importDir = make(map[string]string)
|
||||
w.importMap = make(map[string]map[string]string)
|
||||
dec := json.NewDecoder(stdout)
|
||||
for {
|
||||
var pkg struct {
|
||||
ImportPath, Dir string
|
||||
ImportMap map[string]string
|
||||
}
|
||||
if err := dec.Decode(&pkg); err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
log.Fatalf("%s: invalid output: %v", strings.Join(cmd.Args, " "), err)
|
||||
}
|
||||
|
||||
w.importDir[pkg.ImportPath] = pkg.Dir
|
||||
w.importMap[pkg.Dir] = pkg.ImportMap
|
||||
}
|
||||
}
|
||||
|
||||
// Importing is a sentinel taking the place in Walker.imported
|
||||
// for a package that is in the process of being imported.
|
||||
var importing types.Package
|
||||
|
||||
func (w *Walker) Import(name string) (*types.Package, error) {
|
||||
return w.ImportFrom(name, "", 0)
|
||||
}
|
||||
|
||||
func (w *Walker) ImportFrom(fromPath, fromDir string, mode types.ImportMode) (*types.Package, error) {
|
||||
name := fromPath
|
||||
if canonical, ok := w.importMap[fromDir][fromPath]; ok {
|
||||
name = canonical
|
||||
}
|
||||
|
||||
pkg := w.imported[name]
|
||||
if pkg != nil {
|
||||
if pkg == &importing {
|
||||
|
|
@ -443,7 +518,10 @@ func (w *Walker) Import(name string) (*types.Package, error) {
|
|||
w.imported[name] = &importing
|
||||
|
||||
// Determine package files.
|
||||
dir := filepath.Join(w.root, filepath.FromSlash(name))
|
||||
dir := w.importDir[name]
|
||||
if dir == "" {
|
||||
dir = filepath.Join(w.root, filepath.FromSlash(name))
|
||||
}
|
||||
if fi, err := os.Stat(dir); err != nil || !fi.IsDir() {
|
||||
log.Fatalf("no source in tree for import %q: %v", name, err)
|
||||
}
|
||||
|
|
@ -470,7 +548,7 @@ func (w *Walker) Import(name string) (*types.Package, error) {
|
|||
info, err := context.ImportDir(dir, 0)
|
||||
if err != nil {
|
||||
if _, nogo := err.(*build.NoGoError); nogo {
|
||||
return nil, nil
|
||||
return nil, err
|
||||
}
|
||||
log.Fatalf("pkg %q, dir %q: ScanDir: %v", name, dir, err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -203,3 +203,16 @@ func TestIssue21181(t *testing.T) {
|
|||
w.export(pkg)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue29837(t *testing.T) {
|
||||
for _, c := range contexts {
|
||||
c.Compiler = build.Default.Compiler
|
||||
}
|
||||
for _, context := range contexts {
|
||||
w := NewWalker(context, "testdata/src/issue29837")
|
||||
_, err := w.Import("p")
|
||||
if _, nogo := err.(*build.NoGoError); !nogo {
|
||||
t.Errorf("expected *build.NoGoError, got %T", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
src/cmd/api/testdata/src/issue29837/p/README
vendored
Normal file
1
src/cmd/api/testdata/src/issue29837/p/README
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
Empty directory for test, see https://golang.org/issues/29837.
|
||||
|
|
@ -72,14 +72,11 @@ func IsARM64STLXR(op obj.As) bool {
|
|||
switch op {
|
||||
case arm64.ASTLXRB, arm64.ASTLXRH, arm64.ASTLXRW, arm64.ASTLXR,
|
||||
arm64.ASTXRB, arm64.ASTXRH, arm64.ASTXRW, arm64.ASTXR,
|
||||
arm64.ASTXP, arm64.ASTXPW, arm64.ASTLXP, arm64.ASTLXPW,
|
||||
arm64.ASWPB, arm64.ASWPH, arm64.ASWPW, arm64.ASWPD,
|
||||
arm64.ASWPALB, arm64.ASWPALH, arm64.ASWPALW, arm64.ASWPALD,
|
||||
arm64.ALDADDB, arm64.ALDADDH, arm64.ALDADDW, arm64.ALDADDD,
|
||||
arm64.ALDANDB, arm64.ALDANDH, arm64.ALDANDW, arm64.ALDANDD,
|
||||
arm64.ALDEORB, arm64.ALDEORH, arm64.ALDEORW, arm64.ALDEORD,
|
||||
arm64.ALDORB, arm64.ALDORH, arm64.ALDORW, arm64.ALDORD,
|
||||
arm64.ALDADDALD, arm64.ALDADDALW, arm64.ALDADDALH, arm64.ALDADDALB:
|
||||
arm64.ASTXP, arm64.ASTXPW, arm64.ASTLXP, arm64.ASTLXPW:
|
||||
return true
|
||||
}
|
||||
// atomic instructions
|
||||
if arm64.IsAtomicInstruction(op) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -33,12 +33,13 @@ func IsMIPSCMP(op obj.As) bool {
|
|||
}
|
||||
|
||||
// IsMIPSMUL reports whether the op (as defined by an mips.A* constant) is
|
||||
// one of the MUL/DIV/REM instructions that require special handling.
|
||||
// one of the MUL/DIV/REM/MADD/MSUB instructions that require special handling.
|
||||
func IsMIPSMUL(op obj.As) bool {
|
||||
switch op {
|
||||
case mips.AMUL, mips.AMULU, mips.AMULV, mips.AMULVU,
|
||||
mips.ADIV, mips.ADIVU, mips.ADIVV, mips.ADIVVU,
|
||||
mips.AREM, mips.AREMU, mips.AREMV, mips.AREMVU:
|
||||
mips.AREM, mips.AREMU, mips.AREMV, mips.AREMVU,
|
||||
mips.AMADD, mips.AMSUB:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -789,6 +789,12 @@ func (p *Parser) asmInstruction(op obj.As, cond string, a []obj.Addr) {
|
|||
prog.To = a[4]
|
||||
break
|
||||
}
|
||||
if p.arch.Family == sys.S390X {
|
||||
prog.From = a[0]
|
||||
prog.RestArgs = []obj.Addr{a[1], a[2], a[3]}
|
||||
prog.To = a[4]
|
||||
break
|
||||
}
|
||||
p.errorf("can't handle %s instruction with 5 operands", op)
|
||||
return
|
||||
case 6:
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ func TestAMD64BadInstParser(t *testing.T) {
|
|||
{"VADDPD.BCST.Z.SAE X0, X1, X2", `Z suffix should be the last; can't combine rounding/SAE and broadcast`},
|
||||
{"VADDPD.SAE.SAE X0, X1, X2", `duplicate suffix "SAE"`},
|
||||
{"VADDPD.RZ_SAE.SAE X0, X1, X2", `bad suffix combination`},
|
||||
|
||||
// BSWAP on 16-bit registers is undefined. See #29167,
|
||||
{"BSWAPW DX", `unrecognized instruction`},
|
||||
{"BSWAPW R11", `unrecognized instruction`},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,17 +145,18 @@ func TestFuncAddress(t *testing.T) {
|
|||
|
||||
isFuncSym := strings.HasSuffix(test.input, "(SB)") &&
|
||||
// Ignore static symbols.
|
||||
!strings.Contains(test.input, "<>") &&
|
||||
// Ignore symbols with offsets.
|
||||
!strings.Contains(test.input, "+")
|
||||
!strings.Contains(test.input, "<>")
|
||||
|
||||
wantName := ""
|
||||
if isFuncSym {
|
||||
// Strip $|* and (SB).
|
||||
// Strip $|* and (SB) and +Int.
|
||||
wantName = test.output[:len(test.output)-4]
|
||||
if strings.HasPrefix(wantName, "$") || strings.HasPrefix(wantName, "*") {
|
||||
wantName = wantName[1:]
|
||||
}
|
||||
if i := strings.Index(wantName, "+"); i >= 0 {
|
||||
wantName = wantName[:i]
|
||||
}
|
||||
}
|
||||
if ok != isFuncSym || name != wantName {
|
||||
t.Errorf("fail at %s as function address: got %s, %v; expected %s, %v", test.input, name, ok, wantName, isFuncSym)
|
||||
|
|
|
|||
|
|
@ -800,9 +800,9 @@ func (p *Parser) setPseudoRegister(addr *obj.Addr, reg string, isStatic bool, pr
|
|||
|
||||
// funcAddress parses an external function address. This is a
|
||||
// constrained form of the operand syntax that's always SB-based,
|
||||
// non-static, and has no additional offsets:
|
||||
// non-static, and has at most a simple integer offset:
|
||||
//
|
||||
// [$|*]sym(SB)
|
||||
// [$|*]sym[+Int](SB)
|
||||
func (p *Parser) funcAddress() (string, bool) {
|
||||
switch p.peek() {
|
||||
case '$', '*':
|
||||
|
|
@ -815,7 +815,14 @@ func (p *Parser) funcAddress() (string, bool) {
|
|||
if tok.ScanToken != scanner.Ident || p.atStartOfRegister(name) {
|
||||
return "", false
|
||||
}
|
||||
if p.next().ScanToken != '(' {
|
||||
tok = p.next()
|
||||
if tok.ScanToken == '+' {
|
||||
if p.next().ScanToken != scanner.Int {
|
||||
return "", false
|
||||
}
|
||||
tok = p.next()
|
||||
}
|
||||
if tok.ScanToken != '(' {
|
||||
return "", false
|
||||
}
|
||||
if reg := p.next(); reg.ScanToken != scanner.Ident || reg.String() != "SB" {
|
||||
|
|
|
|||
4
src/cmd/asm/internal/asm/testdata/386.s
vendored
4
src/cmd/asm/internal/asm/testdata/386.s
vendored
|
|
@ -89,6 +89,10 @@ label:
|
|||
loop:
|
||||
LOOP loop // LOOP
|
||||
|
||||
// Tests for TLS reference.
|
||||
MOVL (TLS), AX
|
||||
MOVL 8(TLS), DX
|
||||
|
||||
// LTYPE0 nonnon { outcode(int($1), &$2); }
|
||||
RET
|
||||
RET foo(SB)
|
||||
|
|
|
|||
4
src/cmd/asm/internal/asm/testdata/amd64.s
vendored
4
src/cmd/asm/internal/asm/testdata/amd64.s
vendored
|
|
@ -143,6 +143,10 @@ loop:
|
|||
MOVB foo+32(SP)(CX*4), AH // 8a648c20
|
||||
MOVB foo+32323(SP)(CX*8), R9 // 448a8ccc437e0000
|
||||
|
||||
// Tests for TLS reference.
|
||||
MOVQ (TLS), AX
|
||||
MOVQ 8(TLS), DX
|
||||
|
||||
// LTYPE0 nonnon { outcode($1, &$2); }
|
||||
RET // c3
|
||||
RET foo(SB)
|
||||
|
|
|
|||
2
src/cmd/asm/internal/asm/testdata/amd64enc.s
vendored
2
src/cmd/asm/internal/asm/testdata/amd64enc.s
vendored
|
|
@ -588,8 +588,6 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$0
|
|||
BSRQ (R11), R11 // 4d0fbd1b
|
||||
BSRQ DX, R11 // 4c0fbdda
|
||||
BSRQ R11, R11 // 4d0fbddb
|
||||
BSWAPW DX // 660fca
|
||||
BSWAPW R11 // 66410fcb
|
||||
BSWAPL DX // 0fca
|
||||
BSWAPL R11 // 410fcb
|
||||
BSWAPQ DX // 480fca
|
||||
|
|
|
|||
133
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
133
src/cmd/asm/internal/asm/testdata/arm64.s
vendored
|
|
@ -659,14 +659,14 @@ again:
|
|||
STXP (R1, R2), (RSP), R10 // e10b2ac8
|
||||
STXPW (R1, R2), (R3), R10 // 61082a88
|
||||
STXPW (R1, R2), (RSP), R10 // e10b2a88
|
||||
SWPD R5, (R6), R7 // c78025f8
|
||||
SWPD R5, (RSP), R7 // e78325f8
|
||||
SWPW R5, (R6), R7 // c78025b8
|
||||
SWPW R5, (RSP), R7 // e78325b8
|
||||
SWPH R5, (R6), R7 // c7802578
|
||||
SWPH R5, (RSP), R7 // e7832578
|
||||
SWPB R5, (R6), R7 // c7802538
|
||||
SWPB R5, (RSP), R7 // e7832538
|
||||
SWPAD R5, (R6), R7 // c780a5f8
|
||||
SWPAD R5, (RSP), R7 // e783a5f8
|
||||
SWPAW R5, (R6), R7 // c780a5b8
|
||||
SWPAW R5, (RSP), R7 // e783a5b8
|
||||
SWPAH R5, (R6), R7 // c780a578
|
||||
SWPAH R5, (RSP), R7 // e783a578
|
||||
SWPAB R5, (R6), R7 // c780a538
|
||||
SWPAB R5, (RSP), R7 // e783a538
|
||||
SWPALD R5, (R6), R7 // c780e5f8
|
||||
SWPALD R5, (RSP), R7 // e783e5f8
|
||||
SWPALW R5, (R6), R7 // c780e5b8
|
||||
|
|
@ -675,6 +675,38 @@ again:
|
|||
SWPALH R5, (RSP), R7 // e783e578
|
||||
SWPALB R5, (R6), R7 // c780e538
|
||||
SWPALB R5, (RSP), R7 // e783e538
|
||||
SWPD R5, (R6), R7 // c78025f8
|
||||
SWPD R5, (RSP), R7 // e78325f8
|
||||
SWPW R5, (R6), R7 // c78025b8
|
||||
SWPW R5, (RSP), R7 // e78325b8
|
||||
SWPH R5, (R6), R7 // c7802578
|
||||
SWPH R5, (RSP), R7 // e7832578
|
||||
SWPB R5, (R6), R7 // c7802538
|
||||
SWPB R5, (RSP), R7 // e7832538
|
||||
SWPLD R5, (R6), R7 // c78065f8
|
||||
SWPLD R5, (RSP), R7 // e78365f8
|
||||
SWPLW R5, (R6), R7 // c78065b8
|
||||
SWPLW R5, (RSP), R7 // e78365b8
|
||||
SWPLH R5, (R6), R7 // c7806578
|
||||
SWPLH R5, (RSP), R7 // e7836578
|
||||
SWPLB R5, (R6), R7 // c7806538
|
||||
SWPLB R5, (RSP), R7 // e7836538
|
||||
LDADDAD R5, (R6), R7 // c700a5f8
|
||||
LDADDAD R5, (RSP), R7 // e703a5f8
|
||||
LDADDAW R5, (R6), R7 // c700a5b8
|
||||
LDADDAW R5, (RSP), R7 // e703a5b8
|
||||
LDADDAH R5, (R6), R7 // c700a578
|
||||
LDADDAH R5, (RSP), R7 // e703a578
|
||||
LDADDAB R5, (R6), R7 // c700a538
|
||||
LDADDAB R5, (RSP), R7 // e703a538
|
||||
LDADDALD R5, (R6), R7 // c700e5f8
|
||||
LDADDALD R5, (RSP), R7 // e703e5f8
|
||||
LDADDALW R5, (R6), R7 // c700e5b8
|
||||
LDADDALW R5, (RSP), R7 // e703e5b8
|
||||
LDADDALH R5, (R6), R7 // c700e578
|
||||
LDADDALH R5, (RSP), R7 // e703e578
|
||||
LDADDALB R5, (R6), R7 // c700e538
|
||||
LDADDALB R5, (RSP), R7 // e703e538
|
||||
LDADDD R5, (R6), R7 // c70025f8
|
||||
LDADDD R5, (RSP), R7 // e70325f8
|
||||
LDADDW R5, (R6), R7 // c70025b8
|
||||
|
|
@ -683,6 +715,30 @@ again:
|
|||
LDADDH R5, (RSP), R7 // e7032578
|
||||
LDADDB R5, (R6), R7 // c7002538
|
||||
LDADDB R5, (RSP), R7 // e7032538
|
||||
LDADDLD R5, (R6), R7 // c70065f8
|
||||
LDADDLD R5, (RSP), R7 // e70365f8
|
||||
LDADDLW R5, (R6), R7 // c70065b8
|
||||
LDADDLW R5, (RSP), R7 // e70365b8
|
||||
LDADDLH R5, (R6), R7 // c7006578
|
||||
LDADDLH R5, (RSP), R7 // e7036578
|
||||
LDADDLB R5, (R6), R7 // c7006538
|
||||
LDADDLB R5, (RSP), R7 // e7036538
|
||||
LDANDAD R5, (R6), R7 // c710a5f8
|
||||
LDANDAD R5, (RSP), R7 // e713a5f8
|
||||
LDANDAW R5, (R6), R7 // c710a5b8
|
||||
LDANDAW R5, (RSP), R7 // e713a5b8
|
||||
LDANDAH R5, (R6), R7 // c710a578
|
||||
LDANDAH R5, (RSP), R7 // e713a578
|
||||
LDANDAB R5, (R6), R7 // c710a538
|
||||
LDANDAB R5, (RSP), R7 // e713a538
|
||||
LDANDALD R5, (R6), R7 // c710e5f8
|
||||
LDANDALD R5, (RSP), R7 // e713e5f8
|
||||
LDANDALW R5, (R6), R7 // c710e5b8
|
||||
LDANDALW R5, (RSP), R7 // e713e5b8
|
||||
LDANDALH R5, (R6), R7 // c710e578
|
||||
LDANDALH R5, (RSP), R7 // e713e578
|
||||
LDANDALB R5, (R6), R7 // c710e538
|
||||
LDANDALB R5, (RSP), R7 // e713e538
|
||||
LDANDD R5, (R6), R7 // c71025f8
|
||||
LDANDD R5, (RSP), R7 // e71325f8
|
||||
LDANDW R5, (R6), R7 // c71025b8
|
||||
|
|
@ -691,6 +747,30 @@ again:
|
|||
LDANDH R5, (RSP), R7 // e7132578
|
||||
LDANDB R5, (R6), R7 // c7102538
|
||||
LDANDB R5, (RSP), R7 // e7132538
|
||||
LDANDLD R5, (R6), R7 // c71065f8
|
||||
LDANDLD R5, (RSP), R7 // e71365f8
|
||||
LDANDLW R5, (R6), R7 // c71065b8
|
||||
LDANDLW R5, (RSP), R7 // e71365b8
|
||||
LDANDLH R5, (R6), R7 // c7106578
|
||||
LDANDLH R5, (RSP), R7 // e7136578
|
||||
LDANDLB R5, (R6), R7 // c7106538
|
||||
LDANDLB R5, (RSP), R7 // e7136538
|
||||
LDEORAD R5, (R6), R7 // c720a5f8
|
||||
LDEORAD R5, (RSP), R7 // e723a5f8
|
||||
LDEORAW R5, (R6), R7 // c720a5b8
|
||||
LDEORAW R5, (RSP), R7 // e723a5b8
|
||||
LDEORAH R5, (R6), R7 // c720a578
|
||||
LDEORAH R5, (RSP), R7 // e723a578
|
||||
LDEORAB R5, (R6), R7 // c720a538
|
||||
LDEORAB R5, (RSP), R7 // e723a538
|
||||
LDEORALD R5, (R6), R7 // c720e5f8
|
||||
LDEORALD R5, (RSP), R7 // e723e5f8
|
||||
LDEORALW R5, (R6), R7 // c720e5b8
|
||||
LDEORALW R5, (RSP), R7 // e723e5b8
|
||||
LDEORALH R5, (R6), R7 // c720e578
|
||||
LDEORALH R5, (RSP), R7 // e723e578
|
||||
LDEORALB R5, (R6), R7 // c720e538
|
||||
LDEORALB R5, (RSP), R7 // e723e538
|
||||
LDEORD R5, (R6), R7 // c72025f8
|
||||
LDEORD R5, (RSP), R7 // e72325f8
|
||||
LDEORW R5, (R6), R7 // c72025b8
|
||||
|
|
@ -699,6 +779,30 @@ again:
|
|||
LDEORH R5, (RSP), R7 // e7232578
|
||||
LDEORB R5, (R6), R7 // c7202538
|
||||
LDEORB R5, (RSP), R7 // e7232538
|
||||
LDEORLD R5, (R6), R7 // c72065f8
|
||||
LDEORLD R5, (RSP), R7 // e72365f8
|
||||
LDEORLW R5, (R6), R7 // c72065b8
|
||||
LDEORLW R5, (RSP), R7 // e72365b8
|
||||
LDEORLH R5, (R6), R7 // c7206578
|
||||
LDEORLH R5, (RSP), R7 // e7236578
|
||||
LDEORLB R5, (R6), R7 // c7206538
|
||||
LDEORLB R5, (RSP), R7 // e7236538
|
||||
LDORAD R5, (R6), R7 // c730a5f8
|
||||
LDORAD R5, (RSP), R7 // e733a5f8
|
||||
LDORAW R5, (R6), R7 // c730a5b8
|
||||
LDORAW R5, (RSP), R7 // e733a5b8
|
||||
LDORAH R5, (R6), R7 // c730a578
|
||||
LDORAH R5, (RSP), R7 // e733a578
|
||||
LDORAB R5, (R6), R7 // c730a538
|
||||
LDORAB R5, (RSP), R7 // e733a538
|
||||
LDORALD R5, (R6), R7 // c730e5f8
|
||||
LDORALD R5, (RSP), R7 // e733e5f8
|
||||
LDORALW R5, (R6), R7 // c730e5b8
|
||||
LDORALW R5, (RSP), R7 // e733e5b8
|
||||
LDORALH R5, (R6), R7 // c730e578
|
||||
LDORALH R5, (RSP), R7 // e733e578
|
||||
LDORALB R5, (R6), R7 // c730e538
|
||||
LDORALB R5, (RSP), R7 // e733e538
|
||||
LDORD R5, (R6), R7 // c73025f8
|
||||
LDORD R5, (RSP), R7 // e73325f8
|
||||
LDORW R5, (R6), R7 // c73025b8
|
||||
|
|
@ -707,11 +811,14 @@ again:
|
|||
LDORH R5, (RSP), R7 // e7332578
|
||||
LDORB R5, (R6), R7 // c7302538
|
||||
LDORB R5, (RSP), R7 // e7332538
|
||||
LDADDALD R2, (R1), R3 // 2300e2f8
|
||||
LDADDALW R2, (R1), R3 // 2300e2b8
|
||||
LDADDALH R2, (R1), R3 // 2300e278
|
||||
LDADDALB R2, (R1), R3 // 2300e238
|
||||
|
||||
LDORLD R5, (R6), R7 // c73065f8
|
||||
LDORLD R5, (RSP), R7 // e73365f8
|
||||
LDORLW R5, (R6), R7 // c73065b8
|
||||
LDORLW R5, (RSP), R7 // e73365b8
|
||||
LDORLH R5, (R6), R7 // c7306578
|
||||
LDORLH R5, (RSP), R7 // e7336578
|
||||
LDORLB R5, (R6), R7 // c7306538
|
||||
LDORLB R5, (RSP), R7 // e7336538
|
||||
// RET
|
||||
//
|
||||
// LTYPEA comma
|
||||
|
|
|
|||
120
src/cmd/asm/internal/asm/testdata/arm64error.s
vendored
120
src/cmd/asm/internal/asm/testdata/arm64error.s
vendored
|
|
@ -112,4 +112,124 @@ TEXT errors(SB),$0
|
|||
FSTPD (R1, R2), (R0) // ERROR "invalid register pair"
|
||||
FMOVS (F2), F0 // ERROR "illegal combination"
|
||||
FMOVD F0, (F1) // ERROR "illegal combination"
|
||||
LDADDD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDADDW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDADDH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDADDB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDADDLD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDADDLW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDADDLH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDADDLB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDLD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDLW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDLH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDANDLB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDEORD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDEORW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDEORH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDEORB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDEORLD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDEORLW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDEORLH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDEORLB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDORD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDORW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDORH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDORB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDORLD R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDORLW R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDORLH R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDORLB R5, (R6), ZR // ERROR "illegal destination register"
|
||||
LDADDAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDAB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDALD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDALW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDALH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDALB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDLD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDADDLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDAB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDALD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDALW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDALH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDALB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDLD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDANDLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORAB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORALD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORALW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORALH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORALB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORLD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDEORLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORAB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORALD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORALW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORALH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORALB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORLD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
LDORLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPAD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPAW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPAH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPAB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPALD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPALW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPALH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPALB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPLD R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPLW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPLH R5, (R6), RSP // ERROR "illegal destination register"
|
||||
SWPLB R5, (R6), RSP // ERROR "illegal destination register"
|
||||
STXR R5, (R6), RSP // ERROR "illegal destination register"
|
||||
STXRW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
STLXR R5, (R6), RSP // ERROR "illegal destination register"
|
||||
STLXRW R5, (R6), RSP // ERROR "illegal destination register"
|
||||
STXP (R5, R7), (R6), RSP // ERROR "illegal destination register"
|
||||
STXPW (R5, R7), (R6), RSP // ERROR "illegal destination register"
|
||||
STLXP (R5, R7), (R6), RSP // ERROR "illegal destination register"
|
||||
STLXP (R5, R7), (R6), RSP // ERROR "illegal destination register"
|
||||
RET
|
||||
|
|
|
|||
8
src/cmd/asm/internal/asm/testdata/mips.s
vendored
8
src/cmd/asm/internal/asm/testdata/mips.s
vendored
|
|
@ -424,7 +424,15 @@ label4:
|
|||
CALL foo(SB)
|
||||
RET foo(SB)
|
||||
|
||||
// unary operation
|
||||
NEGW R1, R2 // 00011023
|
||||
CLZ R1, R2 // 70221020
|
||||
CLO R1, R2 // 70221021
|
||||
|
||||
// to (Hi, Lo)
|
||||
MADD R2, R1 // 70220000
|
||||
MSUB R2, R1 // 70220004
|
||||
MUL R2, R1 // 00220018
|
||||
|
||||
// END
|
||||
//
|
||||
|
|
|
|||
6
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
6
src/cmd/asm/internal/asm/testdata/ppc64.s
vendored
|
|
@ -1021,18 +1021,24 @@ label1:
|
|||
// VSX move from VSR, XX1-form
|
||||
// <MNEMONIC> XS,RA produces
|
||||
// <mnemonic> RA,XS
|
||||
// Extended mnemonics accept VMX and FP registers as sources
|
||||
MFVSRD VS0, R1
|
||||
MFVSRWZ VS33, R1
|
||||
MFVSRLD VS63, R1
|
||||
MFVRD V0, R1
|
||||
MFFPRD F0, R1
|
||||
|
||||
// VSX move to VSR, XX1-form
|
||||
// <MNEMONIC> RA,XT produces
|
||||
// <mnemonic> XT,RA
|
||||
// Extended mnemonics accept VMX and FP registers as targets
|
||||
MTVSRD R1, VS0
|
||||
MTVSRWA R1, VS31
|
||||
MTVSRWZ R1, VS63
|
||||
MTVSRDD R1, R2, VS0
|
||||
MTVSRWS R1, VS32
|
||||
MTVRD R1, V13
|
||||
MTFPRD R1, F24
|
||||
|
||||
// VSX AND, XX3-form
|
||||
// <MNEMONIC> XA,XB,XT produces
|
||||
|
|
|
|||
19
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
19
src/cmd/asm/internal/asm/testdata/s390x.s
vendored
|
|
@ -66,6 +66,7 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
|
|||
ADD $32768, R1, R2 // b9040021c22800008000
|
||||
ADDC R1, R2 // b9ea1022
|
||||
ADDC $1, R1, R2 // ec21000100db
|
||||
ADDC $-1, R1, R2 // ec21ffff00db
|
||||
ADDC R1, R2, R3 // b9ea1032
|
||||
ADDW R1, R2 // 1a21
|
||||
ADDW R1, R2, R3 // b9f81032
|
||||
|
|
@ -182,6 +183,21 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
|
|||
XORW (R1), R2 // 57201000
|
||||
XORW -1(R1), R2 // e3201fffff57
|
||||
|
||||
RNSBG $0, $31, $32, R1, R2 // ec21001f2054
|
||||
RXSBG $17, $8, $16, R3, R4 // ec4311081057
|
||||
ROSBG $9, $24, $11, R5, R6 // ec6509180b56
|
||||
RNSBGT $0, $31, $32, R7, R8 // ec87801f2054
|
||||
RXSBGT $17, $8, $16, R9, R10 // eca991081057
|
||||
ROSBGT $9, $24, $11, R11, R0 // ec0b89180b56
|
||||
RISBG $0, $31, $32, R1, R2 // ec21001f2055
|
||||
RISBGN $17, $8, $16, R3, R4 // ec4311081059
|
||||
RISBGZ $9, $24, $11, R5, R6 // ec6509980b55
|
||||
RISBGNZ $0, $31, $32, R7, R8 // ec87009f2059
|
||||
RISBHG $17, $8, $16, R9, R10 // eca91108105d
|
||||
RISBLG $9, $24, $11, R11, R0 // ec0b09180b51
|
||||
RISBHGZ $17, $8, $16, R9, R10 // eca91188105d
|
||||
RISBLGZ $9, $24, $11, R11, R0 // ec0b09980b51
|
||||
|
||||
LAA R1, R2, 524287(R3) // eb213fff7ff8
|
||||
LAAG R4, R5, -524288(R6) // eb54600080e8
|
||||
LAAL R7, R8, 8192(R9) // eb87900002fa
|
||||
|
|
@ -219,6 +235,9 @@ TEXT main·foo(SB),DUPOK|NOSPLIT,$16-0 // TEXT main.foo(SB), DUPOK|NOSPLIT, $16-
|
|||
TMLH R3, $0 // a7300000
|
||||
TMLL R4, $32768 // a7418000
|
||||
|
||||
IPM R3 // b2220030
|
||||
IPM R12 // b22200c0
|
||||
|
||||
BNE 0(PC) // a7740000
|
||||
BEQ 0(PC) // a7840000
|
||||
BLT 0(PC) // a7440000
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ func main() {
|
|||
}
|
||||
}
|
||||
if ok && !*flags.SymABIs {
|
||||
obj.WriteObjFile(ctxt, buf)
|
||||
obj.WriteObjFile(ctxt, buf, "")
|
||||
}
|
||||
if !ok || diag {
|
||||
if failedFile != "" {
|
||||
|
|
|
|||
|
|
@ -200,18 +200,6 @@ func (f *File) saveExprs(x interface{}, context astContext) {
|
|||
}
|
||||
case *ast.CallExpr:
|
||||
f.saveCall(x, context)
|
||||
case *ast.GenDecl:
|
||||
if x.Tok == token.CONST {
|
||||
for _, spec := range x.Specs {
|
||||
vs := spec.(*ast.ValueSpec)
|
||||
if vs.Type == nil {
|
||||
for _, name := range spec.(*ast.ValueSpec).Names {
|
||||
consts[name.Name] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -148,6 +148,8 @@ C.long, C.ulong (unsigned long), C.longlong (long long),
|
|||
C.ulonglong (unsigned long long), C.float, C.double,
|
||||
C.complexfloat (complex float), and C.complexdouble (complex double).
|
||||
The C type void* is represented by Go's unsafe.Pointer.
|
||||
The C sized integer types (int8_t, uint8_t, …) are represented by their Go
|
||||
counterparts (int8, uint8, …).
|
||||
The C types __int128_t and __uint128_t are represented by [16]byte.
|
||||
|
||||
A few special C types which would normally be represented by a pointer
|
||||
|
|
@ -296,7 +298,7 @@ Go functions can be exported for use by C code in the following way:
|
|||
|
||||
They will be available in the C code as:
|
||||
|
||||
extern int64 MyFunction(int arg1, int arg2, GoString arg3);
|
||||
extern int64_t MyFunction(int arg1, int arg2, GoString arg3);
|
||||
extern struct MyFunction2_return MyFunction2(int arg1, int arg2, GoString arg3);
|
||||
|
||||
found in the _cgo_export.h generated header, after any preambles
|
||||
|
|
@ -710,7 +712,7 @@ _cgo_main.c:
|
|||
|
||||
int main() { return 0; }
|
||||
void crosscall2(void(*fn)(void*, int, uintptr_t), void *a, int c, uintptr_t ctxt) { }
|
||||
uintptr_t _cgo_wait_runtime_init_done() { return 0; }
|
||||
uintptr_t _cgo_wait_runtime_init_done(void) { return 0; }
|
||||
void _cgo_release_context(uintptr_t ctxt) { }
|
||||
char* _cgo_topofstack(void) { return (char*)0; }
|
||||
void _cgo_allocate(void *a, int c) { }
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
"internal/xcoff"
|
||||
"math"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
|
@ -897,21 +898,16 @@ func (p *Package) rewriteCall(f *File, call *Call) (string, bool) {
|
|||
needsUnsafe = true
|
||||
}
|
||||
|
||||
// Explicitly convert untyped constants to the
|
||||
// parameter type, to avoid a type mismatch.
|
||||
if p.isConst(f, arg) {
|
||||
// Use "var x T = ..." syntax to explicitly convert untyped
|
||||
// constants to the parameter type, to avoid a type mismatch.
|
||||
ptype := p.rewriteUnsafe(param.Go)
|
||||
|
||||
if !p.needsPointerCheck(f, param.Go, args[i]) || param.BadPointer {
|
||||
if ptype != param.Go {
|
||||
needsUnsafe = true
|
||||
}
|
||||
arg = &ast.CallExpr{
|
||||
Fun: ptype,
|
||||
Args: []ast.Expr{arg},
|
||||
}
|
||||
}
|
||||
|
||||
if !p.needsPointerCheck(f, param.Go, args[i]) {
|
||||
fmt.Fprintf(&sb, "_cgo%d := %s; ", i, gofmtPos(arg, origArg.Pos()))
|
||||
fmt.Fprintf(&sb, "var _cgo%d %s = %s; ", i,
|
||||
gofmtLine(ptype), gofmtPos(arg, origArg.Pos()))
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -1254,47 +1250,6 @@ func (p *Package) isType(t ast.Expr) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// isConst reports whether x is an untyped constant expression.
|
||||
func (p *Package) isConst(f *File, x ast.Expr) bool {
|
||||
switch x := x.(type) {
|
||||
case *ast.BasicLit:
|
||||
return true
|
||||
case *ast.SelectorExpr:
|
||||
id, ok := x.X.(*ast.Ident)
|
||||
if !ok || id.Name != "C" {
|
||||
return false
|
||||
}
|
||||
name := f.Name[x.Sel.Name]
|
||||
if name != nil {
|
||||
return name.IsConst()
|
||||
}
|
||||
case *ast.Ident:
|
||||
return x.Name == "nil" ||
|
||||
strings.HasPrefix(x.Name, "_Ciconst_") ||
|
||||
strings.HasPrefix(x.Name, "_Cfconst_") ||
|
||||
strings.HasPrefix(x.Name, "_Csconst_") ||
|
||||
consts[x.Name]
|
||||
case *ast.UnaryExpr:
|
||||
return p.isConst(f, x.X)
|
||||
case *ast.BinaryExpr:
|
||||
return p.isConst(f, x.X) && p.isConst(f, x.Y)
|
||||
case *ast.ParenExpr:
|
||||
return p.isConst(f, x.X)
|
||||
case *ast.CallExpr:
|
||||
// Calling the builtin function complex on two untyped
|
||||
// constants returns an untyped constant.
|
||||
// TODO: It's possible to construct a case that will
|
||||
// erroneously succeed if there is a local function
|
||||
// named "complex", shadowing the builtin, that returns
|
||||
// a numeric type. I can't think of any cases that will
|
||||
// erroneously fail.
|
||||
if id, ok := x.Fun.(*ast.Ident); ok && id.Name == "complex" && len(x.Args) == 2 {
|
||||
return p.isConst(f, x.Args[0]) && p.isConst(f, x.Args[1])
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// isVariable reports whether x is a variable, possibly with field references.
|
||||
func (p *Package) isVariable(x ast.Expr) bool {
|
||||
switch x := x.(type) {
|
||||
|
|
@ -1633,6 +1588,7 @@ func (p *Package) gccCmd() []string {
|
|||
c = append(c, p.gccMachine()...)
|
||||
if goos == "aix" {
|
||||
c = append(c, "-maix64")
|
||||
c = append(c, "-mcmodel=large")
|
||||
}
|
||||
c = append(c, "-") //read input from standard input
|
||||
return c
|
||||
|
|
@ -2091,6 +2047,8 @@ type typeConv struct {
|
|||
|
||||
ptrSize int64
|
||||
intSize int64
|
||||
|
||||
exactWidthIntegerTypes map[string]*Type
|
||||
}
|
||||
|
||||
var tagGen int
|
||||
|
|
@ -2133,6 +2091,21 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
|
|||
} else {
|
||||
c.goVoidPtr = c.Ident("unsafe.Pointer")
|
||||
}
|
||||
|
||||
c.exactWidthIntegerTypes = make(map[string]*Type)
|
||||
for _, t := range []ast.Expr{
|
||||
c.int8, c.int16, c.int32, c.int64,
|
||||
c.uint8, c.uint16, c.uint32, c.uint64,
|
||||
} {
|
||||
name := t.(*ast.Ident).Name
|
||||
u := new(Type)
|
||||
*u = *goTypes[name]
|
||||
if u.Align > ptrSize {
|
||||
u.Align = ptrSize
|
||||
}
|
||||
u.Go = t
|
||||
c.exactWidthIntegerTypes[name] = u
|
||||
}
|
||||
}
|
||||
|
||||
// base strips away qualifiers and typedefs to get the underlying type
|
||||
|
|
@ -2504,6 +2477,26 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
|
|||
t.Align = c.ptrSize
|
||||
break
|
||||
}
|
||||
// Exact-width integer types. These are always compatible with
|
||||
// the corresponding Go types since the C standard requires
|
||||
// them to have no padding bit and use the two’s complement
|
||||
// representation.
|
||||
if exactWidthIntegerType.MatchString(dt.Name) {
|
||||
sub := c.Type(dt.Type, pos)
|
||||
goname := strings.TrimPrefix(dt.Name, "__")
|
||||
goname = strings.TrimSuffix(goname, "_t")
|
||||
u := c.exactWidthIntegerTypes[goname]
|
||||
if sub.Size != u.Size {
|
||||
fatalf("%s: unexpected size: %d vs. %d – %s", lineno(pos), sub.Size, u.Size, dtype)
|
||||
}
|
||||
if sub.Align != u.Align {
|
||||
fatalf("%s: unexpected alignment: %d vs. %d – %s", lineno(pos), sub.Align, u.Align, dtype)
|
||||
}
|
||||
t.Size = u.Size
|
||||
t.Align = u.Align
|
||||
t.Go = u.Go
|
||||
break
|
||||
}
|
||||
name := c.Ident("_Ctype_" + dt.Name)
|
||||
goIdent[name.Name] = name
|
||||
sub := c.Type(dt.Type, pos)
|
||||
|
|
@ -2511,13 +2504,16 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
|
|||
// Treat this typedef as a uintptr.
|
||||
s := *sub
|
||||
s.Go = c.uintptr
|
||||
s.BadPointer = true
|
||||
sub = &s
|
||||
// Make sure we update any previously computed type.
|
||||
if oldType := typedef[name.Name]; oldType != nil {
|
||||
oldType.Go = sub.Go
|
||||
oldType.BadPointer = true
|
||||
}
|
||||
}
|
||||
t.Go = name
|
||||
t.BadPointer = sub.BadPointer
|
||||
if unionWithPointer[sub.Go] {
|
||||
unionWithPointer[t.Go] = true
|
||||
}
|
||||
|
|
@ -2527,6 +2523,7 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
|
|||
if oldType == nil {
|
||||
tt := *t
|
||||
tt.Go = sub.Go
|
||||
tt.BadPointer = sub.BadPointer
|
||||
typedef[name.Name] = &tt
|
||||
}
|
||||
|
||||
|
|
@ -2635,6 +2632,8 @@ func (c *typeConv) Type(dtype dwarf.Type, pos token.Pos) *Type {
|
|||
return t
|
||||
}
|
||||
|
||||
var exactWidthIntegerType = regexp.MustCompile(`^(__)?u?int(8|16|32|64)_t$`)
|
||||
|
||||
// isStructUnionClass reports whether the type described by the Go syntax x
|
||||
// is a struct, union, or class with a tag.
|
||||
func isStructUnionClass(x ast.Expr) bool {
|
||||
|
|
|
|||
|
|
@ -136,21 +136,31 @@ func gofmt(n interface{}) string {
|
|||
// (due to the printer possibly inserting newlines because of position
|
||||
// information) operators.
|
||||
var gofmtLineReplacer = strings.NewReplacer(
|
||||
"{\n", "{",
|
||||
",\n", ",",
|
||||
// Want to replace \n without ; after everything from
|
||||
// https://golang.org/ref/spec#Operators_and_punctuation
|
||||
// EXCEPT ++ -- ) ] }
|
||||
"++\n", "++;",
|
||||
"--\n", "--;",
|
||||
"+\n", "+",
|
||||
"-\n", "-",
|
||||
"*\n", "*",
|
||||
"/\n", "/",
|
||||
"%\n", "%",
|
||||
"&\n", "&",
|
||||
"|\n", "|",
|
||||
"^\n", "^",
|
||||
"<\n", "<",
|
||||
">\n", ">",
|
||||
"=\n", "=",
|
||||
|
||||
"+\n", "+ ",
|
||||
"-\n", "- ",
|
||||
"*\n", "* ",
|
||||
"/\n", "/ ",
|
||||
"%\n", "% ",
|
||||
"&\n", "& ",
|
||||
"|\n", "| ",
|
||||
"^\n", "^ ",
|
||||
"<\n", "< ",
|
||||
">\n", "> ",
|
||||
"=\n", "= ",
|
||||
"!\n", "! ", // not possible in gofmt today
|
||||
"(\n", "(",
|
||||
"[\n", "[", // not possible in gofmt today
|
||||
"{\n", "{",
|
||||
",\n", ",",
|
||||
".\n", ". ",
|
||||
":\n", ": ", // not possible in gofmt today
|
||||
|
||||
"\n", ";",
|
||||
)
|
||||
|
||||
|
|
|
|||
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