mirror of
https://github.com/golang/go.git
synced 2026-01-29 15:12:08 +03:00
Compare commits
28 Commits
dev.typeal
...
go1.8.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96c72e9468 | ||
|
|
89e6a4d6d0 | ||
|
|
a5a3be1636 | ||
|
|
45a42c9be5 | ||
|
|
6c733cd93b | ||
|
|
d4ccbd8833 | ||
|
|
79be6cb389 | ||
|
|
b838f943ab | ||
|
|
3be9637d56 | ||
|
|
2eac89d5c8 | ||
|
|
142d449081 | ||
|
|
533ee44cd4 | ||
|
|
8093678ae1 | ||
|
|
0bf8909ff8 | ||
|
|
b3b1e12b13 | ||
|
|
1ab2a4e85f | ||
|
|
25be91ae4f | ||
|
|
82cfda2910 | ||
|
|
9ccc2921dd | ||
|
|
ead964dc80 | ||
|
|
7e9658fea9 | ||
|
|
7e2cd1d81e | ||
|
|
f5bcb9b8fe | ||
|
|
4be3fc33ef | ||
|
|
a4544a0f8a | ||
|
|
9d1d78c34c | ||
|
|
d45b26b1b7 | ||
|
|
f3e6216450 |
@@ -63,6 +63,30 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.3">Go
|
||||
1.8.3 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.8.4 (released 2017/10/04) includes two security fixes.
|
||||
It contains the same fixes as Go 1.9.1 and was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.4">Go
|
||||
1.8.4 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.8.5 (released 2017/10/25) includes fixes to the compiler, linker, runtime,
|
||||
documentation, <code>go</code> command,
|
||||
and the <code>crypto/x509</code> and <code>net/smtp</code> packages.
|
||||
It includes a fix to a bug introduced in Go 1.8.4 that broke <code>go</code> <code>get</code>
|
||||
of non-Git repositories under certain conditions.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.5">Go
|
||||
1.8.5 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
go1.8.6 (released 2018/01/22) includes the the same fix in <code>math/big</code>
|
||||
as Go 1.9.3 and was released at the same time.
|
||||
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.6">Go
|
||||
1.8.6 milestone</a> on our issue tracker for details.
|
||||
</p>
|
||||
|
||||
<h2 id="go1.7">go1.7 (released 2016/08/15)</h2>
|
||||
|
||||
<p>
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
This file lists things yet to be moved into go1.8.html or deemed too
|
||||
minor to mention. Either way, delete from here when done.
|
||||
|
||||
Tools:
|
||||
|
||||
go: -buildmode=c-archive now builds PIC on ELF (CL 24180)
|
||||
go: mobile pkg dir change, recommend using go list in scripts (CL 24930, CL 27929)
|
||||
go, dist: can set default pkg-config tool using PKG_CONFIG env var (CL 29991)
|
||||
go: can set secure/insecure GIT schemes using GIT_ALLOW_PROTOCOL env var (CL 30135)
|
||||
|
||||
API additions and behavior changes:
|
||||
|
||||
cmd/compile, runtime, etc: get rid of constant FP registers (CL 28095)
|
||||
cmd/compile, runtime: add go:yeswritebarrierrec pragma (CL 30938)
|
||||
cmd/compile/internal/gc: enable new parser by default (CL 27203)
|
||||
cmd/compile/internal/syntax: fast Go syntax trees, initial commit (CL 27195)
|
||||
cmd/compile: add compiler phase timing (CL 24462)
|
||||
cmd/compile: add inline explainer (CL 22782)
|
||||
cmd/compile: enable flag-specified dump of specific phase+function (CL 23044)
|
||||
|
||||
cmd/internal/obj, cmd/link: darwin dynlink support (CL 29393)
|
||||
cmd/internal/objfile: add ppc64/ppc64le disassembler support (CL 9682)
|
||||
cmd/link, cmd/go: delay linking of mingwex and mingw32 until very end (CL 26670)
|
||||
cmd/link: R_ADDR dynamic relocs for internal PIE (CL 29118)
|
||||
cmd/link: add trampolines for too far calls in ppc64x (CL 30850)
|
||||
cmd/link: allow internal PIE linking (CL 28543)
|
||||
cmd/link: fix -X importpath.name=value when import path needs escaping (CL 31970)
|
||||
cmd/link: fix -buildmode=pie / -linkshared combination (CL 28996)
|
||||
cmd/link: for -buildmode=exe pass -no-pie to external linker (CL 33106)
|
||||
cmd/link: insert trampolines for too-far jumps on ARM (CL 29397)
|
||||
cmd/link: non-executable stack support for Solaris (CL 24142)
|
||||
cmd/link: put text at address 0x1000000 on darwin/amd64 (CL 32185)
|
||||
cmd/link: remove the -shared flag (CL 28852)
|
||||
cmd/link: split large elf text sections on ppc64x (CL 27790)
|
||||
cmd/link: trampoline support for external linking on ARM (CL 31143)
|
||||
cmd/objdump: implement objdump of .o files (CL 24818)
|
||||
|
||||
go/build: allow % in ${SRCDIR} expansion for Jenkins (CL 31611)
|
||||
go/build: do not record go:binary-only-package if build tags not satisfied (CL 31577)
|
||||
go/build: implement default GOPATH (CL 32019)
|
||||
|
||||
runtime/race: update race runtime (CL 32160)
|
||||
runtime: assume 64kB physical pages on ARM (CL 25021)
|
||||
runtime: disable stack rescanning by default (CL 31766)
|
||||
runtime: don't call cgocallback from signal handler (CL 30218)
|
||||
runtime: fix check for vacuous page boundary rounding (CL 27230)
|
||||
runtime: fix map iterator concurrent map check (CL 24749)
|
||||
runtime: fix newextram PC passed to race detector (CL 29712)
|
||||
runtime: implement unconditional hybrid barrier (CL 31765)
|
||||
runtime: include pre-panic/throw logs in core dumps (CL 32013)
|
||||
runtime: limit the number of map overflow buckets (CL 25049)
|
||||
runtime: pass windows float syscall args via XMM (CL 32173)
|
||||
runtime: print sigcode on signal crash (CL 32183)
|
||||
runtime: record current PC for SIGPROF on non-Go thread (CL 30252)
|
||||
runtime: sleep on CLOCK_MONOTONIC in futexsleep1 on freebsd (CL 30154)
|
||||
@@ -143,7 +143,7 @@ packaged Go distribution.
|
||||
<p>
|
||||
To build a bootstrap tool chain from source, use
|
||||
either the git branch <code>release-branch.go1.4</code> or
|
||||
<a href="https://storage.googleapis.com/golang/go1.4-bootstrap-20161024.tar.gz">go1.4-bootstrap-20161024.tar.gz</a>,
|
||||
<a href="https://storage.googleapis.com/golang/go1.4-bootstrap-20170531.tar.gz">go1.4-bootstrap-20170531.tar.gz</a>,
|
||||
which contains the Go 1.4 source code plus accumulated fixes
|
||||
to keep the tools running on newer operating systems.
|
||||
(Go 1.4 was the last distribution in which the tool chain was written in C.)
|
||||
|
||||
144
doc/root.html
144
doc/root.html
@@ -6,7 +6,9 @@
|
||||
<div class="left">
|
||||
|
||||
<div id="learn">
|
||||
{{if not $.GoogleCN}}
|
||||
<a class="popout share">Pop-out</a>
|
||||
{{end}}
|
||||
<div class="rootHeading">Try Go</div>
|
||||
<div class="input">
|
||||
<textarea spellcheck="false" class="code">// You can edit this code!
|
||||
@@ -26,10 +28,10 @@ Hello, 世界
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<a class="run" href="#" title="Run this code [shift-enter]">Run</a>
|
||||
{{if $.Share}}
|
||||
{{if not $.GoogleCN}}
|
||||
<a class="share" href="#" title="Share this code">Share</a>
|
||||
{{end}}
|
||||
<a class="tour" href="//tour.golang.org/" title="Learn Go from your browser">Tour</a>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="toys">
|
||||
<select>
|
||||
@@ -68,85 +70,91 @@ Linux, Mac OS X, Windows, and more.
|
||||
|
||||
<div style="clear: both"></div>
|
||||
|
||||
{{if not $.GoogleCN}}
|
||||
<div class="left">
|
||||
|
||||
<div id="video">
|
||||
<div class="rootHeading">Featured video</div>
|
||||
<iframe width="415" height="241" src="//www.youtube.com/embed/ytEkHepK08c" frameborder="0" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
<div id="video">
|
||||
<div class="rootHeading">Featured video</div>
|
||||
<iframe width="415" height="241" src="//www.youtube.com/embed/ytEkHepK08c" frameborder="0" allowfullscreen></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
|
||||
<div id="blog">
|
||||
<div class="rootHeading">Featured articles</div>
|
||||
<div class="read"><a href="//blog.golang.org/">Read more</a></div>
|
||||
</div>
|
||||
|
||||
<div id="blog">
|
||||
<div class="rootHeading">Featured articles</div>
|
||||
<div class="read"><a href="//blog.golang.org/">Read more</a></div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<div style="clear: both;"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function readableTime(t) {
|
||||
var m = ["January", "February", "March", "April", "May", "June", "July",
|
||||
"August", "September", "October", "November", "December"];
|
||||
var p = t.substring(0, t.indexOf("T")).split("-");
|
||||
var d = new Date(p[0], p[1]-1, p[2]);
|
||||
return d.getDate() + " " + m[d.getMonth()] + " " + d.getFullYear();
|
||||
}
|
||||
window.initFuncs.push(function() {
|
||||
// Set up playground if enabled.
|
||||
if (window.playground) {
|
||||
window.playground({
|
||||
"codeEl": "#learn .code",
|
||||
"outputEl": "#learn .output",
|
||||
"runEl": "#learn .run",
|
||||
"shareEl": "#learn .share",
|
||||
"shareRedirect": "//play.golang.org/p/",
|
||||
"toysEl": "#learn .toys select"
|
||||
});
|
||||
} else {
|
||||
$('#learn').hide()
|
||||
}
|
||||
});
|
||||
|
||||
function feedLoaded(result) {
|
||||
var blog = document.getElementById("blog");
|
||||
var read = blog.getElementsByClassName("read")[0];
|
||||
for (var i = 0; i < result.length && i < 2; i++) {
|
||||
var entry = result[i];
|
||||
var title = document.createElement("a");
|
||||
title.className = "title";
|
||||
title.href = entry.Link;
|
||||
title.innerHTML = entry.Title;
|
||||
blog.insertBefore(title, read);
|
||||
var extract = document.createElement("div");
|
||||
extract.className = "extract";
|
||||
extract.innerHTML = entry.Summary;
|
||||
blog.insertBefore(extract, read);
|
||||
var when = document.createElement("div");
|
||||
when.className = "when";
|
||||
when.innerHTML = "Published " + readableTime(entry.Time);
|
||||
blog.insertBefore(when, read);
|
||||
}
|
||||
}
|
||||
{{if not $.GoogleCN}}
|
||||
|
||||
window.initFuncs.push(function() {
|
||||
// Set up playground if enabled.
|
||||
if (window.playground) {
|
||||
window.playground({
|
||||
"codeEl": "#learn .code",
|
||||
"outputEl": "#learn .output",
|
||||
"runEl": "#learn .run",
|
||||
"shareEl": "#learn .share",
|
||||
"shareRedirect": "//play.golang.org/p/",
|
||||
"toysEl": "#learn .toys select"
|
||||
});
|
||||
} else {
|
||||
$('#learn').hide()
|
||||
function readableTime(t) {
|
||||
var m = ["January", "February", "March", "April", "May", "June", "July",
|
||||
"August", "September", "October", "November", "December"];
|
||||
var p = t.substring(0, t.indexOf("T")).split("-");
|
||||
var d = new Date(p[0], p[1]-1, p[2]);
|
||||
return d.getDate() + " " + m[d.getMonth()] + " " + d.getFullYear();
|
||||
}
|
||||
|
||||
// Load blog feed.
|
||||
$('<script/>').attr('text', 'text/javascript')
|
||||
.attr('src', '//blog.golang.org/.json?jsonp=feedLoaded')
|
||||
.appendTo('body');
|
||||
window.feedLoaded = function(result) {
|
||||
var blog = document.getElementById("blog");
|
||||
var read = blog.getElementsByClassName("read")[0];
|
||||
for (var i = 0; i < result.length && i < 2; i++) {
|
||||
var entry = result[i];
|
||||
var title = document.createElement("a");
|
||||
title.className = "title";
|
||||
title.href = entry.Link;
|
||||
title.innerHTML = entry.Title;
|
||||
blog.insertBefore(title, read);
|
||||
var extract = document.createElement("div");
|
||||
extract.className = "extract";
|
||||
extract.innerHTML = entry.Summary;
|
||||
blog.insertBefore(extract, read);
|
||||
var when = document.createElement("div");
|
||||
when.className = "when";
|
||||
when.innerHTML = "Published " + readableTime(entry.Time);
|
||||
blog.insertBefore(when, read);
|
||||
}
|
||||
}
|
||||
|
||||
// Set the video at random.
|
||||
var videos = [
|
||||
{h: 241, s: "//www.youtube.com/embed/ytEkHepK08c"}, // Tour of Go
|
||||
{h: 241, s: "//www.youtube.com/embed/f6kdp27TYZs"}, // Concurrency Patterns
|
||||
{h: 233, s: "//player.vimeo.com/video/69237265"} // Simple environment
|
||||
];
|
||||
var v = videos[Math.floor(Math.random()*videos.length)];
|
||||
$('#video iframe').attr('height', v.h).attr('src', v.s);
|
||||
});
|
||||
window.initFuncs.push(function() {
|
||||
// Load blog feed.
|
||||
$('<script/>').attr('text', 'text/javascript')
|
||||
.attr('src', '//blog.golang.org/.json?jsonp=feedLoaded')
|
||||
.appendTo('body');
|
||||
|
||||
// Set the video at random.
|
||||
var videos = [
|
||||
{h: 241, s: "//www.youtube.com/embed/ytEkHepK08c"}, // Tour of Go
|
||||
{h: 241, s: "//www.youtube.com/embed/f6kdp27TYZs"}, // Concurrency Patterns
|
||||
{h: 233, s: "//player.vimeo.com/video/69237265"} // Simple environment
|
||||
];
|
||||
var v = videos[Math.floor(Math.random()*videos.length)];
|
||||
$('#video iframe').attr('height', v.h).attr('src', v.s);
|
||||
});
|
||||
|
||||
{{end}}
|
||||
})();
|
||||
</script>
|
||||
|
||||
108
src/cmd/compile/internal/gc/testdata/loadstore.go
vendored
108
src/cmd/compile/internal/gc/testdata/loadstore.go
vendored
@@ -102,12 +102,120 @@ func testDeadStorePanic() {
|
||||
}
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func loadHitStore8(x int8, p *int8) int32 {
|
||||
x *= x // try to trash high bits (arch-dependent)
|
||||
*p = x // store
|
||||
return int32(*p) // load and cast
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func loadHitStoreU8(x uint8, p *uint8) uint32 {
|
||||
x *= x // try to trash high bits (arch-dependent)
|
||||
*p = x // store
|
||||
return uint32(*p) // load and cast
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func loadHitStore16(x int16, p *int16) int32 {
|
||||
x *= x // try to trash high bits (arch-dependent)
|
||||
*p = x // store
|
||||
return int32(*p) // load and cast
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func loadHitStoreU16(x uint16, p *uint16) uint32 {
|
||||
x *= x // try to trash high bits (arch-dependent)
|
||||
*p = x // store
|
||||
return uint32(*p) // load and cast
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func loadHitStore32(x int32, p *int32) int64 {
|
||||
x *= x // try to trash high bits (arch-dependent)
|
||||
*p = x // store
|
||||
return int64(*p) // load and cast
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func loadHitStoreU32(x uint32, p *uint32) uint64 {
|
||||
x *= x // try to trash high bits (arch-dependent)
|
||||
*p = x // store
|
||||
return uint64(*p) // load and cast
|
||||
}
|
||||
|
||||
func testLoadHitStore() {
|
||||
// Test that sign/zero extensions are kept when a load-hit-store
|
||||
// is replaced by a register-register move.
|
||||
{
|
||||
var in int8 = (1 << 6) + 1
|
||||
var p int8
|
||||
got := loadHitStore8(in, &p)
|
||||
want := int32(in * in)
|
||||
if got != want {
|
||||
fmt.Println("testLoadHitStore (int8) failed. want =", want, ", got =", got)
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
{
|
||||
var in uint8 = (1 << 6) + 1
|
||||
var p uint8
|
||||
got := loadHitStoreU8(in, &p)
|
||||
want := uint32(in * in)
|
||||
if got != want {
|
||||
fmt.Println("testLoadHitStore (uint8) failed. want =", want, ", got =", got)
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
{
|
||||
var in int16 = (1 << 10) + 1
|
||||
var p int16
|
||||
got := loadHitStore16(in, &p)
|
||||
want := int32(in * in)
|
||||
if got != want {
|
||||
fmt.Println("testLoadHitStore (int16) failed. want =", want, ", got =", got)
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
{
|
||||
var in uint16 = (1 << 10) + 1
|
||||
var p uint16
|
||||
got := loadHitStoreU16(in, &p)
|
||||
want := uint32(in * in)
|
||||
if got != want {
|
||||
fmt.Println("testLoadHitStore (uint16) failed. want =", want, ", got =", got)
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
{
|
||||
var in int32 = (1 << 30) + 1
|
||||
var p int32
|
||||
got := loadHitStore32(in, &p)
|
||||
want := int64(in * in)
|
||||
if got != want {
|
||||
fmt.Println("testLoadHitStore (int32) failed. want =", want, ", got =", got)
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
{
|
||||
var in uint32 = (1 << 30) + 1
|
||||
var p uint32
|
||||
got := loadHitStoreU32(in, &p)
|
||||
want := uint64(in * in)
|
||||
if got != want {
|
||||
fmt.Println("testLoadHitStore (uint32) failed. want =", want, ", got =", got)
|
||||
failed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
testLoadStoreOrder()
|
||||
testStoreSize()
|
||||
testExtStore()
|
||||
testDeadStorePanic()
|
||||
testLoadHitStore()
|
||||
|
||||
if failed {
|
||||
panic("failed")
|
||||
|
||||
@@ -620,10 +620,12 @@
|
||||
(MOVWLZX x:(MOVWloadidx1 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx1 <v.Type> [off] {sym} ptr idx mem)
|
||||
(MOVWLZX x:(MOVWloadidx2 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWloadidx2 <v.Type> [off] {sym} ptr idx mem)
|
||||
|
||||
// replace load from same location as preceding store with copy
|
||||
(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
// replace load from same location as preceding store with zero/sign extension (or copy in case of full width)
|
||||
(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBLZX x)
|
||||
(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWLZX x)
|
||||
(MOVLload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVBLSXload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBLSX x)
|
||||
(MOVWLSXload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWLSX x)
|
||||
|
||||
// Fold extensions and ANDs together.
|
||||
(MOVBLZX (ANDLconst [c] x)) -> (ANDLconst [c & 0xff] x)
|
||||
|
||||
@@ -762,11 +762,14 @@
|
||||
(MOVLQZX x:(MOVLloadidx1 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVLloadidx1 <v.Type> [off] {sym} ptr idx mem)
|
||||
(MOVLQZX x:(MOVLloadidx4 [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVLloadidx4 <v.Type> [off] {sym} ptr idx mem)
|
||||
|
||||
// replace load from same location as preceding store with copy
|
||||
(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVLload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
// replace load from same location as preceding store with zero/sign extension (or copy in case of full width)
|
||||
(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBQZX x)
|
||||
(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWQZX x)
|
||||
(MOVLload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVLQZX x)
|
||||
(MOVQload [off] {sym} ptr (MOVQstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVBQSXload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBQSX x)
|
||||
(MOVWQSXload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWQSX x)
|
||||
(MOVLQSXload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVLQSX x)
|
||||
|
||||
// Fold extensions and ANDs together.
|
||||
(MOVBQZX (ANDLconst [c] x)) -> (ANDLconst [c & 0xff] x)
|
||||
|
||||
@@ -467,12 +467,13 @@
|
||||
(MOVDstore [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
|
||||
(MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
|
||||
|
||||
// replace load from same location as preceding store with copy
|
||||
(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && isSigned(x.Type) -> x
|
||||
(MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && !isSigned(x.Type) -> x
|
||||
(MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && isSigned(x.Type) -> x
|
||||
(MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && !isSigned(x.Type) -> x
|
||||
// replace load from same location as preceding store with zero/sign extension (or copy in case of full width)
|
||||
(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBreg x)
|
||||
(MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBUreg x)
|
||||
(MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHreg x)
|
||||
(MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHUreg x)
|
||||
(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
|
||||
(MOVFload [off] {sym} ptr (MOVFstore [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
|
||||
|
||||
|
||||
@@ -679,14 +679,14 @@
|
||||
(MOVWstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVWstorezero [off] {sym} ptr mem)
|
||||
(MOVDstore [off] {sym} ptr (MOVDconst [0]) mem) -> (MOVDstorezero [off] {sym} ptr mem)
|
||||
|
||||
// replace load from same location as preceding store with copy
|
||||
// replace load from same location as preceding store with zero/sign extension (or copy in case of full width)
|
||||
// these seem to have bad interaction with other rules, resulting in slower code
|
||||
//(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
//(MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
//(MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
//(MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
//(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
//(MOVWUload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
//(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBreg x)
|
||||
//(MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBUreg x)
|
||||
//(MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHreg x)
|
||||
//(MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHUreg x)
|
||||
//(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWreg x)
|
||||
//(MOVWUload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWUreg x)
|
||||
//(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
//(FMOVSload [off] {sym} ptr (FMOVSstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
//(FMOVDload [off] {sym} ptr (FMOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
|
||||
@@ -522,11 +522,11 @@
|
||||
(MOVWstorezero [off1] {sym1} (MOVWaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
|
||||
(MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
|
||||
|
||||
// replace load from same location as preceding store with copy
|
||||
(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && isSigned(x.Type) -> x
|
||||
(MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && !isSigned(x.Type) -> x
|
||||
(MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && isSigned(x.Type) -> x
|
||||
(MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && !isSigned(x.Type) -> x
|
||||
// replace load from same location as preceding store with zero/sign extension (or copy in case of full width)
|
||||
(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBreg x)
|
||||
(MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBUreg x)
|
||||
(MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHreg x)
|
||||
(MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHUreg x)
|
||||
(MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
|
||||
(MOVFload [off] {sym} ptr (MOVFstore [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
|
||||
|
||||
@@ -656,9 +656,9 @@
|
||||
(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) -> (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)
|
||||
(MOVBZload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVBZreg x)
|
||||
(MOVHZload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVHZreg x)
|
||||
(MOVWZload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVWZreg x)
|
||||
(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDreg x)
|
||||
|
||||
// Don't extend before storing
|
||||
|
||||
@@ -2503,6 +2503,28 @@ func rewriteValue386_Op386MOVBLSX(v *Value, config *Config) bool {
|
||||
func rewriteValue386_Op386MOVBLSXload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVBLSXload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVBLSX x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
ptr := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != Op386MOVBstore {
|
||||
break
|
||||
}
|
||||
off2 := v_1.AuxInt
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386MOVBLSX)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBLSXload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
|
||||
// cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
|
||||
// result: (MOVBLSXload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||
@@ -2606,7 +2628,7 @@ func rewriteValue386_Op386MOVBload(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: x
|
||||
// result: (MOVBLZX x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -2622,8 +2644,7 @@ func rewriteValue386_Op386MOVBload(v *Value, config *Config) bool {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(Op386MOVBLZX)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -5248,6 +5269,28 @@ func rewriteValue386_Op386MOVWLSX(v *Value, config *Config) bool {
|
||||
func rewriteValue386_Op386MOVWLSXload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVWLSXload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVWLSX x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
ptr := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != Op386MOVWstore {
|
||||
break
|
||||
}
|
||||
off2 := v_1.AuxInt
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386MOVWLSX)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWLSXload [off1] {sym1} (LEAL [off2] {sym2} base) mem)
|
||||
// cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2) && (base.Op != OpSB || !config.ctxt.Flag_shared)
|
||||
// result: (MOVWLSXload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||
@@ -5378,7 +5421,7 @@ func rewriteValue386_Op386MOVWload(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: x
|
||||
// result: (MOVWLZX x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5394,8 +5437,7 @@ func rewriteValue386_Op386MOVWload(v *Value, config *Config) bool {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(Op386MOVWLZX)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -3361,6 +3361,28 @@ func rewriteValueAMD64_OpAMD64MOVBQSX(v *Value, config *Config) bool {
|
||||
func rewriteValueAMD64_OpAMD64MOVBQSXload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVBQSXload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVBQSX x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
ptr := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAMD64MOVBstore {
|
||||
break
|
||||
}
|
||||
off2 := v_1.AuxInt
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAMD64MOVBQSX)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVBQSXload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
|
||||
// cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
|
||||
// result: (MOVBQSXload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||
@@ -3539,7 +3561,7 @@ func rewriteValueAMD64_OpAMD64MOVBload(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: x
|
||||
// result: (MOVBQZX x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -3555,8 +3577,7 @@ func rewriteValueAMD64_OpAMD64MOVBload(v *Value, config *Config) bool {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpAMD64MOVBQZX)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -4834,6 +4855,28 @@ func rewriteValueAMD64_OpAMD64MOVLQSX(v *Value, config *Config) bool {
|
||||
func rewriteValueAMD64_OpAMD64MOVLQSXload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVLQSXload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVLQSX x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
ptr := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAMD64MOVLstore {
|
||||
break
|
||||
}
|
||||
off2 := v_1.AuxInt
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAMD64MOVLQSX)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVLQSXload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
|
||||
// cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
|
||||
// result: (MOVLQSXload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||
@@ -5041,7 +5084,7 @@ func rewriteValueAMD64_OpAMD64MOVLload(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVLload [off] {sym} ptr (MOVLstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: x
|
||||
// result: (MOVLQZX x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5057,8 +5100,7 @@ func rewriteValueAMD64_OpAMD64MOVLload(v *Value, config *Config) bool {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpAMD64MOVLQZX)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -8703,6 +8745,28 @@ func rewriteValueAMD64_OpAMD64MOVWQSX(v *Value, config *Config) bool {
|
||||
func rewriteValueAMD64_OpAMD64MOVWQSXload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVWQSXload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVWQSX x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
ptr := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpAMD64MOVWstore {
|
||||
break
|
||||
}
|
||||
off2 := v_1.AuxInt
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpAMD64MOVWQSX)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
// match: (MOVWQSXload [off1] {sym1} (LEAQ [off2] {sym2} base) mem)
|
||||
// cond: is32Bit(off1+off2) && canMergeSym(sym1, sym2)
|
||||
// result: (MOVWQSXload [off1+off2] {mergeSym(sym1,sym2)} base mem)
|
||||
@@ -8883,7 +8947,7 @@ func rewriteValueAMD64_OpAMD64MOVWload(v *Value, config *Config) bool {
|
||||
_ = b
|
||||
// match: (MOVWload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: x
|
||||
// result: (MOVWQZX x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -8899,8 +8963,7 @@ func rewriteValueAMD64_OpAMD64MOVWload(v *Value, config *Config) bool {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpAMD64MOVWQZX)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -5188,8 +5188,8 @@ func rewriteValueARM_OpARMMOVBUload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && !isSigned(x.Type)
|
||||
// result: x
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVBUreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5202,11 +5202,10 @@ func rewriteValueARM_OpARMMOVBUload(v *Value, config *Config) bool {
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && !isSigned(x.Type)) {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpARMMOVBUreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -5317,8 +5316,8 @@ func rewriteValueARM_OpARMMOVBload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && isSigned(x.Type)
|
||||
// result: x
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVBreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5331,11 +5330,10 @@ func rewriteValueARM_OpARMMOVBload(v *Value, config *Config) bool {
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && isSigned(x.Type)) {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpARMMOVBreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -5836,8 +5834,8 @@ func rewriteValueARM_OpARMMOVHUload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && !isSigned(x.Type)
|
||||
// result: x
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVHUreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -5850,11 +5848,10 @@ func rewriteValueARM_OpARMMOVHUload(v *Value, config *Config) bool {
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && !isSigned(x.Type)) {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpARMMOVHUreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -5989,8 +5986,8 @@ func rewriteValueARM_OpARMMOVHload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && isSigned(x.Type)
|
||||
// result: x
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVHreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -6003,11 +6000,10 @@ func rewriteValueARM_OpARMMOVHload(v *Value, config *Config) bool {
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && isSigned(x.Type)) {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpARMMOVHreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -3332,8 +3332,8 @@ func rewriteValueMIPS_OpMIPSMOVBUload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVBUload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && !isSigned(x.Type)
|
||||
// result: x
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVBUreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -3346,11 +3346,10 @@ func rewriteValueMIPS_OpMIPSMOVBUload(v *Value, config *Config) bool {
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && !isSigned(x.Type)) {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpMIPSMOVBUreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -3490,8 +3489,8 @@ func rewriteValueMIPS_OpMIPSMOVBload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && isSigned(x.Type)
|
||||
// result: x
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVBreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -3504,11 +3503,10 @@ func rewriteValueMIPS_OpMIPSMOVBload(v *Value, config *Config) bool {
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && isSigned(x.Type)) {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpMIPSMOVBreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -4148,8 +4146,8 @@ func rewriteValueMIPS_OpMIPSMOVHUload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVHUload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && !isSigned(x.Type)
|
||||
// result: x
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVHUreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -4162,11 +4160,10 @@ func rewriteValueMIPS_OpMIPSMOVHUload(v *Value, config *Config) bool {
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && !isSigned(x.Type)) {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpMIPSMOVHUreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -4330,8 +4327,8 @@ func rewriteValueMIPS_OpMIPSMOVHload(v *Value, config *Config) bool {
|
||||
return true
|
||||
}
|
||||
// match: (MOVHload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _))
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && isSigned(x.Type)
|
||||
// result: x
|
||||
// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
|
||||
// result: (MOVHreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -4344,11 +4341,10 @@ func rewriteValueMIPS_OpMIPSMOVHload(v *Value, config *Config) bool {
|
||||
sym2 := v_1.Aux
|
||||
ptr2 := v_1.Args[0]
|
||||
x := v_1.Args[1]
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) && isSigned(x.Type)) {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpCopy)
|
||||
v.Type = x.Type
|
||||
v.reset(OpMIPSMOVHreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -7851,7 +7851,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: (MOVDreg x)
|
||||
// result: (MOVBZreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -7867,7 +7867,7 @@ func rewriteValueS390X_OpS390XMOVBZload(v *Value, config *Config) bool {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.reset(OpS390XMOVBZreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -11021,7 +11021,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: (MOVDreg x)
|
||||
// result: (MOVHZreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -11037,7 +11037,7 @@ func rewriteValueS390X_OpS390XMOVHZload(v *Value, config *Config) bool {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.reset(OpS390XMOVHZreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
@@ -12406,7 +12406,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: (MOVDreg x)
|
||||
// result: (MOVWZreg x)
|
||||
for {
|
||||
off := v.AuxInt
|
||||
sym := v.Aux
|
||||
@@ -12422,7 +12422,7 @@ func rewriteValueS390X_OpS390XMOVWZload(v *Value, config *Config) bool {
|
||||
if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
|
||||
break
|
||||
}
|
||||
v.reset(OpS390XMOVDreg)
|
||||
v.reset(OpS390XMOVWZreg)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -439,6 +439,11 @@ func downloadPackage(p *Package) error {
|
||||
p.build.PkgRoot = filepath.Join(list[0], "pkg")
|
||||
}
|
||||
root := filepath.Join(p.build.SrcRoot, filepath.FromSlash(rootPath))
|
||||
|
||||
if err := checkNestedVCS(vcs, root, p.build.SrcRoot); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If we've considered this repository already, don't do it again.
|
||||
if downloadRootCache[root] {
|
||||
return nil
|
||||
|
||||
@@ -1120,7 +1120,7 @@ func testMove(t *testing.T, vcs, url, base, config string) {
|
||||
tg.runFail("get", "-d", "-u", url)
|
||||
tg.grepStderr("is a custom import path for", "go get -d -u "+url+" failed for wrong reason")
|
||||
tg.runFail("get", "-d", "-f", "-u", url)
|
||||
tg.grepStderr("validating server certificate|not found", "go get -d -f -u "+url+" failed for wrong reason")
|
||||
tg.grepStderr("validating server certificate|[nN]ot [fF]ound", "go get -d -f -u "+url+" failed for wrong reason")
|
||||
}
|
||||
|
||||
func TestInternalPackageErrorsAreHandled(t *testing.T) {
|
||||
@@ -1141,10 +1141,9 @@ func TestMoveGit(t *testing.T) {
|
||||
testMove(t, "git", "rsc.io/pdf", "pdf", "rsc.io/pdf/.git/config")
|
||||
}
|
||||
|
||||
// TODO(rsc): Set up a test case on bitbucket for hg.
|
||||
// func TestMoveHG(t *testing.T) {
|
||||
// testMove(t, "hg", "rsc.io/x86/x86asm", "x86", "rsc.io/x86/.hg/hgrc")
|
||||
// }
|
||||
func TestMoveHG(t *testing.T) {
|
||||
testMove(t, "hg", "vcs-test.golang.org/go/custom-hg-hello", "custom-hg-hello", "vcs-test.golang.org/go/custom-hg-hello/.hg/hgrc")
|
||||
}
|
||||
|
||||
// TODO(rsc): Set up a test case on SourceForge (?) for svn.
|
||||
// func testMoveSVN(t *testing.T) {
|
||||
@@ -1273,6 +1272,25 @@ func TestGetGitDefaultBranch(t *testing.T) {
|
||||
tg.grepStdout(`\* another-branch`, "not on correct default branch")
|
||||
}
|
||||
|
||||
func TestAccidentalGitCheckout(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()
|
||||
tg.parallel()
|
||||
tg.tempDir("src")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
|
||||
tg.runFail("get", "-u", "vcs-test.golang.org/go/test1-svn-git")
|
||||
tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
|
||||
|
||||
tg.runFail("get", "-u", "vcs-test.golang.org/go/test2-svn-git/test2main")
|
||||
tg.grepStderr("src[\\\\/]vcs-test.* uses git, but parent .*src[\\\\/]vcs-test.* uses svn", "get did not fail for right reason")
|
||||
}
|
||||
|
||||
func TestErrorMessageForSyntaxErrorInTestGoFileSaysFAIL(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
@@ -2719,7 +2737,7 @@ func TestImportMain(t *testing.T) {
|
||||
func TestFoo(t *testing.T) {}
|
||||
`)
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.creatingTemp("x")
|
||||
tg.creatingTemp("x" + exeSuffix)
|
||||
tg.run("build", "x")
|
||||
tg.run("test", "x")
|
||||
|
||||
|
||||
@@ -497,11 +497,28 @@ func vcsFromDir(dir, srcRoot string) (vcs *vcsCmd, root string, err error) {
|
||||
return nil, "", fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
|
||||
}
|
||||
|
||||
var vcsRet *vcsCmd
|
||||
var rootRet string
|
||||
|
||||
origDir := dir
|
||||
for len(dir) > len(srcRoot) {
|
||||
for _, vcs := range vcsList {
|
||||
if _, err := os.Stat(filepath.Join(dir, "."+vcs.cmd)); err == nil {
|
||||
return vcs, filepath.ToSlash(dir[len(srcRoot)+1:]), nil
|
||||
root := filepath.ToSlash(dir[len(srcRoot)+1:])
|
||||
// Record first VCS we find, but keep looking,
|
||||
// to detect mistakes like one kind of VCS inside another.
|
||||
if vcsRet == nil {
|
||||
vcsRet = vcs
|
||||
rootRet = root
|
||||
continue
|
||||
}
|
||||
// Allow .git inside .git, which can arise due to submodules.
|
||||
if vcsRet == vcs && vcs.cmd == "git" {
|
||||
continue
|
||||
}
|
||||
// Otherwise, we have one VCS inside a different VCS.
|
||||
return nil, "", fmt.Errorf("directory %q uses %s, but parent %q uses %s",
|
||||
filepath.Join(srcRoot, rootRet), vcsRet.cmd, filepath.Join(srcRoot, root), vcs.cmd)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -514,9 +531,48 @@ func vcsFromDir(dir, srcRoot string) (vcs *vcsCmd, root string, err error) {
|
||||
dir = ndir
|
||||
}
|
||||
|
||||
if vcsRet != nil {
|
||||
return vcsRet, rootRet, nil
|
||||
}
|
||||
|
||||
return nil, "", fmt.Errorf("directory %q is not using a known version control system", origDir)
|
||||
}
|
||||
|
||||
// checkNestedVCS checks for an incorrectly-nested VCS-inside-VCS
|
||||
// situation for dir, checking parents up until srcRoot.
|
||||
func checkNestedVCS(vcs *vcsCmd, dir, srcRoot string) error {
|
||||
if len(dir) <= len(srcRoot) || dir[len(srcRoot)] != filepath.Separator {
|
||||
return fmt.Errorf("directory %q is outside source root %q", dir, srcRoot)
|
||||
}
|
||||
|
||||
otherDir := dir
|
||||
for len(otherDir) > len(srcRoot) {
|
||||
for _, otherVCS := range vcsList {
|
||||
if _, err := os.Stat(filepath.Join(otherDir, "."+otherVCS.cmd)); err == nil {
|
||||
// Allow expected vcs in original dir.
|
||||
if otherDir == dir && otherVCS == vcs {
|
||||
continue
|
||||
}
|
||||
// Allow .git inside .git, which can arise due to submodules.
|
||||
if otherVCS == vcs && vcs.cmd == "git" {
|
||||
continue
|
||||
}
|
||||
// Otherwise, we have one VCS inside a different VCS.
|
||||
return fmt.Errorf("directory %q uses %s, but parent %q uses %s", dir, vcs.cmd, otherDir, otherVCS.cmd)
|
||||
}
|
||||
}
|
||||
// Move to parent.
|
||||
newDir := filepath.Dir(otherDir)
|
||||
if len(newDir) >= len(otherDir) {
|
||||
// Shouldn't happen, but just in case, stop.
|
||||
break
|
||||
}
|
||||
otherDir = newDir
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// repoRoot represents a version control system, a repo, and a root of
|
||||
// where to put it on disk.
|
||||
type repoRoot struct {
|
||||
|
||||
@@ -322,15 +322,13 @@ func progedit(ctxt *obj.Link, p *obj.Prog) {
|
||||
|
||||
// Rewrite p, if necessary, to access global data via the global offset table.
|
||||
func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
|
||||
var add, lea, mov obj.As
|
||||
var lea, mov obj.As
|
||||
var reg int16
|
||||
if p.Mode == 64 {
|
||||
add = AADDQ
|
||||
lea = ALEAQ
|
||||
mov = AMOVQ
|
||||
reg = REG_R15
|
||||
} else {
|
||||
add = AADDL
|
||||
lea = ALEAL
|
||||
mov = AMOVL
|
||||
reg = REG_CX
|
||||
@@ -347,8 +345,10 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
|
||||
// ADUFFxxx $offset
|
||||
// becomes
|
||||
// $MOV runtime.duffxxx@GOT, $reg
|
||||
// $ADD $offset, $reg
|
||||
// $LEA $offset($reg), $reg
|
||||
// CALL $reg
|
||||
// (we use LEAx rather than ADDx because ADDx clobbers
|
||||
// flags and duffzero on 386 does not otherwise do so)
|
||||
var sym *obj.LSym
|
||||
if p.As == obj.ADUFFZERO {
|
||||
sym = obj.Linklookup(ctxt, "runtime.duffzero", 0)
|
||||
@@ -365,9 +365,10 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
|
||||
p.To.Offset = 0
|
||||
p.To.Sym = nil
|
||||
p1 := obj.Appendp(ctxt, p)
|
||||
p1.As = add
|
||||
p1.From.Type = obj.TYPE_CONST
|
||||
p1.As = lea
|
||||
p1.From.Type = obj.TYPE_MEM
|
||||
p1.From.Offset = offset
|
||||
p1.From.Reg = reg
|
||||
p1.To.Type = obj.TYPE_REG
|
||||
p1.To.Reg = reg
|
||||
p2 := obj.Appendp(ctxt, p1)
|
||||
|
||||
@@ -324,18 +324,36 @@ func isRuntimeDepPkg(pkg string) bool {
|
||||
return strings.HasPrefix(pkg, "runtime/internal/") && !strings.HasSuffix(pkg, "_test")
|
||||
}
|
||||
|
||||
// Estimate the max size needed to hold any new trampolines created for this function. This
|
||||
// is used to determine when the section can be split if it becomes too large, to ensure that
|
||||
// the trampolines are in the same section as the function that uses them.
|
||||
func maxSizeTrampolinesPPC64(s *Symbol, isTramp bool) uint64 {
|
||||
// If Thearch.Trampoline is nil, then trampoline support is not available on this arch.
|
||||
// A trampoline does not need any dependent trampolines.
|
||||
if Thearch.Trampoline == nil || isTramp {
|
||||
return 0
|
||||
}
|
||||
|
||||
n := uint64(0)
|
||||
for ri := range s.R {
|
||||
r := &s.R[ri]
|
||||
if r.Type.IsDirectJump() {
|
||||
n++
|
||||
}
|
||||
}
|
||||
// Trampolines in ppc64 are 4 instructions.
|
||||
return n * 16
|
||||
}
|
||||
|
||||
// detect too-far jumps in function s, and add trampolines if necessary
|
||||
// ARM supports trampoline insertion for internal and external linking
|
||||
// PPC64 & PPC64LE support trampoline insertion for internal linking only
|
||||
// ARM, PPC64 & PPC64LE support trampoline insertion for internal and external linking
|
||||
// On PPC64 & PPC64LE the text sections might be split but will still insert trampolines
|
||||
// where necessary.
|
||||
func trampoline(ctxt *Link, s *Symbol) {
|
||||
if Thearch.Trampoline == nil {
|
||||
return // no need or no support of trampolines on this arch
|
||||
}
|
||||
|
||||
if Linkmode == LinkExternal && SysArch.Family == sys.PPC64 {
|
||||
return
|
||||
}
|
||||
|
||||
for ri := range s.R {
|
||||
r := &s.R[ri]
|
||||
if !r.Type.IsDirectJump() {
|
||||
@@ -2044,14 +2062,14 @@ func (ctxt *Link) textaddress() {
|
||||
sect.Vaddr = va
|
||||
ntramps := 0
|
||||
for _, sym := range ctxt.Textp {
|
||||
sect, n, va = assignAddress(ctxt, sect, n, sym, va)
|
||||
sect, n, va = assignAddress(ctxt, sect, n, sym, va, false)
|
||||
|
||||
trampoline(ctxt, sym) // resolve jumps, may add trampolines if jump too far
|
||||
|
||||
// lay down trampolines after each function
|
||||
for ; ntramps < len(ctxt.tramps); ntramps++ {
|
||||
tramp := ctxt.tramps[ntramps]
|
||||
sect, n, va = assignAddress(ctxt, sect, n, tramp, va)
|
||||
sect, n, va = assignAddress(ctxt, sect, n, tramp, va, true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2077,7 +2095,7 @@ func (ctxt *Link) textaddress() {
|
||||
// assigns address for a text symbol, returns (possibly new) section, its number, and the address
|
||||
// Note: once we have trampoline insertion support for external linking, this function
|
||||
// will not need to create new text sections, and so no need to return sect and n.
|
||||
func assignAddress(ctxt *Link, sect *Section, n int, sym *Symbol, va uint64) (*Section, int, uint64) {
|
||||
func assignAddress(ctxt *Link, sect *Section, n int, sym *Symbol, va uint64, isTramp bool) (*Section, int, uint64) {
|
||||
sym.Sect = sect
|
||||
if sym.Type&obj.SSUB != 0 {
|
||||
return sect, n, va
|
||||
@@ -2106,7 +2124,7 @@ func assignAddress(ctxt *Link, sect *Section, n int, sym *Symbol, va uint64) (*S
|
||||
|
||||
// Only break at outermost syms.
|
||||
|
||||
if SysArch.InFamily(sys.PPC64) && sym.Outer == nil && Iself && Linkmode == LinkExternal && va-sect.Vaddr+funcsize > 0x1c00000 {
|
||||
if SysArch.InFamily(sys.PPC64) && sym.Outer == nil && Iself && Linkmode == LinkExternal && va-sect.Vaddr+funcsize+maxSizeTrampolinesPPC64(sym, isTramp) > 0x1c00000 {
|
||||
|
||||
// Set the length for the previous text section
|
||||
sect.Length = va - sect.Vaddr
|
||||
|
||||
@@ -522,13 +522,22 @@ func archrelocaddr(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) int {
|
||||
// resolve direct jump relocation r in s, and add trampoline if necessary
|
||||
func trampoline(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol) {
|
||||
|
||||
// Trampolines are created if the branch offset is too large and the linker cannot insert a call stub to handle it.
|
||||
// For internal linking, trampolines are always created for long calls.
|
||||
// For external linking, the linker can insert a call stub to handle a long call, but depends on having the TOC address in
|
||||
// r2. For those build modes with external linking where the TOC address is not maintained in r2, trampolines must be created.
|
||||
if ld.Linkmode == ld.LinkExternal && (ctxt.DynlinkingGo() || ld.Buildmode == ld.BuildmodeCArchive || ld.Buildmode == ld.BuildmodeCShared || ld.Buildmode == ld.BuildmodePIE) {
|
||||
// No trampolines needed since r2 contains the TOC
|
||||
return
|
||||
}
|
||||
|
||||
t := ld.Symaddr(r.Sym) + r.Add - (s.Value + int64(r.Off))
|
||||
switch r.Type {
|
||||
case obj.R_CALLPOWER:
|
||||
|
||||
// If branch offset is too far then create a trampoline.
|
||||
|
||||
if int64(int32(t<<6)>>6) != t || (*ld.FlagDebugTramp > 1 && s.File != r.Sym.File) {
|
||||
if (ld.Linkmode == ld.LinkExternal && s.Sect != r.Sym.Sect) || (ld.Linkmode == ld.LinkInternal && int64(int32(t<<6)>>6) != t) || (*ld.FlagDebugTramp > 1 && s.File != r.Sym.File) {
|
||||
var tramp *ld.Symbol
|
||||
for i := 0; ; i++ {
|
||||
|
||||
@@ -552,26 +561,20 @@ func trampoline(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol) {
|
||||
|
||||
t = ld.Symaddr(tramp) + r.Add - (s.Value + int64(r.Off))
|
||||
|
||||
// If the offset of the trampoline that has been found is within range, use it.
|
||||
if int64(int32(t<<6)>>6) == t {
|
||||
// With internal linking, the trampoline can be used if it is not too far.
|
||||
// With external linking, the trampoline must be in this section for it to be reused.
|
||||
if (ld.Linkmode == ld.LinkInternal && int64(int32(t<<6)>>6) == t) || (ld.Linkmode == ld.LinkExternal && s.Sect == tramp.Sect) {
|
||||
break
|
||||
}
|
||||
}
|
||||
if tramp.Type == 0 {
|
||||
ctxt.AddTramp(tramp)
|
||||
tramp.Size = 16 // 4 instructions
|
||||
tramp.P = make([]byte, tramp.Size)
|
||||
t = ld.Symaddr(r.Sym) + r.Add
|
||||
f := t & 0xffff0000
|
||||
o1 := uint32(0x3fe00000 | (f >> 16)) // lis r31,trampaddr hi (r31 is temp reg)
|
||||
f = t & 0xffff
|
||||
o2 := uint32(0x63ff0000 | f) // ori r31,trampaddr lo
|
||||
o3 := uint32(0x7fe903a6) // mtctr
|
||||
o4 := uint32(0x4e800420) // bctr
|
||||
ld.SysArch.ByteOrder.PutUint32(tramp.P, o1)
|
||||
ld.SysArch.ByteOrder.PutUint32(tramp.P[4:], o2)
|
||||
ld.SysArch.ByteOrder.PutUint32(tramp.P[8:], o3)
|
||||
ld.SysArch.ByteOrder.PutUint32(tramp.P[12:], o4)
|
||||
if ctxt.DynlinkingGo() || ld.Buildmode == ld.BuildmodeCArchive || ld.Buildmode == ld.BuildmodeCShared || ld.Buildmode == ld.BuildmodePIE {
|
||||
// Should have returned for above cases
|
||||
ld.Errorf(s, "unexpected trampoline for shared or dynamic linking\n")
|
||||
} else {
|
||||
ctxt.AddTramp(tramp)
|
||||
gentramp(tramp, r.Sym, int64(r.Add))
|
||||
}
|
||||
}
|
||||
r.Sym = tramp
|
||||
r.Add = 0 // This was folded into the trampoline target address
|
||||
@@ -582,6 +585,42 @@ func trampoline(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol) {
|
||||
}
|
||||
}
|
||||
|
||||
func gentramp(tramp, target *ld.Symbol, offset int64) {
|
||||
// Used for default build mode for an executable
|
||||
// Address of the call target is generated using
|
||||
// relocation and doesn't depend on r2 (TOC).
|
||||
tramp.Size = 16 // 4 instructions
|
||||
tramp.P = make([]byte, tramp.Size)
|
||||
t := ld.Symaddr(target) + offset
|
||||
o1 := uint32(0x3fe00000) // lis r31,targetaddr hi
|
||||
o2 := uint32(0x3bff0000) // addi r31,targetaddr lo
|
||||
// With external linking, the target address must be
|
||||
// relocated using LO and HA
|
||||
if ld.Linkmode == ld.LinkExternal {
|
||||
tr := ld.Addrel(tramp)
|
||||
tr.Off = 0
|
||||
tr.Type = obj.R_ADDRPOWER
|
||||
tr.Siz = 8 // generates 2 relocations: HA + LO
|
||||
tr.Sym = target
|
||||
tr.Add = offset
|
||||
} else {
|
||||
// adjustment needed if lo has sign bit set
|
||||
// when using addi to compute address
|
||||
val := uint32((t & 0xffff0000) >> 16)
|
||||
if t&0x8000 != 0 {
|
||||
val += 1
|
||||
}
|
||||
o1 |= val // hi part of addr
|
||||
o2 |= uint32(t & 0xffff) // lo part of addr
|
||||
}
|
||||
o3 := uint32(0x7fe903a6) // mtctr r31
|
||||
o4 := uint32(0x4e800420) // bctr
|
||||
ld.SysArch.ByteOrder.PutUint32(tramp.P, o1)
|
||||
ld.SysArch.ByteOrder.PutUint32(tramp.P[4:], o2)
|
||||
ld.SysArch.ByteOrder.PutUint32(tramp.P[8:], o3)
|
||||
ld.SysArch.ByteOrder.PutUint32(tramp.P[12:], o4)
|
||||
}
|
||||
|
||||
func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) int {
|
||||
if ld.Linkmode == ld.LinkExternal {
|
||||
switch r.Type {
|
||||
|
||||
@@ -191,6 +191,10 @@ func matchNameConstraint(domain, constraint string) bool {
|
||||
|
||||
// isValid performs validity checks on the c.
|
||||
func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error {
|
||||
if len(c.UnhandledCriticalExtensions) > 0 {
|
||||
return UnhandledCriticalExtension{}
|
||||
}
|
||||
|
||||
if len(currentChain) > 0 {
|
||||
child := currentChain[len(currentChain)-1]
|
||||
if !bytes.Equal(child.RawIssuer, c.RawSubject) {
|
||||
@@ -279,10 +283,6 @@ func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err e
|
||||
return c.systemVerify(&opts)
|
||||
}
|
||||
|
||||
if len(c.UnhandledCriticalExtensions) > 0 {
|
||||
return nil, UnhandledCriticalExtension{}
|
||||
}
|
||||
|
||||
if opts.Roots == nil {
|
||||
opts.Roots = systemRootsPool()
|
||||
if opts.Roots == nil {
|
||||
|
||||
@@ -263,6 +263,30 @@ var verifyTests = []verifyTest{
|
||||
|
||||
errorCallback: expectSubjectIssuerMismatcthError,
|
||||
},
|
||||
{
|
||||
// Test that unknown critical extensions in a leaf cause a
|
||||
// verify error.
|
||||
leaf: criticalExtLeafWithExt,
|
||||
dnsName: "example.com",
|
||||
intermediates: []string{criticalExtIntermediate},
|
||||
roots: []string{criticalExtRoot},
|
||||
currentTime: 1486684488,
|
||||
systemSkip: true,
|
||||
|
||||
errorCallback: expectUnhandledCriticalExtension,
|
||||
},
|
||||
{
|
||||
// Test that unknown critical extensions in an intermediate
|
||||
// cause a verify error.
|
||||
leaf: criticalExtLeaf,
|
||||
dnsName: "example.com",
|
||||
intermediates: []string{criticalExtIntermediateWithExt},
|
||||
roots: []string{criticalExtRoot},
|
||||
currentTime: 1486684488,
|
||||
systemSkip: true,
|
||||
|
||||
errorCallback: expectUnhandledCriticalExtension,
|
||||
},
|
||||
}
|
||||
|
||||
func expectHostnameError(t *testing.T, i int, err error) (ok bool) {
|
||||
@@ -330,6 +354,14 @@ func expectSubjectIssuerMismatcthError(t *testing.T, i int, err error) (ok bool)
|
||||
return true
|
||||
}
|
||||
|
||||
func expectUnhandledCriticalExtension(t *testing.T, i int, err error) (ok bool) {
|
||||
if _, ok := err.(UnhandledCriticalExtension); !ok {
|
||||
t.Errorf("#%d: error was not an UnhandledCriticalExtension: %s", i, err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func certificateFromPEM(pemBytes string) (*Certificate, error) {
|
||||
block, _ := pem.Decode([]byte(pemBytes))
|
||||
if block == nil {
|
||||
@@ -1379,3 +1411,67 @@ w67CoNRb81dy+4Q1lGpA8ORoLWh5fIq2t2eNGc4qB8vlTIKiESzAwu7u3sRfuWQi
|
||||
4R+gnfLd37FWflMHwztFbVTuNtPOljCX0LN7KcuoXYlr05RhQrmoN7fQHsrZMNLs
|
||||
8FVjHdKKu+uPstwd04Uy4BR/H2y1yerN9j/L6ZkMl98iiA==
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const criticalExtRoot = `-----BEGIN CERTIFICATE-----
|
||||
MIIBqzCCAVGgAwIBAgIJAJ+mI/85cXApMAoGCCqGSM49BAMCMB0xDDAKBgNVBAoT
|
||||
A09yZzENMAsGA1UEAxMEUm9vdDAeFw0xNTAxMDEwMDAwMDBaFw0yNTAxMDEwMDAw
|
||||
MDBaMB0xDDAKBgNVBAoTA09yZzENMAsGA1UEAxMEUm9vdDBZMBMGByqGSM49AgEG
|
||||
CCqGSM49AwEHA0IABJGp9joiG2QSQA+1FczEDAsWo84rFiP3GTL+n+ugcS6TyNib
|
||||
gzMsdbJgVi+a33y0SzLZxB+YvU3/4KTk8yKLC+2jejB4MA4GA1UdDwEB/wQEAwIC
|
||||
BDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB
|
||||
/zAZBgNVHQ4EEgQQQDfXAftAL7gcflQEJ4xZATAbBgNVHSMEFDASgBBAN9cB+0Av
|
||||
uBx+VAQnjFkBMAoGCCqGSM49BAMCA0gAMEUCIFeSV00fABFceWR52K+CfIgOHotY
|
||||
FizzGiLB47hGwjMuAiEA8e0um2Kr8FPQ4wmFKaTRKHMaZizCGl3m+RG5QsE1KWo=
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const criticalExtIntermediate = `-----BEGIN CERTIFICATE-----
|
||||
MIIBszCCAVmgAwIBAgIJAL2kcGZKpzVqMAoGCCqGSM49BAMCMB0xDDAKBgNVBAoT
|
||||
A09yZzENMAsGA1UEAxMEUm9vdDAeFw0xNTAxMDEwMDAwMDBaFw0yNTAxMDEwMDAw
|
||||
MDBaMCUxDDAKBgNVBAoTA09yZzEVMBMGA1UEAxMMSW50ZXJtZWRpYXRlMFkwEwYH
|
||||
KoZIzj0CAQYIKoZIzj0DAQcDQgAESqVq92iPEq01cL4o99WiXDc5GZjpjNlzMS1n
|
||||
rk8oHcVDp4tQRRQG3F4A6dF1rn/L923ha3b0fhDLlAvXZB+7EKN6MHgwDgYDVR0P
|
||||
AQH/BAQDAgIEMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMB
|
||||
Af8EBTADAQH/MBkGA1UdDgQSBBCMGmiotXbbXVd7H40UsgajMBsGA1UdIwQUMBKA
|
||||
EEA31wH7QC+4HH5UBCeMWQEwCgYIKoZIzj0EAwIDSAAwRQIhAOhhNRb6KV7h3wbE
|
||||
cdap8bojzvUcPD78fbsQPCNw1jPxAiBOeAJhlTwpKn9KHpeJphYSzydj9NqcS26Y
|
||||
xXbdbm27KQ==
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const criticalExtLeafWithExt = `-----BEGIN CERTIFICATE-----
|
||||
MIIBxTCCAWugAwIBAgIJAJZAUtw5ccb1MAoGCCqGSM49BAMCMCUxDDAKBgNVBAoT
|
||||
A09yZzEVMBMGA1UEAxMMSW50ZXJtZWRpYXRlMB4XDTE1MDEwMTAwMDAwMFoXDTI1
|
||||
MDEwMTAwMDAwMFowJDEMMAoGA1UEChMDT3JnMRQwEgYDVQQDEwtleGFtcGxlLmNv
|
||||
bTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABF3ABa2+B6gUyg6ayCaRQWYY/+No
|
||||
6PceLqEavZNUeVNuz7bS74Toy8I7R3bGMkMgbKpLSPlPTroAATvebTXoBaijgYQw
|
||||
gYEwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcD
|
||||
AjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBBRNtBL2vq8nCV3qVp7ycxMMBsGA1Ud
|
||||
IwQUMBKAEIwaaKi1dttdV3sfjRSyBqMwCgYDUQMEAQH/BAAwCgYIKoZIzj0EAwID
|
||||
SAAwRQIgVjy8GBgZFiagexEuDLqtGjIRJQtBcf7lYgf6XFPH1h4CIQCT6nHhGo6E
|
||||
I+crEm4P5q72AnA/Iy0m24l7OvLuXObAmg==
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const criticalExtIntermediateWithExt = `-----BEGIN CERTIFICATE-----
|
||||
MIIB2TCCAX6gAwIBAgIIQD3NrSZtcUUwCgYIKoZIzj0EAwIwHTEMMAoGA1UEChMD
|
||||
T3JnMQ0wCwYDVQQDEwRSb290MB4XDTE1MDEwMTAwMDAwMFoXDTI1MDEwMTAwMDAw
|
||||
MFowPTEMMAoGA1UEChMDT3JnMS0wKwYDVQQDEyRJbnRlcm1lZGlhdGUgd2l0aCBD
|
||||
cml0aWNhbCBFeHRlbnNpb24wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQtnmzH
|
||||
mcRm10bdDBnJE7xQEJ25cLCL5okuEphRR0Zneo6+nQZikoh+UBbtt5GV3Dms7LeP
|
||||
oF5HOplYDCd8wi/wo4GHMIGEMA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggr
|
||||
BgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQKxdv
|
||||
UuQZ6sO3XvBsxgNZ3zAbBgNVHSMEFDASgBBAN9cB+0AvuBx+VAQnjFkBMAoGA1ED
|
||||
BAEB/wQAMAoGCCqGSM49BAMCA0kAMEYCIQCQzTPd6XKex+OAPsKT/1DsoMsg8vcG
|
||||
c2qZ4Q0apT/kvgIhAKu2TnNQMIUdcO0BYQIl+Uhxc78dc9h4lO+YJB47pHGx
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
const criticalExtLeaf = `-----BEGIN CERTIFICATE-----
|
||||
MIIBzzCCAXWgAwIBAgIJANoWFIlhCI9MMAoGCCqGSM49BAMCMD0xDDAKBgNVBAoT
|
||||
A09yZzEtMCsGA1UEAxMkSW50ZXJtZWRpYXRlIHdpdGggQ3JpdGljYWwgRXh0ZW5z
|
||||
aW9uMB4XDTE1MDEwMTAwMDAwMFoXDTI1MDEwMTAwMDAwMFowJDEMMAoGA1UEChMD
|
||||
T3JnMRQwEgYDVQQDEwtleGFtcGxlLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEH
|
||||
A0IABG1Lfh8A0Ho2UvZN5H0+ONil9c8jwtC0y0xIZftyQE+Fwr9XwqG3rV2g4M1h
|
||||
GnJa9lV9MPHg8+b85Hixm0ZSw7SjdzB1MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUE
|
||||
FjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAZBgNVHQ4EEgQQ
|
||||
UNhY4JhezH9gQYqvDMWrWDAbBgNVHSMEFDASgBArF29S5Bnqw7de8GzGA1nfMAoG
|
||||
CCqGSM49BAMCA0gAMEUCIQClA3d4tdrDu9Eb5ZBpgyC+fU1xTZB0dKQHz6M5fPZA
|
||||
2AIgN96lM+CPGicwhN24uQI6flOsO3H0TJ5lNzBYLtnQtlc=
|
||||
-----END CERTIFICATE-----`
|
||||
|
||||
@@ -518,74 +518,6 @@ func TestCreateSelfSignedCertificate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnknownCriticalExtension(t *testing.T) {
|
||||
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to generate ECDSA key: %s", err)
|
||||
}
|
||||
|
||||
oids := []asn1.ObjectIdentifier{
|
||||
// This OID is in the PKIX arc, but unknown.
|
||||
{2, 5, 29, 999999},
|
||||
// This is a nonsense, unassigned OID.
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
for _, oid := range oids {
|
||||
template := Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{
|
||||
CommonName: "foo",
|
||||
},
|
||||
NotBefore: time.Unix(1000, 0),
|
||||
NotAfter: time.Now().AddDate(1, 0, 0),
|
||||
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
|
||||
KeyUsage: KeyUsageCertSign,
|
||||
ExtKeyUsage: []ExtKeyUsage{ExtKeyUsageServerAuth},
|
||||
|
||||
ExtraExtensions: []pkix.Extension{
|
||||
{
|
||||
Id: oid,
|
||||
Critical: true,
|
||||
Value: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
derBytes, err := CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create certificate: %s", err)
|
||||
}
|
||||
|
||||
cert, err := ParseCertificate(derBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("Certificate with unknown critical extension was not parsed: %s", err)
|
||||
}
|
||||
|
||||
roots := NewCertPool()
|
||||
roots.AddCert(cert)
|
||||
|
||||
// Setting Roots ensures that Verify won't delegate to the OS
|
||||
// library and thus the correct error should always be
|
||||
// returned.
|
||||
_, err = cert.Verify(VerifyOptions{Roots: roots})
|
||||
if err == nil {
|
||||
t.Fatal("Certificate with unknown critical extension was verified without error")
|
||||
}
|
||||
if _, ok := err.(UnhandledCriticalExtension); !ok {
|
||||
t.Fatalf("Error was %#v, but wanted one of type UnhandledCriticalExtension", err)
|
||||
}
|
||||
|
||||
cert.UnhandledCriticalExtensions = nil
|
||||
if _, err = cert.Verify(VerifyOptions{Roots: roots}); err != nil {
|
||||
t.Errorf("Certificate failed to verify after unhandled critical extensions were cleared: %s", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Self-signed certificate using ECDSA with SHA1 & secp256r1
|
||||
var ecdsaSHA1CertPem = `
|
||||
-----BEGIN CERTIFICATE-----
|
||||
|
||||
@@ -1487,6 +1487,26 @@ func TestSqrt(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// We can't test this together with the other Exp tests above because
|
||||
// it requires a different receiver setup.
|
||||
func TestIssue22830(t *testing.T) {
|
||||
one := new(Int).SetInt64(1)
|
||||
base, _ := new(Int).SetString("84555555300000000000", 10)
|
||||
mod, _ := new(Int).SetString("66666670001111111111", 10)
|
||||
want, _ := new(Int).SetString("17888885298888888889", 10)
|
||||
|
||||
var tests = []int64{
|
||||
0, 1, -1,
|
||||
}
|
||||
|
||||
for _, n := range tests {
|
||||
m := NewInt(n)
|
||||
if got := m.Exp(base, one, mod); got.Cmp(want) != 0 {
|
||||
t.Errorf("(%v).Exp(%s, 1, %s) = %s, want %s", n, base, mod, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSqrt(b *testing.B) {
|
||||
n, _ := new(Int).SetString("1"+strings.Repeat("0", 1001), 10)
|
||||
b.ResetTimer()
|
||||
|
||||
@@ -575,8 +575,8 @@ func (z nat) divLarge(u, uIn, v nat) (q, r nat) {
|
||||
// determine if z can be reused
|
||||
// TODO(gri) should find a better solution - this if statement
|
||||
// is very costly (see e.g. time pidigits -s -n 10000)
|
||||
if alias(z, uIn) || alias(z, v) {
|
||||
z = nil // z is an alias for uIn or v - cannot reuse
|
||||
if alias(z, u) || alias(z, uIn) || alias(z, v) {
|
||||
z = nil // z is an alias for u or uIn or v - cannot reuse
|
||||
}
|
||||
q = z.make(m + 1)
|
||||
|
||||
|
||||
@@ -225,6 +225,8 @@ func dialClosedPort() (actual, expected time.Duration) {
|
||||
// but other platforms should be instantaneous.
|
||||
if runtime.GOOS == "windows" {
|
||||
expected = 1500 * time.Millisecond
|
||||
} else if runtime.GOOS == "darwin" {
|
||||
expected = 150 * time.Millisecond
|
||||
} else {
|
||||
expected = 95 * time.Millisecond
|
||||
}
|
||||
|
||||
@@ -1091,7 +1091,12 @@ func TestLinuxSendfile(t *testing.T) {
|
||||
// and will error out if we specify that with `-e trace='.
|
||||
syscalls = "sendfile"
|
||||
case "mips64":
|
||||
t.Skip("TODO: update this test to be robust against various versions of strace on mips64. See golang.org/issue/33430")
|
||||
t.Skip("TODO: update this test to be robust against various versions of strace on mips64. See golang.org/issue/18008")
|
||||
}
|
||||
|
||||
// Attempt to run strace, and skip on failure - this test requires SYS_PTRACE.
|
||||
if err := exec.Command("strace", "-f", "-q", "-e", "trace="+syscalls, os.Args[0], "-test.run=^$").Run(); err != nil {
|
||||
t.Skipf("skipping; failed to run strace: %v", err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
|
||||
@@ -503,21 +503,26 @@ func TestInterfaceAddrsWithNetsh(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func getmacSpeaksEnglish(t *testing.T) bool {
|
||||
// check that getmac exists as a powershell command, and that it
|
||||
// speaks English.
|
||||
func checkGetmac(t *testing.T) {
|
||||
out, err := runCmd("getmac", "/?")
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "term 'getmac' is not recognized as the name of a cmdlet") {
|
||||
t.Skipf("getmac not available")
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
return bytes.Contains(out, []byte("network adapters on a system"))
|
||||
if !bytes.Contains(out, []byte("network adapters on a system")) {
|
||||
t.Skipf("skipping test on non-English system")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInterfaceHardwareAddrWithGetmac(t *testing.T) {
|
||||
if isWindowsXP(t) {
|
||||
t.Skip("Windows XP does not have powershell command")
|
||||
}
|
||||
if !getmacSpeaksEnglish(t) {
|
||||
t.Skip("English version of getmac required for this test")
|
||||
}
|
||||
checkGetmac(t)
|
||||
|
||||
ift, err := Interfaces()
|
||||
if err != nil {
|
||||
|
||||
@@ -44,26 +44,29 @@ type plainAuth struct {
|
||||
}
|
||||
|
||||
// PlainAuth returns an Auth that implements the PLAIN authentication
|
||||
// mechanism as defined in RFC 4616.
|
||||
// The returned Auth uses the given username and password to authenticate
|
||||
// on TLS connections to host and act as identity. Usually identity will be
|
||||
// left blank to act as username.
|
||||
// mechanism as defined in RFC 4616. The returned Auth uses the given
|
||||
// username and password to authenticate to host and act as identity.
|
||||
// Usually identity should be the empty string, to act as username.
|
||||
//
|
||||
// PlainAuth will only send the credentials if the connection is using TLS
|
||||
// or is connected to localhost. Otherwise authentication will fail with an
|
||||
// error, without sending the credentials.
|
||||
func PlainAuth(identity, username, password, host string) Auth {
|
||||
return &plainAuth{identity, username, password, host}
|
||||
}
|
||||
|
||||
func isLocalhost(name string) bool {
|
||||
return name == "localhost" || name == "127.0.0.1" || name == "::1"
|
||||
}
|
||||
|
||||
func (a *plainAuth) Start(server *ServerInfo) (string, []byte, error) {
|
||||
if !server.TLS {
|
||||
advertised := false
|
||||
for _, mechanism := range server.Auth {
|
||||
if mechanism == "PLAIN" {
|
||||
advertised = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !advertised {
|
||||
return "", nil, errors.New("unencrypted connection")
|
||||
}
|
||||
// Must have TLS, or else localhost server.
|
||||
// Note: If TLS is not true, then we can't trust ANYTHING in ServerInfo.
|
||||
// In particular, it doesn't matter if the server advertises PLAIN auth.
|
||||
// That might just be the attacker saying
|
||||
// "it's ok, you can trust me with your password."
|
||||
if !server.TLS && !isLocalhost(server.Name) {
|
||||
return "", nil, errors.New("unencrypted connection")
|
||||
}
|
||||
if server.Name != a.host {
|
||||
return "", nil, errors.New("wrong host name")
|
||||
|
||||
@@ -67,6 +67,7 @@ func NewClient(conn net.Conn, host string) (*Client, error) {
|
||||
return nil, err
|
||||
}
|
||||
c := &Client{Text: text, conn: conn, serverName: host, localName: "localhost"}
|
||||
_, c.tls = conn.(*tls.Conn)
|
||||
return c, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -60,29 +60,41 @@ testLoop:
|
||||
}
|
||||
|
||||
func TestAuthPlain(t *testing.T) {
|
||||
auth := PlainAuth("foo", "bar", "baz", "servername")
|
||||
|
||||
tests := []struct {
|
||||
server *ServerInfo
|
||||
err string
|
||||
authName string
|
||||
server *ServerInfo
|
||||
err string
|
||||
}{
|
||||
{
|
||||
server: &ServerInfo{Name: "servername", TLS: true},
|
||||
authName: "servername",
|
||||
server: &ServerInfo{Name: "servername", TLS: true},
|
||||
},
|
||||
{
|
||||
// Okay; explicitly advertised by server.
|
||||
server: &ServerInfo{Name: "servername", Auth: []string{"PLAIN"}},
|
||||
// OK to use PlainAuth on localhost without TLS
|
||||
authName: "localhost",
|
||||
server: &ServerInfo{Name: "localhost", TLS: false},
|
||||
},
|
||||
{
|
||||
server: &ServerInfo{Name: "servername", Auth: []string{"CRAM-MD5"}},
|
||||
err: "unencrypted connection",
|
||||
// NOT OK on non-localhost, even if server says PLAIN is OK.
|
||||
// (We don't know that the server is the real server.)
|
||||
authName: "servername",
|
||||
server: &ServerInfo{Name: "servername", Auth: []string{"PLAIN"}},
|
||||
err: "unencrypted connection",
|
||||
},
|
||||
{
|
||||
server: &ServerInfo{Name: "attacker", TLS: true},
|
||||
err: "wrong host name",
|
||||
authName: "servername",
|
||||
server: &ServerInfo{Name: "servername", Auth: []string{"CRAM-MD5"}},
|
||||
err: "unencrypted connection",
|
||||
},
|
||||
{
|
||||
authName: "servername",
|
||||
server: &ServerInfo{Name: "attacker", TLS: true},
|
||||
err: "wrong host name",
|
||||
},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
auth := PlainAuth("foo", "bar", "baz", tt.authName)
|
||||
_, _, err := auth.Start(tt.server)
|
||||
got := ""
|
||||
if err != nil {
|
||||
@@ -350,6 +362,53 @@ HELO localhost
|
||||
QUIT
|
||||
`
|
||||
|
||||
func TestNewClientWithTLS(t *testing.T) {
|
||||
cert, err := tls.X509KeyPair(localhostCert, localhostKey)
|
||||
if err != nil {
|
||||
t.Fatalf("loadcert: %v", err)
|
||||
}
|
||||
|
||||
config := tls.Config{Certificates: []tls.Certificate{cert}}
|
||||
|
||||
ln, err := tls.Listen("tcp", "127.0.0.1:0", &config)
|
||||
if err != nil {
|
||||
ln, err = tls.Listen("tcp", "[::1]:0", &config)
|
||||
if err != nil {
|
||||
t.Fatalf("server: listen: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
go func() {
|
||||
conn, err := ln.Accept()
|
||||
if err != nil {
|
||||
t.Fatalf("server: accept: %s", err)
|
||||
return
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
_, err = conn.Write([]byte("220 SIGNS\r\n"))
|
||||
if err != nil {
|
||||
t.Fatalf("server: write: %s", err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
config.InsecureSkipVerify = true
|
||||
conn, err := tls.Dial("tcp", ln.Addr().String(), &config)
|
||||
if err != nil {
|
||||
t.Fatalf("client: dial: %s", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
client, err := NewClient(conn, ln.Addr().String())
|
||||
if err != nil {
|
||||
t.Fatalf("smtp: newclient: %s", err)
|
||||
}
|
||||
if !client.tls {
|
||||
t.Errorf("client.tls Got: %t Expected: %t", client.tls, true)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHello(t *testing.T) {
|
||||
|
||||
if len(helloServer) != len(helloClient) {
|
||||
|
||||
@@ -404,6 +404,8 @@ func TestDirectorySymbolicLink(t *testing.T) {
|
||||
func TestNetworkSymbolicLink(t *testing.T) {
|
||||
testenv.MustHaveSymlink(t)
|
||||
|
||||
const _NERR_ServerNotStarted = syscall.Errno(2114)
|
||||
|
||||
dir, err := ioutil.TempDir("", "TestNetworkSymbolicLink")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -454,6 +456,9 @@ func TestNetworkSymbolicLink(t *testing.T) {
|
||||
if err == syscall.ERROR_ACCESS_DENIED {
|
||||
t.Skip("you don't have enough privileges to add network share")
|
||||
}
|
||||
if err == _NERR_ServerNotStarted {
|
||||
t.Skip(_NERR_ServerNotStarted.Error())
|
||||
}
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
|
||||
@@ -169,7 +169,7 @@ func TestPeriodicGC(t *testing.T) {
|
||||
// slack if things are slow.
|
||||
var numGCs uint32
|
||||
const want = 2
|
||||
for i := 0; i < 20 && numGCs < want; i++ {
|
||||
for i := 0; i < 200 && numGCs < want; i++ {
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
|
||||
// Test that periodic GC actually happened.
|
||||
|
||||
@@ -100,7 +100,7 @@ TEXT runtime·usleep(SB),NOSPLIT,$8
|
||||
MOVL AX, 0(SP)
|
||||
MOVL $1000, AX // usec to nsec
|
||||
MULL DX
|
||||
MOVL DX, 4(SP)
|
||||
MOVL AX, 4(SP)
|
||||
|
||||
// pselect6(0, 0, 0, 0, &ts, 0)
|
||||
MOVL $308, AX
|
||||
|
||||
34
test/fixedbugs/issue20530.go
Normal file
34
test/fixedbugs/issue20530.go
Normal file
@@ -0,0 +1,34 @@
|
||||
// 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
|
||||
|
||||
var a uint8
|
||||
|
||||
//go:noinline
|
||||
func f() {
|
||||
b := int8(func() int32 { return -1 }())
|
||||
a = uint8(b)
|
||||
if int32(a) != 255 {
|
||||
// Failing case prints 'got 255 expected 255'
|
||||
println("got", a, "expected 255")
|
||||
}
|
||||
}
|
||||
|
||||
//go:noinline
|
||||
func g() {
|
||||
b := int8(func() uint32 { return 0xffffffff }())
|
||||
a = uint8(b)
|
||||
if int32(a) != 255 {
|
||||
// Failing case prints 'got 255 expected 255'
|
||||
println("got", a, "expected 255")
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
f()
|
||||
g()
|
||||
}
|
||||
Reference in New Issue
Block a user