mirror of
https://github.com/golang/go.git
synced 2026-02-02 09:02:05 +03:00
Compare commits
24 Commits
dev.boring
...
go1.9.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6732fcc06d | ||
|
|
135c5a056c | ||
|
|
867fb18b6d | ||
|
|
c03ee1985c | ||
|
|
a563954b79 | ||
|
|
6ac64a0692 | ||
|
|
f94c408f4b | ||
|
|
6452bf4a05 | ||
|
|
5380990b84 | ||
|
|
edd3537817 | ||
|
|
0a72be280e | ||
|
|
e36f34fa55 | ||
|
|
75c7c40d29 | ||
|
|
f4870b7758 | ||
|
|
2308c9c95e | ||
|
|
f8a22093e2 | ||
|
|
a94581d021 | ||
|
|
f548fb287b | ||
|
|
0b25e97d03 | ||
|
|
3618ac2ca5 | ||
|
|
1cca09a8ed | ||
|
|
5c08eef870 | ||
|
|
aae9998d41 | ||
|
|
5476967b1a |
@@ -117,6 +117,6 @@ guidelines</a> for information on design, testing, and our code review process.
|
||||
<p>
|
||||
Check <a href="//golang.org/issue">the tracker</a> for
|
||||
open issues that interest you. Those labeled
|
||||
<a href="https://github.com/golang/go/issues?q=is%3Aopen+is%3Aissue+label%3Ahelpwanted">helpwanted</a>
|
||||
<a href="https://github.com/golang/go/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22">help wanted</a>
|
||||
are particularly in need of outside help.
|
||||
</p>
|
||||
|
||||
@@ -49,6 +49,20 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.2">Go
|
||||
1.9.2 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.9.3 (released 2018/01/22) includes fixes to the compiler, runtime,
|
||||
and the <code>database/sql</code>, <code>math/big</code>, <code>net/http</code>,
|
||||
and <code>net/url</code> packages.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.3">Go
|
||||
1.9.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.9.4 (released 2018/02/07) includes a security fix to “go get”.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.9.4">Go
|
||||
1.9.4</a> milestone on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.8">go1.8 (released 2017/02/16)</h2>
|
||||
|
||||
<p>
|
||||
@@ -89,6 +103,30 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.4">Go
|
||||
1.8.4 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.8.5 (released 2017/10/25) includes fixes to the compiler, linker, runtime,
|
||||
documentation, <code>go</code> command,
|
||||
and the <code>crypto/x509</code> and <code>net/smtp</code> packages.
|
||||
It includes a fix to a bug introduced in Go 1.8.4 that broke <code>go</code> <code>get</code>
|
||||
of non-Git repositories under certain conditions.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.5">Go
|
||||
1.8.5 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.8.6 (released 2018/01/22) includes the the same fix in <code>math/big</code>
|
||||
as Go 1.9.3 and was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.6">Go
|
||||
1.8.6 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.8.7 (released 2018/02/07) includes a security fix to “go get”.
|
||||
It contains the same fix as Go 1.9.4 and was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.7">Go
|
||||
1.8.7</a> milestone on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.7">go1.7 (released 2016/08/15)</h2>
|
||||
|
||||
<p>
|
||||
@@ -262,7 +300,7 @@ See the <a href="https://github.com/golang/go/commits/go1.3.2">change history</a
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.3.3 (released 2014/09/30) includes further bug fixes to cgo, the runtime package, and the nacl port.
|
||||
go1.3.3 (released 2014/09/30) includes further bug fixes to cgo, the runtime package, and the nacl port.
|
||||
See the <a href="https://github.com/golang/go/commits/go1.3.3">change history</a> for details.
|
||||
</p>
|
||||
|
||||
@@ -326,7 +364,7 @@ about the future of Go 1.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The go1 release corresponds to
|
||||
The go1 release corresponds to
|
||||
<code><a href="weekly.html#2012-03-27">weekly.2012-03-27</a></code>.
|
||||
</p>
|
||||
|
||||
@@ -342,7 +380,7 @@ It also includes several minor code and documentation fixes.
|
||||
|
||||
<p>
|
||||
go1.0.2 (released 2012/06/13) was issued to fix two bugs in the implementation
|
||||
of maps using struct or array keys:
|
||||
of maps using struct or array keys:
|
||||
<a href="//golang.org/issue/3695">issue 3695</a> and
|
||||
<a href="//golang.org/issue/3573">issue 3573</a>.
|
||||
It also includes many minor code and documentation fixes.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<!--{
|
||||
"Title": "Documentation",
|
||||
"Path": "/doc/"
|
||||
"Path": "/doc/",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<p>
|
||||
@@ -33,14 +34,20 @@ libraries.
|
||||
|
||||
<img class="gopher" src="/doc/gopher/doc.png"/>
|
||||
|
||||
<h3 id="go_tour"><a href="//tour.golang.org/">A Tour of Go</a></h3>
|
||||
<h3 id="go_tour">
|
||||
{{if $.GoogleCN}}
|
||||
A Tour of Go
|
||||
{{else}}
|
||||
<a href="//tour.golang.org/">A Tour of Go</a>
|
||||
{{end}}
|
||||
</h3>
|
||||
<p>
|
||||
An interactive introduction to Go in three sections.
|
||||
The first section covers basic syntax and data structures; the second discusses
|
||||
methods and interfaces; and the third introduces Go's concurrency primitives.
|
||||
Each section concludes with a few exercises so you can practice what you've
|
||||
learned. You can <a href="//tour.golang.org/">take the tour online</a> or
|
||||
install it locally with:
|
||||
learned. You can {{if not $.GoogleCN}}<a href="//tour.golang.org/">take the tour
|
||||
online</a> or{{end}} install it locally with:
|
||||
</p>
|
||||
<p>
|
||||
<pre>
|
||||
@@ -51,10 +58,13 @@ This will place the <code>gotour</code> binary in your workspace's <code>bin</co
|
||||
|
||||
<h3 id="code"><a href="code.html">How to write Go code</a></h3>
|
||||
<p>
|
||||
Also available as a
|
||||
<a href="//www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>, this doc
|
||||
explains how to use the <a href="/cmd/go/">go command</a> to fetch, build, and
|
||||
install packages, commands, and run tests.
|
||||
{{if not $.GoogleCN}}
|
||||
Also available as a <a href="//www.youtube.com/watch?v=XCsL89YtqCs">screencast</a>, this
|
||||
{{else}}
|
||||
This
|
||||
{{end}}
|
||||
doc explains how to use the <a href="/cmd/go/">go command</a>
|
||||
to fetch, build, and install packages, commands, and run tests.
|
||||
</p>
|
||||
|
||||
<h3 id="editors"><a href="editors.html">Editor plugins and IDEs</a></h3>
|
||||
@@ -115,9 +125,11 @@ same variable in a different goroutine.
|
||||
|
||||
<h2 id="articles">Articles</h2>
|
||||
|
||||
{{if not $.GoogleCN}}
|
||||
<h3 id="blog"><a href="//blog.golang.org/">The Go Blog</a></h3>
|
||||
<p>The official blog of the Go project, featuring news and in-depth articles by
|
||||
the Go team and guests.</p>
|
||||
{{end}}
|
||||
|
||||
<h4>Codewalks</h4>
|
||||
<p>
|
||||
@@ -130,6 +142,7 @@ Guided tours of Go programs.
|
||||
<li><a href="/doc/articles/wiki/">Writing Web Applications</a> - building a simple web application.</li>
|
||||
</ul>
|
||||
|
||||
{{if not $.GoogleCN}}
|
||||
<h4>Language</h4>
|
||||
<ul>
|
||||
<li><a href="/blog/json-rpc-tale-of-interfaces">JSON-RPC: a tale of interfaces</a></li>
|
||||
@@ -150,17 +163,20 @@ Guided tours of Go programs.
|
||||
<li><a href="/blog/go-image-package">The Go image package</a> - the fundamentals of the <a href="/pkg/image/">image</a> package.</li>
|
||||
<li><a href="/blog/go-imagedraw-package">The Go image/draw package</a> - the fundamentals of the <a href="/pkg/image/draw/">image/draw</a> package.</li>
|
||||
</ul>
|
||||
{{end}}
|
||||
|
||||
<h4>Tools</h4>
|
||||
<ul>
|
||||
<li><a href="/doc/articles/go_command.html">About the Go command</a> - why we wrote it, what it is, what it's not, and how to use it.</li>
|
||||
<li><a href="/blog/c-go-cgo">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
|
||||
<li><a href="/doc/gdb">Debugging Go Code with GDB</a></li>
|
||||
<li><a href="/doc/articles/race_detector.html">Data Race Detector</a> - a manual for the data race detector.</li>
|
||||
<li><a href="/doc/asm">A Quick Guide to Go's Assembler</a> - an introduction to the assembler used by Go.</li>
|
||||
{{if not $.GoogleCN}}
|
||||
<li><a href="/blog/c-go-cgo">C? Go? Cgo!</a> - linking against C code with <a href="/cmd/cgo/">cgo</a>.</li>
|
||||
<li><a href="/blog/godoc-documenting-go-code">Godoc: documenting Go code</a> - writing good documentation for <a href="/cmd/godoc/">godoc</a>.</li>
|
||||
<li><a href="/blog/profiling-go-programs">Profiling Go Programs</a></li>
|
||||
<li><a href="/doc/articles/race_detector.html">Data Race Detector</a> - a manual for the data race detector.</li>
|
||||
<li><a href="/blog/race-detector">Introducing the Go Race Detector</a> - an introduction to the race detector.</li>
|
||||
<li><a href="/doc/asm">A Quick Guide to Go's Assembler</a> - an introduction to the assembler used by Go.</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
|
||||
<h4 id="articles_more">More</h4>
|
||||
@@ -169,7 +185,7 @@ See the <a href="/wiki/Articles">Articles page</a> at the
|
||||
<a href="/wiki">Wiki</a> for more Go articles.
|
||||
</p>
|
||||
|
||||
|
||||
{{if not $.GoogleCN}}
|
||||
<h2 id="talks">Talks</h2>
|
||||
|
||||
<img class="gopher" src="/doc/gopher/talks.png"/>
|
||||
@@ -200,7 +216,7 @@ This talk expands on the <i>Go Concurrency Patterns</i> talk to dive deeper into
|
||||
<p>
|
||||
See the <a href="/talks">Go Talks site</a> and <a href="/wiki/GoTalks">wiki page</a> for more Go talks.
|
||||
</p>
|
||||
|
||||
{{end}}
|
||||
|
||||
<h2 id="nonenglish">Non-English Documentation</h2>
|
||||
|
||||
|
||||
@@ -775,7 +775,7 @@ to turn a string into an error. It replaces the old <code>os.NewError</code>.
|
||||
</p>
|
||||
|
||||
{{code "/doc/progs/go1.go" `/ErrSyntax/`}}
|
||||
|
||||
|
||||
<p>
|
||||
<em>Updating</em>:
|
||||
Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
|
||||
@@ -1827,7 +1827,7 @@ for full details.
|
||||
<tr><td>Uitob(x, b)</td> <td>FormatUint(uint64(x), b)</td></tr>
|
||||
<tr><td>Uitob64(x, b)</td> <td>FormatUint(x, b)</td></tr>
|
||||
</table>
|
||||
|
||||
|
||||
<p>
|
||||
<em>Updating</em>:
|
||||
Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
|
||||
@@ -1841,7 +1841,7 @@ a cast that must be added by hand; the <code>go</code> <code>fix</code> tool wil
|
||||
<h3 id="templates">The template packages</h3>
|
||||
|
||||
<p>
|
||||
The <code>template</code> and <code>exp/template/html</code> packages have moved to
|
||||
The <code>template</code> and <code>exp/template/html</code> packages have moved to
|
||||
<a href="/pkg/text/template/"><code>text/template</code></a> and
|
||||
<a href="/pkg/html/template/"><code>html/template</code></a>.
|
||||
More significant, the interface to these packages has been simplified.
|
||||
@@ -2035,4 +2035,4 @@ They are available for many combinations of architecture and operating system
|
||||
Installation details are described on the
|
||||
<a href="/doc/install">Getting Started</a> page, while
|
||||
the distributions themselves are listed on the
|
||||
<a href="https://golang.org/dl/">downloads page</a>.
|
||||
<a href="/dl/">downloads page</a>.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<!--{
|
||||
"Title": "Help",
|
||||
"Path": "/help/"
|
||||
"Path": "/help/",
|
||||
"Template": true
|
||||
}-->
|
||||
|
||||
<div id="manual-nav"></div>
|
||||
@@ -9,6 +10,7 @@
|
||||
|
||||
<img class="gopher" src="/doc/gopher/help.png"/>
|
||||
|
||||
{{if not $.GoogleCN}}
|
||||
<h3 id="mailinglist"><a href="https://groups.google.com/group/golang-nuts">Go Nuts Mailing List</a></h3>
|
||||
<p>
|
||||
Get help from Go users, and share your work on the official mailing list.
|
||||
@@ -31,10 +33,12 @@ forum for Go programmers.
|
||||
<h3 id="irc"><a href="irc:irc.freenode.net/go-nuts">Go IRC Channel</a></h3>
|
||||
<p>Get live support at <b>#go-nuts</b> on <b>irc.freenode.net</b>, the official
|
||||
Go IRC channel.</p>
|
||||
{{end}}
|
||||
|
||||
<h3 id="faq"><a href="/doc/faq">Frequently Asked Questions (FAQ)</a></h3>
|
||||
<p>Answers to common questions about Go.</p>
|
||||
|
||||
{{if not $.GoogleCN}}
|
||||
<h2 id="inform">Stay informed</h2>
|
||||
|
||||
<h3 id="announce"><a href="https://groups.google.com/group/golang-announce">Go Announcements Mailing List</a></h3>
|
||||
@@ -64,6 +68,7 @@ for Go news and discussion.
|
||||
The <a href="https://changelog.com/gotime">Go Time podcast</a> is a panel of Go experts and special guests
|
||||
discussing the Go programming language, the community, and everything in between.
|
||||
</p>
|
||||
{{end}}
|
||||
|
||||
<h2 id="community">Community resources</h2>
|
||||
|
||||
@@ -73,11 +78,13 @@ Each month in places around the world, groups of Go programmers ("gophers")
|
||||
meet to talk about Go. Find a chapter near you.
|
||||
</p>
|
||||
|
||||
{{if not $.GoogleCN}}
|
||||
<h3 id="playground"><a href="/play">Go Playground</a></h3>
|
||||
<p>A place to write, run, and share Go code.</p>
|
||||
|
||||
<h3 id="wiki"><a href="/wiki">Go Wiki</a></h3>
|
||||
<p>A wiki maintained by the Go community.</p>
|
||||
{{end}}
|
||||
|
||||
<h3 id="conduct"><a href="/conduct">Code of Conduct</a></h3>
|
||||
<p>
|
||||
|
||||
@@ -8,14 +8,14 @@
|
||||
<h2 id="download">Download the Go distribution</h2>
|
||||
|
||||
<p>
|
||||
<a href="https://golang.org/dl/" id="start" class="download">
|
||||
<a href="/dl/" id="start" class="download">
|
||||
<span class="big">Download Go</span>
|
||||
<span class="desc">Click here to visit the downloads page</span>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="https://golang.org/dl/" target="_blank">Official binary
|
||||
<a href="/dl/" target="_blank">Official binary
|
||||
distributions</a> are available for the FreeBSD (release 8-STABLE and above),
|
||||
Linux, Mac OS X (10.8 and above), and Windows operating systems and
|
||||
the 32-bit (<code>386</code>) and 64-bit (<code>amd64</code>) x86 processor
|
||||
@@ -33,7 +33,7 @@ system and architecture, try
|
||||
<h2 id="requirements">System requirements</h2>
|
||||
|
||||
<p>
|
||||
Go <a href="https://golang.org/dl/">binary distributions</a> are available for these supported operating systems and architectures.
|
||||
Go <a href="/dl/">binary distributions</a> are available for these supported operating systems and architectures.
|
||||
Please ensure your system meets these requirements before proceeding.
|
||||
If your OS or architecture is not on the list, you may be able to
|
||||
<a href="/doc/install/source">install from source</a> or
|
||||
@@ -77,7 +77,7 @@ first <a href="#uninstall">remove the existing version</a>.
|
||||
<h3 id="tarball">Linux, Mac OS X, and FreeBSD tarballs</h3>
|
||||
|
||||
<p>
|
||||
<a href="https://golang.org/dl/">Download the archive</a>
|
||||
<a href="/dl/">Download the archive</a>
|
||||
and extract it into <code>/usr/local</code>, creating a Go tree in
|
||||
<code>/usr/local/go</code>. For example:
|
||||
</p>
|
||||
@@ -138,7 +138,7 @@ location.
|
||||
<h3 id="osx">Mac OS X package installer</h3>
|
||||
|
||||
<p>
|
||||
<a href="https://golang.org/dl/">Download the package file</a>,
|
||||
<a href="/dl/">Download the package file</a>,
|
||||
open it, and follow the prompts to install the Go tools.
|
||||
The package installs the Go distribution to <code>/usr/local/go</code>.
|
||||
</p>
|
||||
@@ -167,7 +167,7 @@ MSI installer that configures your installation automatically.
|
||||
<h4 id="windows_msi">MSI installer</h4>
|
||||
|
||||
<p>
|
||||
Open the <a href="https://golang.org/dl/">MSI file</a>
|
||||
Open the <a href="/dl/">MSI file</a>
|
||||
and follow the prompts to install the Go tools.
|
||||
By default, the installer puts the Go distribution in <code>c:\Go</code>.
|
||||
</p>
|
||||
@@ -185,7 +185,7 @@ command prompts for the change to take effect.
|
||||
<h4 id="windows_zip">Zip archive</h4>
|
||||
|
||||
<p>
|
||||
<a href="https://golang.org/dl/">Download the zip file</a> and extract it into the directory of your choice (we suggest <code>c:\Go</code>).
|
||||
<a href="/dl/">Download the zip file</a> and extract it into the directory of your choice (we suggest <code>c:\Go</code>).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -58,7 +58,7 @@ simple, reliable, and efficient software.
|
||||
|
||||
<div id="gopher"></div>
|
||||
|
||||
<a href="https://golang.org/dl/" id="start">
|
||||
<a href="/dl/" id="start">
|
||||
<span class="big">Download Go</span>
|
||||
<span class="desc">
|
||||
Binary distributions available for<br>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
package main
|
||||
|
||||
/*
|
||||
#cgo LDFLAGS: -c
|
||||
#cgo LDFLAGS: -L/nonexist
|
||||
|
||||
void test() {
|
||||
xxx; // ERROR HERE
|
||||
|
||||
@@ -55,11 +55,21 @@ For example:
|
||||
|
||||
The default pkg-config tool may be changed by setting the PKG_CONFIG environment variable.
|
||||
|
||||
For security reasons, only a limited set of flags are allowed, notably -D, -I, and -l.
|
||||
To allow additional flags, set CGO_CFLAGS_ALLOW to a regular expression
|
||||
matching the new flags. To disallow flags that would otherwise be allowed,
|
||||
set CGO_CFLAGS_DISALLOW to a regular expression matching arguments
|
||||
that must be disallowed. In both cases the regular expression must match
|
||||
a full argument: to allow -mfoo=bar, use CGO_CFLAGS_ALLOW='-mfoo.*',
|
||||
not just CGO_CFLAGS_ALLOW='-mfoo'. Similarly named variables control
|
||||
the allowed CPPFLAGS, CXXFLAGS, FFLAGS, and LDFLAGS.
|
||||
|
||||
When building, the CGO_CFLAGS, CGO_CPPFLAGS, CGO_CXXFLAGS, CGO_FFLAGS and
|
||||
CGO_LDFLAGS environment variables are added to the flags derived from
|
||||
these directives. Package-specific flags should be set using the
|
||||
directives, not the environment variables, so that builds work in
|
||||
unmodified environments.
|
||||
unmodified environments. Flags obtained from environment variables
|
||||
are not subject to the security limitations described above.
|
||||
|
||||
All the cgo CPPFLAGS and CFLAGS directives in a package are concatenated and
|
||||
used to compile C files in that package. All the CPPFLAGS and CXXFLAGS
|
||||
|
||||
@@ -86,7 +86,9 @@ var runtimeDecls = [...]struct {
|
||||
{"mapaccess2_fat", funcTag, 67},
|
||||
{"mapassign", funcTag, 62},
|
||||
{"mapassign_fast32", funcTag, 63},
|
||||
{"mapassign_fast32ptr", funcTag, 63},
|
||||
{"mapassign_fast64", funcTag, 63},
|
||||
{"mapassign_fast64ptr", funcTag, 63},
|
||||
{"mapassign_faststr", funcTag, 63},
|
||||
{"mapiterinit", funcTag, 68},
|
||||
{"mapdelete", funcTag, 68},
|
||||
|
||||
@@ -106,7 +106,9 @@ func mapaccess2_faststr(mapType *byte, hmap map[any]any, key any) (val *any, pre
|
||||
func mapaccess2_fat(mapType *byte, hmap map[any]any, key *any, zero *byte) (val *any, pres bool)
|
||||
func mapassign(mapType *byte, hmap map[any]any, key *any) (val *any)
|
||||
func mapassign_fast32(mapType *byte, hmap map[any]any, key any) (val *any)
|
||||
func mapassign_fast32ptr(mapType *byte, hmap map[any]any, key any) (val *any)
|
||||
func mapassign_fast64(mapType *byte, hmap map[any]any, key any) (val *any)
|
||||
func mapassign_fast64ptr(mapType *byte, hmap map[any]any, key any) (val *any)
|
||||
func mapassign_faststr(mapType *byte, hmap map[any]any, key any) (val *any)
|
||||
func mapiterinit(mapType *byte, hmap map[any]any, hiter *any)
|
||||
func mapdelete(mapType *byte, hmap map[any]any, key *any)
|
||||
|
||||
@@ -7,6 +7,7 @@ package gc
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -1190,6 +1191,11 @@ func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma {
|
||||
p.linknames = append(p.linknames, linkname{pos, f[1], f[2]})
|
||||
|
||||
case strings.HasPrefix(text, "go:cgo_"):
|
||||
// For security, we disallow //go:cgo_* directives outside cgo-generated files.
|
||||
// Exception: they are allowed in the standard library, for runtime and syscall.
|
||||
if !isCgoGeneratedFile(pos) && !compiling_std {
|
||||
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
|
||||
}
|
||||
p.pragcgobuf += p.pragcgo(pos, text)
|
||||
fallthrough // because of //go:cgo_unsafe_args
|
||||
default:
|
||||
@@ -1211,6 +1217,16 @@ func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma {
|
||||
return 0
|
||||
}
|
||||
|
||||
// isCgoGeneratedFile reports whether pos is in a file
|
||||
// generated by cgo, which is to say a file with name
|
||||
// beginning with "_cgo_". Such files are allowed to
|
||||
// contain cgo directives, and for security reasons
|
||||
// (primarily misuse of linker flags), other files are not.
|
||||
// See golang.org/issue/23672.
|
||||
func isCgoGeneratedFile(pos src.Pos) bool {
|
||||
return strings.HasPrefix(filepath.Base(filepath.Clean(pos.AbsFilename())), "_cgo_")
|
||||
}
|
||||
|
||||
func mkname(sym *types.Sym) *Node {
|
||||
n := oldname(sym)
|
||||
if n.Name != nil && n.Name.Pack != nil {
|
||||
|
||||
@@ -2785,21 +2785,23 @@ func mapfndel(name string, t *types.Type) *Node {
|
||||
const (
|
||||
mapslow = iota
|
||||
mapfast32
|
||||
mapfast32ptr
|
||||
mapfast64
|
||||
mapfast64ptr
|
||||
mapfaststr
|
||||
nmapfast
|
||||
)
|
||||
|
||||
type mapnames [nmapfast]string
|
||||
|
||||
func mkmapnames(base string) mapnames {
|
||||
return mapnames{base, base + "_fast32", base + "_fast64", base + "_faststr"}
|
||||
func mkmapnames(base string, ptr string) mapnames {
|
||||
return mapnames{base, base + "_fast32", base + "_fast32" + ptr, base + "_fast64", base + "_fast64" + ptr, base + "_faststr"}
|
||||
}
|
||||
|
||||
var mapaccess1 mapnames = mkmapnames("mapaccess1")
|
||||
var mapaccess2 mapnames = mkmapnames("mapaccess2")
|
||||
var mapassign mapnames = mkmapnames("mapassign")
|
||||
var mapdelete mapnames = mkmapnames("mapdelete")
|
||||
var mapaccess1 mapnames = mkmapnames("mapaccess1", "")
|
||||
var mapaccess2 mapnames = mkmapnames("mapaccess2", "")
|
||||
var mapassign mapnames = mkmapnames("mapassign", "ptr")
|
||||
var mapdelete mapnames = mkmapnames("mapdelete", "")
|
||||
|
||||
func mapfast(t *types.Type) int {
|
||||
// Check ../../runtime/hashmap.go:maxValueSize before changing.
|
||||
@@ -2808,9 +2810,22 @@ func mapfast(t *types.Type) int {
|
||||
}
|
||||
switch algtype(t.Key()) {
|
||||
case AMEM32:
|
||||
return mapfast32
|
||||
if !t.Key().HasPointer() {
|
||||
return mapfast32
|
||||
}
|
||||
if Widthptr == 4 {
|
||||
return mapfast32ptr
|
||||
}
|
||||
Fatalf("small pointer %v", t.Key())
|
||||
case AMEM64:
|
||||
return mapfast64
|
||||
if !t.Key().HasPointer() {
|
||||
return mapfast64
|
||||
}
|
||||
if Widthptr == 8 {
|
||||
return mapfast64ptr
|
||||
}
|
||||
// Two-word object, at least one of which is a pointer.
|
||||
// Use the slow path.
|
||||
case ASTRING:
|
||||
return mapfaststr
|
||||
}
|
||||
|
||||
@@ -798,45 +798,45 @@
|
||||
(MOVLstoreconstidx1 [c] {sym} ptr (SHLLconst [2] idx) mem) -> (MOVLstoreconstidx4 [c] {sym} ptr idx mem)
|
||||
|
||||
// combine ADDL into indexed loads and stores
|
||||
(MOVBloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVBloadidx1 [c+d] {sym} ptr idx mem)
|
||||
(MOVWloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVWloadidx1 [c+d] {sym} ptr idx mem)
|
||||
(MOVWloadidx2 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVWloadidx2 [c+d] {sym} ptr idx mem)
|
||||
(MOVLloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVLloadidx1 [c+d] {sym} ptr idx mem)
|
||||
(MOVLloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVLloadidx4 [c+d] {sym} ptr idx mem)
|
||||
(MOVSSloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSSloadidx1 [c+d] {sym} ptr idx mem)
|
||||
(MOVSSloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSSloadidx4 [c+d] {sym} ptr idx mem)
|
||||
(MOVSDloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSDloadidx1 [c+d] {sym} ptr idx mem)
|
||||
(MOVSDloadidx8 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSDloadidx8 [c+d] {sym} ptr idx mem)
|
||||
(MOVBloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVWloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVWloadidx2 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVWloadidx2 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVLloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVLloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVLloadidx4 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVSSloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSSloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVSSloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSSloadidx4 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVSDloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSDloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVSDloadidx8 [c] {sym} (ADDLconst [d] ptr) idx mem) -> (MOVSDloadidx8 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
|
||||
(MOVBstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
(MOVWstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVWstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
(MOVWstoreidx2 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVWstoreidx2 [c+d] {sym} ptr idx val mem)
|
||||
(MOVLstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVLstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
(MOVLstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVLstoreidx4 [c+d] {sym} ptr idx val mem)
|
||||
(MOVSSstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
(MOVSSstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSSstoreidx4 [c+d] {sym} ptr idx val mem)
|
||||
(MOVSDstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
(MOVSDstoreidx8 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSDstoreidx8 [c+d] {sym} ptr idx val mem)
|
||||
(MOVBstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVWstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVWstoreidx2 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVWstoreidx2 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVLstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVLstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVLstoreidx4 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVSSstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSSstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVSSstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSSstoreidx4 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVSDstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSDstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVSDstoreidx8 [c] {sym} (ADDLconst [d] ptr) idx val mem) -> (MOVSDstoreidx8 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
|
||||
(MOVBloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVBloadidx1 [c+d] {sym} ptr idx mem)
|
||||
(MOVWloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVWloadidx1 [c+d] {sym} ptr idx mem)
|
||||
(MOVWloadidx2 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVWloadidx2 [c+2*d] {sym} ptr idx mem)
|
||||
(MOVLloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVLloadidx1 [c+d] {sym} ptr idx mem)
|
||||
(MOVLloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVLloadidx4 [c+4*d] {sym} ptr idx mem)
|
||||
(MOVSSloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSSloadidx1 [c+d] {sym} ptr idx mem)
|
||||
(MOVSSloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSSloadidx4 [c+4*d] {sym} ptr idx mem)
|
||||
(MOVSDloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSDloadidx1 [c+d] {sym} ptr idx mem)
|
||||
(MOVSDloadidx8 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSDloadidx8 [c+8*d] {sym} ptr idx mem)
|
||||
(MOVBloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVWloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVWloadidx2 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVWloadidx2 [int64(int32(c+2*d))] {sym} ptr idx mem)
|
||||
(MOVLloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVLloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVLloadidx4 [int64(int32(c+4*d))] {sym} ptr idx mem)
|
||||
(MOVSSloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSSloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVSSloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSSloadidx4 [int64(int32(c+4*d))] {sym} ptr idx mem)
|
||||
(MOVSDloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSDloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
(MOVSDloadidx8 [c] {sym} ptr (ADDLconst [d] idx) mem) -> (MOVSDloadidx8 [int64(int32(c+8*d))] {sym} ptr idx mem)
|
||||
|
||||
(MOVBstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
(MOVWstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVWstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
(MOVWstoreidx2 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVWstoreidx2 [c+2*d] {sym} ptr idx val mem)
|
||||
(MOVLstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVLstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
(MOVLstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVLstoreidx4 [c+4*d] {sym} ptr idx val mem)
|
||||
(MOVSSstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
(MOVSSstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSSstoreidx4 [c+4*d] {sym} ptr idx val mem)
|
||||
(MOVSDstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
(MOVSDstoreidx8 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx8 [c+8*d] {sym} ptr idx val mem)
|
||||
(MOVBstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVWstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVWstoreidx2 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVWstoreidx2 [int64(int32(c+2*d))] {sym} ptr idx val mem)
|
||||
(MOVLstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVLstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVLstoreidx4 [int64(int32(c+4*d))] {sym} ptr idx val mem)
|
||||
(MOVSSstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSSstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVSSstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSSstoreidx4 [int64(int32(c+4*d))] {sym} ptr idx val mem)
|
||||
(MOVSDstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
(MOVSDstoreidx8 [c] {sym} ptr (ADDLconst [d] idx) val mem) -> (MOVSDstoreidx8 [int64(int32(c+8*d))] {sym} ptr idx val mem)
|
||||
|
||||
(MOVBstoreconstidx1 [x] {sym} (ADDLconst [c] ptr) idx mem) ->
|
||||
(MOVBstoreconstidx1 [ValAndOff(x).add(c)] {sym} ptr idx mem)
|
||||
|
||||
@@ -819,7 +819,7 @@
|
||||
(Store _ (ArrayMake0) mem) -> mem
|
||||
(Store dst (ArrayMake1 e) mem) -> (Store {e.Type} dst e mem)
|
||||
|
||||
(ArraySelect [0] (Load ptr mem)) -> (Load ptr mem)
|
||||
(ArraySelect [0] x:(Load ptr mem)) -> @x.Block (Load <v.Type> ptr mem)
|
||||
|
||||
// Putting [1]{*byte} and similar into direct interfaces.
|
||||
(IMake typ (ArrayMake1 val)) -> (IMake typ val)
|
||||
|
||||
@@ -1103,12 +1103,15 @@ func (s *regAllocState) regalloc(f *Func) {
|
||||
if v.Op == OpKeepAlive {
|
||||
// Make sure the argument to v is still live here.
|
||||
s.advanceUses(v)
|
||||
vi := &s.values[v.Args[0].ID]
|
||||
if vi.spill != nil {
|
||||
a := v.Args[0]
|
||||
vi := &s.values[a.ID]
|
||||
if vi.regs == 0 && !vi.rematerializeable {
|
||||
// Use the spill location.
|
||||
v.SetArg(0, vi.spill)
|
||||
// This forces later liveness analysis to make the
|
||||
// value live at this point.
|
||||
v.SetArg(0, s.makeSpill(a, b))
|
||||
} else {
|
||||
// No need to keep unspilled values live.
|
||||
// In-register and rematerializeable values are already live.
|
||||
// These are typically rematerializeable constants like nil,
|
||||
// or values of a variable that were modified since the last call.
|
||||
v.Op = OpCopy
|
||||
|
||||
@@ -3148,7 +3148,7 @@ func rewriteValue386_Op386MOVBload_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
|
||||
// match: (MOVBloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem)
|
||||
// cond:
|
||||
// result: (MOVBloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -3162,7 +3162,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
|
||||
idx := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVBloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -3171,7 +3171,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVBloadidx1 [c] {sym} idx (ADDLconst [d] ptr) mem)
|
||||
// cond:
|
||||
// result: (MOVBloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -3185,7 +3185,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
|
||||
ptr := v_1.Args[0]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVBloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -3194,7 +3194,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVBloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem)
|
||||
// cond:
|
||||
// result: (MOVBloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -3208,7 +3208,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
|
||||
idx := v_1.Args[0]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVBloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -3217,7 +3217,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVBloadidx1 [c] {sym} (ADDLconst [d] idx) ptr mem)
|
||||
// cond:
|
||||
// result: (MOVBloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVBloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -3231,7 +3231,7 @@ func rewriteValue386_Op386MOVBloadidx1_0(v *Value) bool {
|
||||
ptr := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVBloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -3747,7 +3747,7 @@ func rewriteValue386_Op386MOVBstoreconstidx1_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
|
||||
// match: (MOVBstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem)
|
||||
// cond:
|
||||
// result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -3762,7 +3762,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVBstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -3772,7 +3772,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVBstoreidx1 [c] {sym} idx (ADDLconst [d] ptr) val mem)
|
||||
// cond:
|
||||
// result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -3787,7 +3787,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVBstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -3797,7 +3797,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVBstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem)
|
||||
// cond:
|
||||
// result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -3812,7 +3812,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVBstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -3822,7 +3822,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVBstoreidx1 [c] {sym} (ADDLconst [d] idx) ptr val mem)
|
||||
// cond:
|
||||
// result: (MOVBstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVBstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -3837,7 +3837,7 @@ func rewriteValue386_Op386MOVBstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVBstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -4486,7 +4486,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVLloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem)
|
||||
// cond:
|
||||
// result: (MOVLloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -4500,7 +4500,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
|
||||
idx := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVLloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -4509,7 +4509,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVLloadidx1 [c] {sym} idx (ADDLconst [d] ptr) mem)
|
||||
// cond:
|
||||
// result: (MOVLloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -4523,7 +4523,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
|
||||
ptr := v_1.Args[0]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVLloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -4532,7 +4532,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVLloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem)
|
||||
// cond:
|
||||
// result: (MOVLloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -4546,7 +4546,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
|
||||
idx := v_1.Args[0]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVLloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -4555,7 +4555,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVLloadidx1 [c] {sym} (ADDLconst [d] idx) ptr mem)
|
||||
// cond:
|
||||
// result: (MOVLloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVLloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -4569,7 +4569,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
|
||||
ptr := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVLloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -4581,7 +4581,7 @@ func rewriteValue386_Op386MOVLloadidx1_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVLloadidx4_0(v *Value) bool {
|
||||
// match: (MOVLloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem)
|
||||
// cond:
|
||||
// result: (MOVLloadidx4 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVLloadidx4 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -4595,7 +4595,7 @@ func rewriteValue386_Op386MOVLloadidx4_0(v *Value) bool {
|
||||
idx := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVLloadidx4)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -4604,7 +4604,7 @@ func rewriteValue386_Op386MOVLloadidx4_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVLloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem)
|
||||
// cond:
|
||||
// result: (MOVLloadidx4 [c+4*d] {sym} ptr idx mem)
|
||||
// result: (MOVLloadidx4 [int64(int32(c+4*d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -4618,7 +4618,7 @@ func rewriteValue386_Op386MOVLloadidx4_0(v *Value) bool {
|
||||
idx := v_1.Args[0]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVLloadidx4)
|
||||
v.AuxInt = c + 4*d
|
||||
v.AuxInt = int64(int32(c + 4*d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5114,7 +5114,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVLstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem)
|
||||
// cond:
|
||||
// result: (MOVLstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5129,7 +5129,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVLstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5139,7 +5139,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVLstoreidx1 [c] {sym} idx (ADDLconst [d] ptr) val mem)
|
||||
// cond:
|
||||
// result: (MOVLstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5154,7 +5154,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVLstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5164,7 +5164,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVLstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem)
|
||||
// cond:
|
||||
// result: (MOVLstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5179,7 +5179,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVLstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5189,7 +5189,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVLstoreidx1 [c] {sym} (ADDLconst [d] idx) ptr val mem)
|
||||
// cond:
|
||||
// result: (MOVLstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVLstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5204,7 +5204,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVLstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5217,7 +5217,7 @@ func rewriteValue386_Op386MOVLstoreidx1_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVLstoreidx4_0(v *Value) bool {
|
||||
// match: (MOVLstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem)
|
||||
// cond:
|
||||
// result: (MOVLstoreidx4 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVLstoreidx4 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5232,7 +5232,7 @@ func rewriteValue386_Op386MOVLstoreidx4_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVLstoreidx4)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5242,7 +5242,7 @@ func rewriteValue386_Op386MOVLstoreidx4_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVLstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem)
|
||||
// cond:
|
||||
// result: (MOVLstoreidx4 [c+4*d] {sym} ptr idx val mem)
|
||||
// result: (MOVLstoreidx4 [int64(int32(c+4*d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5257,7 +5257,7 @@ func rewriteValue386_Op386MOVLstoreidx4_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVLstoreidx4)
|
||||
v.AuxInt = c + 4*d
|
||||
v.AuxInt = int64(int32(c + 4*d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5431,7 +5431,7 @@ func rewriteValue386_Op386MOVSDload_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVSDloadidx1_0(v *Value) bool {
|
||||
// match: (MOVSDloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem)
|
||||
// cond:
|
||||
// result: (MOVSDloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVSDloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5445,7 +5445,7 @@ func rewriteValue386_Op386MOVSDloadidx1_0(v *Value) bool {
|
||||
idx := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVSDloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5454,7 +5454,7 @@ func rewriteValue386_Op386MOVSDloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVSDloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem)
|
||||
// cond:
|
||||
// result: (MOVSDloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVSDloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5468,7 +5468,7 @@ func rewriteValue386_Op386MOVSDloadidx1_0(v *Value) bool {
|
||||
idx := v_1.Args[0]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVSDloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5480,7 +5480,7 @@ func rewriteValue386_Op386MOVSDloadidx1_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVSDloadidx8_0(v *Value) bool {
|
||||
// match: (MOVSDloadidx8 [c] {sym} (ADDLconst [d] ptr) idx mem)
|
||||
// cond:
|
||||
// result: (MOVSDloadidx8 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVSDloadidx8 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5494,7 +5494,7 @@ func rewriteValue386_Op386MOVSDloadidx8_0(v *Value) bool {
|
||||
idx := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVSDloadidx8)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5503,7 +5503,7 @@ func rewriteValue386_Op386MOVSDloadidx8_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVSDloadidx8 [c] {sym} ptr (ADDLconst [d] idx) mem)
|
||||
// cond:
|
||||
// result: (MOVSDloadidx8 [c+8*d] {sym} ptr idx mem)
|
||||
// result: (MOVSDloadidx8 [int64(int32(c+8*d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5517,7 +5517,7 @@ func rewriteValue386_Op386MOVSDloadidx8_0(v *Value) bool {
|
||||
idx := v_1.Args[0]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVSDloadidx8)
|
||||
v.AuxInt = c + 8*d
|
||||
v.AuxInt = int64(int32(c + 8*d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5677,7 +5677,7 @@ func rewriteValue386_Op386MOVSDstore_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVSDstoreidx1_0(v *Value) bool {
|
||||
// match: (MOVSDstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem)
|
||||
// cond:
|
||||
// result: (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVSDstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5692,7 +5692,7 @@ func rewriteValue386_Op386MOVSDstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVSDstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5702,7 +5702,7 @@ func rewriteValue386_Op386MOVSDstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVSDstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem)
|
||||
// cond:
|
||||
// result: (MOVSDstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVSDstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5717,7 +5717,7 @@ func rewriteValue386_Op386MOVSDstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVSDstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5730,7 +5730,7 @@ func rewriteValue386_Op386MOVSDstoreidx1_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVSDstoreidx8_0(v *Value) bool {
|
||||
// match: (MOVSDstoreidx8 [c] {sym} (ADDLconst [d] ptr) idx val mem)
|
||||
// cond:
|
||||
// result: (MOVSDstoreidx8 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVSDstoreidx8 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5745,7 +5745,7 @@ func rewriteValue386_Op386MOVSDstoreidx8_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVSDstoreidx8)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5755,7 +5755,7 @@ func rewriteValue386_Op386MOVSDstoreidx8_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVSDstoreidx8 [c] {sym} ptr (ADDLconst [d] idx) val mem)
|
||||
// cond:
|
||||
// result: (MOVSDstoreidx8 [c+8*d] {sym} ptr idx val mem)
|
||||
// result: (MOVSDstoreidx8 [int64(int32(c+8*d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5770,7 +5770,7 @@ func rewriteValue386_Op386MOVSDstoreidx8_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVSDstoreidx8)
|
||||
v.AuxInt = c + 8*d
|
||||
v.AuxInt = int64(int32(c + 8*d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5944,7 +5944,7 @@ func rewriteValue386_Op386MOVSSload_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVSSloadidx1_0(v *Value) bool {
|
||||
// match: (MOVSSloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem)
|
||||
// cond:
|
||||
// result: (MOVSSloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVSSloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5958,7 +5958,7 @@ func rewriteValue386_Op386MOVSSloadidx1_0(v *Value) bool {
|
||||
idx := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVSSloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5967,7 +5967,7 @@ func rewriteValue386_Op386MOVSSloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVSSloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem)
|
||||
// cond:
|
||||
// result: (MOVSSloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVSSloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5981,7 +5981,7 @@ func rewriteValue386_Op386MOVSSloadidx1_0(v *Value) bool {
|
||||
idx := v_1.Args[0]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVSSloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -5993,7 +5993,7 @@ func rewriteValue386_Op386MOVSSloadidx1_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVSSloadidx4_0(v *Value) bool {
|
||||
// match: (MOVSSloadidx4 [c] {sym} (ADDLconst [d] ptr) idx mem)
|
||||
// cond:
|
||||
// result: (MOVSSloadidx4 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVSSloadidx4 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6007,7 +6007,7 @@ func rewriteValue386_Op386MOVSSloadidx4_0(v *Value) bool {
|
||||
idx := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVSSloadidx4)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -6016,7 +6016,7 @@ func rewriteValue386_Op386MOVSSloadidx4_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVSSloadidx4 [c] {sym} ptr (ADDLconst [d] idx) mem)
|
||||
// cond:
|
||||
// result: (MOVSSloadidx4 [c+4*d] {sym} ptr idx mem)
|
||||
// result: (MOVSSloadidx4 [int64(int32(c+4*d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6030,7 +6030,7 @@ func rewriteValue386_Op386MOVSSloadidx4_0(v *Value) bool {
|
||||
idx := v_1.Args[0]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVSSloadidx4)
|
||||
v.AuxInt = c + 4*d
|
||||
v.AuxInt = int64(int32(c + 4*d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -6190,7 +6190,7 @@ func rewriteValue386_Op386MOVSSstore_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVSSstoreidx1_0(v *Value) bool {
|
||||
// match: (MOVSSstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem)
|
||||
// cond:
|
||||
// result: (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVSSstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6205,7 +6205,7 @@ func rewriteValue386_Op386MOVSSstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVSSstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -6215,7 +6215,7 @@ func rewriteValue386_Op386MOVSSstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVSSstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem)
|
||||
// cond:
|
||||
// result: (MOVSSstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVSSstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6230,7 +6230,7 @@ func rewriteValue386_Op386MOVSSstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVSSstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -6243,7 +6243,7 @@ func rewriteValue386_Op386MOVSSstoreidx1_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVSSstoreidx4_0(v *Value) bool {
|
||||
// match: (MOVSSstoreidx4 [c] {sym} (ADDLconst [d] ptr) idx val mem)
|
||||
// cond:
|
||||
// result: (MOVSSstoreidx4 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVSSstoreidx4 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6258,7 +6258,7 @@ func rewriteValue386_Op386MOVSSstoreidx4_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVSSstoreidx4)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -6268,7 +6268,7 @@ func rewriteValue386_Op386MOVSSstoreidx4_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVSSstoreidx4 [c] {sym} ptr (ADDLconst [d] idx) val mem)
|
||||
// cond:
|
||||
// result: (MOVSSstoreidx4 [c+4*d] {sym} ptr idx val mem)
|
||||
// result: (MOVSSstoreidx4 [int64(int32(c+4*d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6283,7 +6283,7 @@ func rewriteValue386_Op386MOVSSstoreidx4_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVSSstoreidx4)
|
||||
v.AuxInt = c + 4*d
|
||||
v.AuxInt = int64(int32(c + 4*d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -6715,7 +6715,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVWloadidx1 [c] {sym} (ADDLconst [d] ptr) idx mem)
|
||||
// cond:
|
||||
// result: (MOVWloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6729,7 +6729,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
|
||||
idx := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVWloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -6738,7 +6738,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVWloadidx1 [c] {sym} idx (ADDLconst [d] ptr) mem)
|
||||
// cond:
|
||||
// result: (MOVWloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6752,7 +6752,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
|
||||
ptr := v_1.Args[0]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVWloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -6761,7 +6761,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVWloadidx1 [c] {sym} ptr (ADDLconst [d] idx) mem)
|
||||
// cond:
|
||||
// result: (MOVWloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6775,7 +6775,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
|
||||
idx := v_1.Args[0]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVWloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -6784,7 +6784,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVWloadidx1 [c] {sym} (ADDLconst [d] idx) ptr mem)
|
||||
// cond:
|
||||
// result: (MOVWloadidx1 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVWloadidx1 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6798,7 +6798,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
|
||||
ptr := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVWloadidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -6810,7 +6810,7 @@ func rewriteValue386_Op386MOVWloadidx1_0(v *Value) bool {
|
||||
func rewriteValue386_Op386MOVWloadidx2_0(v *Value) bool {
|
||||
// match: (MOVWloadidx2 [c] {sym} (ADDLconst [d] ptr) idx mem)
|
||||
// cond:
|
||||
// result: (MOVWloadidx2 [c+d] {sym} ptr idx mem)
|
||||
// result: (MOVWloadidx2 [int64(int32(c+d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6824,7 +6824,7 @@ func rewriteValue386_Op386MOVWloadidx2_0(v *Value) bool {
|
||||
idx := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVWloadidx2)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -6833,7 +6833,7 @@ func rewriteValue386_Op386MOVWloadidx2_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVWloadidx2 [c] {sym} ptr (ADDLconst [d] idx) mem)
|
||||
// cond:
|
||||
// result: (MOVWloadidx2 [c+2*d] {sym} ptr idx mem)
|
||||
// result: (MOVWloadidx2 [int64(int32(c+2*d))] {sym} ptr idx mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6847,7 +6847,7 @@ func rewriteValue386_Op386MOVWloadidx2_0(v *Value) bool {
|
||||
idx := v_1.Args[0]
|
||||
mem := v.Args[2]
|
||||
v.reset(Op386MOVWloadidx2)
|
||||
v.AuxInt = c + 2*d
|
||||
v.AuxInt = int64(int32(c + 2*d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -7590,7 +7590,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVWstoreidx1 [c] {sym} (ADDLconst [d] ptr) idx val mem)
|
||||
// cond:
|
||||
// result: (MOVWstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -7605,7 +7605,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVWstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -7615,7 +7615,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVWstoreidx1 [c] {sym} idx (ADDLconst [d] ptr) val mem)
|
||||
// cond:
|
||||
// result: (MOVWstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -7630,7 +7630,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVWstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -7640,7 +7640,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVWstoreidx1 [c] {sym} ptr (ADDLconst [d] idx) val mem)
|
||||
// cond:
|
||||
// result: (MOVWstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -7655,7 +7655,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVWstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -7665,7 +7665,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVWstoreidx1 [c] {sym} (ADDLconst [d] idx) ptr val mem)
|
||||
// cond:
|
||||
// result: (MOVWstoreidx1 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVWstoreidx1 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -7680,7 +7680,7 @@ func rewriteValue386_Op386MOVWstoreidx1_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVWstoreidx1)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -8118,7 +8118,7 @@ func rewriteValue386_Op386MOVWstoreidx2_0(v *Value) bool {
|
||||
_ = b
|
||||
// match: (MOVWstoreidx2 [c] {sym} (ADDLconst [d] ptr) idx val mem)
|
||||
// cond:
|
||||
// result: (MOVWstoreidx2 [c+d] {sym} ptr idx val mem)
|
||||
// result: (MOVWstoreidx2 [int64(int32(c+d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -8133,7 +8133,7 @@ func rewriteValue386_Op386MOVWstoreidx2_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVWstoreidx2)
|
||||
v.AuxInt = c + d
|
||||
v.AuxInt = int64(int32(c + d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
@@ -8143,7 +8143,7 @@ func rewriteValue386_Op386MOVWstoreidx2_0(v *Value) bool {
|
||||
}
|
||||
// match: (MOVWstoreidx2 [c] {sym} ptr (ADDLconst [d] idx) val mem)
|
||||
// cond:
|
||||
// result: (MOVWstoreidx2 [c+2*d] {sym} ptr idx val mem)
|
||||
// result: (MOVWstoreidx2 [int64(int32(c+2*d))] {sym} ptr idx val mem)
|
||||
for {
|
||||
c := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -8158,7 +8158,7 @@ func rewriteValue386_Op386MOVWstoreidx2_0(v *Value) bool {
|
||||
val := v.Args[2]
|
||||
mem := v.Args[3]
|
||||
v.reset(Op386MOVWstoreidx2)
|
||||
v.AuxInt = c + 2*d
|
||||
v.AuxInt = int64(int32(c + 2*d))
|
||||
v.Aux = sym
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(idx)
|
||||
|
||||
@@ -5670,6 +5670,8 @@ func rewriteValuegeneric_OpArg_10(v *Value) bool {
|
||||
return false
|
||||
}
|
||||
func rewriteValuegeneric_OpArraySelect_0(v *Value) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (ArraySelect (ArrayMake1 x))
|
||||
// cond:
|
||||
// result: x
|
||||
@@ -5684,23 +5686,26 @@ func rewriteValuegeneric_OpArraySelect_0(v *Value) bool {
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (ArraySelect [0] (Load ptr mem))
|
||||
// match: (ArraySelect [0] x:(Load ptr mem))
|
||||
// cond:
|
||||
// result: (Load ptr mem)
|
||||
// result: @x.Block (Load <v.Type> ptr mem)
|
||||
for {
|
||||
if v.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpLoad {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpLoad {
|
||||
break
|
||||
}
|
||||
_ = v_0.Args[1]
|
||||
ptr := v_0.Args[0]
|
||||
mem := v_0.Args[1]
|
||||
v.reset(OpLoad)
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(mem)
|
||||
_ = x.Args[1]
|
||||
ptr := x.Args[0]
|
||||
mem := x.Args[1]
|
||||
b = x.Block
|
||||
v0 := b.NewValue0(v.Pos, OpLoad, v.Type)
|
||||
v.reset(OpCopy)
|
||||
v.AddArg(v0)
|
||||
v0.AddArg(ptr)
|
||||
v0.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (ArraySelect [0] x:(IData _))
|
||||
|
||||
@@ -46,6 +46,9 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) {
|
||||
case ssa.Op386MOVSSloadidx1, ssa.Op386MOVSDloadidx1:
|
||||
p.From.Scale = 1
|
||||
p.From.Index = v.Args[1].Reg()
|
||||
if p.From.Index == x86.REG_SP {
|
||||
p.From.Reg, p.From.Index = p.From.Index, p.From.Reg
|
||||
}
|
||||
case ssa.Op386MOVSSloadidx4:
|
||||
p.From.Scale = 4
|
||||
p.From.Index = v.Args[1].Reg()
|
||||
@@ -95,6 +98,9 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) {
|
||||
case ssa.Op386MOVSSstoreidx1, ssa.Op386MOVSDstoreidx1:
|
||||
p.To.Scale = 1
|
||||
p.To.Index = v.Args[1].Reg()
|
||||
if p.To.Index == x86.REG_SP {
|
||||
p.To.Reg, p.To.Index = p.To.Index, p.To.Reg
|
||||
}
|
||||
case ssa.Op386MOVSSstoreidx4:
|
||||
p.To.Scale = 4
|
||||
p.To.Index = v.Args[1].Reg()
|
||||
|
||||
2
src/cmd/dist/build.go
vendored
2
src/cmd/dist/build.go
vendored
@@ -701,7 +701,7 @@ func install(dir string) {
|
||||
} else {
|
||||
archive = b
|
||||
}
|
||||
compile := []string{pathf("%s/compile", tooldir), "-pack", "-o", b, "-p", pkg}
|
||||
compile := []string{pathf("%s/compile", tooldir), "-std", "-pack", "-o", b, "-p", pkg}
|
||||
if gogcflags != "" {
|
||||
compile = append(compile, strings.Fields(gogcflags)...)
|
||||
}
|
||||
|
||||
@@ -1106,17 +1106,26 @@
|
||||
// CGO_CFLAGS
|
||||
// Flags that cgo will pass to the compiler when compiling
|
||||
// C code.
|
||||
// CGO_CPPFLAGS
|
||||
// Flags that cgo will pass to the compiler when compiling
|
||||
// C or C++ code.
|
||||
// CGO_CXXFLAGS
|
||||
// Flags that cgo will pass to the compiler when compiling
|
||||
// C++ code.
|
||||
// CGO_FFLAGS
|
||||
// Flags that cgo will pass to the compiler when compiling
|
||||
// Fortran code.
|
||||
// CGO_LDFLAGS
|
||||
// Flags that cgo will pass to the compiler when linking.
|
||||
// CGO_CFLAGS_ALLOW
|
||||
// A regular expression specifying additional flags to allow
|
||||
// to appear in #cgo CFLAGS source code directives.
|
||||
// Does not apply to the CGO_CFLAGS environment variable.
|
||||
// CGO_CFLAGS_DISALLOW
|
||||
// A regular expression specifying flags that must be disallowed
|
||||
// from appearing in #cgo CFLAGS source code directives.
|
||||
// Does not apply to the CGO_CFLAGS environment variable.
|
||||
// CGO_CPPFLAGS, CGO_CPPFLAGS_ALLOW, CGO_CPPFLAGS_DISALLOW
|
||||
// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
|
||||
// but for the C preprocessor.
|
||||
// CGO_CXXFLAGS, CGO_CXXFLAGS_ALLOW, CGO_CXXFLAGS_DISALLOW
|
||||
// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
|
||||
// but for the C++ compiler.
|
||||
// CGO_FFLAGS, CGO_FFLAGS_ALLOW, CGO_FFLAGS_DISALLOW
|
||||
// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
|
||||
// but for the Fortran compiler.
|
||||
// CGO_LDFLAGS, CGO_LDFLAGS_ALLOW, CGO_LDFLAGS_DISALLOW
|
||||
// Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
|
||||
// but for the linker.
|
||||
// CXX
|
||||
// The command to use to compile C++ code.
|
||||
// PKG_CONFIG
|
||||
|
||||
@@ -2449,7 +2449,7 @@ func TestCgoHandlesWlORIGIN(t *testing.T) {
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.tempFile("src/origin/origin.go", `package origin
|
||||
// #cgo !darwin LDFLAGS: -Wl,-rpath -Wl,$ORIGIN
|
||||
// #cgo !darwin LDFLAGS: -Wl,-rpath,$ORIGIN
|
||||
// void f(void) {}
|
||||
import "C"
|
||||
func f() { C.f() }`)
|
||||
@@ -4349,3 +4349,150 @@ func TestListTests(t *testing.T) {
|
||||
t.Run("Example1", testWith("Example", "ExampleSimple"))
|
||||
t.Run("Example2", testWith("Example", "ExampleWithEmptyOutput"))
|
||||
}
|
||||
|
||||
func TestBadCommandLines(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
||||
tg.tempFile("src/x/x.go", "package x\n")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
|
||||
tg.run("build", "x")
|
||||
|
||||
tg.tempFile("src/x/@y.go", "package x\n")
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("invalid input file name \"@y.go\"", "did not reject @y.go")
|
||||
tg.must(os.Remove(tg.path("src/x/@y.go")))
|
||||
|
||||
tg.tempFile("src/x/-y.go", "package x\n")
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("invalid input file name \"-y.go\"", "did not reject -y.go")
|
||||
tg.must(os.Remove(tg.path("src/x/-y.go")))
|
||||
|
||||
tg.runFail("build", "-gcflags=@x", "x")
|
||||
tg.grepStderr("invalid command-line argument @x in command", "did not reject @x during exec")
|
||||
|
||||
tg.tempFile("src/@x/x.go", "package x\n")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.runFail("build", "@x")
|
||||
tg.grepStderr("invalid input directory name \"@x\"", "did not reject @x directory")
|
||||
|
||||
tg.tempFile("src/@x/y/y.go", "package y\n")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.runFail("build", "@x/y")
|
||||
tg.grepStderr("invalid import path \"@x/y\"", "did not reject @x/y import path")
|
||||
|
||||
tg.tempFile("src/-x/x.go", "package x\n")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.runFail("build", "--", "-x")
|
||||
tg.grepStderr("invalid input directory name \"-x\"", "did not reject -x directory")
|
||||
|
||||
tg.tempFile("src/-x/y/y.go", "package y\n")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.runFail("build", "--", "-x/y")
|
||||
tg.grepStderr("invalid import path \"-x/y\"", "did not reject -x/y import path")
|
||||
}
|
||||
|
||||
func TestBadCgoDirectives(t *testing.T) {
|
||||
if !canCgo {
|
||||
t.Skip("no cgo")
|
||||
}
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
||||
tg.tempFile("src/x/x.go", "package x\n")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
|
||||
tg.tempFile("src/x/x.go", `package x
|
||||
|
||||
//go:cgo_ldflag "-fplugin=foo.so"
|
||||
|
||||
`)
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("//go:cgo_ldflag .* only allowed in cgo-generated code", "did not reject //go:cgo_ldflag directive")
|
||||
|
||||
tg.must(os.Remove(tg.path("src/x/x.go")))
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("no Go files", "did not report missing source code")
|
||||
tg.tempFile("src/x/_cgo_yy.go", `package x
|
||||
|
||||
//go:cgo_ldflag "-fplugin=foo.so"
|
||||
|
||||
`)
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("no Go files", "did not report missing source code") // _* files are ignored...
|
||||
|
||||
tg.runFail("build", tg.path("src/x/_cgo_yy.go")) // ... but if forced, the comment is rejected
|
||||
// Actually, today there is a separate issue that _ files named
|
||||
// on the command-line are ignored. Once that is fixed,
|
||||
// we want to see the cgo_ldflag error.
|
||||
tg.grepStderr("//go:cgo_ldflag only allowed in cgo-generated code|no Go files", "did not reject //go:cgo_ldflag directive")
|
||||
tg.must(os.Remove(tg.path("src/x/_cgo_yy.go")))
|
||||
|
||||
tg.tempFile("src/x/x.go", "package x\n")
|
||||
tg.tempFile("src/x/y.go", `package x
|
||||
// #cgo CFLAGS: -fplugin=foo.so
|
||||
import "C"
|
||||
`)
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("invalid flag in #cgo CFLAGS: -fplugin=foo.so", "did not reject -fplugin")
|
||||
|
||||
tg.tempFile("src/x/y.go", `package x
|
||||
// #cgo CFLAGS: -Ibar -fplugin=foo.so
|
||||
import "C"
|
||||
`)
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("invalid flag in #cgo CFLAGS: -fplugin=foo.so", "did not reject -fplugin")
|
||||
|
||||
tg.tempFile("src/x/y.go", `package x
|
||||
// #cgo pkg-config: -foo
|
||||
import "C"
|
||||
`)
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("invalid pkg-config package name: -foo", "did not reject pkg-config: -foo")
|
||||
|
||||
tg.tempFile("src/x/y.go", `package x
|
||||
// #cgo pkg-config: @foo
|
||||
import "C"
|
||||
`)
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("invalid pkg-config package name: @foo", "did not reject pkg-config: -foo")
|
||||
|
||||
tg.tempFile("src/x/y.go", `package x
|
||||
// #cgo CFLAGS: @foo
|
||||
import "C"
|
||||
`)
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("invalid flag in #cgo CFLAGS: @foo", "did not reject @foo flag")
|
||||
|
||||
tg.tempFile("src/x/y.go", `package x
|
||||
// #cgo CFLAGS: -D
|
||||
import "C"
|
||||
`)
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("invalid flag in #cgo CFLAGS: -D without argument", "did not reject trailing -I flag")
|
||||
|
||||
// Note that -I @foo is allowed because we rewrite it into -I /path/to/src/@foo
|
||||
// before the check is applied. There's no such rewrite for -D.
|
||||
|
||||
tg.tempFile("src/x/y.go", `package x
|
||||
// #cgo CFLAGS: -D @foo
|
||||
import "C"
|
||||
`)
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("invalid flag in #cgo CFLAGS: -D @foo", "did not reject -D @foo flag")
|
||||
|
||||
tg.tempFile("src/x/y.go", `package x
|
||||
// #cgo CFLAGS: -D@foo
|
||||
import "C"
|
||||
`)
|
||||
tg.runFail("build", "x")
|
||||
tg.grepStderr("invalid flag in #cgo CFLAGS: -D@foo", "did not reject -D@foo flag")
|
||||
|
||||
tg.setenv("CGO_CFLAGS", "-D@foo")
|
||||
tg.tempFile("src/x/y.go", `package x
|
||||
import "C"
|
||||
`)
|
||||
tg.run("build", "-n", "x")
|
||||
tg.grepStderr("-D@foo", "did not find -D@foo in commands")
|
||||
}
|
||||
|
||||
@@ -101,7 +101,12 @@ func findEnv(env []cfg.EnvVar, name string) string {
|
||||
func ExtraEnvVars() []cfg.EnvVar {
|
||||
var b work.Builder
|
||||
b.Init()
|
||||
cppflags, cflags, cxxflags, fflags, ldflags := b.CFlags(&load.Package{})
|
||||
cppflags, cflags, cxxflags, fflags, ldflags, err := b.CFlags(&load.Package{})
|
||||
if err != nil {
|
||||
// Should not happen - b.CFlags was given an empty package.
|
||||
fmt.Fprintf(os.Stderr, "go: invalid cflags: %v\n", err)
|
||||
return nil
|
||||
}
|
||||
return []cfg.EnvVar{
|
||||
{Name: "CGO_CFLAGS", Value: strings.Join(cflags, " ")},
|
||||
{Name: "CGO_CPPFLAGS", Value: strings.Join(cppflags, " ")},
|
||||
|
||||
@@ -481,17 +481,26 @@ Environment variables for use with cgo:
|
||||
CGO_CFLAGS
|
||||
Flags that cgo will pass to the compiler when compiling
|
||||
C code.
|
||||
CGO_CPPFLAGS
|
||||
Flags that cgo will pass to the compiler when compiling
|
||||
C or C++ code.
|
||||
CGO_CXXFLAGS
|
||||
Flags that cgo will pass to the compiler when compiling
|
||||
C++ code.
|
||||
CGO_FFLAGS
|
||||
Flags that cgo will pass to the compiler when compiling
|
||||
Fortran code.
|
||||
CGO_LDFLAGS
|
||||
Flags that cgo will pass to the compiler when linking.
|
||||
CGO_CFLAGS_ALLOW
|
||||
A regular expression specifying additional flags to allow
|
||||
to appear in #cgo CFLAGS source code directives.
|
||||
Does not apply to the CGO_CFLAGS environment variable.
|
||||
CGO_CFLAGS_DISALLOW
|
||||
A regular expression specifying flags that must be disallowed
|
||||
from appearing in #cgo CFLAGS source code directives.
|
||||
Does not apply to the CGO_CFLAGS environment variable.
|
||||
CGO_CPPFLAGS, CGO_CPPFLAGS_ALLOW, CGO_CPPFLAGS_DISALLOW
|
||||
Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
|
||||
but for the C preprocessor.
|
||||
CGO_CXXFLAGS, CGO_CXXFLAGS_ALLOW, CGO_CXXFLAGS_DISALLOW
|
||||
Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
|
||||
but for the C++ compiler.
|
||||
CGO_FFLAGS, CGO_FFLAGS_ALLOW, CGO_FFLAGS_DISALLOW
|
||||
Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
|
||||
but for the Fortran compiler.
|
||||
CGO_LDFLAGS, CGO_LDFLAGS_ALLOW, CGO_LDFLAGS_DISALLOW
|
||||
Like CGO_CFLAGS, CGO_CFLAGS_ALLOW, and CGO_CFLAGS_DISALLOW,
|
||||
but for the linker.
|
||||
CXX
|
||||
The command to use to compile C++ code.
|
||||
PKG_CONFIG
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
|
||||
"cmd/go/internal/base"
|
||||
"cmd/go/internal/buildid"
|
||||
@@ -53,6 +54,8 @@ type PackagePublic struct {
|
||||
BinaryOnly bool `json:",omitempty"` // package cannot be recompiled
|
||||
|
||||
// Source files
|
||||
// If you add to this list you MUST add to p.AllFiles (below) too.
|
||||
// Otherwise file name security lists will not apply to any new additions.
|
||||
GoFiles []string `json:",omitempty"` // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
|
||||
CgoFiles []string `json:",omitempty"` // .go sources files that import "C"
|
||||
IgnoredGoFiles []string `json:",omitempty"` // .go sources ignored due to build constraints
|
||||
@@ -84,12 +87,38 @@ type PackagePublic struct {
|
||||
DepsErrors []*PackageError `json:",omitempty"` // errors loading dependencies
|
||||
|
||||
// Test information
|
||||
// If you add to this list you MUST add to p.AllFiles (below) too.
|
||||
// Otherwise file name security lists will not apply to any new additions.
|
||||
TestGoFiles []string `json:",omitempty"` // _test.go files in package
|
||||
TestImports []string `json:",omitempty"` // imports from TestGoFiles
|
||||
XTestGoFiles []string `json:",omitempty"` // _test.go files outside package
|
||||
XTestImports []string `json:",omitempty"` // imports from XTestGoFiles
|
||||
}
|
||||
|
||||
// AllFiles returns the names of all the files considered for the package.
|
||||
// This is used for sanity and security checks, so we include all files,
|
||||
// even IgnoredGoFiles, because some subcommands consider them.
|
||||
// The go/build package filtered others out (like foo_wrongGOARCH.s)
|
||||
// and that's OK.
|
||||
func (p *Package) AllFiles() []string {
|
||||
return str.StringList(
|
||||
p.GoFiles,
|
||||
p.CgoFiles,
|
||||
p.IgnoredGoFiles,
|
||||
p.CFiles,
|
||||
p.CXXFiles,
|
||||
p.MFiles,
|
||||
p.HFiles,
|
||||
p.FFiles,
|
||||
p.SFiles,
|
||||
p.SwigFiles,
|
||||
p.SwigCXXFiles,
|
||||
p.SysoFiles,
|
||||
p.TestGoFiles,
|
||||
p.XTestGoFiles,
|
||||
)
|
||||
}
|
||||
|
||||
type PackageInternal struct {
|
||||
// Unexported fields are not part of the public API.
|
||||
Build *build.Package
|
||||
@@ -1025,22 +1054,8 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) *Package
|
||||
// To avoid problems on case-insensitive files, we reject any package
|
||||
// where two different input files have equal names under a case-insensitive
|
||||
// comparison.
|
||||
f1, f2 := str.FoldDup(str.StringList(
|
||||
p.GoFiles,
|
||||
p.CgoFiles,
|
||||
p.IgnoredGoFiles,
|
||||
p.CFiles,
|
||||
p.CXXFiles,
|
||||
p.MFiles,
|
||||
p.HFiles,
|
||||
p.FFiles,
|
||||
p.SFiles,
|
||||
p.SysoFiles,
|
||||
p.SwigFiles,
|
||||
p.SwigCXXFiles,
|
||||
p.TestGoFiles,
|
||||
p.XTestGoFiles,
|
||||
))
|
||||
inputs := p.AllFiles()
|
||||
f1, f2 := str.FoldDup(inputs)
|
||||
if f1 != "" {
|
||||
p.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
@@ -1049,6 +1064,37 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) *Package
|
||||
return p
|
||||
}
|
||||
|
||||
// If first letter of input file is ASCII, it must be alphanumeric.
|
||||
// This avoids files turning into flags when invoking commands,
|
||||
// and other problems we haven't thought of yet.
|
||||
// Also, _cgo_ files must be generated by us, not supplied.
|
||||
// They are allowed to have //go:cgo_ldflag directives.
|
||||
// The directory scan ignores files beginning with _,
|
||||
// so we shouldn't see any _cgo_ files anyway, but just be safe.
|
||||
for _, file := range inputs {
|
||||
if !SafeArg(file) || strings.HasPrefix(file, "_cgo_") {
|
||||
p.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Err: fmt.Sprintf("invalid input file name %q", file),
|
||||
}
|
||||
return p
|
||||
}
|
||||
}
|
||||
if name := pathpkg.Base(p.ImportPath); !SafeArg(name) {
|
||||
p.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Err: fmt.Sprintf("invalid input directory name %q", name),
|
||||
}
|
||||
return p
|
||||
}
|
||||
if !SafeArg(p.ImportPath) {
|
||||
p.Error = &PackageError{
|
||||
ImportStack: stk.Copy(),
|
||||
Err: fmt.Sprintf("invalid import path %q", p.ImportPath),
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// Build list of imported packages and full dependency list.
|
||||
imports := make([]*Package, 0, len(p.Imports))
|
||||
deps := make(map[string]*Package)
|
||||
@@ -1164,6 +1210,22 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) *Package
|
||||
return p
|
||||
}
|
||||
|
||||
// SafeArg reports whether arg is a "safe" command-line argument,
|
||||
// meaning that when it appears in a command-line, it probably
|
||||
// doesn't have some special meaning other than its own name.
|
||||
// Obviously args beginning with - are not safe (they look like flags).
|
||||
// Less obviously, args beginning with @ are not safe (they look like
|
||||
// GNU binutils flagfile specifiers, sometimes called "response files").
|
||||
// To be conservative, we reject almost any arg beginning with non-alphanumeric ASCII.
|
||||
// We accept leading . _ and / as likely in file system paths.
|
||||
func SafeArg(name string) bool {
|
||||
if name == "" {
|
||||
return false
|
||||
}
|
||||
c := name[0]
|
||||
return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
|
||||
}
|
||||
|
||||
// usesSwig reports whether the package needs to run SWIG.
|
||||
func (p *Package) UsesSwig() bool {
|
||||
return len(p.SwigFiles) > 0 || len(p.SwigCXXFiles) > 0
|
||||
|
||||
@@ -1526,26 +1526,35 @@ func splitPkgConfigOutput(out []byte) []string {
|
||||
// Calls pkg-config if needed and returns the cflags/ldflags needed to build the package.
|
||||
func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, err error) {
|
||||
if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
|
||||
for _, pkg := range pkgs {
|
||||
if !load.SafeArg(pkg) {
|
||||
return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg)
|
||||
}
|
||||
}
|
||||
var out []byte
|
||||
out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", pkgs)
|
||||
out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", "--", pkgs)
|
||||
if err != nil {
|
||||
b.showOutput(p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pkgs, " "), string(out))
|
||||
b.Print(err.Error() + "\n")
|
||||
err = errPrintedOutput
|
||||
return
|
||||
return nil, nil, errPrintedOutput
|
||||
}
|
||||
if len(out) > 0 {
|
||||
cflags = splitPkgConfigOutput(out)
|
||||
if err := checkCompilerFlags("CFLAGS", "pkg-config --cflags", cflags); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", pkgs)
|
||||
out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", "--", pkgs)
|
||||
if err != nil {
|
||||
b.showOutput(p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pkgs, " "), string(out))
|
||||
b.Print(err.Error() + "\n")
|
||||
err = errPrintedOutput
|
||||
return
|
||||
return nil, nil, errPrintedOutput
|
||||
}
|
||||
if len(out) > 0 {
|
||||
ldflags = strings.Fields(string(out))
|
||||
if err := checkLinkerFlags("CFLAGS", "pkg-config --cflags", ldflags); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
@@ -1959,6 +1968,17 @@ func (b *Builder) processOutput(out []byte) string {
|
||||
// It returns the command output and any errors that occurred.
|
||||
func (b *Builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) {
|
||||
cmdline := str.StringList(cmdargs...)
|
||||
|
||||
for _, arg := range cmdline {
|
||||
// GNU binutils commands, including gcc and gccgo, interpret an argument
|
||||
// @foo anywhere in the command line (even following --) as meaning
|
||||
// "read and insert arguments from the file named foo."
|
||||
// Don't say anything that might be misinterpreted that way.
|
||||
if strings.HasPrefix(arg, "@") {
|
||||
return nil, fmt.Errorf("invalid command-line argument %s in command: %s", arg, joinUnambiguously(cmdline))
|
||||
}
|
||||
}
|
||||
|
||||
if cfg.BuildN || cfg.BuildX {
|
||||
var envcmdline string
|
||||
for i := range env {
|
||||
@@ -3270,22 +3290,44 @@ func envList(key, def string) []string {
|
||||
}
|
||||
|
||||
// CFlags returns the flags to use when invoking the C, C++ or Fortran compilers, or cgo.
|
||||
func (b *Builder) CFlags(p *load.Package) (cppflags, cflags, cxxflags, fflags, ldflags []string) {
|
||||
func (b *Builder) CFlags(p *load.Package) (cppflags, cflags, cxxflags, fflags, ldflags []string, err error) {
|
||||
defaults := "-g -O2"
|
||||
|
||||
cppflags = str.StringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS)
|
||||
cflags = str.StringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS)
|
||||
cxxflags = str.StringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS)
|
||||
fflags = str.StringList(envList("CGO_FFLAGS", defaults), p.CgoFFLAGS)
|
||||
ldflags = str.StringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS)
|
||||
if cppflags, err = buildFlags("CPPFLAGS", "", p.CgoCPPFLAGS, checkCompilerFlags); err != nil {
|
||||
return
|
||||
}
|
||||
if cflags, err = buildFlags("CFLAGS", defaults, p.CgoCFLAGS, checkCompilerFlags); err != nil {
|
||||
return
|
||||
}
|
||||
if cxxflags, err = buildFlags("CXXFLAGS", defaults, p.CgoCXXFLAGS, checkCompilerFlags); err != nil {
|
||||
return
|
||||
}
|
||||
if fflags, err = buildFlags("FFLAGS", defaults, p.CgoFFLAGS, checkCompilerFlags); err != nil {
|
||||
return
|
||||
}
|
||||
if ldflags, err = buildFlags("LDFLAGS", defaults, p.CgoLDFLAGS, checkLinkerFlags); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func buildFlags(name, defaults string, fromPackage []string, check func(string, string, []string) error) ([]string, error) {
|
||||
if err := check(name, "#cgo "+name, fromPackage); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return str.StringList(envList("CGO_"+name, defaults), fromPackage), nil
|
||||
}
|
||||
|
||||
var cgoRe = regexp.MustCompile(`[/\\:]`)
|
||||
|
||||
func (b *Builder) cgo(a *Action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofiles, objdirCgofiles, gccfiles, gxxfiles, mfiles, ffiles []string) (outGo, outObj []string, err error) {
|
||||
p := a.Package
|
||||
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS := b.CFlags(p)
|
||||
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, cgoFFLAGS, cgoLDFLAGS, err := b.CFlags(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...)
|
||||
cgoLDFLAGS = append(cgoLDFLAGS, pcLDFLAGS...)
|
||||
// If we are compiling Objective-C code, then we need to link against libobjc
|
||||
@@ -3349,6 +3391,12 @@ func (b *Builder) cgo(a *Action, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, cgofil
|
||||
}
|
||||
|
||||
// Update $CGO_LDFLAGS with p.CgoLDFLAGS.
|
||||
// These flags are recorded in the generated _cgo_gotypes.go file
|
||||
// using //go:cgo_ldflag directives, the compiler records them in the
|
||||
// object file for the package, and then the Go linker passes them
|
||||
// along to the host linker. At this point in the code, cgoLDFLAGS
|
||||
// consists of the original $CGO_LDFLAGS (unchecked) and all the
|
||||
// flags put together from source code (checked).
|
||||
var cgoenv []string
|
||||
if len(cgoLDFLAGS) > 0 {
|
||||
flags := make([]string, len(cgoLDFLAGS))
|
||||
@@ -3698,7 +3746,11 @@ func (b *Builder) swigIntSize(obj string) (intsize string, err error) {
|
||||
|
||||
// Run SWIG on one SWIG input file.
|
||||
func (b *Builder) swigOne(p *load.Package, file, obj string, pcCFLAGS []string, cxx bool, intgosize string) (outGo, outC string, err error) {
|
||||
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _ := b.CFlags(p)
|
||||
cgoCPPFLAGS, cgoCFLAGS, cgoCXXFLAGS, _, _, err := b.CFlags(p)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
var cflags []string
|
||||
if cxx {
|
||||
cflags = str.StringList(cgoCPPFLAGS, pcCFLAGS, cgoCXXFLAGS)
|
||||
|
||||
160
src/cmd/go/internal/work/security.go
Normal file
160
src/cmd/go/internal/work/security.go
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Checking of compiler and linker flags.
|
||||
// We must avoid flags like -fplugin=, which can allow
|
||||
// arbitrary code execution during the build.
|
||||
// Do not make changes here without carefully
|
||||
// considering the implications.
|
||||
// (That's why the code is isolated in a file named security.go.)
|
||||
//
|
||||
// Note that -Wl,foo means split foo on commas and pass to
|
||||
// the linker, so that -Wl,-foo,bar means pass -foo bar to
|
||||
// the linker. Similarly -Wa,foo for the assembler and so on.
|
||||
// If any of these are permitted, the wildcard portion must
|
||||
// disallow commas.
|
||||
//
|
||||
// Note also that GNU binutils accept any argument @foo
|
||||
// as meaning "read more flags from the file foo", so we must
|
||||
// guard against any command-line argument beginning with @,
|
||||
// even things like "-I @foo".
|
||||
// We use load.SafeArg (which is even more conservative)
|
||||
// to reject these.
|
||||
//
|
||||
// Even worse, gcc -I@foo (one arg) turns into cc1 -I @foo (two args),
|
||||
// so although gcc doesn't expand the @foo, cc1 will.
|
||||
// So out of paranoia, we reject @ at the beginning of every
|
||||
// flag argument that might be split into its own argument.
|
||||
|
||||
package work
|
||||
|
||||
import (
|
||||
"cmd/go/internal/load"
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
var re = regexp.MustCompile
|
||||
|
||||
var validCompilerFlags = []*regexp.Regexp{
|
||||
re(`-D([A-Za-z_].*)`),
|
||||
re(`-I([^@\-].*)`),
|
||||
re(`-O`),
|
||||
re(`-O([^@\-].*)`),
|
||||
re(`-W`),
|
||||
re(`-W([^@,]+)`), // -Wall but not -Wa,-foo.
|
||||
re(`-f(no-)?objc-arc`),
|
||||
re(`-f(no-)?omit-frame-pointer`),
|
||||
re(`-f(no-)?(pic|PIC|pie|PIE)`),
|
||||
re(`-f(no-)?split-stack`),
|
||||
re(`-f(no-)?stack-(.+)`),
|
||||
re(`-f(no-)?strict-aliasing`),
|
||||
re(`-fsanitize=(.+)`),
|
||||
re(`-g([^@\-].*)?`),
|
||||
re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`),
|
||||
re(`-m(no-)?stack-(.+)`),
|
||||
re(`-mmacosx-(.+)`),
|
||||
re(`-mnop-fun-dllimport`),
|
||||
re(`-pthread`),
|
||||
re(`-std=([^@\-].*)`),
|
||||
re(`-x([^@\-].*)`),
|
||||
}
|
||||
|
||||
var validCompilerFlagsWithNextArg = []string{
|
||||
"-D",
|
||||
"-I",
|
||||
"-framework",
|
||||
"-x",
|
||||
}
|
||||
|
||||
var validLinkerFlags = []*regexp.Regexp{
|
||||
re(`-F([^@\-].*)`),
|
||||
re(`-l([^@\-].*)`),
|
||||
re(`-L([^@\-].*)`),
|
||||
re(`-f(no-)?(pic|PIC|pie|PIE)`),
|
||||
re(`-fsanitize=([^@\-].*)`),
|
||||
re(`-g([^@\-].*)?`),
|
||||
re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`),
|
||||
re(`-(pic|PIC|pie|PIE)`),
|
||||
re(`-pthread`),
|
||||
|
||||
// Note that any wildcards in -Wl need to exclude comma,
|
||||
// since -Wl splits its argument at commas and passes
|
||||
// them all to the linker uninterpreted. Allowing comma
|
||||
// in a wildcard would allow tunnelling arbitrary additional
|
||||
// linker arguments through one of these.
|
||||
re(`-Wl,-rpath,([^,@\-][^,]+)`),
|
||||
re(`-Wl,--(no-)?warn-([^,]+)`),
|
||||
|
||||
re(`[a-zA-Z0-9_].*\.(o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o)
|
||||
}
|
||||
|
||||
var validLinkerFlagsWithNextArg = []string{
|
||||
"-F",
|
||||
"-l",
|
||||
"-L",
|
||||
"-framework",
|
||||
}
|
||||
|
||||
func checkCompilerFlags(name, source string, list []string) error {
|
||||
return checkFlags(name, source, list, validCompilerFlags, validCompilerFlagsWithNextArg)
|
||||
}
|
||||
|
||||
func checkLinkerFlags(name, source string, list []string) error {
|
||||
return checkFlags(name, source, list, validLinkerFlags, validLinkerFlagsWithNextArg)
|
||||
}
|
||||
|
||||
func checkFlags(name, source string, list []string, valid []*regexp.Regexp, validNext []string) error {
|
||||
// Let users override rules with $CGO_CFLAGS_ALLOW, $CGO_CFLAGS_DISALLOW, etc.
|
||||
var (
|
||||
allow *regexp.Regexp
|
||||
disallow *regexp.Regexp
|
||||
)
|
||||
if env := os.Getenv("CGO_" + name + "_ALLOW"); env != "" {
|
||||
r, err := regexp.Compile(env)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing $CGO_%s_ALLOW: %v", name, err)
|
||||
}
|
||||
allow = r
|
||||
}
|
||||
if env := os.Getenv("CGO_" + name + "_DISALLOW"); env != "" {
|
||||
r, err := regexp.Compile(env)
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing $CGO_%s_DISALLOW: %v", name, err)
|
||||
}
|
||||
disallow = r
|
||||
}
|
||||
|
||||
Args:
|
||||
for i := 0; i < len(list); i++ {
|
||||
arg := list[i]
|
||||
if disallow != nil && disallow.FindString(arg) == arg {
|
||||
goto Bad
|
||||
}
|
||||
if allow != nil && allow.FindString(arg) == arg {
|
||||
continue Args
|
||||
}
|
||||
for _, re := range valid {
|
||||
if re.FindString(arg) == arg { // must be complete match
|
||||
continue Args
|
||||
}
|
||||
}
|
||||
for _, x := range validNext {
|
||||
if arg == x {
|
||||
if i+1 < len(list) && load.SafeArg(list[i+1]) {
|
||||
i++
|
||||
continue Args
|
||||
}
|
||||
if i+1 < len(list) {
|
||||
return fmt.Errorf("invalid flag in %s: %s %s", source, arg, list[i+1])
|
||||
}
|
||||
return fmt.Errorf("invalid flag in %s: %s without argument", source, arg)
|
||||
}
|
||||
}
|
||||
Bad:
|
||||
return fmt.Errorf("invalid flag in %s: %s", source, arg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
240
src/cmd/go/internal/work/security_test.go
Normal file
240
src/cmd/go/internal/work/security_test.go
Normal file
@@ -0,0 +1,240 @@
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package work
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var goodCompilerFlags = [][]string{
|
||||
{"-DFOO"},
|
||||
{"-Dfoo=bar"},
|
||||
{"-I/"},
|
||||
{"-I/etc/passwd"},
|
||||
{"-I."},
|
||||
{"-O"},
|
||||
{"-O2"},
|
||||
{"-Osmall"},
|
||||
{"-W"},
|
||||
{"-Wall"},
|
||||
{"-fobjc-arc"},
|
||||
{"-fno-objc-arc"},
|
||||
{"-fomit-frame-pointer"},
|
||||
{"-fno-omit-frame-pointer"},
|
||||
{"-fpic"},
|
||||
{"-fno-pic"},
|
||||
{"-fPIC"},
|
||||
{"-fno-PIC"},
|
||||
{"-fpie"},
|
||||
{"-fno-pie"},
|
||||
{"-fPIE"},
|
||||
{"-fno-PIE"},
|
||||
{"-fsplit-stack"},
|
||||
{"-fno-split-stack"},
|
||||
{"-fstack-xxx"},
|
||||
{"-fno-stack-xxx"},
|
||||
{"-fsanitize=hands"},
|
||||
{"-g"},
|
||||
{"-ggdb"},
|
||||
{"-march=souza"},
|
||||
{"-mcpu=123"},
|
||||
{"-mfpu=123"},
|
||||
{"-mtune=happybirthday"},
|
||||
{"-mstack-overflow"},
|
||||
{"-mno-stack-overflow"},
|
||||
{"-mmacosx-version"},
|
||||
{"-mnop-fun-dllimport"},
|
||||
{"-pthread"},
|
||||
{"-std=c99"},
|
||||
{"-xc"},
|
||||
{"-D", "FOO"},
|
||||
{"-D", "foo=bar"},
|
||||
{"-I", "."},
|
||||
{"-I", "/etc/passwd"},
|
||||
{"-I", "世界"},
|
||||
{"-framework", "Chocolate"},
|
||||
{"-x", "c"},
|
||||
}
|
||||
|
||||
var badCompilerFlags = [][]string{
|
||||
{"-D@X"},
|
||||
{"-D-X"},
|
||||
{"-I@dir"},
|
||||
{"-I-dir"},
|
||||
{"-O@1"},
|
||||
{"-Wa,-foo"},
|
||||
{"-W@foo"},
|
||||
{"-g@gdb"},
|
||||
{"-g-gdb"},
|
||||
{"-march=@dawn"},
|
||||
{"-march=-dawn"},
|
||||
{"-std=@c99"},
|
||||
{"-std=-c99"},
|
||||
{"-x@c"},
|
||||
{"-x-c"},
|
||||
{"-D", "@foo"},
|
||||
{"-D", "-foo"},
|
||||
{"-I", "@foo"},
|
||||
{"-I", "-foo"},
|
||||
{"-framework", "-Caffeine"},
|
||||
{"-framework", "@Home"},
|
||||
{"-x", "--c"},
|
||||
{"-x", "@obj"},
|
||||
}
|
||||
|
||||
func TestCheckCompilerFlags(t *testing.T) {
|
||||
for _, f := range goodCompilerFlags {
|
||||
if err := checkCompilerFlags("test", "test", f); err != nil {
|
||||
t.Errorf("unexpected error for %q: %v", f, err)
|
||||
}
|
||||
}
|
||||
for _, f := range badCompilerFlags {
|
||||
if err := checkCompilerFlags("test", "test", f); err == nil {
|
||||
t.Errorf("missing error for %q", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var goodLinkerFlags = [][]string{
|
||||
{"-Fbar"},
|
||||
{"-lbar"},
|
||||
{"-Lbar"},
|
||||
{"-fpic"},
|
||||
{"-fno-pic"},
|
||||
{"-fPIC"},
|
||||
{"-fno-PIC"},
|
||||
{"-fpie"},
|
||||
{"-fno-pie"},
|
||||
{"-fPIE"},
|
||||
{"-fno-PIE"},
|
||||
{"-fsanitize=hands"},
|
||||
{"-g"},
|
||||
{"-ggdb"},
|
||||
{"-march=souza"},
|
||||
{"-mcpu=123"},
|
||||
{"-mfpu=123"},
|
||||
{"-mtune=happybirthday"},
|
||||
{"-pic"},
|
||||
{"-pthread"},
|
||||
{"-Wl,-rpath,foo"},
|
||||
{"-Wl,-rpath,$ORIGIN/foo"},
|
||||
{"-Wl,--warn-error"},
|
||||
{"-Wl,--no-warn-error"},
|
||||
{"foo.so"},
|
||||
{"_世界.dll"},
|
||||
{"libcgosotest.dylib"},
|
||||
{"-F", "framework"},
|
||||
{"-l", "."},
|
||||
{"-l", "/etc/passwd"},
|
||||
{"-l", "世界"},
|
||||
{"-L", "framework"},
|
||||
{"-framework", "Chocolate"},
|
||||
}
|
||||
|
||||
var badLinkerFlags = [][]string{
|
||||
{"-DFOO"},
|
||||
{"-Dfoo=bar"},
|
||||
{"-O"},
|
||||
{"-O2"},
|
||||
{"-Osmall"},
|
||||
{"-W"},
|
||||
{"-Wall"},
|
||||
{"-fobjc-arc"},
|
||||
{"-fno-objc-arc"},
|
||||
{"-fomit-frame-pointer"},
|
||||
{"-fno-omit-frame-pointer"},
|
||||
{"-fsplit-stack"},
|
||||
{"-fno-split-stack"},
|
||||
{"-fstack-xxx"},
|
||||
{"-fno-stack-xxx"},
|
||||
{"-mstack-overflow"},
|
||||
{"-mno-stack-overflow"},
|
||||
{"-mmacosx-version"},
|
||||
{"-mnop-fun-dllimport"},
|
||||
{"-std=c99"},
|
||||
{"-xc"},
|
||||
{"-D", "FOO"},
|
||||
{"-D", "foo=bar"},
|
||||
{"-I", "FOO"},
|
||||
{"-L", "@foo"},
|
||||
{"-L", "-foo"},
|
||||
{"-x", "c"},
|
||||
{"-D@X"},
|
||||
{"-D-X"},
|
||||
{"-I@dir"},
|
||||
{"-I-dir"},
|
||||
{"-O@1"},
|
||||
{"-Wa,-foo"},
|
||||
{"-W@foo"},
|
||||
{"-g@gdb"},
|
||||
{"-g-gdb"},
|
||||
{"-march=@dawn"},
|
||||
{"-march=-dawn"},
|
||||
{"-std=@c99"},
|
||||
{"-std=-c99"},
|
||||
{"-x@c"},
|
||||
{"-x-c"},
|
||||
{"-D", "@foo"},
|
||||
{"-D", "-foo"},
|
||||
{"-I", "@foo"},
|
||||
{"-I", "-foo"},
|
||||
{"-l", "@foo"},
|
||||
{"-l", "-foo"},
|
||||
{"-framework", "-Caffeine"},
|
||||
{"-framework", "@Home"},
|
||||
{"-x", "--c"},
|
||||
{"-x", "@obj"},
|
||||
{"-Wl,-rpath,@foo"},
|
||||
}
|
||||
|
||||
func TestCheckLinkerFlags(t *testing.T) {
|
||||
for _, f := range goodLinkerFlags {
|
||||
if err := checkLinkerFlags("test", "test", f); err != nil {
|
||||
t.Errorf("unexpected error for %q: %v", f, err)
|
||||
}
|
||||
}
|
||||
for _, f := range badLinkerFlags {
|
||||
if err := checkLinkerFlags("test", "test", f); err == nil {
|
||||
t.Errorf("missing error for %q", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckFlagAllowDisallow(t *testing.T) {
|
||||
if err := checkCompilerFlags("TEST", "test", []string{"-disallow"}); err == nil {
|
||||
t.Fatalf("missing error for -disallow")
|
||||
}
|
||||
os.Setenv("CGO_TEST_ALLOW", "-disallo")
|
||||
if err := checkCompilerFlags("TEST", "test", []string{"-disallow"}); err == nil {
|
||||
t.Fatalf("missing error for -disallow with CGO_TEST_ALLOW=-disallo")
|
||||
}
|
||||
os.Setenv("CGO_TEST_ALLOW", "-disallow")
|
||||
if err := checkCompilerFlags("TEST", "test", []string{"-disallow"}); err != nil {
|
||||
t.Fatalf("unexpected error for -disallow with CGO_TEST_ALLOW=-disallow: %v", err)
|
||||
}
|
||||
os.Unsetenv("CGO_TEST_ALLOW")
|
||||
|
||||
if err := checkCompilerFlags("TEST", "test", []string{"-Wall"}); err != nil {
|
||||
t.Fatalf("unexpected error for -Wall: %v", err)
|
||||
}
|
||||
os.Setenv("CGO_TEST_DISALLOW", "-Wall")
|
||||
if err := checkCompilerFlags("TEST", "test", []string{"-Wall"}); err == nil {
|
||||
t.Fatalf("missing error for -Wall with CGO_TEST_DISALLOW=-Wall")
|
||||
}
|
||||
os.Setenv("CGO_TEST_ALLOW", "-Wall") // disallow wins
|
||||
if err := checkCompilerFlags("TEST", "test", []string{"-Wall"}); err == nil {
|
||||
t.Fatalf("missing error for -Wall with CGO_TEST_DISALLOW=-Wall and CGO_TEST_ALLOW=-Wall")
|
||||
}
|
||||
|
||||
os.Setenv("CGO_TEST_ALLOW", "-fplugin.*")
|
||||
os.Setenv("CGO_TEST_DISALLOW", "-fplugin=lint.so")
|
||||
if err := checkCompilerFlags("TEST", "test", []string{"-fplugin=faster.so"}); err != nil {
|
||||
t.Fatalf("unexpected error for -fplugin=faster.so: %v", err)
|
||||
}
|
||||
if err := checkCompilerFlags("TEST", "test", []string{"-fplugin=lint.so"}); err == nil {
|
||||
t.Fatalf("missing error for -fplugin=lint.so: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -1769,14 +1769,20 @@ func (tx *Tx) closePrepared() {
|
||||
|
||||
// Commit commits the transaction.
|
||||
func (tx *Tx) Commit() error {
|
||||
if !atomic.CompareAndSwapInt32(&tx.done, 0, 1) {
|
||||
return ErrTxDone
|
||||
}
|
||||
// Check context first to avoid transaction leak.
|
||||
// If put it behind tx.done CompareAndSwap statement, we cant't ensure
|
||||
// the consistency between tx.done and the real COMMIT operation.
|
||||
select {
|
||||
default:
|
||||
case <-tx.ctx.Done():
|
||||
if atomic.LoadInt32(&tx.done) == 1 {
|
||||
return ErrTxDone
|
||||
}
|
||||
return tx.ctx.Err()
|
||||
}
|
||||
if !atomic.CompareAndSwapInt32(&tx.done, 0, 1) {
|
||||
return ErrTxDone
|
||||
}
|
||||
var err error
|
||||
withLock(tx.dc, func() {
|
||||
err = tx.txi.Commit()
|
||||
|
||||
@@ -1536,6 +1536,26 @@ func TestSqrt(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// We can't test this together with the other Exp tests above because
|
||||
// it requires a different receiver setup.
|
||||
func TestIssue22830(t *testing.T) {
|
||||
one := new(Int).SetInt64(1)
|
||||
base, _ := new(Int).SetString("84555555300000000000", 10)
|
||||
mod, _ := new(Int).SetString("66666670001111111111", 10)
|
||||
want, _ := new(Int).SetString("17888885298888888889", 10)
|
||||
|
||||
var tests = []int64{
|
||||
0, 1, -1,
|
||||
}
|
||||
|
||||
for _, n := range tests {
|
||||
m := NewInt(n)
|
||||
if got := m.Exp(base, one, mod); got.Cmp(want) != 0 {
|
||||
t.Errorf("(%v).Exp(%s, 1, %s) = %s, want %s", n, base, mod, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSqrt(b *testing.B) {
|
||||
n, _ := new(Int).SetString("1"+strings.Repeat("0", 1001), 10)
|
||||
b.ResetTimer()
|
||||
|
||||
@@ -566,8 +566,8 @@ func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
|
||||
// determine if z can be reused
|
||||
// TODO(gri) should find a better solution - this if statement
|
||||
// is very costly (see e.g. time pidigits -s -n 10000)
|
||||
if alias(z, uIn) || alias(z, v) {
|
||||
z = nil // z is an alias for uIn or v - cannot reuse
|
||||
if alias(z, u) || alias(z, uIn) || alias(z, v) {
|
||||
z = nil // z is an alias for u or uIn or v - cannot reuse
|
||||
}
|
||||
q = z.make(m + 1)
|
||||
|
||||
|
||||
@@ -8222,6 +8222,14 @@ func (rl *http2clientConnReadLoop) processData(f *http2DataFrame) error {
|
||||
return nil
|
||||
}
|
||||
if f.Length > 0 {
|
||||
if cs.req.Method == "HEAD" && len(data) > 0 {
|
||||
cc.logf("protocol error: received DATA on a HEAD request")
|
||||
rl.endStreamError(cs, http2StreamError{
|
||||
StreamID: f.StreamID,
|
||||
Code: http2ErrCodeProtocol,
|
||||
})
|
||||
return nil
|
||||
}
|
||||
// Check connection-level flow control.
|
||||
cc.mu.Lock()
|
||||
if cs.inflow.available() >= int32(f.Length) {
|
||||
|
||||
@@ -545,6 +545,9 @@ func parseAuthority(authority string) (user *Userinfo, host string, err error) {
|
||||
return nil, host, nil
|
||||
}
|
||||
userinfo := authority[:i]
|
||||
if !validUserinfo(userinfo) {
|
||||
return nil, "", errors.New("net/url: invalid userinfo")
|
||||
}
|
||||
if !strings.Contains(userinfo, ":") {
|
||||
if userinfo, err = unescape(userinfo, encodeUserPassword); err != nil {
|
||||
return nil, "", err
|
||||
@@ -1051,3 +1054,33 @@ func (u *URL) UnmarshalBinary(text []byte) error {
|
||||
*u = *u1
|
||||
return nil
|
||||
}
|
||||
|
||||
// validUserinfo reports whether s is a valid userinfo string per RFC 3986
|
||||
// Section 3.2.1:
|
||||
// userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
|
||||
// unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
// sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||
// / "*" / "+" / "," / ";" / "="
|
||||
//
|
||||
// It doesn't validate pct-encoded. The caller does that via func unescape.
|
||||
func validUserinfo(s string) bool {
|
||||
for _, r := range s {
|
||||
if 'A' <= r && r <= 'Z' {
|
||||
continue
|
||||
}
|
||||
if 'a' <= r && r <= 'z' {
|
||||
continue
|
||||
}
|
||||
if '0' <= r && r <= '9' {
|
||||
continue
|
||||
}
|
||||
switch r {
|
||||
case '-', '.', '_', ':', '~', '!', '$', '&', '\'',
|
||||
'(', ')', '*', '+', ',', ';', '=', '%', '@':
|
||||
continue
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1683,3 +1683,10 @@ func TestGob(t *testing.T) {
|
||||
t.Errorf("json decoded to: %s\nwant: %s\n", u1, u)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInvalidUserPassword(t *testing.T) {
|
||||
_, err := Parse("http://us\ner:pass\nword@foo.com/")
|
||||
if got, wantsub := fmt.Sprint(err), "net/url: invalid userinfo"; !strings.Contains(got, wantsub) {
|
||||
t.Errorf("error = %q; want substring %q", got, wantsub)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,3 +411,16 @@ func TestCgoNumGoroutine(t *testing.T) {
|
||||
t.Errorf("expected %q got %v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSigStackSwapping(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "plan9", "windows":
|
||||
t.Skip("no sigaltstack on %s", runtime.GOOS)
|
||||
}
|
||||
t.Parallel()
|
||||
got := runTestProg(t, "testprogcgo", "SigStack")
|
||||
want := "OK\n"
|
||||
if got != want {
|
||||
t.Errorf("expected %q got %v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,6 +507,94 @@ done:
|
||||
return val
|
||||
}
|
||||
|
||||
func mapassign_fast32ptr(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
|
||||
if h == nil {
|
||||
panic(plainError("assignment to entry in nil map"))
|
||||
}
|
||||
if raceenabled {
|
||||
callerpc := getcallerpc(unsafe.Pointer(&t))
|
||||
racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapassign_fast32))
|
||||
}
|
||||
if h.flags&hashWriting != 0 {
|
||||
throw("concurrent map writes")
|
||||
}
|
||||
hash := t.key.alg.hash(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
|
||||
|
||||
// Set hashWriting after calling alg.hash for consistency with mapassign.
|
||||
h.flags |= hashWriting
|
||||
|
||||
if h.buckets == nil {
|
||||
h.buckets = newarray(t.bucket, 1)
|
||||
}
|
||||
|
||||
again:
|
||||
bucket := hash & (uintptr(1)<<h.B - 1)
|
||||
if h.growing() {
|
||||
growWork(t, h, bucket)
|
||||
}
|
||||
b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
|
||||
top := uint8(hash >> (sys.PtrSize*8 - 8))
|
||||
if top < minTopHash {
|
||||
top += minTopHash
|
||||
}
|
||||
|
||||
var inserti *uint8
|
||||
var insertk unsafe.Pointer
|
||||
var val unsafe.Pointer
|
||||
for {
|
||||
for i := uintptr(0); i < bucketCnt; i++ {
|
||||
if b.tophash[i] != top {
|
||||
if b.tophash[i] == empty && inserti == nil {
|
||||
inserti = &b.tophash[i]
|
||||
insertk = add(unsafe.Pointer(b), dataOffset+i*4)
|
||||
val = add(unsafe.Pointer(b), dataOffset+bucketCnt*4+i*uintptr(t.valuesize))
|
||||
}
|
||||
continue
|
||||
}
|
||||
k := *((*unsafe.Pointer)(add(unsafe.Pointer(b), dataOffset+i*4)))
|
||||
if k != key {
|
||||
continue
|
||||
}
|
||||
val = add(unsafe.Pointer(b), dataOffset+bucketCnt*4+i*uintptr(t.valuesize))
|
||||
goto done
|
||||
}
|
||||
ovf := b.overflow(t)
|
||||
if ovf == nil {
|
||||
break
|
||||
}
|
||||
b = ovf
|
||||
}
|
||||
|
||||
// Did not find mapping for key. Allocate new cell & add entry.
|
||||
|
||||
// If we hit the max load factor or we have too many overflow buckets,
|
||||
// and we're not already in the middle of growing, start growing.
|
||||
if !h.growing() && (overLoadFactor(int64(h.count), h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
|
||||
hashGrow(t, h)
|
||||
goto again // Growing the table invalidates everything, so try again
|
||||
}
|
||||
|
||||
if inserti == nil {
|
||||
// all current buckets are full, allocate a new one.
|
||||
newb := h.newoverflow(t, b)
|
||||
inserti = &newb.tophash[0]
|
||||
insertk = add(unsafe.Pointer(newb), dataOffset)
|
||||
val = add(insertk, bucketCnt*4)
|
||||
}
|
||||
|
||||
// store new key/value at insert position
|
||||
typedmemmove(t.key, insertk, unsafe.Pointer(&key))
|
||||
*inserti = top
|
||||
h.count++
|
||||
|
||||
done:
|
||||
if h.flags&hashWriting == 0 {
|
||||
throw("concurrent map writes")
|
||||
}
|
||||
h.flags &^= hashWriting
|
||||
return val
|
||||
}
|
||||
|
||||
func mapassign_fast64(t *maptype, h *hmap, key uint64) unsafe.Pointer {
|
||||
if h == nil {
|
||||
panic(plainError("assignment to entry in nil map"))
|
||||
@@ -595,6 +683,94 @@ done:
|
||||
return val
|
||||
}
|
||||
|
||||
func mapassign_fast64ptr(t *maptype, h *hmap, key unsafe.Pointer) unsafe.Pointer {
|
||||
if h == nil {
|
||||
panic(plainError("assignment to entry in nil map"))
|
||||
}
|
||||
if raceenabled {
|
||||
callerpc := getcallerpc(unsafe.Pointer(&t))
|
||||
racewritepc(unsafe.Pointer(h), callerpc, funcPC(mapassign_fast64))
|
||||
}
|
||||
if h.flags&hashWriting != 0 {
|
||||
throw("concurrent map writes")
|
||||
}
|
||||
hash := t.key.alg.hash(noescape(unsafe.Pointer(&key)), uintptr(h.hash0))
|
||||
|
||||
// Set hashWriting after calling alg.hash for consistency with mapassign.
|
||||
h.flags |= hashWriting
|
||||
|
||||
if h.buckets == nil {
|
||||
h.buckets = newarray(t.bucket, 1)
|
||||
}
|
||||
|
||||
again:
|
||||
bucket := hash & (uintptr(1)<<h.B - 1)
|
||||
if h.growing() {
|
||||
growWork(t, h, bucket)
|
||||
}
|
||||
b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) + bucket*uintptr(t.bucketsize)))
|
||||
top := uint8(hash >> (sys.PtrSize*8 - 8))
|
||||
if top < minTopHash {
|
||||
top += minTopHash
|
||||
}
|
||||
|
||||
var inserti *uint8
|
||||
var insertk unsafe.Pointer
|
||||
var val unsafe.Pointer
|
||||
for {
|
||||
for i := uintptr(0); i < bucketCnt; i++ {
|
||||
if b.tophash[i] != top {
|
||||
if b.tophash[i] == empty && inserti == nil {
|
||||
inserti = &b.tophash[i]
|
||||
insertk = add(unsafe.Pointer(b), dataOffset+i*8)
|
||||
val = add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.valuesize))
|
||||
}
|
||||
continue
|
||||
}
|
||||
k := *((*unsafe.Pointer)(add(unsafe.Pointer(b), dataOffset+i*8)))
|
||||
if k != key {
|
||||
continue
|
||||
}
|
||||
val = add(unsafe.Pointer(b), dataOffset+bucketCnt*8+i*uintptr(t.valuesize))
|
||||
goto done
|
||||
}
|
||||
ovf := b.overflow(t)
|
||||
if ovf == nil {
|
||||
break
|
||||
}
|
||||
b = ovf
|
||||
}
|
||||
|
||||
// Did not find mapping for key. Allocate new cell & add entry.
|
||||
|
||||
// If we hit the max load factor or we have too many overflow buckets,
|
||||
// and we're not already in the middle of growing, start growing.
|
||||
if !h.growing() && (overLoadFactor(int64(h.count), h.B) || tooManyOverflowBuckets(h.noverflow, h.B)) {
|
||||
hashGrow(t, h)
|
||||
goto again // Growing the table invalidates everything, so try again
|
||||
}
|
||||
|
||||
if inserti == nil {
|
||||
// all current buckets are full, allocate a new one.
|
||||
newb := h.newoverflow(t, b)
|
||||
inserti = &newb.tophash[0]
|
||||
insertk = add(unsafe.Pointer(newb), dataOffset)
|
||||
val = add(insertk, bucketCnt*8)
|
||||
}
|
||||
|
||||
// store new key/value at insert position
|
||||
typedmemmove(t.key, insertk, unsafe.Pointer(&key))
|
||||
*inserti = top
|
||||
h.count++
|
||||
|
||||
done:
|
||||
if h.flags&hashWriting == 0 {
|
||||
throw("concurrent map writes")
|
||||
}
|
||||
h.flags &^= hashWriting
|
||||
return val
|
||||
}
|
||||
|
||||
func mapassign_faststr(t *maptype, h *hmap, ky string) unsafe.Pointer {
|
||||
if h == nil {
|
||||
panic(plainError("assignment to entry in nil map"))
|
||||
|
||||
@@ -1251,7 +1251,12 @@ func gcStart(mode gcMode, trigger gcTrigger) {
|
||||
|
||||
gcResetMarkState()
|
||||
|
||||
work.stwprocs, work.maxprocs = gcprocs(), gomaxprocs
|
||||
work.stwprocs, work.maxprocs = gomaxprocs, gomaxprocs
|
||||
if work.stwprocs > ncpu {
|
||||
// This is used to compute CPU time of the STW phases,
|
||||
// so it can't be more than ncpu, even if GOMAXPROCS is.
|
||||
work.stwprocs = ncpu
|
||||
}
|
||||
work.heap0 = atomic.Load64(&memstats.heap_live)
|
||||
work.pauseNS = 0
|
||||
work.mode = mode
|
||||
|
||||
@@ -153,3 +153,6 @@ func setThreadCPUProfiler(hz int32) {
|
||||
// TODO: Enable profiling interrupts.
|
||||
getg().m.profilehz = hz
|
||||
}
|
||||
|
||||
// gsignalStack is unused on Plan 9.
|
||||
type gsignalStack struct{}
|
||||
|
||||
@@ -285,6 +285,9 @@ func sigenable(uint32) {}
|
||||
func sigignore(uint32) {}
|
||||
func closeonexec(int32) {}
|
||||
|
||||
// gsignalStack is unused on nacl.
|
||||
type gsignalStack struct{}
|
||||
|
||||
var writelock uint32 // test-and-set spin lock for write
|
||||
|
||||
/*
|
||||
|
||||
@@ -386,10 +386,11 @@ type m struct {
|
||||
divmod uint32 // div/mod denominator for arm - known to liblink
|
||||
|
||||
// Fields not known to debuggers.
|
||||
procid uint64 // for debuggers, but offset not hard-coded
|
||||
gsignal *g // signal-handling g
|
||||
sigmask sigset // storage for saved signal mask
|
||||
tls [6]uintptr // thread-local storage (for x86 extern register)
|
||||
procid uint64 // for debuggers, but offset not hard-coded
|
||||
gsignal *g // signal-handling g
|
||||
goSigStack gsignalStack // Go-allocated signal handling stack
|
||||
sigmask sigset // storage for saved signal mask
|
||||
tls [6]uintptr // thread-local storage (for x86 extern register)
|
||||
mstartfn func()
|
||||
curg *g // current running goroutine
|
||||
caughtsig guintptr // goroutine running during fatal signal
|
||||
|
||||
@@ -702,7 +702,7 @@ func minitSignalStack() {
|
||||
signalstack(&_g_.m.gsignal.stack)
|
||||
_g_.m.newSigstack = true
|
||||
} else {
|
||||
setGsignalStack(&st, nil)
|
||||
setGsignalStack(&st, &_g_.m.goSigStack)
|
||||
_g_.m.newSigstack = false
|
||||
}
|
||||
}
|
||||
@@ -732,6 +732,14 @@ func unminitSignals() {
|
||||
if getg().m.newSigstack {
|
||||
st := stackt{ss_flags: _SS_DISABLE}
|
||||
sigaltstack(&st, nil)
|
||||
} else {
|
||||
// We got the signal stack from someone else. Restore
|
||||
// the Go-allocated stack in case this M gets reused
|
||||
// for another thread (e.g., it's an extram). Also, on
|
||||
// Android, libc allocates a signal stack for all
|
||||
// threads, so it's important to restore the Go stack
|
||||
// even on Go-created threads so we can free it.
|
||||
restoreGsignalStack(&getg().m.goSigStack)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -223,3 +223,6 @@ func crash() {
|
||||
// It's okay to leave this empty for now: if crash returns
|
||||
// the ordinary exit-after-panic happens.
|
||||
}
|
||||
|
||||
// gsignalStack is unused on Windows.
|
||||
type gsignalStack struct{}
|
||||
|
||||
@@ -139,11 +139,31 @@ TEXT runtime·mincore(SB),NOSPLIT,$0-28
|
||||
RET
|
||||
|
||||
// func walltime() (sec int64, nsec int32)
|
||||
TEXT runtime·walltime(SB),NOSPLIT,$16
|
||||
// Be careful. We're calling a function with gcc calling convention here.
|
||||
// We're guaranteed 128 bytes on entry, and we've taken 16, and the
|
||||
// call uses another 8.
|
||||
// That leaves 104 for the gettime code to use. Hope that's enough!
|
||||
TEXT runtime·walltime(SB),NOSPLIT,$0-12
|
||||
// We don't know how much stack space the VDSO code will need,
|
||||
// so switch to g0.
|
||||
// In particular, a kernel configured with CONFIG_OPTIMIZE_INLINING=n
|
||||
// and hardening can use a full page of stack space in gettime_sym
|
||||
// due to stack probes inserted to avoid stack/heap collisions.
|
||||
// See issue #20427.
|
||||
|
||||
MOVQ SP, BP // Save old SP; BP unchanged by C code.
|
||||
|
||||
get_tls(CX)
|
||||
MOVQ g(CX), AX
|
||||
MOVQ g_m(AX), CX
|
||||
MOVQ m_curg(CX), DX
|
||||
|
||||
CMPQ AX, DX // Only switch if on curg.
|
||||
JNE noswitch
|
||||
|
||||
MOVQ m_g0(CX), DX
|
||||
MOVQ (g_sched+gobuf_sp)(DX), SP // Set SP to g0 stack
|
||||
|
||||
noswitch:
|
||||
SUBQ $16, SP // Space for results
|
||||
ANDQ $~15, SP // Align for C code
|
||||
|
||||
MOVQ runtime·__vdso_clock_gettime_sym(SB), AX
|
||||
CMPQ AX, $0
|
||||
JEQ fallback
|
||||
@@ -152,6 +172,7 @@ TEXT runtime·walltime(SB),NOSPLIT,$16
|
||||
CALL AX
|
||||
MOVQ 0(SP), AX // sec
|
||||
MOVQ 8(SP), DX // nsec
|
||||
MOVQ BP, SP // Restore real SP
|
||||
MOVQ AX, sec+0(FP)
|
||||
MOVL DX, nsec+8(FP)
|
||||
RET
|
||||
@@ -163,13 +184,31 @@ fallback:
|
||||
MOVQ 0(SP), AX // sec
|
||||
MOVL 8(SP), DX // usec
|
||||
IMULQ $1000, DX
|
||||
MOVQ BP, SP // Restore real SP
|
||||
MOVQ AX, sec+0(FP)
|
||||
MOVL DX, nsec+8(FP)
|
||||
RET
|
||||
|
||||
TEXT runtime·nanotime(SB),NOSPLIT,$16
|
||||
// Duplicate time.now here to avoid using up precious stack space.
|
||||
// See comment above in time.now.
|
||||
TEXT runtime·nanotime(SB),NOSPLIT,$0-8
|
||||
// Switch to g0 stack. See comment above in runtime·walltime.
|
||||
|
||||
MOVQ SP, BP // Save old SP; BX unchanged by C code.
|
||||
|
||||
get_tls(CX)
|
||||
MOVQ g(CX), AX
|
||||
MOVQ g_m(AX), CX
|
||||
MOVQ m_curg(CX), DX
|
||||
|
||||
CMPQ AX, DX // Only switch if on curg.
|
||||
JNE noswitch
|
||||
|
||||
MOVQ m_g0(CX), DX
|
||||
MOVQ (g_sched+gobuf_sp)(DX), SP // Set SP to g0 stack
|
||||
|
||||
noswitch:
|
||||
SUBQ $16, SP // Space for results
|
||||
ANDQ $~15, SP // Align for C code
|
||||
|
||||
MOVQ runtime·__vdso_clock_gettime_sym(SB), AX
|
||||
CMPQ AX, $0
|
||||
JEQ fallback
|
||||
@@ -178,6 +217,7 @@ TEXT runtime·nanotime(SB),NOSPLIT,$16
|
||||
CALL AX
|
||||
MOVQ 0(SP), AX // sec
|
||||
MOVQ 8(SP), DX // nsec
|
||||
MOVQ BP, SP // Restore real SP
|
||||
// sec is in AX, nsec in DX
|
||||
// return nsec in AX
|
||||
IMULQ $1000000000, AX
|
||||
@@ -191,6 +231,7 @@ fallback:
|
||||
CALL AX
|
||||
MOVQ 0(SP), AX // sec
|
||||
MOVL 8(SP), DX // usec
|
||||
MOVQ BP, SP // Restore real SP
|
||||
IMULQ $1000, DX
|
||||
// sec is in AX, nsec in DX
|
||||
// return nsec in AX
|
||||
|
||||
95
src/runtime/testdata/testprogcgo/sigstack.go
vendored
Normal file
95
src/runtime/testdata/testprogcgo/sigstack.go
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright 2017 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 !plan9,!windows
|
||||
|
||||
// Test handling of Go-allocated signal stacks when calling from
|
||||
// C-created threads with and without signal stacks. (See issue
|
||||
// #22930.)
|
||||
|
||||
package main
|
||||
|
||||
/*
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifndef MAP_STACK
|
||||
#define MAP_STACK 0
|
||||
#endif
|
||||
|
||||
extern void SigStackCallback();
|
||||
|
||||
static void* WithSigStack(void* arg __attribute__((unused))) {
|
||||
// Set up an alternate system stack.
|
||||
void* base = mmap(0, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON|MAP_STACK, -1, 0);
|
||||
if (base == MAP_FAILED) {
|
||||
perror("mmap failed");
|
||||
abort();
|
||||
}
|
||||
stack_t st = {}, ost = {};
|
||||
st.ss_sp = (char*)base;
|
||||
st.ss_flags = 0;
|
||||
st.ss_size = SIGSTKSZ;
|
||||
if (sigaltstack(&st, &ost) < 0) {
|
||||
perror("sigaltstack failed");
|
||||
abort();
|
||||
}
|
||||
|
||||
// Call Go.
|
||||
SigStackCallback();
|
||||
|
||||
// Disable signal stack and protect it so we can detect reuse.
|
||||
if (ost.ss_flags & SS_DISABLE) {
|
||||
// Darwin libsystem has a bug where it checks ss_size
|
||||
// even if SS_DISABLE is set. (The kernel gets it right.)
|
||||
ost.ss_size = SIGSTKSZ;
|
||||
}
|
||||
if (sigaltstack(&ost, NULL) < 0) {
|
||||
perror("sigaltstack restore failed");
|
||||
abort();
|
||||
}
|
||||
mprotect(base, SIGSTKSZ, PROT_NONE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void* WithoutSigStack(void* arg __attribute__((unused))) {
|
||||
SigStackCallback();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void DoThread(int sigstack) {
|
||||
pthread_t tid;
|
||||
if (sigstack) {
|
||||
pthread_create(&tid, NULL, WithSigStack, NULL);
|
||||
} else {
|
||||
pthread_create(&tid, NULL, WithoutSigStack, NULL);
|
||||
}
|
||||
pthread_join(tid, NULL);
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
func init() {
|
||||
register("SigStack", SigStack)
|
||||
}
|
||||
|
||||
func SigStack() {
|
||||
C.DoThread(0)
|
||||
C.DoThread(1)
|
||||
C.DoThread(0)
|
||||
C.DoThread(1)
|
||||
println("OK")
|
||||
}
|
||||
|
||||
var BadPtr *int
|
||||
|
||||
//export SigStackCallback
|
||||
func SigStackCallback() {
|
||||
// Cause the Go signal handler to run.
|
||||
defer func() { recover() }()
|
||||
*BadPtr = 42
|
||||
}
|
||||
@@ -38,3 +38,25 @@ func f6(a []float32, i int64) float32 {
|
||||
// like 0x80000000 and silently using them as
|
||||
// signed 32 bit offsets.)
|
||||
// f4 was ok, but testing it can't hurt.
|
||||
|
||||
func f7(ss []*string, i int) string {
|
||||
const offset = 3 << 29 // 3<<29 * 4 = 3<<31 = 1<<31 mod 1<<32.
|
||||
if i > offset {
|
||||
return *ss[i-offset]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func f8(ss []*string, i int) string {
|
||||
const offset = 3<<29 + 10
|
||||
if i > offset {
|
||||
return *ss[i-offset]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func f9(ss []*string, i int) string {
|
||||
const offset = 3<<29 - 10
|
||||
if i > offset {
|
||||
return *ss[i-offset]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
18
test/fixedbugs/issue22429.go
Normal file
18
test/fixedbugs/issue22429.go
Normal file
@@ -0,0 +1,18 @@
|
||||
// compile
|
||||
|
||||
// Copyright 2017 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.
|
||||
|
||||
// Make sure SSA->assembly pass can handle SP as an index register.
|
||||
|
||||
package p
|
||||
|
||||
type T struct {
|
||||
a,b,c,d float32
|
||||
}
|
||||
|
||||
func f(a *[8]T, i,j,k int) float32 {
|
||||
b := *a
|
||||
return b[i].a + b[j].b + b[k].c
|
||||
}
|
||||
26
test/fixedbugs/issue22458.go
Normal file
26
test/fixedbugs/issue22458.go
Normal file
@@ -0,0 +1,26 @@
|
||||
// compile
|
||||
|
||||
// Copyright 2017 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.
|
||||
|
||||
// Make sure KeepAlive introduces a use of the spilled variable.
|
||||
|
||||
package main
|
||||
|
||||
import "runtime"
|
||||
|
||||
type node struct {
|
||||
next *node
|
||||
}
|
||||
|
||||
var x bool
|
||||
|
||||
func main() {
|
||||
var head *node
|
||||
for x {
|
||||
head = &node{head}
|
||||
}
|
||||
|
||||
runtime.KeepAlive(head)
|
||||
}
|
||||
30
test/fixedbugs/issue22683.go
Normal file
30
test/fixedbugs/issue22683.go
Normal file
@@ -0,0 +1,30 @@
|
||||
// cmpout
|
||||
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type foo struct {
|
||||
bar [1]*int
|
||||
}
|
||||
|
||||
func main() {
|
||||
ch := make(chan foo, 2)
|
||||
var a int
|
||||
var b [1]*int
|
||||
b[0] = &a
|
||||
ch <- foo{bar: b}
|
||||
close(ch)
|
||||
|
||||
for v := range ch {
|
||||
for i := 0; i < 1; i++ {
|
||||
fmt.Println(v.bar[0] != nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
1
test/fixedbugs/issue22683.out
Normal file
1
test/fixedbugs/issue22683.out
Normal file
@@ -0,0 +1 @@
|
||||
true
|
||||
29
test/fixedbugs/issue22781.go
Normal file
29
test/fixedbugs/issue22781.go
Normal file
@@ -0,0 +1,29 @@
|
||||
// run
|
||||
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "runtime/debug"
|
||||
|
||||
type T struct {
|
||||
// >= 16 bytes to avoid tiny alloc.
|
||||
a, b int
|
||||
}
|
||||
|
||||
func main() {
|
||||
debug.SetGCPercent(1)
|
||||
for i := 0; i < 100000; i++ {
|
||||
m := make(map[*T]struct{}, 0)
|
||||
for j := 0; j < 20; j++ {
|
||||
// During the call to mapassign_fast64, the key argument
|
||||
// was incorrectly treated as a uint64. If the stack was
|
||||
// scanned during that call, the only pointer to k was
|
||||
// missed, leading to *k being collected prematurely.
|
||||
k := new(T)
|
||||
m[k] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user