mirror of
https://github.com/golang/go.git
synced 2026-01-29 23:22:06 +03:00
Compare commits
28 Commits
dev.corety
...
go1.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd6b6202dd | ||
|
|
606eb9b0c1 | ||
|
|
bcda91c18d | ||
|
|
7d7a0a9d64 | ||
|
|
cedc511a6e | ||
|
|
ae13ccfd6d | ||
|
|
7cec9a583d | ||
|
|
d84dee069a | ||
|
|
f1e44a4b74 | ||
|
|
3ade54063e | ||
|
|
0545006bdb | ||
|
|
1363eeba65 | ||
|
|
1edfd64761 | ||
|
|
6eb0f5440e | ||
|
|
c543cc353d | ||
|
|
f0749fe163 | ||
|
|
ba878ac0c8 | ||
|
|
6177f6d448 | ||
|
|
67cd1fa780 | ||
|
|
758a7281ab | ||
|
|
470704531d | ||
|
|
648bb34484 | ||
|
|
d8d2f036a5 | ||
|
|
2a5f65a98c | ||
|
|
2f6c20b46c | ||
|
|
59f181b6fd | ||
|
|
d18087cb25 | ||
|
|
3de6e96e4b |
@@ -148,29 +148,26 @@ These actions are explicitly forbidden in Go spaces:
|
||||
|
||||
<p>
|
||||
The Go spaces are not free speech venues; they are for discussion about Go.
|
||||
These spaces have moderators.
|
||||
The goal of the moderators is to facilitate civil discussion about Go.
|
||||
Each of these spaces have their own moderators.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When using the official Go spaces you should act in the spirit of the “Gopher
|
||||
values”.
|
||||
If you conduct yourself in a way that is explicitly forbidden by the CoC,
|
||||
you will be warned and asked to stop.
|
||||
If you do not stop, you will be removed from our community spaces temporarily.
|
||||
Repeated, willful breaches of the CoC will result in a permanent ban.
|
||||
If a reported conflict cannot be resolved amicably, the CoC Working Group
|
||||
may make a recommendation to the relevant forum moderators.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Moderators are held to a higher standard than other community members.
|
||||
If a moderator creates an inappropriate situation, they should expect less
|
||||
leeway than others, and should expect to be removed from their position if they
|
||||
cannot adhere to the CoC.
|
||||
CoC Working Group members and forum moderators are held to a higher standard than other community members.
|
||||
If a working group member or moderator creates an inappropriate situation, they
|
||||
should expect less leeway than others, and should expect to be removed from
|
||||
their position if they cannot adhere to the CoC.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Complaints about moderator actions must be handled using the reporting process
|
||||
below.
|
||||
Complaints about working group member or moderator actions must be handled
|
||||
using the reporting process below.
|
||||
</p>
|
||||
|
||||
<h2 id="reporting">Reporting issues</h2>
|
||||
@@ -185,8 +182,6 @@ satisfaction of all parties. They are:
|
||||
<ul>
|
||||
<li>Aditya Mukerjee <dev@chimeracoder.net>
|
||||
<li>Andrew Gerrand <adg@golang.org>
|
||||
<li>Dave Cheney <dave@cheney.net>
|
||||
<li>Jason Buberel <jbuberel@google.com>
|
||||
<li>Peggy Li <peggyli.224@gmail.com>
|
||||
<li>Sarah Adams <sadams.codes@gmail.com>
|
||||
<li>Steve Francia <steve.francia@gmail.com>
|
||||
@@ -201,13 +196,10 @@ particular individual or group.
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li>Mail <a href="mailto:conduct@golang.org">conduct@golang.org</a> or
|
||||
<a href="https://golang.org/s/conduct-report">submit an anonymous report</a>.
|
||||
<li>Mail <a href="mailto:conduct@golang.org">conduct@golang.org</a>.
|
||||
<ul>
|
||||
<li>Your message will reach the Working Group.
|
||||
<li>Reports are confidential within the Working Group.
|
||||
<li>Should you choose to remain anonymous then the Working Group cannot
|
||||
notify you of the outcome of your report.
|
||||
<li>You may contact a member of the group directly if you do not feel
|
||||
comfortable contacting the group as a whole. That member will then raise
|
||||
the issue with the Working Group as a whole, preserving the privacy of the
|
||||
@@ -229,11 +221,8 @@ particular individual or group.
|
||||
<li>The Working Group will reach a decision as to how to act. These may include:
|
||||
<ul>
|
||||
<li>Nothing.
|
||||
<li>A request for a private or public apology.
|
||||
<li>A private or public warning.
|
||||
<li>An imposed vacation (for instance, asking someone to abstain for a week
|
||||
from a mailing list or IRC).
|
||||
<li>A permanent or temporary ban from some or all Go spaces.
|
||||
<li>Passing the report along to the offender.
|
||||
<li>A recommendation of action to the relevant forum moderators.
|
||||
</ul>
|
||||
<li>The Working Group will reach out to the original reporter to let them know
|
||||
the decision.
|
||||
@@ -246,7 +235,6 @@ particular individual or group.
|
||||
conflicts in the most harmonious way possible.</b>
|
||||
We hope that in most cases issues may be resolved through polite discussion and
|
||||
mutual agreement.
|
||||
Bannings and other forceful measures are to be employed only as a last resort.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -30,6 +30,13 @@ to fix critical security problems in both Go 1.4 and Go 1.5 as they arise.
|
||||
See the <a href="/security">security policy</a> for more details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.8">go1.8 (released 2017/02/16)</h2>
|
||||
|
||||
<p>
|
||||
Go 1.8 is a major release of Go.
|
||||
Read the <a href="/doc/go1.8">Go 1.8 Release Notes</a> for more information.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.7">go1.7 (released 2016/08/15)</h2>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -15,12 +15,7 @@ Do not send CLs removing the interior tags from such phrases.
|
||||
ul li { margin: 0.5em 0; }
|
||||
</style>
|
||||
|
||||
<h2 id="introduction">DRAFT RELEASE NOTES - Introduction to Go 1.8</h2>
|
||||
|
||||
<p><strong>
|
||||
Go 1.8 is not yet released. These are work-in-progress
|
||||
release notes. Go 1.8 is expected to be released in February 2017.
|
||||
</strong></p>
|
||||
<h2 id="introduction">Introduction to Go 1.8</h2>
|
||||
|
||||
<p>
|
||||
The latest Go release, version 1.8, arrives six months after <a href="go1.7">Go 1.7</a>.
|
||||
@@ -799,9 +794,9 @@ Optimizations and minor bug fixes are not listed.
|
||||
hardware support for AES-GCM is present.
|
||||
</p>
|
||||
|
||||
<p> <!-- CL 27315 -->
|
||||
<p> <!-- CL 27315, CL 35290 -->
|
||||
AES-128-CBC cipher suites with SHA-256 are also
|
||||
now supported.
|
||||
now supported, but disabled by default.
|
||||
</p>
|
||||
|
||||
</dd>
|
||||
|
||||
@@ -221,7 +221,7 @@ To build without <code>cgo</code>, set the environment variable
|
||||
Change to the directory that will be its parent
|
||||
and make sure the <code>go</code> directory does not exist.
|
||||
Then clone the repository and check out the latest release tag
|
||||
(<code class="versionTag">go1.7.4</code>, for example):</p>
|
||||
(<code class="versionTag">go1.8</code>, for example):</p>
|
||||
|
||||
<pre>
|
||||
$ git clone https://go.googlesource.com/go
|
||||
@@ -409,7 +409,7 @@ New releases are announced on the
|
||||
<a href="//groups.google.com/group/golang-announce">golang-announce</a>
|
||||
mailing list.
|
||||
Each announcement mentions the latest release tag, for instance,
|
||||
<code class="versionTag">go1.7.4</code>.
|
||||
<code class="versionTag">go1.8</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -585,7 +585,7 @@ func isliteral(n *Node) bool {
|
||||
}
|
||||
|
||||
func (n *Node) isSimpleName() bool {
|
||||
return n.Op == ONAME && n.Addable && n.Class != PAUTOHEAP
|
||||
return n.Op == ONAME && n.Addable && n.Class != PAUTOHEAP && n.Class != PEXTERN
|
||||
}
|
||||
|
||||
func litas(l *Node, r *Node, init *Nodes) {
|
||||
|
||||
@@ -424,7 +424,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
p.To.Type = obj.TYPE_MEM
|
||||
p.To.Reg = v.Args[0].Reg()
|
||||
gc.AddAux2(&p.To, v, sc.Off())
|
||||
case ssa.OpCopy, ssa.OpS390XMOVDconvert:
|
||||
case ssa.OpCopy, ssa.OpS390XMOVDconvert, ssa.OpS390XMOVDreg:
|
||||
if v.Type.IsMemory() {
|
||||
return
|
||||
}
|
||||
@@ -433,6 +433,11 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
if x != y {
|
||||
opregreg(moveByType(v.Type), y, x)
|
||||
}
|
||||
case ssa.OpS390XMOVDnop:
|
||||
if v.Reg() != v.Args[0].Reg() {
|
||||
v.Fatalf("input[0] and output not in same register %s", v.LongString())
|
||||
}
|
||||
// nothing to do
|
||||
case ssa.OpLoadReg:
|
||||
if v.Type.IsFlags() {
|
||||
v.Fatalf("load flags not implemented: %v", v.LongString())
|
||||
|
||||
@@ -529,109 +529,147 @@
|
||||
// can be encoded in the instructions
|
||||
// since this rewriting takes place before stack allocation, the offset to SP is unknown,
|
||||
// so don't do it for args and locals with unaligned offset
|
||||
(MOVBload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBload [off1+off2] {sym} ptr mem)
|
||||
(MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBUload [off1+off2] {sym} ptr mem)
|
||||
(MOVBload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2) ->
|
||||
(MOVBload [off1+off2] {sym} ptr mem)
|
||||
(MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2) ->
|
||||
(MOVBUload [off1+off2] {sym} ptr mem)
|
||||
(MOVHload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
&& (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(MOVHload [off1+off2] {sym} ptr mem)
|
||||
(MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
&& (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(MOVHUload [off1+off2] {sym} ptr mem)
|
||||
(MOVWload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(MOVWload [off1+off2] {sym} ptr mem)
|
||||
(MOVWUload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(MOVWUload [off1+off2] {sym} ptr mem)
|
||||
(MOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
&& (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(MOVDload [off1+off2] {sym} ptr mem)
|
||||
(FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(FMOVSload [off1+off2] {sym} ptr mem)
|
||||
(FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
&& (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(FMOVDload [off1+off2] {sym} ptr mem)
|
||||
|
||||
(MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVBstore [off1+off2] {sym} ptr val mem)
|
||||
(MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(off1+off2) ->
|
||||
(MOVBstore [off1+off2] {sym} ptr val mem)
|
||||
(MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem)
|
||||
&& (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(MOVHstore [off1+off2] {sym} ptr val mem)
|
||||
(MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem)
|
||||
&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(MOVWstore [off1+off2] {sym} ptr val mem)
|
||||
(MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
|
||||
&& (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(MOVDstore [off1+off2] {sym} ptr val mem)
|
||||
(FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem)
|
||||
&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(FMOVSstore [off1+off2] {sym} ptr val mem)
|
||||
(FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
|
||||
&& (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(FMOVDstore [off1+off2] {sym} ptr val mem)
|
||||
(MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBstorezero [off1+off2] {sym} ptr mem)
|
||||
(MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2) ->
|
||||
(MOVBstorezero [off1+off2] {sym} ptr mem)
|
||||
(MOVHstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
&& (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(MOVHstorezero [off1+off2] {sym} ptr mem)
|
||||
(MOVWstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(MOVWstorezero [off1+off2] {sym} ptr mem)
|
||||
(MOVDstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
&& (off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)) ->
|
||||
(MOVDstorezero [off1+off2] {sym} ptr mem)
|
||||
|
||||
(MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
|
||||
(MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2) ->
|
||||
(MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
|
||||
(MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2) ->
|
||||
(MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(MOVHload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(MOVHUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(MOVWload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(MOVWUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(MOVWUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(MOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
|
||||
(MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
|
||||
(MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2) ->
|
||||
(MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
(MOVHstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
(MOVWstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
(MOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
(FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
(FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
(MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
|
||||
(MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2) ->
|
||||
(MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(MOVHstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(MOVWstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
(MOVDstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
|
||||
&& is32Bit(off1+off2)
|
||||
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
|
||||
(MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
|
||||
|
||||
@@ -312,9 +312,12 @@
|
||||
|
||||
// Lowering loads
|
||||
(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem)
|
||||
(Load <t> ptr mem) && is32BitInt(t) -> (MOVWZload ptr mem)
|
||||
(Load <t> ptr mem) && is16BitInt(t) -> (MOVHZload ptr mem)
|
||||
(Load <t> ptr mem) && (t.IsBoolean() || is8BitInt(t)) -> (MOVBZload ptr mem)
|
||||
(Load <t> ptr mem) && is32BitInt(t) && isSigned(t) -> (MOVWload ptr mem)
|
||||
(Load <t> ptr mem) && is32BitInt(t) && !isSigned(t) -> (MOVWZload ptr mem)
|
||||
(Load <t> ptr mem) && is16BitInt(t) && isSigned(t) -> (MOVHload ptr mem)
|
||||
(Load <t> ptr mem) && is16BitInt(t) && !isSigned(t) -> (MOVHZload ptr mem)
|
||||
(Load <t> ptr mem) && is8BitInt(t) && isSigned(t) -> (MOVBload ptr mem)
|
||||
(Load <t> ptr mem) && (t.IsBoolean() || (is8BitInt(t) && !isSigned(t))) -> (MOVBZload ptr mem)
|
||||
(Load <t> ptr mem) && is32BitFloat(t) -> (FMOVSload ptr mem)
|
||||
(Load <t> ptr mem) && is64BitFloat(t) -> (FMOVDload ptr mem)
|
||||
|
||||
@@ -445,16 +448,20 @@
|
||||
// ***************************
|
||||
// TODO: Should the optimizations be a separate pass?
|
||||
|
||||
// if a register move has only 1 use, just use the same register without emitting instruction
|
||||
// MOVDnop doesn't emit instruction, only for ensuring the type.
|
||||
(MOVDreg x) && x.Uses == 1 -> (MOVDnop x)
|
||||
|
||||
// Fold sign extensions into conditional moves of constants.
|
||||
// Designed to remove the MOVBZreg inserted by the If lowering.
|
||||
(MOVBZreg x:(MOVDLT (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
|
||||
(MOVBZreg x:(MOVDLE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
|
||||
(MOVBZreg x:(MOVDGT (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
|
||||
(MOVBZreg x:(MOVDGE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
|
||||
(MOVBZreg x:(MOVDEQ (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
|
||||
(MOVBZreg x:(MOVDNE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
|
||||
(MOVBZreg x:(MOVDGTnoinv (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
|
||||
(MOVBZreg x:(MOVDGEnoinv (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
|
||||
(MOVBZreg x:(MOVDLT (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
|
||||
(MOVBZreg x:(MOVDLE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
|
||||
(MOVBZreg x:(MOVDGT (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
|
||||
(MOVBZreg x:(MOVDGE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
|
||||
(MOVBZreg x:(MOVDEQ (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
|
||||
(MOVBZreg x:(MOVDNE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
|
||||
(MOVBZreg x:(MOVDGTnoinv (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
|
||||
(MOVBZreg x:(MOVDGEnoinv (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
|
||||
|
||||
// Fold boolean tests into blocks.
|
||||
(NE (CMPWconst [0] (MOVDLT (MOVDconst [0]) (MOVDconst [1]) cmp)) yes no) -> (LT cmp yes no)
|
||||
@@ -572,46 +579,46 @@
|
||||
(MOVDNE x y (InvertFlags cmp)) -> (MOVDNE x y cmp)
|
||||
|
||||
// don't extend after proper load
|
||||
(MOVBreg x:(MOVBload _ _)) -> x
|
||||
(MOVBZreg x:(MOVBZload _ _)) -> x
|
||||
(MOVHreg x:(MOVBload _ _)) -> x
|
||||
(MOVHreg x:(MOVBZload _ _)) -> x
|
||||
(MOVHreg x:(MOVHload _ _)) -> x
|
||||
(MOVHZreg x:(MOVBZload _ _)) -> x
|
||||
(MOVHZreg x:(MOVHZload _ _)) -> x
|
||||
(MOVWreg x:(MOVBload _ _)) -> x
|
||||
(MOVWreg x:(MOVBZload _ _)) -> x
|
||||
(MOVWreg x:(MOVHload _ _)) -> x
|
||||
(MOVWreg x:(MOVHZload _ _)) -> x
|
||||
(MOVWreg x:(MOVWload _ _)) -> x
|
||||
(MOVWZreg x:(MOVBZload _ _)) -> x
|
||||
(MOVWZreg x:(MOVHZload _ _)) -> x
|
||||
(MOVWZreg x:(MOVWZload _ _)) -> x
|
||||
(MOVBreg x:(MOVBload _ _)) -> (MOVDreg x)
|
||||
(MOVBZreg x:(MOVBZload _ _)) -> (MOVDreg x)
|
||||
(MOVHreg x:(MOVBload _ _)) -> (MOVDreg x)
|
||||
(MOVHreg x:(MOVBZload _ _)) -> (MOVDreg x)
|
||||
(MOVHreg x:(MOVHload _ _)) -> (MOVDreg x)
|
||||
(MOVHZreg x:(MOVBZload _ _)) -> (MOVDreg x)
|
||||
(MOVHZreg x:(MOVHZload _ _)) -> (MOVDreg x)
|
||||
(MOVWreg x:(MOVBload _ _)) -> (MOVDreg x)
|
||||
(MOVWreg x:(MOVBZload _ _)) -> (MOVDreg x)
|
||||
(MOVWreg x:(MOVHload _ _)) -> (MOVDreg x)
|
||||
(MOVWreg x:(MOVHZload _ _)) -> (MOVDreg x)
|
||||
(MOVWreg x:(MOVWload _ _)) -> (MOVDreg x)
|
||||
(MOVWZreg x:(MOVBZload _ _)) -> (MOVDreg x)
|
||||
(MOVWZreg x:(MOVHZload _ _)) -> (MOVDreg x)
|
||||
(MOVWZreg x:(MOVWZload _ _)) -> (MOVDreg x)
|
||||
|
||||
// don't extend if argument is already extended
|
||||
(MOVBreg x:(Arg <t>)) && is8BitInt(t) && isSigned(t) -> x
|
||||
(MOVBZreg x:(Arg <t>)) && is8BitInt(t) && !isSigned(t) -> x
|
||||
(MOVHreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && isSigned(t) -> x
|
||||
(MOVHZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && !isSigned(t) -> x
|
||||
(MOVWreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t) -> x
|
||||
(MOVWZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t) -> x
|
||||
(MOVBreg x:(Arg <t>)) && is8BitInt(t) && isSigned(t) -> (MOVDreg x)
|
||||
(MOVBZreg x:(Arg <t>)) && is8BitInt(t) && !isSigned(t) -> (MOVDreg x)
|
||||
(MOVHreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && isSigned(t) -> (MOVDreg x)
|
||||
(MOVHZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && !isSigned(t) -> (MOVDreg x)
|
||||
(MOVWreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t) -> (MOVDreg x)
|
||||
(MOVWZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t) -> (MOVDreg x)
|
||||
|
||||
// fold double extensions
|
||||
(MOVBreg x:(MOVBreg _)) -> x
|
||||
(MOVBZreg x:(MOVBZreg _)) -> x
|
||||
(MOVHreg x:(MOVBreg _)) -> x
|
||||
(MOVHreg x:(MOVBZreg _)) -> x
|
||||
(MOVHreg x:(MOVHreg _)) -> x
|
||||
(MOVHZreg x:(MOVBZreg _)) -> x
|
||||
(MOVHZreg x:(MOVHZreg _)) -> x
|
||||
(MOVWreg x:(MOVBreg _)) -> x
|
||||
(MOVWreg x:(MOVBZreg _)) -> x
|
||||
(MOVWreg x:(MOVHreg _)) -> x
|
||||
(MOVWreg x:(MOVHreg _)) -> x
|
||||
(MOVWreg x:(MOVWreg _)) -> x
|
||||
(MOVWZreg x:(MOVBZreg _)) -> x
|
||||
(MOVWZreg x:(MOVHZreg _)) -> x
|
||||
(MOVWZreg x:(MOVWZreg _)) -> x
|
||||
(MOVBreg x:(MOVBreg _)) -> (MOVDreg x)
|
||||
(MOVBZreg x:(MOVBZreg _)) -> (MOVDreg x)
|
||||
(MOVHreg x:(MOVBreg _)) -> (MOVDreg x)
|
||||
(MOVHreg x:(MOVBZreg _)) -> (MOVDreg x)
|
||||
(MOVHreg x:(MOVHreg _)) -> (MOVDreg x)
|
||||
(MOVHZreg x:(MOVBZreg _)) -> (MOVDreg x)
|
||||
(MOVHZreg x:(MOVHZreg _)) -> (MOVDreg x)
|
||||
(MOVWreg x:(MOVBreg _)) -> (MOVDreg x)
|
||||
(MOVWreg x:(MOVBZreg _)) -> (MOVDreg x)
|
||||
(MOVWreg x:(MOVHreg _)) -> (MOVDreg x)
|
||||
(MOVWreg x:(MOVHreg _)) -> (MOVDreg x)
|
||||
(MOVWreg x:(MOVWreg _)) -> (MOVDreg x)
|
||||
(MOVWZreg x:(MOVBZreg _)) -> (MOVDreg x)
|
||||
(MOVWZreg x:(MOVHZreg _)) -> (MOVDreg x)
|
||||
(MOVWZreg x:(MOVWZreg _)) -> (MOVDreg x)
|
||||
|
||||
// fold extensions into constants
|
||||
(MOVBreg (MOVDconst [c])) -> (MOVDconst [int64(int8(c))])
|
||||
@@ -641,10 +648,10 @@
|
||||
(MOVWZreg x:(MOVWZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWZloadidx <v.Type> [off] {sym} ptr idx mem)
|
||||
|
||||
// replace load from same location as preceding store with copy
|
||||
(MOVBZload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVHZload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVWZload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVBZload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDreg x)
|
||||
(MOVHZload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDreg x)
|
||||
(MOVWZload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDreg x)
|
||||
(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDreg x)
|
||||
|
||||
// Don't extend before storing
|
||||
(MOVWstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
|
||||
|
||||
@@ -311,6 +311,9 @@ func init() {
|
||||
{name: "MOVHZreg", argLength: 1, reg: gp11sp, asm: "MOVHZ", typ: "UInt64"}, // zero extend arg0 from int16 to int64
|
||||
{name: "MOVWreg", argLength: 1, reg: gp11sp, asm: "MOVW", typ: "Int64"}, // sign extend arg0 from int32 to int64
|
||||
{name: "MOVWZreg", argLength: 1, reg: gp11sp, asm: "MOVWZ", typ: "UInt64"}, // zero extend arg0 from int32 to int64
|
||||
{name: "MOVDreg", argLength: 1, reg: gp11sp, asm: "MOVD"}, // move from arg0
|
||||
|
||||
{name: "MOVDnop", argLength: 1, reg: gp11, resultInArg0: true}, // nop, return arg0 in same register
|
||||
|
||||
{name: "MOVDconst", reg: gp01, asm: "MOVD", typ: "UInt64", aux: "Int64", rematerializeable: true}, // auxint
|
||||
|
||||
|
||||
@@ -1473,6 +1473,8 @@ const (
|
||||
OpS390XMOVHZreg
|
||||
OpS390XMOVWreg
|
||||
OpS390XMOVWZreg
|
||||
OpS390XMOVDreg
|
||||
OpS390XMOVDnop
|
||||
OpS390XMOVDconst
|
||||
OpS390XCFDBRA
|
||||
OpS390XCGDBRA
|
||||
@@ -18570,6 +18572,32 @@ var opcodeTable = [...]opInfo{
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVDreg",
|
||||
argLen: 1,
|
||||
asm: s390x.AMOVD,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 54271}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14 SP
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVDnop",
|
||||
argLen: 1,
|
||||
resultInArg0: true,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVDconst",
|
||||
auxType: auxInt64,
|
||||
|
||||
@@ -2625,7 +2625,7 @@ func rewriteValueARM64_OpARM64FMOVDload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond: (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (FMOVDload [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -2637,7 +2637,7 @@ func rewriteValueARM64_OpARM64FMOVDload(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64FMOVDload)
|
||||
@@ -2648,7 +2648,7 @@ func rewriteValueARM64_OpARM64FMOVDload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -2661,7 +2661,7 @@ func rewriteValueARM64_OpARM64FMOVDload(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64FMOVDload)
|
||||
@@ -2677,7 +2677,7 @@ func rewriteValueARM64_OpARM64FMOVDstore(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
|
||||
// cond: (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (FMOVDstore [off1+off2] {sym} ptr val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -2690,7 +2690,7 @@ func rewriteValueARM64_OpARM64FMOVDstore(v *Value, config *Config) bool {
|
||||
ptr := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64FMOVDstore)
|
||||
@@ -2702,7 +2702,7 @@ func rewriteValueARM64_OpARM64FMOVDstore(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -2716,7 +2716,7 @@ func rewriteValueARM64_OpARM64FMOVDstore(v *Value, config *Config) bool {
|
||||
ptr := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64FMOVDstore)
|
||||
@@ -2733,7 +2733,7 @@ func rewriteValueARM64_OpARM64FMOVSload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (FMOVSload [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -2745,7 +2745,7 @@ func rewriteValueARM64_OpARM64FMOVSload(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64FMOVSload)
|
||||
@@ -2756,7 +2756,7 @@ func rewriteValueARM64_OpARM64FMOVSload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -2769,7 +2769,7 @@ func rewriteValueARM64_OpARM64FMOVSload(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64FMOVSload)
|
||||
@@ -2785,7 +2785,7 @@ func rewriteValueARM64_OpARM64FMOVSstore(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem)
|
||||
// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (FMOVSstore [off1+off2] {sym} ptr val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -2798,7 +2798,7 @@ func rewriteValueARM64_OpARM64FMOVSstore(v *Value, config *Config) bool {
|
||||
ptr := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64FMOVSstore)
|
||||
@@ -2810,7 +2810,7 @@ func rewriteValueARM64_OpARM64FMOVSstore(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -2824,7 +2824,7 @@ func rewriteValueARM64_OpARM64FMOVSstore(v *Value, config *Config) bool {
|
||||
ptr := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64FMOVSstore)
|
||||
@@ -3511,7 +3511,7 @@ func rewriteValueARM64_OpARM64MOVBUload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond:
|
||||
// cond: is32Bit(off1+off2)
|
||||
// result: (MOVBUload [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -3523,6 +3523,9 @@ func rewriteValueARM64_OpARM64MOVBUload(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(is32Bit(off1 + off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVBUload)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = sym
|
||||
@@ -3531,7 +3534,7 @@ func rewriteValueARM64_OpARM64MOVBUload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2)
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2)
|
||||
// result: (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -3544,7 +3547,7 @@ func rewriteValueARM64_OpARM64MOVBUload(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2)) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVBUload)
|
||||
@@ -3623,7 +3626,7 @@ func rewriteValueARM64_OpARM64MOVBload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVBload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond:
|
||||
// cond: is32Bit(off1+off2)
|
||||
// result: (MOVBload [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -3635,6 +3638,9 @@ func rewriteValueARM64_OpARM64MOVBload(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(is32Bit(off1 + off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVBload)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = sym
|
||||
@@ -3643,7 +3649,7 @@ func rewriteValueARM64_OpARM64MOVBload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2)
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2)
|
||||
// result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -3656,7 +3662,7 @@ func rewriteValueARM64_OpARM64MOVBload(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2)) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVBload)
|
||||
@@ -3735,7 +3741,7 @@ func rewriteValueARM64_OpARM64MOVBstore(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem)
|
||||
// cond:
|
||||
// cond: is32Bit(off1+off2)
|
||||
// result: (MOVBstore [off1+off2] {sym} ptr val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -3748,6 +3754,9 @@ func rewriteValueARM64_OpARM64MOVBstore(v *Value, config *Config) bool {
|
||||
ptr := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(is32Bit(off1 + off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVBstore)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = sym
|
||||
@@ -3757,7 +3766,7 @@ func rewriteValueARM64_OpARM64MOVBstore(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
|
||||
// cond: canMergeSym(sym1,sym2)
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2)
|
||||
// result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -3771,7 +3780,7 @@ func rewriteValueARM64_OpARM64MOVBstore(v *Value, config *Config) bool {
|
||||
ptr := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(canMergeSym(sym1, sym2)) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVBstore)
|
||||
@@ -3936,7 +3945,7 @@ func rewriteValueARM64_OpARM64MOVBstorezero(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond:
|
||||
// cond: is32Bit(off1+off2)
|
||||
// result: (MOVBstorezero [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -3948,6 +3957,9 @@ func rewriteValueARM64_OpARM64MOVBstorezero(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(is32Bit(off1 + off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVBstorezero)
|
||||
v.AuxInt = off1 + off2
|
||||
v.Aux = sym
|
||||
@@ -3956,7 +3968,7 @@ func rewriteValueARM64_OpARM64MOVBstorezero(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2)
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2)
|
||||
// result: (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -3969,7 +3981,7 @@ func rewriteValueARM64_OpARM64MOVBstorezero(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2)) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVBstorezero)
|
||||
@@ -3985,7 +3997,7 @@ func rewriteValueARM64_OpARM64MOVDload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond: (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (MOVDload [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -3997,7 +4009,7 @@ func rewriteValueARM64_OpARM64MOVDload(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVDload)
|
||||
@@ -4008,7 +4020,7 @@ func rewriteValueARM64_OpARM64MOVDload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4021,7 +4033,7 @@ func rewriteValueARM64_OpARM64MOVDload(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVDload)
|
||||
@@ -4088,7 +4100,7 @@ func rewriteValueARM64_OpARM64MOVDstore(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
|
||||
// cond: (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (MOVDstore [off1+off2] {sym} ptr val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4101,7 +4113,7 @@ func rewriteValueARM64_OpARM64MOVDstore(v *Value, config *Config) bool {
|
||||
ptr := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVDstore)
|
||||
@@ -4113,7 +4125,7 @@ func rewriteValueARM64_OpARM64MOVDstore(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4127,7 +4139,7 @@ func rewriteValueARM64_OpARM64MOVDstore(v *Value, config *Config) bool {
|
||||
ptr := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVDstore)
|
||||
@@ -4166,7 +4178,7 @@ func rewriteValueARM64_OpARM64MOVDstorezero(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVDstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond: (off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (MOVDstorezero [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4178,7 +4190,7 @@ func rewriteValueARM64_OpARM64MOVDstorezero(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !((off1+off2)%2 == 8 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%2 == 8 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVDstorezero)
|
||||
@@ -4189,7 +4201,7 @@ func rewriteValueARM64_OpARM64MOVDstorezero(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVDstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4202,7 +4214,7 @@ func rewriteValueARM64_OpARM64MOVDstorezero(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVDstorezero)
|
||||
@@ -4218,7 +4230,7 @@ func rewriteValueARM64_OpARM64MOVHUload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond: (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (MOVHUload [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4230,7 +4242,7 @@ func rewriteValueARM64_OpARM64MOVHUload(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVHUload)
|
||||
@@ -4241,7 +4253,7 @@ func rewriteValueARM64_OpARM64MOVHUload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVHUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4254,7 +4266,7 @@ func rewriteValueARM64_OpARM64MOVHUload(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVHUload)
|
||||
@@ -4357,7 +4369,7 @@ func rewriteValueARM64_OpARM64MOVHload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVHload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond: (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (MOVHload [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4369,7 +4381,7 @@ func rewriteValueARM64_OpARM64MOVHload(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVHload)
|
||||
@@ -4380,7 +4392,7 @@ func rewriteValueARM64_OpARM64MOVHload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVHload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4393,7 +4405,7 @@ func rewriteValueARM64_OpARM64MOVHload(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVHload)
|
||||
@@ -4520,7 +4532,7 @@ func rewriteValueARM64_OpARM64MOVHstore(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem)
|
||||
// cond: (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (MOVHstore [off1+off2] {sym} ptr val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4533,7 +4545,7 @@ func rewriteValueARM64_OpARM64MOVHstore(v *Value, config *Config) bool {
|
||||
ptr := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVHstore)
|
||||
@@ -4545,7 +4557,7 @@ func rewriteValueARM64_OpARM64MOVHstore(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVHstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4559,7 +4571,7 @@ func rewriteValueARM64_OpARM64MOVHstore(v *Value, config *Config) bool {
|
||||
ptr := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVHstore)
|
||||
@@ -4682,7 +4694,7 @@ func rewriteValueARM64_OpARM64MOVHstorezero(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVHstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond: (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (MOVHstorezero [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4694,7 +4706,7 @@ func rewriteValueARM64_OpARM64MOVHstorezero(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVHstorezero)
|
||||
@@ -4705,7 +4717,7 @@ func rewriteValueARM64_OpARM64MOVHstorezero(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVHstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4718,7 +4730,7 @@ func rewriteValueARM64_OpARM64MOVHstorezero(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVHstorezero)
|
||||
@@ -4734,7 +4746,7 @@ func rewriteValueARM64_OpARM64MOVWUload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVWUload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (MOVWUload [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4746,7 +4758,7 @@ func rewriteValueARM64_OpARM64MOVWUload(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVWUload)
|
||||
@@ -4757,7 +4769,7 @@ func rewriteValueARM64_OpARM64MOVWUload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVWUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4770,7 +4782,7 @@ func rewriteValueARM64_OpARM64MOVWUload(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVWUload)
|
||||
@@ -4897,7 +4909,7 @@ func rewriteValueARM64_OpARM64MOVWload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVWload [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (MOVWload [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4909,7 +4921,7 @@ func rewriteValueARM64_OpARM64MOVWload(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVWload)
|
||||
@@ -4920,7 +4932,7 @@ func rewriteValueARM64_OpARM64MOVWload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVWload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -4933,7 +4945,7 @@ func rewriteValueARM64_OpARM64MOVWload(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVWload)
|
||||
@@ -5108,7 +5120,7 @@ func rewriteValueARM64_OpARM64MOVWstore(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem)
|
||||
// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (MOVWstore [off1+off2] {sym} ptr val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -5121,7 +5133,7 @@ func rewriteValueARM64_OpARM64MOVWstore(v *Value, config *Config) bool {
|
||||
ptr := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVWstore)
|
||||
@@ -5133,7 +5145,7 @@ func rewriteValueARM64_OpARM64MOVWstore(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVWstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -5147,7 +5159,7 @@ func rewriteValueARM64_OpARM64MOVWstore(v *Value, config *Config) bool {
|
||||
ptr := v_0.Args[0]
|
||||
val := v.Args[1]
|
||||
mem := v.Args[2]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVWstore)
|
||||
@@ -5228,7 +5240,7 @@ func rewriteValueARM64_OpARM64MOVWstorezero(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVWstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
|
||||
// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
|
||||
// cond: is32Bit(off1+off2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym))
|
||||
// result: (MOVWstorezero [off1+off2] {sym} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -5240,7 +5252,7 @@ func rewriteValueARM64_OpARM64MOVWstorezero(v *Value, config *Config) bool {
|
||||
off2 := v_0.AuxInt
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
|
||||
if !(is32Bit(off1+off2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVWstorezero)
|
||||
@@ -5251,7 +5263,7 @@ func rewriteValueARM64_OpARM64MOVWstorezero(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVWstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
|
||||
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
|
||||
// result: (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
for {
|
||||
off1 := v.AuxInt
|
||||
@@ -5264,7 +5276,7 @@ func rewriteValueARM64_OpARM64MOVWstorezero(v *Value, config *Config) bool {
|
||||
sym2 := v_0.Aux
|
||||
ptr := v_0.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpARM64MOVWstorezero)
|
||||
|
||||
@@ -524,6 +524,8 @@ func rewriteValueS390X(v *Value, config *Config) bool {
|
||||
return rewriteValueS390X_OpS390XMOVDload(v, config)
|
||||
case OpS390XMOVDloadidx:
|
||||
return rewriteValueS390X_OpS390XMOVDloadidx(v, config)
|
||||
case OpS390XMOVDreg:
|
||||
return rewriteValueS390X_OpS390XMOVDreg(v, config)
|
||||
case OpS390XMOVDstore:
|
||||
return rewriteValueS390X_OpS390XMOVDstore(v, config)
|
||||
case OpS390XMOVDstoreconst:
|
||||
@@ -3236,13 +3238,28 @@ func rewriteValueS390X_OpLoad(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: is32BitInt(t)
|
||||
// cond: is32BitInt(t) && isSigned(t)
|
||||
// result: (MOVWload ptr mem)
|
||||
for {
|
||||
t := v.Type
|
||||
ptr := v.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(is32BitInt(t) && isSigned(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVWload)
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: is32BitInt(t) && !isSigned(t)
|
||||
// result: (MOVWZload ptr mem)
|
||||
for {
|
||||
t := v.Type
|
||||
ptr := v.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(is32BitInt(t)) {
|
||||
if !(is32BitInt(t) && !isSigned(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVWZload)
|
||||
@@ -3251,13 +3268,28 @@ func rewriteValueS390X_OpLoad(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: is16BitInt(t)
|
||||
// cond: is16BitInt(t) && isSigned(t)
|
||||
// result: (MOVHload ptr mem)
|
||||
for {
|
||||
t := v.Type
|
||||
ptr := v.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(is16BitInt(t) && isSigned(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVHload)
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: is16BitInt(t) && !isSigned(t)
|
||||
// result: (MOVHZload ptr mem)
|
||||
for {
|
||||
t := v.Type
|
||||
ptr := v.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(is16BitInt(t)) {
|
||||
if !(is16BitInt(t) && !isSigned(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVHZload)
|
||||
@@ -3266,13 +3298,28 @@ func rewriteValueS390X_OpLoad(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: (t.IsBoolean() || is8BitInt(t))
|
||||
// cond: is8BitInt(t) && isSigned(t)
|
||||
// result: (MOVBload ptr mem)
|
||||
for {
|
||||
t := v.Type
|
||||
ptr := v.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(is8BitInt(t) && isSigned(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVBload)
|
||||
v.AddArg(ptr)
|
||||
v.AddArg(mem)
|
||||
return true
|
||||
}
|
||||
// match: (Load <t> ptr mem)
|
||||
// cond: (t.IsBoolean() || (is8BitInt(t) && !isSigned(t)))
|
||||
// result: (MOVBZload ptr mem)
|
||||
for {
|
||||
t := v.Type
|
||||
ptr := v.Args[0]
|
||||
mem := v.Args[1]
|
||||
if !(t.IsBoolean() || is8BitInt(t)) {
|
||||
if !(t.IsBoolean() || (is8BitInt(t) && !isSigned(t))) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVBZload)
|
||||
@@ -7802,7 +7849,7 @@ func rewriteValueS390X_OpS390XMOVBZload(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVBZload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -7818,8 +7865,7 @@ func rewriteValueS390X_OpS390XMOVBZload(v *Value, config *Config) bool {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -7976,7 +8022,7 @@ func rewriteValueS390X_OpS390XMOVBZreg(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVBZreg x:(MOVDLT (MOVDconst [c]) (MOVDconst [d]) _))
|
||||
// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVDLT {
|
||||
@@ -7995,14 +8041,13 @@ func rewriteValueS390X_OpS390XMOVBZreg(v *Value, config *Config) bool {
|
||||
if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBZreg x:(MOVDLE (MOVDconst [c]) (MOVDconst [d]) _))
|
||||
// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVDLE {
|
||||
@@ -8021,14 +8066,13 @@ func rewriteValueS390X_OpS390XMOVBZreg(v *Value, config *Config) bool {
|
||||
if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBZreg x:(MOVDGT (MOVDconst [c]) (MOVDconst [d]) _))
|
||||
// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVDGT {
|
||||
@@ -8047,14 +8091,13 @@ func rewriteValueS390X_OpS390XMOVBZreg(v *Value, config *Config) bool {
|
||||
if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBZreg x:(MOVDGE (MOVDconst [c]) (MOVDconst [d]) _))
|
||||
// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVDGE {
|
||||
@@ -8073,14 +8116,13 @@ func rewriteValueS390X_OpS390XMOVBZreg(v *Value, config *Config) bool {
|
||||
if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBZreg x:(MOVDEQ (MOVDconst [c]) (MOVDconst [d]) _))
|
||||
// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVDEQ {
|
||||
@@ -8099,14 +8141,13 @@ func rewriteValueS390X_OpS390XMOVBZreg(v *Value, config *Config) bool {
|
||||
if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBZreg x:(MOVDNE (MOVDconst [c]) (MOVDconst [d]) _))
|
||||
// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVDNE {
|
||||
@@ -8125,14 +8166,13 @@ func rewriteValueS390X_OpS390XMOVBZreg(v *Value, config *Config) bool {
|
||||
if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBZreg x:(MOVDGTnoinv (MOVDconst [c]) (MOVDconst [d]) _))
|
||||
// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVDGTnoinv {
|
||||
@@ -8151,14 +8191,13 @@ func rewriteValueS390X_OpS390XMOVBZreg(v *Value, config *Config) bool {
|
||||
if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBZreg x:(MOVDGEnoinv (MOVDconst [c]) (MOVDconst [d]) _))
|
||||
// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVDGEnoinv {
|
||||
@@ -8177,27 +8216,25 @@ func rewriteValueS390X_OpS390XMOVBZreg(v *Value, config *Config) bool {
|
||||
if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBZreg x:(MOVBZload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBZload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBZreg x:(Arg <t>))
|
||||
// cond: is8BitInt(t) && !isSigned(t)
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpArg {
|
||||
@@ -8207,21 +8244,19 @@ func rewriteValueS390X_OpS390XMOVBZreg(v *Value, config *Config) bool {
|
||||
if !(is8BitInt(t) && !isSigned(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBZreg x:(MOVBZreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBZreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -8349,20 +8384,19 @@ func rewriteValueS390X_OpS390XMOVBreg(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVBreg x:(MOVBload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBreg x:(Arg <t>))
|
||||
// cond: is8BitInt(t) && isSigned(t)
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpArg {
|
||||
@@ -8372,21 +8406,19 @@ func rewriteValueS390X_OpS390XMOVBreg(v *Value, config *Config) bool {
|
||||
if !(is8BitInt(t) && isSigned(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBreg x:(MOVBreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -9995,7 +10027,7 @@ func rewriteValueS390X_OpS390XMOVDload(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -10011,8 +10043,7 @@ func rewriteValueS390X_OpS390XMOVDload(v *Value, config *Config) bool {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -10164,6 +10195,23 @@ func rewriteValueS390X_OpS390XMOVDloadidx(v *Value, config *Config) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueS390X_OpS390XMOVDreg(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVDreg x)
|
||||
// cond: x.Uses == 1
|
||||
// result: (MOVDnop x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if !(x.Uses == 1) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVDnop)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValueS390X_OpS390XMOVDstore(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
@@ -10912,7 +10960,7 @@ func rewriteValueS390X_OpS390XMOVHZload(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVHZload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -10928,8 +10976,7 @@ func rewriteValueS390X_OpS390XMOVHZload(v *Value, config *Config) bool {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -11086,33 +11133,31 @@ func rewriteValueS390X_OpS390XMOVHZreg(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVHZreg x:(MOVBZload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBZload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVHZreg x:(MOVHZload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVHZload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVHZreg x:(Arg <t>))
|
||||
// cond: (is8BitInt(t) || is16BitInt(t)) && !isSigned(t)
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpArg {
|
||||
@@ -11122,34 +11167,31 @@ func rewriteValueS390X_OpS390XMOVHZreg(v *Value, config *Config) bool {
|
||||
if !((is8BitInt(t) || is16BitInt(t)) && !isSigned(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVHZreg x:(MOVBZreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBZreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVHZreg x:(MOVHZreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVHZreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -11277,46 +11319,43 @@ func rewriteValueS390X_OpS390XMOVHreg(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVHreg x:(MOVBload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVHreg x:(MOVBZload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBZload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVHreg x:(MOVHload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVHload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVHreg x:(Arg <t>))
|
||||
// cond: (is8BitInt(t) || is16BitInt(t)) && isSigned(t)
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpArg {
|
||||
@@ -11326,47 +11365,43 @@ func rewriteValueS390X_OpS390XMOVHreg(v *Value, config *Config) bool {
|
||||
if !((is8BitInt(t) || is16BitInt(t)) && isSigned(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVHreg x:(MOVBreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVHreg x:(MOVBZreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBZreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVHreg x:(MOVHreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVHreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -12310,7 +12345,7 @@ func rewriteValueS390X_OpS390XMOVWZload(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVWZload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -12326,8 +12361,7 @@ func rewriteValueS390X_OpS390XMOVWZload(v *Value, config *Config) bool {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -12484,46 +12518,43 @@ func rewriteValueS390X_OpS390XMOVWZreg(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVWZreg x:(MOVBZload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBZload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWZreg x:(MOVHZload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVHZload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWZreg x:(MOVWZload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVWZload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWZreg x:(Arg <t>))
|
||||
// cond: (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t)
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpArg {
|
||||
@@ -12533,47 +12564,43 @@ func rewriteValueS390X_OpS390XMOVWZreg(v *Value, config *Config) bool {
|
||||
if !((is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWZreg x:(MOVBZreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBZreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWZreg x:(MOVHZreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVHZreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWZreg x:(MOVWZreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVWZreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -12701,72 +12728,67 @@ func rewriteValueS390X_OpS390XMOVWreg(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVWreg x:(MOVBload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWreg x:(MOVBZload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBZload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWreg x:(MOVHload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVHload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWreg x:(MOVHZload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVHZload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWreg x:(MOVWload _ _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVWload {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWreg x:(Arg <t>))
|
||||
// cond: (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t)
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpArg {
|
||||
@@ -12776,73 +12798,67 @@ func rewriteValueS390X_OpS390XMOVWreg(v *Value, config *Config) bool {
|
||||
if !((is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWreg x:(MOVBreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWreg x:(MOVBZreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVBZreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWreg x:(MOVHreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVHreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWreg x:(MOVHreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVHreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWreg x:(MOVWreg _))
|
||||
// cond:
|
||||
// result: x
|
||||
// result: (MOVDreg x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if x.Op != OpS390XMOVWreg {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1634,6 +1634,8 @@ func (p *parser) stmtBody(context string) []Stmt {
|
||||
return body
|
||||
}
|
||||
|
||||
var dummyCond = &Name{Value: "false"}
|
||||
|
||||
func (p *parser) header(forStmt bool) (init SimpleStmt, cond Expr, post SimpleStmt) {
|
||||
if p.tok == _Lbrace {
|
||||
return
|
||||
@@ -1680,7 +1682,8 @@ func (p *parser) header(forStmt bool) (init SimpleStmt, cond Expr, post SimpleSt
|
||||
case *ExprStmt:
|
||||
cond = s.X
|
||||
default:
|
||||
p.error("invalid condition, tag, or type switch guard")
|
||||
p.syntax_error(fmt.Sprintf("%s used as value", String(s)))
|
||||
cond = dummyCond // avoid follow-up error for if statements
|
||||
}
|
||||
|
||||
p.xnest = outer
|
||||
|
||||
@@ -428,7 +428,7 @@ func downloadPackage(p *Package) error {
|
||||
return fmt.Errorf("cannot download, $GOPATH not set. For more details see: 'go help gopath'")
|
||||
}
|
||||
// Guard against people setting GOPATH=$GOROOT.
|
||||
if list[0] == goroot {
|
||||
if filepath.Clean(list[0]) == filepath.Clean(goroot) {
|
||||
return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: 'go help gopath'")
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(list[0], "src/cmd/go/alldocs.go")); err == nil {
|
||||
|
||||
@@ -1683,173 +1683,111 @@ func homeEnvName() string {
|
||||
}
|
||||
}
|
||||
|
||||
// Test go env missing GOPATH shows default.
|
||||
func TestMissingGOPATHEnvShowsDefault(t *testing.T) {
|
||||
func TestDefaultGOPATH(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.setenv("GOPATH", "")
|
||||
tg.tempDir("home/go")
|
||||
tg.setenv(homeEnvName(), tg.path("home"))
|
||||
|
||||
tg.run("env", "GOPATH")
|
||||
tg.grepStdout(regexp.QuoteMeta(tg.path("home/go")), "want GOPATH=$HOME/go")
|
||||
|
||||
want := filepath.Join(os.Getenv(homeEnvName()), "go")
|
||||
got := strings.TrimSpace(tg.getStdout())
|
||||
if got != want {
|
||||
t.Errorf("got %q; want %q", got, want)
|
||||
}
|
||||
tg.setenv("GOROOT", tg.path("home/go"))
|
||||
tg.run("env", "GOPATH")
|
||||
tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go")
|
||||
|
||||
tg.setenv("GOROOT", tg.path("home/go")+"/")
|
||||
tg.run("env", "GOPATH")
|
||||
tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go/")
|
||||
}
|
||||
|
||||
// Test go get missing GOPATH causes go get to warn if directory doesn't exist.
|
||||
func TestMissingGOPATHGetWarnsIfNotExists(t *testing.T) {
|
||||
func TestDefaultGOPATHGet(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
t.Skip("skipping because git binary not found")
|
||||
}
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
||||
// setenv variables for test and defer deleting temporary home directory.
|
||||
tg.setenv("GOPATH", "")
|
||||
tmp, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("could not create tmp home: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
tg.setenv(homeEnvName(), tmp)
|
||||
tg.tempDir("home")
|
||||
tg.setenv(homeEnvName(), tg.path("home"))
|
||||
|
||||
// warn for creating directory
|
||||
tg.run("get", "-v", "github.com/golang/example/hello")
|
||||
tg.grepStderr("created GOPATH="+regexp.QuoteMeta(tg.path("home/go"))+"; see 'go help gopath'", "did not create GOPATH")
|
||||
|
||||
want := fmt.Sprintf("created GOPATH=%s; see 'go help gopath'", filepath.Join(tmp, "go"))
|
||||
got := strings.TrimSpace(tg.getStderr())
|
||||
if !strings.Contains(got, want) {
|
||||
t.Errorf("got %q; want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// Test go get missing GOPATH causes no warning if directory exists.
|
||||
func TestMissingGOPATHGetDoesntWarnIfExists(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
if _, err := exec.LookPath("git"); err != nil {
|
||||
t.Skip("skipping because git binary not found")
|
||||
}
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
||||
// setenv variables for test and defer resetting them.
|
||||
tg.setenv("GOPATH", "")
|
||||
tmp, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("could not create tmp home: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
if err := os.Mkdir(filepath.Join(tmp, "go"), 0777); err != nil {
|
||||
t.Fatalf("could not create $HOME/go: %v", err)
|
||||
}
|
||||
|
||||
tg.setenv(homeEnvName(), tmp)
|
||||
|
||||
// no warning if directory already exists
|
||||
tg.must(os.RemoveAll(tg.path("home/go")))
|
||||
tg.tempDir("home/go")
|
||||
tg.run("get", "github.com/golang/example/hello")
|
||||
tg.grepStderrNot(".", "expected no output on standard error")
|
||||
|
||||
got := strings.TrimSpace(tg.getStderr())
|
||||
if got != "" {
|
||||
t.Errorf("got %q; wants empty", got)
|
||||
}
|
||||
// error if $HOME/go is a file
|
||||
tg.must(os.RemoveAll(tg.path("home/go")))
|
||||
tg.tempFile("home/go", "")
|
||||
tg.runFail("get", "github.com/golang/example/hello")
|
||||
tg.grepStderr(`mkdir .*[/\\]go: .*(not a directory|cannot find the path)`, "expected error because $HOME/go is a file")
|
||||
}
|
||||
|
||||
// Test go get missing GOPATH fails if pointed file is not a directory.
|
||||
func TestMissingGOPATHGetFailsIfItsNotDirectory(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
||||
// setenv variables for test and defer resetting them.
|
||||
tg.setenv("GOPATH", "")
|
||||
tmp, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("could not create tmp home: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
tg.tempDir("home")
|
||||
tg.setenv(homeEnvName(), tg.path("home"))
|
||||
|
||||
path := filepath.Join(tmp, "go")
|
||||
if err := ioutil.WriteFile(path, nil, 0777); err != nil {
|
||||
t.Fatalf("could not create GOPATH at %s: %v", path, err)
|
||||
}
|
||||
tg.setenv(homeEnvName(), tmp)
|
||||
|
||||
const pkg = "github.com/golang/example/hello"
|
||||
tg.runFail("get", pkg)
|
||||
|
||||
msg := "not a directory"
|
||||
if runtime.GOOS == "windows" {
|
||||
msg = "The system cannot find the path specified."
|
||||
}
|
||||
want := fmt.Sprintf("package %s: mkdir %s: %s", pkg, filepath.Join(tmp, "go"), msg)
|
||||
got := strings.TrimSpace(tg.getStderr())
|
||||
if got != want {
|
||||
t.Errorf("got %q; wants %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
// Test go install of missing package when missing GOPATH fails and shows default GOPATH.
|
||||
func TestMissingGOPATHInstallMissingPackageFailsAndShowsDefault(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
||||
// setenv variables for test and defer resetting them.
|
||||
tg.setenv("GOPATH", "")
|
||||
tmp, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("could not create tmp home: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmp)
|
||||
if err := os.Mkdir(filepath.Join(tmp, "go"), 0777); err != nil {
|
||||
t.Fatalf("could not create $HOME/go: %v", err)
|
||||
}
|
||||
tg.setenv(homeEnvName(), tmp)
|
||||
|
||||
const pkg = "github.com/golang/example/hello"
|
||||
tg.runFail("install", pkg)
|
||||
|
||||
pkgPath := filepath.Join(strings.Split(pkg, "/")...)
|
||||
want := fmt.Sprintf("can't load package: package %s: cannot find package \"%s\" in any of:", pkg, pkg) +
|
||||
fmt.Sprintf("\n\t%s (from $GOROOT)", filepath.Join(runtime.GOROOT(), "src", pkgPath)) +
|
||||
fmt.Sprintf("\n\t%s (from $GOPATH)", filepath.Join(tmp, "go", "src", pkgPath))
|
||||
|
||||
got := strings.TrimSpace(tg.getStderr())
|
||||
if got != want {
|
||||
t.Errorf("got %q; wants %q", got, want)
|
||||
}
|
||||
tg.runFail("install", "github.com/golang/example/hello")
|
||||
tg.grepStderr(regexp.QuoteMeta(tg.path("home/go/src/github.com/golang/example/hello"))+`.*from \$GOPATH`, "expected default GOPATH")
|
||||
}
|
||||
|
||||
// Issue 4186. go get cannot be used to download packages to $GOROOT.
|
||||
// Test that without GOPATH set, go get should fail.
|
||||
func TestWithoutGOPATHGoGetFails(t *testing.T) {
|
||||
func TestGoGetIntoGOROOT(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.tempDir("src")
|
||||
tg.setenv("GOPATH", "")
|
||||
tg.setenv("GOROOT", tg.path("."))
|
||||
tg.runFail("get", "-d", "golang.org/x/codereview/cmd/hgpatch")
|
||||
}
|
||||
|
||||
// Test that with GOPATH=$GOROOT, go get should fail.
|
||||
func TestWithGOPATHEqualsGOROOTGoGetFails(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.tempDir("src")
|
||||
// Fails because GOROOT=GOPATH
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.setenv("GOROOT", tg.path("."))
|
||||
tg.runFail("get", "-d", "golang.org/x/codereview/cmd/hgpatch")
|
||||
tg.runFail("get", "-d", "github.com/golang/example/hello")
|
||||
tg.grepStderr("warning: GOPATH set to GOROOT", "go should detect GOPATH=GOROOT")
|
||||
tg.grepStderr(`\$GOPATH must not be set to \$GOROOT`, "go should detect GOPATH=GOROOT")
|
||||
|
||||
// Fails because GOROOT=GOPATH after cleaning.
|
||||
tg.setenv("GOPATH", tg.path(".")+"/")
|
||||
tg.setenv("GOROOT", tg.path("."))
|
||||
tg.runFail("get", "-d", "github.com/golang/example/hello")
|
||||
tg.grepStderr("warning: GOPATH set to GOROOT", "go should detect GOPATH=GOROOT")
|
||||
tg.grepStderr(`\$GOPATH must not be set to \$GOROOT`, "go should detect GOPATH=GOROOT")
|
||||
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.setenv("GOROOT", tg.path(".")+"/")
|
||||
tg.runFail("get", "-d", "github.com/golang/example/hello")
|
||||
tg.grepStderr("warning: GOPATH set to GOROOT", "go should detect GOPATH=GOROOT")
|
||||
tg.grepStderr(`\$GOPATH must not be set to \$GOROOT`, "go should detect GOPATH=GOROOT")
|
||||
|
||||
// Fails because GOROOT=$HOME/go so default GOPATH unset.
|
||||
tg.tempDir("home/go")
|
||||
tg.setenv(homeEnvName(), tg.path("home"))
|
||||
tg.setenv("GOPATH", "")
|
||||
tg.setenv("GOROOT", tg.path("home/go"))
|
||||
tg.runFail("get", "-d", "github.com/golang/example/hello")
|
||||
tg.grepStderr(`\$GOPATH not set`, "expected GOPATH not set")
|
||||
|
||||
tg.setenv(homeEnvName(), tg.path("home")+"/")
|
||||
tg.setenv("GOPATH", "")
|
||||
tg.setenv("GOROOT", tg.path("home/go"))
|
||||
tg.runFail("get", "-d", "github.com/golang/example/hello")
|
||||
tg.grepStderr(`\$GOPATH not set`, "expected GOPATH not set")
|
||||
|
||||
tg.setenv(homeEnvName(), tg.path("home"))
|
||||
tg.setenv("GOPATH", "")
|
||||
tg.setenv("GOROOT", tg.path("home/go")+"/")
|
||||
tg.runFail("get", "-d", "github.com/golang/example/hello")
|
||||
tg.grepStderr(`\$GOPATH not set`, "expected GOPATH not set")
|
||||
}
|
||||
|
||||
func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
|
||||
@@ -3744,6 +3682,13 @@ func TestMatchesOnlySubtestParallelIsOK(t *testing.T) {
|
||||
tg.grepBoth(okPattern, "go test did not say ok")
|
||||
}
|
||||
|
||||
// Issue 18845
|
||||
func TestBenchTimeout(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.run("test", "-bench", ".", "-timeout", "750ms", "testdata/timeoutbench_test.go")
|
||||
}
|
||||
|
||||
func TestLinkXImportPathEscape(t *testing.T) {
|
||||
// golang.org/issue/16710
|
||||
tg := testgo(t)
|
||||
|
||||
@@ -136,7 +136,7 @@ func main() {
|
||||
// Diagnose common mistake: GOPATH==GOROOT.
|
||||
// This setting is equivalent to not setting GOPATH at all,
|
||||
// which is not what most people want when they do it.
|
||||
if gopath := buildContext.GOPATH; gopath == runtime.GOROOT() {
|
||||
if gopath := buildContext.GOPATH; filepath.Clean(gopath) == filepath.Clean(runtime.GOROOT()) {
|
||||
fmt.Fprintf(os.Stderr, "warning: GOPATH set to GOROOT (%s) has no effect\n", gopath)
|
||||
} else {
|
||||
for _, p := range filepath.SplitList(gopath) {
|
||||
|
||||
10
src/cmd/go/testdata/timeoutbench_test.go
vendored
Normal file
10
src/cmd/go/testdata/timeoutbench_test.go
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
package timeoutbench_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func BenchmarkSleep1s(b *testing.B) {
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
@@ -238,6 +238,8 @@ func determineLinkMode(ctxt *Link) {
|
||||
Linkmode = LinkExternal
|
||||
} else if iscgo && externalobj {
|
||||
Linkmode = LinkExternal
|
||||
} else if Buildmode == BuildmodePIE {
|
||||
Linkmode = LinkExternal // https://golang.org/issue/18968
|
||||
} else {
|
||||
Linkmode = LinkInternal
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ package x509
|
||||
// Possible certificate files; stop after finding one.
|
||||
var certFiles = []string{
|
||||
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
|
||||
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
|
||||
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
|
||||
"/etc/ssl/ca-bundle.pem", // OpenSUSE
|
||||
"/etc/pki/tls/cacert.pem", // OpenELEC
|
||||
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
|
||||
}
|
||||
|
||||
@@ -35,15 +35,12 @@ func ctxDriverExec(ctx context.Context, execer driver.Execer, query string, nvda
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resi, err := execer.Exec(query, dargs)
|
||||
if err == nil {
|
||||
select {
|
||||
default:
|
||||
case <-ctx.Done():
|
||||
return resi, ctx.Err()
|
||||
}
|
||||
select {
|
||||
default:
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
return resi, err
|
||||
return execer.Exec(query, dargs)
|
||||
}
|
||||
|
||||
func ctxDriverQuery(ctx context.Context, queryer driver.Queryer, query string, nvdargs []driver.NamedValue) (driver.Rows, error) {
|
||||
@@ -56,16 +53,12 @@ func ctxDriverQuery(ctx context.Context, queryer driver.Queryer, query string, n
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rowsi, err := queryer.Query(query, dargs)
|
||||
if err == nil {
|
||||
select {
|
||||
default:
|
||||
case <-ctx.Done():
|
||||
rowsi.Close()
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
select {
|
||||
default:
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
return rowsi, err
|
||||
return queryer.Query(query, dargs)
|
||||
}
|
||||
|
||||
func ctxDriverStmtExec(ctx context.Context, si driver.Stmt, nvdargs []driver.NamedValue) (driver.Result, error) {
|
||||
@@ -77,15 +70,12 @@ func ctxDriverStmtExec(ctx context.Context, si driver.Stmt, nvdargs []driver.Nam
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resi, err := si.Exec(dargs)
|
||||
if err == nil {
|
||||
select {
|
||||
default:
|
||||
case <-ctx.Done():
|
||||
return resi, ctx.Err()
|
||||
}
|
||||
select {
|
||||
default:
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
return resi, err
|
||||
return si.Exec(dargs)
|
||||
}
|
||||
|
||||
func ctxDriverStmtQuery(ctx context.Context, si driver.Stmt, nvdargs []driver.NamedValue) (driver.Rows, error) {
|
||||
@@ -97,16 +87,12 @@ func ctxDriverStmtQuery(ctx context.Context, si driver.Stmt, nvdargs []driver.Na
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rowsi, err := si.Query(dargs)
|
||||
if err == nil {
|
||||
select {
|
||||
default:
|
||||
case <-ctx.Done():
|
||||
rowsi.Close()
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
select {
|
||||
default:
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
return rowsi, err
|
||||
return si.Query(dargs)
|
||||
}
|
||||
|
||||
var errLevelNotSupported = errors.New("sql: selected isolation level is not supported")
|
||||
|
||||
@@ -305,8 +305,9 @@ type DB struct {
|
||||
|
||||
mu sync.Mutex // protects following fields
|
||||
freeConn []*driverConn
|
||||
connRequests []chan connRequest
|
||||
numOpen int // number of opened and pending open connections
|
||||
connRequests map[uint64]chan connRequest
|
||||
nextRequest uint64 // Next key to use in connRequests.
|
||||
numOpen int // number of opened and pending open connections
|
||||
// Used to signal the need for new connections
|
||||
// a goroutine running connectionOpener() reads on this chan and
|
||||
// maybeOpenNewConnections sends on the chan (one send per needed connection)
|
||||
@@ -572,10 +573,11 @@ func Open(driverName, dataSourceName string) (*DB, error) {
|
||||
return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
|
||||
}
|
||||
db := &DB{
|
||||
driver: driveri,
|
||||
dsn: dataSourceName,
|
||||
openerCh: make(chan struct{}, connectionRequestQueueSize),
|
||||
lastPut: make(map[*driverConn]string),
|
||||
driver: driveri,
|
||||
dsn: dataSourceName,
|
||||
openerCh: make(chan struct{}, connectionRequestQueueSize),
|
||||
lastPut: make(map[*driverConn]string),
|
||||
connRequests: make(map[uint64]chan connRequest),
|
||||
}
|
||||
go db.connectionOpener()
|
||||
return db, nil
|
||||
@@ -881,6 +883,14 @@ type connRequest struct {
|
||||
|
||||
var errDBClosed = errors.New("sql: database is closed")
|
||||
|
||||
// nextRequestKeyLocked returns the next connection request key.
|
||||
// It is assumed that nextRequest will not overflow.
|
||||
func (db *DB) nextRequestKeyLocked() uint64 {
|
||||
next := db.nextRequest
|
||||
db.nextRequest++
|
||||
return next
|
||||
}
|
||||
|
||||
// conn returns a newly-opened or cached *driverConn.
|
||||
func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn, error) {
|
||||
db.mu.Lock()
|
||||
@@ -918,12 +928,25 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn
|
||||
// Make the connRequest channel. It's buffered so that the
|
||||
// connectionOpener doesn't block while waiting for the req to be read.
|
||||
req := make(chan connRequest, 1)
|
||||
db.connRequests = append(db.connRequests, req)
|
||||
reqKey := db.nextRequestKeyLocked()
|
||||
db.connRequests[reqKey] = req
|
||||
db.mu.Unlock()
|
||||
|
||||
// Timeout the connection request with the context.
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
// Remove the connection request and ensure no value has been sent
|
||||
// on it after removing.
|
||||
db.mu.Lock()
|
||||
delete(db.connRequests, reqKey)
|
||||
db.mu.Unlock()
|
||||
select {
|
||||
default:
|
||||
case ret, ok := <-req:
|
||||
if ok {
|
||||
db.putConn(ret.conn, ret.err)
|
||||
}
|
||||
}
|
||||
return nil, ctx.Err()
|
||||
case ret, ok := <-req:
|
||||
if !ok {
|
||||
@@ -1044,12 +1067,12 @@ func (db *DB) putConnDBLocked(dc *driverConn, err error) bool {
|
||||
return false
|
||||
}
|
||||
if c := len(db.connRequests); c > 0 {
|
||||
req := db.connRequests[0]
|
||||
// This copy is O(n) but in practice faster than a linked list.
|
||||
// TODO: consider compacting it down less often and
|
||||
// moving the base instead?
|
||||
copy(db.connRequests, db.connRequests[1:])
|
||||
db.connRequests = db.connRequests[:c-1]
|
||||
var req chan connRequest
|
||||
var reqKey uint64
|
||||
for reqKey, req = range db.connRequests {
|
||||
break
|
||||
}
|
||||
delete(db.connRequests, reqKey) // Remove from pending requests.
|
||||
if err == nil {
|
||||
dc.inUse = true
|
||||
}
|
||||
@@ -2071,14 +2094,21 @@ type Rows struct {
|
||||
dc *driverConn // owned; must call releaseConn when closed to release
|
||||
releaseConn func(error)
|
||||
rowsi driver.Rows
|
||||
cancel func() // called when Rows is closed, may be nil.
|
||||
closeStmt *driverStmt // if non-nil, statement to Close on close
|
||||
|
||||
// closed value is 1 when the Rows is closed.
|
||||
// Use atomic operations on value when checking value.
|
||||
closed int32
|
||||
cancel func() // called when Rows is closed, may be nil.
|
||||
lastcols []driver.Value
|
||||
lasterr error // non-nil only if closed is true
|
||||
closeStmt *driverStmt // if non-nil, statement to Close on close
|
||||
// closemu prevents Rows from closing while there
|
||||
// is an active streaming result. It is held for read during non-close operations
|
||||
// and exclusively during close.
|
||||
//
|
||||
// closemu guards lasterr and closed.
|
||||
closemu sync.RWMutex
|
||||
closed bool
|
||||
lasterr error // non-nil only if closed is true
|
||||
|
||||
// lastcols is only used in Scan, Next, and NextResultSet which are expected
|
||||
// not not be called concurrently.
|
||||
lastcols []driver.Value
|
||||
}
|
||||
|
||||
func (rs *Rows) initContextClose(ctx context.Context) {
|
||||
@@ -2089,7 +2119,7 @@ func (rs *Rows) initContextClose(ctx context.Context) {
|
||||
// awaitDone blocks until the rows are closed or the context canceled.
|
||||
func (rs *Rows) awaitDone(ctx context.Context) {
|
||||
<-ctx.Done()
|
||||
rs.Close()
|
||||
rs.close(ctx.Err())
|
||||
}
|
||||
|
||||
// Next prepares the next result row for reading with the Scan method. It
|
||||
@@ -2099,8 +2129,19 @@ func (rs *Rows) awaitDone(ctx context.Context) {
|
||||
//
|
||||
// Every call to Scan, even the first one, must be preceded by a call to Next.
|
||||
func (rs *Rows) Next() bool {
|
||||
if rs.isClosed() {
|
||||
return false
|
||||
var doClose, ok bool
|
||||
withLock(rs.closemu.RLocker(), func() {
|
||||
doClose, ok = rs.nextLocked()
|
||||
})
|
||||
if doClose {
|
||||
rs.Close()
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
func (rs *Rows) nextLocked() (doClose, ok bool) {
|
||||
if rs.closed {
|
||||
return false, false
|
||||
}
|
||||
if rs.lastcols == nil {
|
||||
rs.lastcols = make([]driver.Value, len(rs.rowsi.Columns()))
|
||||
@@ -2109,23 +2150,21 @@ func (rs *Rows) Next() bool {
|
||||
if rs.lasterr != nil {
|
||||
// Close the connection if there is a driver error.
|
||||
if rs.lasterr != io.EOF {
|
||||
rs.Close()
|
||||
return false
|
||||
return true, false
|
||||
}
|
||||
nextResultSet, ok := rs.rowsi.(driver.RowsNextResultSet)
|
||||
if !ok {
|
||||
rs.Close()
|
||||
return false
|
||||
return true, false
|
||||
}
|
||||
// The driver is at the end of the current result set.
|
||||
// Test to see if there is another result set after the current one.
|
||||
// Only close Rows if there is no further result sets to read.
|
||||
if !nextResultSet.HasNextResultSet() {
|
||||
rs.Close()
|
||||
doClose = true
|
||||
}
|
||||
return false
|
||||
return doClose, false
|
||||
}
|
||||
return true
|
||||
return false, true
|
||||
}
|
||||
|
||||
// NextResultSet prepares the next result set for reading. It returns true if
|
||||
@@ -2137,18 +2176,28 @@ func (rs *Rows) Next() bool {
|
||||
// scanning. If there are further result sets they may not have rows in the result
|
||||
// set.
|
||||
func (rs *Rows) NextResultSet() bool {
|
||||
if rs.isClosed() {
|
||||
var doClose bool
|
||||
defer func() {
|
||||
if doClose {
|
||||
rs.Close()
|
||||
}
|
||||
}()
|
||||
rs.closemu.RLock()
|
||||
defer rs.closemu.RUnlock()
|
||||
|
||||
if rs.closed {
|
||||
return false
|
||||
}
|
||||
|
||||
rs.lastcols = nil
|
||||
nextResultSet, ok := rs.rowsi.(driver.RowsNextResultSet)
|
||||
if !ok {
|
||||
rs.Close()
|
||||
doClose = true
|
||||
return false
|
||||
}
|
||||
rs.lasterr = nextResultSet.NextResultSet()
|
||||
if rs.lasterr != nil {
|
||||
rs.Close()
|
||||
doClose = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -2157,6 +2206,8 @@ func (rs *Rows) NextResultSet() bool {
|
||||
// Err returns the error, if any, that was encountered during iteration.
|
||||
// Err may be called after an explicit or implicit Close.
|
||||
func (rs *Rows) Err() error {
|
||||
rs.closemu.RLock()
|
||||
defer rs.closemu.RUnlock()
|
||||
if rs.lasterr == io.EOF {
|
||||
return nil
|
||||
}
|
||||
@@ -2167,7 +2218,9 @@ func (rs *Rows) Err() error {
|
||||
// Columns returns an error if the rows are closed, or if the rows
|
||||
// are from QueryRow and there was a deferred error.
|
||||
func (rs *Rows) Columns() ([]string, error) {
|
||||
if rs.isClosed() {
|
||||
rs.closemu.RLock()
|
||||
defer rs.closemu.RUnlock()
|
||||
if rs.closed {
|
||||
return nil, errors.New("sql: Rows are closed")
|
||||
}
|
||||
if rs.rowsi == nil {
|
||||
@@ -2179,7 +2232,9 @@ func (rs *Rows) Columns() ([]string, error) {
|
||||
// ColumnTypes returns column information such as column type, length,
|
||||
// and nullable. Some information may not be available from some drivers.
|
||||
func (rs *Rows) ColumnTypes() ([]*ColumnType, error) {
|
||||
if rs.isClosed() {
|
||||
rs.closemu.RLock()
|
||||
defer rs.closemu.RUnlock()
|
||||
if rs.closed {
|
||||
return nil, errors.New("sql: Rows are closed")
|
||||
}
|
||||
if rs.rowsi == nil {
|
||||
@@ -2329,9 +2384,13 @@ func rowsColumnInfoSetup(rowsi driver.Rows) []*ColumnType {
|
||||
// For scanning into *bool, the source may be true, false, 1, 0, or
|
||||
// string inputs parseable by strconv.ParseBool.
|
||||
func (rs *Rows) Scan(dest ...interface{}) error {
|
||||
if rs.isClosed() {
|
||||
rs.closemu.RLock()
|
||||
if rs.closed {
|
||||
rs.closemu.RUnlock()
|
||||
return errors.New("sql: Rows are closed")
|
||||
}
|
||||
rs.closemu.RUnlock()
|
||||
|
||||
if rs.lastcols == nil {
|
||||
return errors.New("sql: Scan called without calling Next")
|
||||
}
|
||||
@@ -2351,20 +2410,28 @@ func (rs *Rows) Scan(dest ...interface{}) error {
|
||||
// hook throug a test only mutex.
|
||||
var rowsCloseHook = func() func(*Rows, *error) { return nil }
|
||||
|
||||
func (rs *Rows) isClosed() bool {
|
||||
return atomic.LoadInt32(&rs.closed) != 0
|
||||
}
|
||||
|
||||
// Close closes the Rows, preventing further enumeration. If Next is called
|
||||
// and returns false and there are no further result sets,
|
||||
// the Rows are closed automatically and it will suffice to check the
|
||||
// result of Err. Close is idempotent and does not affect the result of Err.
|
||||
func (rs *Rows) Close() error {
|
||||
if !atomic.CompareAndSwapInt32(&rs.closed, 0, 1) {
|
||||
return rs.close(nil)
|
||||
}
|
||||
|
||||
func (rs *Rows) close(err error) error {
|
||||
rs.closemu.Lock()
|
||||
defer rs.closemu.Unlock()
|
||||
|
||||
if rs.closed {
|
||||
return nil
|
||||
}
|
||||
rs.closed = true
|
||||
|
||||
err := rs.rowsi.Close()
|
||||
if rs.lasterr == nil {
|
||||
rs.lasterr = err
|
||||
}
|
||||
|
||||
err = rs.rowsi.Close()
|
||||
if fn := rowsCloseHook(); fn != nil {
|
||||
fn(rs, &err)
|
||||
}
|
||||
|
||||
@@ -153,8 +153,13 @@ func closeDB(t testing.TB, db *DB) {
|
||||
if err != nil {
|
||||
t.Fatalf("error closing DB: %v", err)
|
||||
}
|
||||
if count := db.numOpenConns(); count != 0 {
|
||||
t.Fatalf("%d connections still open after closing DB", count)
|
||||
|
||||
var numOpen int
|
||||
if !waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
|
||||
numOpen = db.numOpenConns()
|
||||
return numOpen == 0
|
||||
}) {
|
||||
t.Fatalf("%d connections still open after closing DB", numOpen)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,6 +281,7 @@ func TestQuery(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestQueryContext tests canceling the context while scanning the rows.
|
||||
func TestQueryContext(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
@@ -297,7 +303,7 @@ func TestQueryContext(t *testing.T) {
|
||||
for rows.Next() {
|
||||
if index == 2 {
|
||||
cancel()
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
waitForRowsClose(t, rows, 5*time.Second)
|
||||
}
|
||||
var r row
|
||||
err = rows.Scan(&r.age, &r.name)
|
||||
@@ -313,9 +319,13 @@ func TestQueryContext(t *testing.T) {
|
||||
got = append(got, r)
|
||||
index++
|
||||
}
|
||||
err = rows.Err()
|
||||
if err != nil {
|
||||
t.Fatalf("Err: %v", err)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
if err := ctx.Err(); err != context.Canceled {
|
||||
t.Fatalf("context err = %v; want context.Canceled")
|
||||
}
|
||||
default:
|
||||
t.Fatalf("context err = nil; want context.Canceled")
|
||||
}
|
||||
want := []row{
|
||||
{age: 1, name: "Alice"},
|
||||
@@ -327,6 +337,7 @@ func TestQueryContext(t *testing.T) {
|
||||
|
||||
// And verify that the final rows.Next() call, which hit EOF,
|
||||
// also closed the rows connection.
|
||||
waitForRowsClose(t, rows, 5*time.Second)
|
||||
waitForFree(t, db, 5*time.Second, 1)
|
||||
if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
|
||||
t.Errorf("executed %d Prepare statements; want 1", prepares)
|
||||
@@ -356,12 +367,27 @@ func waitForFree(t *testing.T, db *DB, maxWait time.Duration, want int) {
|
||||
}
|
||||
}
|
||||
|
||||
func waitForRowsClose(t *testing.T, rows *Rows, maxWait time.Duration) {
|
||||
if !waitCondition(maxWait, 5*time.Millisecond, func() bool {
|
||||
rows.closemu.RLock()
|
||||
defer rows.closemu.RUnlock()
|
||||
return rows.closed
|
||||
}) {
|
||||
t.Fatal("failed to close rows")
|
||||
}
|
||||
}
|
||||
|
||||
// TestQueryContextWait ensures that rows and all internal statements are closed when
|
||||
// a query context is closed during execution.
|
||||
func TestQueryContextWait(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
prepares0 := numPrepares(t, db)
|
||||
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Millisecond*15)
|
||||
// TODO(kardianos): convert this from using a timeout to using an explicit
|
||||
// cancel when the query signals that is is "executing" the query.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond)
|
||||
defer cancel()
|
||||
|
||||
// This will trigger the *fakeConn.Prepare method which will take time
|
||||
// performing the query. The ctxDriverPrepare func will check the context
|
||||
@@ -374,10 +400,15 @@ func TestQueryContextWait(t *testing.T) {
|
||||
// Verify closed rows connection after error condition.
|
||||
waitForFree(t, db, 5*time.Second, 1)
|
||||
if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
|
||||
t.Errorf("executed %d Prepare statements; want 1", prepares)
|
||||
// TODO(kardianos): if the context timeouts before the db.QueryContext
|
||||
// executes this check may fail. After adjusting how the context
|
||||
// is canceled above revert this back to a Fatal error.
|
||||
t.Logf("executed %d Prepare statements; want 1", prepares)
|
||||
}
|
||||
}
|
||||
|
||||
// TestTxContextWait tests the transaction behavior when the tx context is canceled
|
||||
// during execution of the query.
|
||||
func TestTxContextWait(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
@@ -386,6 +417,10 @@ func TestTxContextWait(t *testing.T) {
|
||||
|
||||
tx, err := db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
// Guard against the context being canceled before BeginTx completes.
|
||||
if err == context.DeadlineExceeded {
|
||||
t.Skip("tx context canceled prior to first use")
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -398,12 +433,6 @@ func TestTxContextWait(t *testing.T) {
|
||||
}
|
||||
|
||||
waitForFree(t, db, 5*time.Second, 0)
|
||||
|
||||
// Ensure the dropped connection allows more connections to be made.
|
||||
// Checked on DB Close.
|
||||
waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
|
||||
return db.numOpenConns() == 0
|
||||
})
|
||||
}
|
||||
|
||||
func TestMultiResultSetQuery(t *testing.T) {
|
||||
@@ -527,6 +556,63 @@ func TestQueryNamedArg(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPoolExhaustOnCancel(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("long test")
|
||||
}
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
||||
max := 3
|
||||
|
||||
db.SetMaxOpenConns(max)
|
||||
|
||||
// First saturate the connection pool.
|
||||
// Then start new requests for a connection that is cancelled after it is requested.
|
||||
|
||||
var saturate, saturateDone sync.WaitGroup
|
||||
saturate.Add(max)
|
||||
saturateDone.Add(max)
|
||||
|
||||
for i := 0; i < max; i++ {
|
||||
go func() {
|
||||
saturate.Done()
|
||||
rows, err := db.Query("WAIT|500ms|SELECT|people|name,photo|")
|
||||
if err != nil {
|
||||
t.Fatalf("Query: %v", err)
|
||||
}
|
||||
rows.Close()
|
||||
saturateDone.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
saturate.Wait()
|
||||
|
||||
// Now cancel the request while it is waiting.
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
|
||||
defer cancel()
|
||||
|
||||
for i := 0; i < max; i++ {
|
||||
ctxReq, cancelReq := context.WithCancel(ctx)
|
||||
go func() {
|
||||
time.Sleep(time.Millisecond * 100)
|
||||
cancelReq()
|
||||
}()
|
||||
err := db.PingContext(ctxReq)
|
||||
if err != context.Canceled {
|
||||
t.Fatalf("PingContext (Exhaust): %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
saturateDone.Wait()
|
||||
|
||||
// Now try to open a normal connection.
|
||||
err := db.PingContext(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("PingContext (Normal): %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestByteOwnership(t *testing.T) {
|
||||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
@@ -2677,7 +2763,6 @@ func TestIssue18429(t *testing.T) {
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
time.Sleep(milliWait * 3 * time.Millisecond)
|
||||
}
|
||||
|
||||
// TestIssue18719 closes the context right before use. The sql.driverConn
|
||||
@@ -2720,14 +2805,8 @@ func TestIssue18719(t *testing.T) {
|
||||
// Do not explicitly rollback. The rollback will happen from the
|
||||
// canceled context.
|
||||
|
||||
// Wait for connections to return to pool.
|
||||
var numOpen int
|
||||
if !waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
|
||||
numOpen = db.numOpenConns()
|
||||
return numOpen == 0
|
||||
}) {
|
||||
t.Fatalf("open conns after hitting EOF = %d; want 0", numOpen)
|
||||
}
|
||||
cancel()
|
||||
waitForRowsClose(t, rows, 5*time.Second)
|
||||
}
|
||||
|
||||
func TestConcurrency(t *testing.T) {
|
||||
|
||||
@@ -775,6 +775,20 @@ func (p *printer) marshalSimple(typ reflect.Type, val reflect.Value) (string, []
|
||||
|
||||
var ddBytes = []byte("--")
|
||||
|
||||
// indirect drills into interfaces and pointers, returning the pointed-at value.
|
||||
// If it encounters a nil interface or pointer, indirect returns that nil value.
|
||||
// This can turn into an infinite loop given a cyclic chain,
|
||||
// but it matches the Go 1 behavior.
|
||||
func indirect(vf reflect.Value) reflect.Value {
|
||||
for vf.Kind() == reflect.Interface || vf.Kind() == reflect.Ptr {
|
||||
if vf.IsNil() {
|
||||
return vf
|
||||
}
|
||||
vf = vf.Elem()
|
||||
}
|
||||
return vf
|
||||
}
|
||||
|
||||
func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
|
||||
s := parentStack{p: p}
|
||||
for i := range tinfo.fields {
|
||||
@@ -816,17 +830,9 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
|
||||
continue
|
||||
}
|
||||
}
|
||||
// Drill into interfaces and pointers.
|
||||
// This can turn into an infinite loop given a cyclic chain,
|
||||
// but it matches the Go 1 behavior.
|
||||
for vf.Kind() == reflect.Interface || vf.Kind() == reflect.Ptr {
|
||||
if vf.IsNil() {
|
||||
return nil
|
||||
}
|
||||
vf = vf.Elem()
|
||||
}
|
||||
|
||||
var scratch [64]byte
|
||||
vf = indirect(vf)
|
||||
switch vf.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if err := emit(p, strconv.AppendInt(scratch[:0], vf.Int(), 10)); err != nil {
|
||||
@@ -861,6 +867,7 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
|
||||
if err := s.trim(finfo.parents); err != nil {
|
||||
return err
|
||||
}
|
||||
vf = indirect(vf)
|
||||
k := vf.Kind()
|
||||
if !(k == reflect.String || k == reflect.Slice && vf.Type().Elem().Kind() == reflect.Uint8) {
|
||||
return fmt.Errorf("xml: bad type for comment field of %s", val.Type())
|
||||
@@ -901,6 +908,7 @@ func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
|
||||
continue
|
||||
|
||||
case fInnerXml:
|
||||
vf = indirect(vf)
|
||||
iface := vf.Interface()
|
||||
switch raw := iface.(type) {
|
||||
case []byte:
|
||||
|
||||
@@ -386,6 +386,140 @@ func ifaceptr(x interface{}) interface{} {
|
||||
return &x
|
||||
}
|
||||
|
||||
func stringptr(x string) *string {
|
||||
return &x
|
||||
}
|
||||
|
||||
type T1 struct{}
|
||||
type T2 struct{}
|
||||
type T3 struct{}
|
||||
|
||||
type IndirComment struct {
|
||||
T1 T1
|
||||
Comment *string `xml:",comment"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type DirectComment struct {
|
||||
T1 T1
|
||||
Comment string `xml:",comment"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IfaceComment struct {
|
||||
T1 T1
|
||||
Comment interface{} `xml:",comment"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IndirChardata struct {
|
||||
T1 T1
|
||||
Chardata *string `xml:",chardata"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type DirectChardata struct {
|
||||
T1 T1
|
||||
Chardata string `xml:",chardata"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IfaceChardata struct {
|
||||
T1 T1
|
||||
Chardata interface{} `xml:",chardata"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IndirCDATA struct {
|
||||
T1 T1
|
||||
CDATA *string `xml:",cdata"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type DirectCDATA struct {
|
||||
T1 T1
|
||||
CDATA string `xml:",cdata"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IfaceCDATA struct {
|
||||
T1 T1
|
||||
CDATA interface{} `xml:",cdata"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IndirInnerXML struct {
|
||||
T1 T1
|
||||
InnerXML *string `xml:",innerxml"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type DirectInnerXML struct {
|
||||
T1 T1
|
||||
InnerXML string `xml:",innerxml"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IfaceInnerXML struct {
|
||||
T1 T1
|
||||
InnerXML interface{} `xml:",innerxml"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IndirElement struct {
|
||||
T1 T1
|
||||
Element *string
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type DirectElement struct {
|
||||
T1 T1
|
||||
Element string
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IfaceElement struct {
|
||||
T1 T1
|
||||
Element interface{}
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IndirOmitEmpty struct {
|
||||
T1 T1
|
||||
OmitEmpty *string `xml:",omitempty"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type DirectOmitEmpty struct {
|
||||
T1 T1
|
||||
OmitEmpty string `xml:",omitempty"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IfaceOmitEmpty struct {
|
||||
T1 T1
|
||||
OmitEmpty interface{} `xml:",omitempty"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IndirAny struct {
|
||||
T1 T1
|
||||
Any *string `xml:",any"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type DirectAny struct {
|
||||
T1 T1
|
||||
Any string `xml:",any"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
type IfaceAny struct {
|
||||
T1 T1
|
||||
Any interface{} `xml:",any"`
|
||||
T2 T2
|
||||
}
|
||||
|
||||
var (
|
||||
nameAttr = "Sarah"
|
||||
ageAttr = uint(12)
|
||||
@@ -398,10 +532,12 @@ var (
|
||||
// please try to make them two-way as well to ensure that
|
||||
// marshaling and unmarshaling are as symmetrical as feasible.
|
||||
var marshalTests = []struct {
|
||||
Value interface{}
|
||||
ExpectXML string
|
||||
MarshalOnly bool
|
||||
UnmarshalOnly bool
|
||||
Value interface{}
|
||||
ExpectXML string
|
||||
MarshalOnly bool
|
||||
MarshalError string
|
||||
UnmarshalOnly bool
|
||||
UnmarshalError string
|
||||
}{
|
||||
// Test nil marshals to nothing
|
||||
{Value: nil, ExpectXML: ``, MarshalOnly: true},
|
||||
@@ -1133,6 +1269,382 @@ var marshalTests = []struct {
|
||||
ExpectXML: `<NestedAndCData><A><B></B><B></B></A><![CDATA[test]]></NestedAndCData>`,
|
||||
Value: &NestedAndCData{AB: make([]string, 2), CDATA: "test"},
|
||||
},
|
||||
// Test pointer indirection in various kinds of fields.
|
||||
// https://golang.org/issue/19063
|
||||
{
|
||||
ExpectXML: `<IndirComment><T1></T1><!--hi--><T2></T2></IndirComment>`,
|
||||
Value: &IndirComment{Comment: stringptr("hi")},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirComment><T1></T1><T2></T2></IndirComment>`,
|
||||
Value: &IndirComment{Comment: stringptr("")},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirComment><T1></T1><T2></T2></IndirComment>`,
|
||||
Value: &IndirComment{Comment: nil},
|
||||
MarshalError: "xml: bad type for comment field of xml.IndirComment",
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirComment><T1></T1><!--hi--><T2></T2></IndirComment>`,
|
||||
Value: &IndirComment{Comment: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceComment><T1></T1><!--hi--><T2></T2></IfaceComment>`,
|
||||
Value: &IfaceComment{Comment: "hi"},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceComment><T1></T1><!--hi--><T2></T2></IfaceComment>`,
|
||||
Value: &IfaceComment{Comment: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceComment><T1></T1><T2></T2></IfaceComment>`,
|
||||
Value: &IfaceComment{Comment: nil},
|
||||
MarshalError: "xml: bad type for comment field of xml.IfaceComment",
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceComment><T1></T1><T2></T2></IfaceComment>`,
|
||||
Value: &IfaceComment{Comment: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectComment><T1></T1><!--hi--><T2></T2></DirectComment>`,
|
||||
Value: &DirectComment{Comment: string("hi")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectComment><T1></T1><T2></T2></DirectComment>`,
|
||||
Value: &DirectComment{Comment: string("")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirChardata><T1></T1>hi<T2></T2></IndirChardata>`,
|
||||
Value: &IndirChardata{Chardata: stringptr("hi")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirChardata><T1></T1><![CDATA[hi]]><T2></T2></IndirChardata>`,
|
||||
Value: &IndirChardata{Chardata: stringptr("hi")},
|
||||
UnmarshalOnly: true, // marshals without CDATA
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirChardata><T1></T1><T2></T2></IndirChardata>`,
|
||||
Value: &IndirChardata{Chardata: stringptr("")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirChardata><T1></T1><T2></T2></IndirChardata>`,
|
||||
Value: &IndirChardata{Chardata: nil},
|
||||
MarshalOnly: true, // unmarshal leaves Chardata=stringptr("")
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceChardata><T1></T1>hi<T2></T2></IfaceChardata>`,
|
||||
Value: &IfaceChardata{Chardata: string("hi")},
|
||||
UnmarshalError: "cannot unmarshal into interface {}",
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceChardata><T1></T1><![CDATA[hi]]><T2></T2></IfaceChardata>`,
|
||||
Value: &IfaceChardata{Chardata: string("hi")},
|
||||
UnmarshalOnly: true, // marshals without CDATA
|
||||
UnmarshalError: "cannot unmarshal into interface {}",
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceChardata><T1></T1><T2></T2></IfaceChardata>`,
|
||||
Value: &IfaceChardata{Chardata: string("")},
|
||||
UnmarshalError: "cannot unmarshal into interface {}",
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceChardata><T1></T1><T2></T2></IfaceChardata>`,
|
||||
Value: &IfaceChardata{Chardata: nil},
|
||||
UnmarshalError: "cannot unmarshal into interface {}",
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectChardata><T1></T1>hi<T2></T2></DirectChardata>`,
|
||||
Value: &DirectChardata{Chardata: string("hi")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectChardata><T1></T1><![CDATA[hi]]><T2></T2></DirectChardata>`,
|
||||
Value: &DirectChardata{Chardata: string("hi")},
|
||||
UnmarshalOnly: true, // marshals without CDATA
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectChardata><T1></T1><T2></T2></DirectChardata>`,
|
||||
Value: &DirectChardata{Chardata: string("")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirCDATA><T1></T1><![CDATA[hi]]><T2></T2></IndirCDATA>`,
|
||||
Value: &IndirCDATA{CDATA: stringptr("hi")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirCDATA><T1></T1>hi<T2></T2></IndirCDATA>`,
|
||||
Value: &IndirCDATA{CDATA: stringptr("hi")},
|
||||
UnmarshalOnly: true, // marshals with CDATA
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirCDATA><T1></T1><T2></T2></IndirCDATA>`,
|
||||
Value: &IndirCDATA{CDATA: stringptr("")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirCDATA><T1></T1><T2></T2></IndirCDATA>`,
|
||||
Value: &IndirCDATA{CDATA: nil},
|
||||
MarshalOnly: true, // unmarshal leaves CDATA=stringptr("")
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceCDATA><T1></T1><![CDATA[hi]]><T2></T2></IfaceCDATA>`,
|
||||
Value: &IfaceCDATA{CDATA: string("hi")},
|
||||
UnmarshalError: "cannot unmarshal into interface {}",
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceCDATA><T1></T1>hi<T2></T2></IfaceCDATA>`,
|
||||
Value: &IfaceCDATA{CDATA: string("hi")},
|
||||
UnmarshalOnly: true, // marshals with CDATA
|
||||
UnmarshalError: "cannot unmarshal into interface {}",
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceCDATA><T1></T1><T2></T2></IfaceCDATA>`,
|
||||
Value: &IfaceCDATA{CDATA: string("")},
|
||||
UnmarshalError: "cannot unmarshal into interface {}",
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceCDATA><T1></T1><T2></T2></IfaceCDATA>`,
|
||||
Value: &IfaceCDATA{CDATA: nil},
|
||||
UnmarshalError: "cannot unmarshal into interface {}",
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectCDATA><T1></T1><![CDATA[hi]]><T2></T2></DirectCDATA>`,
|
||||
Value: &DirectCDATA{CDATA: string("hi")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectCDATA><T1></T1>hi<T2></T2></DirectCDATA>`,
|
||||
Value: &DirectCDATA{CDATA: string("hi")},
|
||||
UnmarshalOnly: true, // marshals with CDATA
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectCDATA><T1></T1><T2></T2></DirectCDATA>`,
|
||||
Value: &DirectCDATA{CDATA: string("")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirInnerXML><T1></T1><hi/><T2></T2></IndirInnerXML>`,
|
||||
Value: &IndirInnerXML{InnerXML: stringptr("<hi/>")},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirInnerXML><T1></T1><T2></T2></IndirInnerXML>`,
|
||||
Value: &IndirInnerXML{InnerXML: stringptr("")},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirInnerXML><T1></T1><T2></T2></IndirInnerXML>`,
|
||||
Value: &IndirInnerXML{InnerXML: nil},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirInnerXML><T1></T1><hi/><T2></T2></IndirInnerXML>`,
|
||||
Value: &IndirInnerXML{InnerXML: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceInnerXML><T1></T1><hi/><T2></T2></IfaceInnerXML>`,
|
||||
Value: &IfaceInnerXML{InnerXML: "<hi/>"},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceInnerXML><T1></T1><hi/><T2></T2></IfaceInnerXML>`,
|
||||
Value: &IfaceInnerXML{InnerXML: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceInnerXML><T1></T1><T2></T2></IfaceInnerXML>`,
|
||||
Value: &IfaceInnerXML{InnerXML: nil},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceInnerXML><T1></T1><T2></T2></IfaceInnerXML>`,
|
||||
Value: &IfaceInnerXML{InnerXML: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectInnerXML><T1></T1><hi/><T2></T2></DirectInnerXML>`,
|
||||
Value: &DirectInnerXML{InnerXML: string("<hi/>")},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectInnerXML><T1></T1><hi/><T2></T2></DirectInnerXML>`,
|
||||
Value: &DirectInnerXML{InnerXML: string("<T1></T1><hi/><T2></T2>")},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectInnerXML><T1></T1><T2></T2></DirectInnerXML>`,
|
||||
Value: &DirectInnerXML{InnerXML: string("")},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectInnerXML><T1></T1><T2></T2></DirectInnerXML>`,
|
||||
Value: &DirectInnerXML{InnerXML: string("<T1></T1><T2></T2>")},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirElement><T1></T1><Element>hi</Element><T2></T2></IndirElement>`,
|
||||
Value: &IndirElement{Element: stringptr("hi")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirElement><T1></T1><Element></Element><T2></T2></IndirElement>`,
|
||||
Value: &IndirElement{Element: stringptr("")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirElement><T1></T1><T2></T2></IndirElement>`,
|
||||
Value: &IndirElement{Element: nil},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceElement><T1></T1><Element>hi</Element><T2></T2></IfaceElement>`,
|
||||
Value: &IfaceElement{Element: "hi"},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceElement><T1></T1><Element>hi</Element><T2></T2></IfaceElement>`,
|
||||
Value: &IfaceElement{Element: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceElement><T1></T1><T2></T2></IfaceElement>`,
|
||||
Value: &IfaceElement{Element: nil},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceElement><T1></T1><T2></T2></IfaceElement>`,
|
||||
Value: &IfaceElement{Element: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectElement><T1></T1><Element>hi</Element><T2></T2></DirectElement>`,
|
||||
Value: &DirectElement{Element: string("hi")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectElement><T1></T1><Element></Element><T2></T2></DirectElement>`,
|
||||
Value: &DirectElement{Element: string("")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IndirOmitEmpty>`,
|
||||
Value: &IndirOmitEmpty{OmitEmpty: stringptr("hi")},
|
||||
},
|
||||
{
|
||||
// Note: Changed in Go 1.8 to include <OmitEmpty> element (because x.OmitEmpty != nil).
|
||||
ExpectXML: `<IndirOmitEmpty><T1></T1><OmitEmpty></OmitEmpty><T2></T2></IndirOmitEmpty>`,
|
||||
Value: &IndirOmitEmpty{OmitEmpty: stringptr("")},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirOmitEmpty><T1></T1><OmitEmpty></OmitEmpty><T2></T2></IndirOmitEmpty>`,
|
||||
Value: &IndirOmitEmpty{OmitEmpty: stringptr("")},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirOmitEmpty><T1></T1><T2></T2></IndirOmitEmpty>`,
|
||||
Value: &IndirOmitEmpty{OmitEmpty: nil},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IfaceOmitEmpty>`,
|
||||
Value: &IfaceOmitEmpty{OmitEmpty: "hi"},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IfaceOmitEmpty>`,
|
||||
Value: &IfaceOmitEmpty{OmitEmpty: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceOmitEmpty><T1></T1><T2></T2></IfaceOmitEmpty>`,
|
||||
Value: &IfaceOmitEmpty{OmitEmpty: nil},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceOmitEmpty><T1></T1><T2></T2></IfaceOmitEmpty>`,
|
||||
Value: &IfaceOmitEmpty{OmitEmpty: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></DirectOmitEmpty>`,
|
||||
Value: &DirectOmitEmpty{OmitEmpty: string("hi")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectOmitEmpty><T1></T1><T2></T2></DirectOmitEmpty>`,
|
||||
Value: &DirectOmitEmpty{OmitEmpty: string("")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirAny><T1></T1><Any>hi</Any><T2></T2></IndirAny>`,
|
||||
Value: &IndirAny{Any: stringptr("hi")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirAny><T1></T1><Any></Any><T2></T2></IndirAny>`,
|
||||
Value: &IndirAny{Any: stringptr("")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirAny><T1></T1><T2></T2></IndirAny>`,
|
||||
Value: &IndirAny{Any: nil},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceAny><T1></T1><Any>hi</Any><T2></T2></IfaceAny>`,
|
||||
Value: &IfaceAny{Any: "hi"},
|
||||
MarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceAny><T1></T1><Any>hi</Any><T2></T2></IfaceAny>`,
|
||||
Value: &IfaceAny{Any: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceAny><T1></T1><T2></T2></IfaceAny>`,
|
||||
Value: &IfaceAny{Any: nil},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceAny><T1></T1><T2></T2></IfaceAny>`,
|
||||
Value: &IfaceAny{Any: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectAny><T1></T1><Any>hi</Any><T2></T2></DirectAny>`,
|
||||
Value: &DirectAny{Any: string("hi")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectAny><T1></T1><Any></Any><T2></T2></DirectAny>`,
|
||||
Value: &DirectAny{Any: string("")},
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirFoo><T1></T1><Foo>hi</Foo><T2></T2></IndirFoo>`,
|
||||
Value: &IndirAny{Any: stringptr("hi")},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirFoo><T1></T1><Foo></Foo><T2></T2></IndirFoo>`,
|
||||
Value: &IndirAny{Any: stringptr("")},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IndirFoo><T1></T1><T2></T2></IndirFoo>`,
|
||||
Value: &IndirAny{Any: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceFoo><T1></T1><Foo>hi</Foo><T2></T2></IfaceFoo>`,
|
||||
Value: &IfaceAny{Any: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceFoo><T1></T1><T2></T2></IfaceFoo>`,
|
||||
Value: &IfaceAny{Any: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<IfaceFoo><T1></T1><T2></T2></IfaceFoo>`,
|
||||
Value: &IfaceAny{Any: nil},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectFoo><T1></T1><Foo>hi</Foo><T2></T2></DirectFoo>`,
|
||||
Value: &DirectAny{Any: string("hi")},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
{
|
||||
ExpectXML: `<DirectFoo><T1></T1><Foo></Foo><T2></T2></DirectFoo>`,
|
||||
Value: &DirectAny{Any: string("")},
|
||||
UnmarshalOnly: true,
|
||||
},
|
||||
}
|
||||
|
||||
func TestMarshal(t *testing.T) {
|
||||
@@ -1142,7 +1654,17 @@ func TestMarshal(t *testing.T) {
|
||||
}
|
||||
data, err := Marshal(test.Value)
|
||||
if err != nil {
|
||||
t.Errorf("#%d: marshal(%#v): %s", idx, test.Value, err)
|
||||
if test.MarshalError == "" {
|
||||
t.Errorf("#%d: marshal(%#v): %s", idx, test.Value, err)
|
||||
continue
|
||||
}
|
||||
if !strings.Contains(err.Error(), test.MarshalError) {
|
||||
t.Errorf("#%d: marshal(%#v): %s, want %q", idx, test.Value, err, test.MarshalError)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if test.MarshalError != "" {
|
||||
t.Errorf("#%d: Marshal succeeded, want error %q", idx, test.MarshalError)
|
||||
continue
|
||||
}
|
||||
if got, want := string(data), test.ExpectXML; got != want {
|
||||
@@ -1268,8 +1790,16 @@ func TestUnmarshal(t *testing.T) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("#%d: unexpected error: %#v", i, err)
|
||||
} else if got, want := dest, test.Value; !reflect.DeepEqual(got, want) {
|
||||
if test.UnmarshalError == "" {
|
||||
t.Errorf("#%d: unmarshal(%#v): %s", i, test.ExpectXML, err)
|
||||
continue
|
||||
}
|
||||
if !strings.Contains(err.Error(), test.UnmarshalError) {
|
||||
t.Errorf("#%d: unmarshal(%#v): %s, want %q", i, test.ExpectXML, err, test.UnmarshalError)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if got, want := dest, test.Value; !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("#%d: unmarshal(%q):\nhave %#v\nwant %#v", i, test.ExpectXML, got, want)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ func defaultGOPATH() string {
|
||||
}
|
||||
if home := os.Getenv(env); home != "" {
|
||||
def := filepath.Join(home, "go")
|
||||
if def == runtime.GOROOT() {
|
||||
if filepath.Clean(def) == filepath.Clean(runtime.GOROOT()) {
|
||||
// Don't set the default GOPATH to GOROOT,
|
||||
// as that will trigger warnings from the go tool.
|
||||
return ""
|
||||
|
||||
@@ -2478,17 +2478,24 @@ func TestNumMethodOnDDD(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPtrTo(t *testing.T) {
|
||||
// This block of code means that the ptrToThis field of the
|
||||
// reflect data for *unsafe.Pointer is non zero, see
|
||||
// https://golang.org/issue/19003
|
||||
var x unsafe.Pointer
|
||||
var y = &x
|
||||
var z = &y
|
||||
|
||||
var i int
|
||||
|
||||
typ := TypeOf(i)
|
||||
typ := TypeOf(z)
|
||||
for i = 0; i < 100; i++ {
|
||||
typ = PtrTo(typ)
|
||||
}
|
||||
for i = 0; i < 100; i++ {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
if typ != TypeOf(i) {
|
||||
t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, TypeOf(i))
|
||||
if typ != TypeOf(z) {
|
||||
t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, TypeOf(z))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1469,6 +1469,7 @@ func (t *rtype) ptrTo() *rtype {
|
||||
pp := *prototype
|
||||
|
||||
pp.str = resolveReflectName(newName(s, "", "", false))
|
||||
pp.ptrToThis = 0
|
||||
|
||||
// For the type structures linked into the binary, the
|
||||
// compiler provides a good hash of the string.
|
||||
|
||||
@@ -628,10 +628,12 @@ func (c *gcControllerState) endCycle() {
|
||||
//go:nowritebarrier
|
||||
func (c *gcControllerState) enlistWorker() {
|
||||
// If there are idle Ps, wake one so it will run an idle worker.
|
||||
if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 {
|
||||
wakep()
|
||||
return
|
||||
}
|
||||
// NOTE: This is suspected of causing deadlocks. See golang.org/issue/19112.
|
||||
//
|
||||
// if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 {
|
||||
// wakep()
|
||||
// return
|
||||
// }
|
||||
|
||||
// There are no idle Ps. If we need more dedicated workers,
|
||||
// try to preempt a running P so it will switch to a worker.
|
||||
|
||||
@@ -821,6 +821,7 @@ func (m *M) Run() int {
|
||||
haveExamples = len(m.examples) > 0
|
||||
testRan, testOk := runTests(m.deps.MatchString, m.tests)
|
||||
exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples)
|
||||
stopAlarm()
|
||||
if !testRan && !exampleRan && *matchBenchmarks == "" {
|
||||
fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
|
||||
}
|
||||
|
||||
8
src/vendor/golang_org/x/crypto/curve25519/const_amd64.h
vendored
Normal file
8
src/vendor/golang_org/x/crypto/curve25519/const_amd64.h
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This code was translated into a form compatible with 6a from the public
|
||||
// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
|
||||
|
||||
#define REDMASK51 0x0007FFFFFFFFFFFF
|
||||
@@ -7,8 +7,8 @@
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
|
||||
GLOBL ·REDMASK51(SB), 8, $8
|
||||
// These constants cannot be encoded in non-MOVQ immediates.
|
||||
// We access them directly from memory instead.
|
||||
|
||||
DATA ·_121666_213(SB)/8, $996687872
|
||||
GLOBL ·_121666_213(SB), 8, $8
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func freeze(inout *[5]uint64)
|
||||
TEXT ·freeze(SB),7,$0-8
|
||||
MOVQ inout+0(FP), DI
|
||||
@@ -16,7 +18,7 @@ TEXT ·freeze(SB),7,$0-8
|
||||
MOVQ 16(DI),CX
|
||||
MOVQ 24(DI),R8
|
||||
MOVQ 32(DI),R9
|
||||
MOVQ ·REDMASK51(SB),AX
|
||||
MOVQ $REDMASK51,AX
|
||||
MOVQ AX,R10
|
||||
SUBQ $18,R10
|
||||
MOVQ $3,R11
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func ladderstep(inout *[5][5]uint64)
|
||||
TEXT ·ladderstep(SB),0,$296-8
|
||||
MOVQ inout+0(FP),DI
|
||||
@@ -118,7 +120,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 72(SP)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@@ -233,7 +235,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 32(SP)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@@ -438,7 +440,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 72(SP)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@@ -588,7 +590,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 32(SP)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@@ -728,7 +730,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 152(DI)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@@ -843,7 +845,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 192(DI)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@@ -993,7 +995,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 32(DI)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@@ -1143,7 +1145,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 112(SP)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
@@ -1329,7 +1331,7 @@ TEXT ·ladderstep(SB),0,$296-8
|
||||
MULQ 192(SP)
|
||||
ADDQ AX,R12
|
||||
ADCQ DX,R13
|
||||
MOVQ ·REDMASK51(SB),DX
|
||||
MOVQ $REDMASK51,DX
|
||||
SHLQ $13,CX:SI
|
||||
ANDQ DX,SI
|
||||
SHLQ $13,R9:R8
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func mul(dest, a, b *[5]uint64)
|
||||
TEXT ·mul(SB),0,$16-24
|
||||
MOVQ dest+0(FP), DI
|
||||
@@ -121,7 +123,7 @@ TEXT ·mul(SB),0,$16-24
|
||||
MULQ 32(CX)
|
||||
ADDQ AX,R14
|
||||
ADCQ DX,R15
|
||||
MOVQ ·REDMASK51(SB),SI
|
||||
MOVQ $REDMASK51,SI
|
||||
SHLQ $13,R9:R8
|
||||
ANDQ SI,R8
|
||||
SHLQ $13,R11:R10
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
// +build amd64,!gccgo,!appengine
|
||||
|
||||
#include "const_amd64.h"
|
||||
|
||||
// func square(out, in *[5]uint64)
|
||||
TEXT ·square(SB),7,$0-16
|
||||
MOVQ out+0(FP), DI
|
||||
@@ -84,7 +86,7 @@ TEXT ·square(SB),7,$0-16
|
||||
MULQ 32(SI)
|
||||
ADDQ AX,R13
|
||||
ADCQ DX,R14
|
||||
MOVQ ·REDMASK51(SB),SI
|
||||
MOVQ $REDMASK51,SI
|
||||
SHLQ $13,R8:CX
|
||||
ANDQ SI,CX
|
||||
SHLQ $13,R10:R9
|
||||
|
||||
36
test/fixedbugs/issue18906.go
Normal file
36
test/fixedbugs/issue18906.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// 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
|
||||
|
||||
//go:noinline
|
||||
func f(x int) {
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func val() int8 {
|
||||
return -1
|
||||
}
|
||||
|
||||
var (
|
||||
array = [257]int{}
|
||||
slice = array[1:]
|
||||
)
|
||||
|
||||
func init() {
|
||||
for i := range array {
|
||||
array[i] = i - 1
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
x := val()
|
||||
y := int(uint8(x))
|
||||
f(y) // try and force y to be calculated and spilled
|
||||
if slice[y] != 255 {
|
||||
panic("incorrect value")
|
||||
}
|
||||
}
|
||||
21
test/fixedbugs/issue18915.go
Normal file
21
test/fixedbugs/issue18915.go
Normal file
@@ -0,0 +1,21 @@
|
||||
// errorcheck
|
||||
|
||||
// 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 error message for invalid conditions
|
||||
// or tags are consistent with earlier Go versions.
|
||||
|
||||
package p
|
||||
|
||||
func _() {
|
||||
if a := 10 { // ERROR "a := 10 used as value"
|
||||
}
|
||||
|
||||
for b := 10 { // ERROR "b := 10 used as value"
|
||||
}
|
||||
|
||||
switch c := 10 { // ERROR "c := 10 used as value"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// +build amd64
|
||||
// +build !386,!arm,!mips,!mipsle,!amd64p32
|
||||
// compile
|
||||
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
|
||||
@@ -220,3 +220,19 @@ func f22(x *int) (y *int) {
|
||||
*p = x // no barrier
|
||||
return
|
||||
}
|
||||
|
||||
type T23 struct {
|
||||
p *int
|
||||
a int
|
||||
}
|
||||
|
||||
var t23 T23
|
||||
var i23 int
|
||||
|
||||
func f23() {
|
||||
// zeroing global needs write barrier for the hybrid barrier.
|
||||
t23 = T23{} // ERROR "write barrier"
|
||||
// also test partial assignments
|
||||
t23 = T23{a: 1} // ERROR "write barrier"
|
||||
t23 = T23{p: &i23} // ERROR "write barrier"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user