aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorDan Willemsen <dwillemsen@google.com>2018-08-27 23:21:26 -0700
committerDan Willemsen <dwillemsen@google.com>2018-08-27 23:21:26 -0700
commitc74133257abfed957ccfd7cf361759c4e4364263 (patch)
tree3662c9f5bd50c1ea4e162a7ffbdb9829cc8a7445 /test
parentee04cf91e69ed1ea9cb2e00c5a4764f6b67c4175 (diff)
downloaddarwin-x86-c74133257abfed957ccfd7cf361759c4e4364263.tar.gz
Test: m -j blueprint_tools Change-Id: I3c22814607204e2bd3ab0de6e67775f1c052714c
Diffstat (limited to 'test')
-rw-r--r--test/README.md2
-rw-r--r--test/alias2.go4
-rw-r--r--test/align.go29
-rw-r--r--test/append.go25
-rw-r--r--test/append1.go2
-rw-r--r--test/bounds.go92
-rw-r--r--test/chancap.go9
-rw-r--r--test/closure3.dir/main.go69
-rw-r--r--test/closure4.go21
-rw-r--r--test/codegen/README147
-rw-r--r--test/codegen/arithmetic.go184
-rw-r--r--test/codegen/bitfield.go232
-rw-r--r--test/codegen/bits.go292
-rw-r--r--test/codegen/comparisons.go149
-rw-r--r--test/codegen/condmove.go182
-rw-r--r--test/codegen/copy.go80
-rw-r--r--test/codegen/floats.go99
-rw-r--r--test/codegen/issue22703.go535
-rw-r--r--test/codegen/mapaccess.go462
-rw-r--r--test/codegen/maps.go95
-rw-r--r--test/codegen/math.go146
-rw-r--r--test/codegen/mathbits.go269
-rw-r--r--test/codegen/memcombine.go580
-rw-r--r--test/codegen/rotate.go160
-rw-r--r--test/codegen/shift.go99
-rw-r--r--test/codegen/slices.go63
-rw-r--r--test/codegen/stack.go95
-rw-r--r--test/codegen/strings.go15
-rw-r--r--test/codegen/structs.go46
-rw-r--r--test/const1.go4
-rw-r--r--test/deferprint.go2
-rw-r--r--test/escape4.go4
-rw-r--r--test/escape5.go65
-rw-r--r--test/escape_array.go7
-rw-r--r--test/escape_because.go35
-rw-r--r--test/fixedbugs/bug206.go2
-rw-r--r--test/fixedbugs/bug248.dir/bug1.go2
-rw-r--r--test/fixedbugs/bug248.dir/bug2.go106
-rw-r--r--test/fixedbugs/bug248.dir/bug3.go102
-rw-r--r--test/fixedbugs/bug248.go53
-rw-r--r--test/fixedbugs/bug273.go12
-rw-r--r--test/fixedbugs/bug302.go2
-rw-r--r--test/fixedbugs/bug328.go2
-rw-r--r--test/fixedbugs/bug345.dir/main.go7
-rw-r--r--test/fixedbugs/bug345.go43
-rw-r--r--test/fixedbugs/bug369.go2
-rw-r--r--test/fixedbugs/bug409.go2
-rw-r--r--test/fixedbugs/bug429_run.go2
-rw-r--r--test/fixedbugs/issue10958.go2
-rw-r--r--test/fixedbugs/issue11656.go3
-rw-r--r--test/fixedbugs/issue11771.go2
-rw-r--r--test/fixedbugs/issue12621.go20
-rw-r--r--test/fixedbugs/issue14321.go33
-rw-r--r--test/fixedbugs/issue14636.go2
-rw-r--r--test/fixedbugs/issue15747.go14
-rw-r--r--test/fixedbugs/issue16037_run.go2
-rw-r--r--test/fixedbugs/issue18640.go21
-rw-r--r--test/fixedbugs/issue18902.go141
-rw-r--r--test/fixedbugs/issue18902b.go161
-rw-r--r--test/fixedbugs/issue18911.dir/a.go7
-rw-r--r--test/fixedbugs/issue18911.dir/b.go21
-rw-r--r--test/fixedbugs/issue18911.go7
-rw-r--r--test/fixedbugs/issue19182.go1
-rw-r--r--test/fixedbugs/issue19359.go54
-rw-r--r--test/fixedbugs/issue19658.go2
-rw-r--r--test/fixedbugs/issue20250.go8
-rw-r--r--test/fixedbugs/issue20529.go5
-rw-r--r--test/fixedbugs/issue20780.go20
-rw-r--r--test/fixedbugs/issue20923.go19
-rw-r--r--test/fixedbugs/issue21221.go18
-rw-r--r--test/fixedbugs/issue21317.go2
-rw-r--r--test/fixedbugs/issue21887.go2
-rw-r--r--test/fixedbugs/issue22305.go15
-rw-r--r--test/fixedbugs/issue22660.go2
-rw-r--r--test/fixedbugs/issue22662.go46
-rw-r--r--test/fixedbugs/issue22662b.go65
-rw-r--r--test/fixedbugs/issue22683.go2
-rw-r--r--test/fixedbugs/issue22822.go16
-rw-r--r--test/fixedbugs/issue22881.go47
-rw-r--r--test/fixedbugs/issue23094.go11
-rw-r--r--test/fixedbugs/issue23116.go15
-rw-r--r--test/fixedbugs/issue23188.go32
-rw-r--r--test/fixedbugs/issue23298.go14
-rw-r--r--test/fixedbugs/issue23414.go13
-rw-r--r--test/fixedbugs/issue23489.go20
-rw-r--r--test/fixedbugs/issue23504.go15
-rw-r--r--test/fixedbugs/issue23521.go43
-rw-r--r--test/fixedbugs/issue23545.go4
-rw-r--r--test/fixedbugs/issue23546.go22
-rw-r--r--test/fixedbugs/issue23586.go24
-rw-r--r--test/fixedbugs/issue23587.go12
-rw-r--r--test/fixedbugs/issue23609.go27
-rw-r--r--test/fixedbugs/issue23664.go17
-rw-r--r--test/fixedbugs/issue23732.go42
-rw-r--r--test/fixedbugs/issue23823.go15
-rw-r--r--test/fixedbugs/issue23912.go30
-rw-r--r--test/fixedbugs/issue24120.go14
-rw-r--r--test/fixedbugs/issue24159.go20
-rw-r--r--test/fixedbugs/issue24173.go19
-rw-r--r--test/fixedbugs/issue24187.go33
-rw-r--r--test/fixedbugs/issue24339.go20
-rw-r--r--test/fixedbugs/issue24419.go51
-rw-r--r--test/fixedbugs/issue24449.go62
-rw-r--r--test/fixedbugs/issue24470.go15
-rw-r--r--test/fixedbugs/issue24503.go28
-rw-r--r--test/fixedbugs/issue24547.go46
-rw-r--r--test/fixedbugs/issue24651a.go24
-rw-r--r--test/fixedbugs/issue24651b.go24
-rw-r--r--test/fixedbugs/issue24693.dir/a.go11
-rw-r--r--test/fixedbugs/issue24693.dir/b.go38
-rw-r--r--test/fixedbugs/issue24693.dir/c.go12
-rw-r--r--test/fixedbugs/issue24693.go7
-rw-r--r--test/fixedbugs/issue24693.out2
-rw-r--r--test/fixedbugs/issue24761.dir/a.go15
-rw-r--r--test/fixedbugs/issue24761.dir/b.go11
-rw-r--r--test/fixedbugs/issue24761.go7
-rw-r--r--test/fixedbugs/issue24763.go21
-rw-r--r--test/fixedbugs/issue24799.go58
-rw-r--r--test/fixedbugs/issue24801.dir/a.go9
-rw-r--r--test/fixedbugs/issue24801.dir/main.go11
-rw-r--r--test/fixedbugs/issue24801.go5
-rw-r--r--test/fixedbugs/issue24817.go64
-rw-r--r--test/fixedbugs/issue24937.go15
-rw-r--r--test/fixedbugs/issue24939.go21
-rw-r--r--test/fixedbugs/issue25006.go30
-rw-r--r--test/fixedbugs/issue25055.dir/a.go7
-rw-r--r--test/fixedbugs/issue25055.dir/b.go9
-rw-r--r--test/fixedbugs/issue25055.go7
-rw-r--r--test/fixedbugs/issue25101.go16
-rw-r--r--test/fixedbugs/issue25322.go23
-rw-r--r--test/fixedbugs/issue25322.out1
-rw-r--r--test/fixedbugs/issue25507.go29
-rw-r--r--test/fixedbugs/issue25516.go26
-rw-r--r--test/fixedbugs/issue25727.go21
-rw-r--r--test/fixedbugs/issue25741.go14
-rw-r--r--test/fixedbugs/issue25776.go99
-rw-r--r--test/fixedbugs/issue25958.go17
-rw-r--r--test/fixedbugs/issue25966.go24
-rw-r--r--test/fixedbugs/issue25984.dir/p.go15
-rw-r--r--test/fixedbugs/issue25984.dir/q.go11
-rw-r--r--test/fixedbugs/issue25984.go7
-rw-r--r--test/fixedbugs/issue25993.go21
-rw-r--r--test/fixedbugs/issue26024.go28
-rw-r--r--test/fixedbugs/issue26043.go32
-rw-r--r--test/fixedbugs/issue26094.go49
-rw-r--r--test/fixedbugs/issue26097.go47
-rw-r--r--test/fixedbugs/issue26105.go25
-rw-r--r--test/fixedbugs/issue26116.go18
-rw-r--r--test/fixedbugs/issue26120.go23
-rw-r--r--test/fixedbugs/issue26153.go29
-rw-r--r--test/fixedbugs/issue26163.go17
-rw-r--r--test/fixedbugs/issue26248.go39
-rw-r--r--test/fixedbugs/issue26335.go32
-rw-r--r--test/fixedbugs/issue26340.go21
-rw-r--r--test/fixedbugs/issue26341.dir/a.go11
-rw-r--r--test/fixedbugs/issue26341.dir/b.go13
-rw-r--r--test/fixedbugs/issue26341.go7
-rw-r--r--test/fixedbugs/issue26407.go58
-rw-r--r--test/fixedbugs/issue26416.go27
-rw-r--r--test/fixedbugs/issue26426.go29
-rw-r--r--test/fixedbugs/issue26438.go26
-rw-r--r--test/fixedbugs/issue26495.go36
-rw-r--r--test/fixedbugs/issue4085b.go19
-rw-r--r--test/fixedbugs/issue6899.go2
-rw-r--r--test/fixedbugs/issue9355.go2
-rw-r--r--test/fixedbugs/issue9604b.go3
-rw-r--r--test/fixedbugs/issue9862_run.go2
-rw-r--r--test/gc2.go2
-rw-r--r--test/gcgort.go1850
-rw-r--r--test/goprint.go2
-rw-r--r--test/helloworld.go2
-rw-r--r--test/inline_big.go1029
-rw-r--r--test/inline_variadic.go4
-rw-r--r--test/ken/cplx0.go2
-rw-r--r--test/ken/string.go2
-rw-r--r--test/linkmain_run.go2
-rw-r--r--test/linkobj.go2
-rw-r--r--test/linkx_run.go2
-rw-r--r--test/live.go36
-rw-r--r--test/live_syscall.go2
-rw-r--r--test/locklinear.go6
-rw-r--r--test/loopbce.go203
-rw-r--r--test/makemap.go6
-rw-r--r--test/mapclear.go89
-rw-r--r--test/method7.go7
-rw-r--r--test/nilptr3.go2
-rw-r--r--test/nilptr3_wasm.go270
-rw-r--r--test/nosplit.go2
-rw-r--r--test/peano.go8
-rw-r--r--test/print.go2
-rw-r--r--test/printbig.go2
-rw-r--r--test/prove.go295
-rw-r--r--test/retjmp.dir/a.s12
-rw-r--r--test/retjmp.dir/main.go32
-rw-r--r--test/retjmp.go9
-rw-r--r--test/run.go436
-rw-r--r--test/sigchld.go2
-rw-r--r--test/sinit_run.go2
-rw-r--r--test/sliceopt.go45
-rw-r--r--test/strcopy.go29
-rw-r--r--test/syntax/typesw.go2
-rw-r--r--test/uintptrescapes2.go20
202 files changed, 10911 insertions, 895 deletions
diff --git a/test/README.md b/test/README.md
index ca6a8c658..068dc1b22 100644
--- a/test/README.md
+++ b/test/README.md
@@ -4,7 +4,7 @@ They are run as part of all.bash.
To run just these tests, execute:
- go run run.go
+ ../bin/go run run.go
Standard library tests should be written as regular Go tests in the appropriate package.
diff --git a/test/alias2.go b/test/alias2.go
index 32c365499..7ea1b2908 100644
--- a/test/alias2.go
+++ b/test/alias2.go
@@ -95,10 +95,10 @@ type _ = reflect.ValueOf // ERROR "reflect.ValueOf is not a type|expected type"
func (A1) m() {} // ERROR "cannot define new methods on non-local type int|may not define methods on non-local type"
func (A2) m() {} // ERROR "invalid receiver type"
func (A3) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
-func (A4) m() {} // ERROR "reflect.Value.m redeclared in this block" "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
+func (A4) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
type B1 = struct{}
-func (B1) m() {} // ERROR "m redeclared in this block" "invalid receiver type"
+func (B1) m() {} // ERROR "invalid receiver type"
// TODO(gri) expand
diff --git a/test/align.go b/test/align.go
new file mode 100644
index 000000000..61d07c49b
--- /dev/null
+++ b/test/align.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+// On 32-bit archs, one of the f fields of a [2]T
+// will be unaligned (address of 4 mod 8).
+// Make sure we can access the f fields successfully,
+// particularly for load-add combo instructions
+// introduced by CL 102036.
+type T struct {
+ pad uint32
+ f float64
+}
+
+//go:noinline
+func f(t, u *T) float64 {
+ return 3.0 + t.f + u.f
+}
+
+func main() {
+ t := [2]T{{0, 1.0}, {0, 2.0}}
+ sink = f(&t[0], &t[1])
+}
+
+var sink float64
diff --git a/test/append.go b/test/append.go
index 3f6251ee5..3d1606340 100644
--- a/test/append.go
+++ b/test/append.go
@@ -13,14 +13,12 @@ import (
"reflect"
)
-
func verify(name string, result, expected interface{}) {
if !reflect.DeepEqual(result, expected) {
panic(name)
}
}
-
func main() {
for _, t := range tests {
verify(t.name, t.result, t.expected)
@@ -30,6 +28,10 @@ func main() {
verifyType()
}
+var (
+ zero int = 0
+ one int = 1
+)
var tests = []struct {
name string
@@ -49,7 +51,6 @@ var tests = []struct {
{"bool i", append([]bool{true, false, true}, []bool{true}...), []bool{true, false, true, true}},
{"bool j", append([]bool{true, false, true}, []bool{true, true, true}...), []bool{true, false, true, true, true, true}},
-
{"byte a", append([]byte{}), []byte{}},
{"byte b", append([]byte{}, 0), []byte{0}},
{"byte c", append([]byte{}, 0, 1, 2, 3), []byte{0, 1, 2, 3}},
@@ -84,7 +85,6 @@ var tests = []struct {
{"int16 i", append([]int16{0, 1, 2}, []int16{3}...), []int16{0, 1, 2, 3}},
{"int16 j", append([]int16{0, 1, 2}, []int16{3, 4, 5}...), []int16{0, 1, 2, 3, 4, 5}},
-
{"uint32 a", append([]uint32{}), []uint32{}},
{"uint32 b", append([]uint32{}, 0), []uint32{0}},
{"uint32 c", append([]uint32{}, 0, 1, 2, 3), []uint32{0, 1, 2, 3}},
@@ -99,7 +99,6 @@ var tests = []struct {
{"uint32 i", append([]uint32{0, 1, 2}, []uint32{3}...), []uint32{0, 1, 2, 3}},
{"uint32 j", append([]uint32{0, 1, 2}, []uint32{3, 4, 5}...), []uint32{0, 1, 2, 3, 4, 5}},
-
{"float64 a", append([]float64{}), []float64{}},
{"float64 b", append([]float64{}, 0), []float64{0}},
{"float64 c", append([]float64{}, 0, 1, 2, 3), []float64{0, 1, 2, 3}},
@@ -114,7 +113,6 @@ var tests = []struct {
{"float64 i", append([]float64{0, 1, 2}, []float64{3}...), []float64{0, 1, 2, 3}},
{"float64 j", append([]float64{0, 1, 2}, []float64{3, 4, 5}...), []float64{0, 1, 2, 3, 4, 5}},
-
{"complex128 a", append([]complex128{}), []complex128{}},
{"complex128 b", append([]complex128{}, 0), []complex128{0}},
{"complex128 c", append([]complex128{}, 0, 1, 2, 3), []complex128{0, 1, 2, 3}},
@@ -129,7 +127,6 @@ var tests = []struct {
{"complex128 i", append([]complex128{0, 1, 2}, []complex128{3}...), []complex128{0, 1, 2, 3}},
{"complex128 j", append([]complex128{0, 1, 2}, []complex128{3, 4, 5}...), []complex128{0, 1, 2, 3, 4, 5}},
-
{"string a", append([]string{}), []string{}},
{"string b", append([]string{}, "0"), []string{"0"}},
{"string c", append([]string{}, "0", "1", "2", "3"), []string{"0", "1", "2", "3"}},
@@ -143,8 +140,19 @@ var tests = []struct {
{"string i", append([]string{"0", "1", "2"}, []string{"3"}...), []string{"0", "1", "2", "3"}},
{"string j", append([]string{"0", "1", "2"}, []string{"3", "4", "5"}...), []string{"0", "1", "2", "3", "4", "5"}},
-}
+ {"make a", append([]string{}, make([]string, 0)...), []string{}},
+ {"make b", append([]string(nil), make([]string, 0)...), []string(nil)},
+
+ {"make c", append([]struct{}{}, make([]struct{}, 0)...), []struct{}{}},
+ {"make d", append([]struct{}{}, make([]struct{}, 2)...), make([]struct{}, 2)},
+
+ {"make e", append([]int{0, 1}, make([]int, 0)...), []int{0, 1}},
+ {"make f", append([]int{0, 1}, make([]int, 2)...), []int{0, 1, 0, 0}},
+
+ {"make g", append([]*int{&zero, &one}, make([]*int, 0)...), []*int{&zero, &one}},
+ {"make h", append([]*int{&zero, &one}, make([]*int, 2)...), []*int{&zero, &one, nil, nil}},
+}
func verifyStruct() {
type T struct {
@@ -185,7 +193,6 @@ func verifyStruct() {
verify("struct m", append(s, e...), r)
}
-
func verifyInterface() {
type T interface{}
type S []T
diff --git a/test/append1.go b/test/append1.go
index 6d42368e4..0fe24c095 100644
--- a/test/append1.go
+++ b/test/append1.go
@@ -17,4 +17,6 @@ func main() {
_ = append(s...) // ERROR "cannot use ... on first argument"
_ = append(s, 2, s...) // ERROR "too many arguments to append"
+ _ = append(s, make([]int, 0)) // ERROR "cannot use make.* as type int in append"
+ _ = append(s, make([]int, -1)...) // ERROR "negative len argument in make"
}
diff --git a/test/bounds.go b/test/bounds.go
index a0febb515..34c444877 100644
--- a/test/bounds.go
+++ b/test/bounds.go
@@ -12,23 +12,23 @@ package foo
var (
s []int
- a1 [1]int
- a1k [1000]int
+ a1 [1]int
+ a1k [1000]int
a100k [100000]int
- p1 *[1]int
- p1k *[1000]int
+ p1 *[1]int
+ p1k *[1000]int
p100k *[100000]int
- i int
- ui uint
- i8 int8
- ui8 uint8
- i16 int16
+ i int
+ ui uint
+ i8 int8
+ ui8 uint8
+ i16 int16
ui16 uint16
- i32 int32
+ i32 int32
ui32 uint32
- i64 int64
+ i64 int64
ui64 uint64
)
@@ -61,11 +61,11 @@ func main() {
// Unsigned 8-bit numbers don't need checks for len >= 2⁸.
use(s[ui8])
use(a1[ui8])
- use(a1k[ui8]) // ERROR "index bounds check elided"
- use(a100k[ui8]) // ERROR "index bounds check elided"
+ use(a1k[ui8]) // ERROR "index bounds check elided"
+ use(a100k[ui8]) // ERROR "index bounds check elided"
use(p1[ui8])
- use(p1k[ui8]) // ERROR "index bounds check elided"
- use(p100k[ui8]) // ERROR "index bounds check elided"
+ use(p1k[ui8]) // ERROR "index bounds check elided"
+ use(p100k[ui8]) // ERROR "index bounds check elided"
use(s[i16])
use(a1[i16])
@@ -79,10 +79,10 @@ func main() {
use(s[ui16])
use(a1[ui16])
use(a1k[ui16])
- use(a100k[ui16]) // ERROR "index bounds check elided"
+ use(a100k[ui16]) // ERROR "index bounds check elided"
use(p1[ui16])
use(p1k[ui16])
- use(p100k[ui16]) // ERROR "index bounds check elided"
+ use(p100k[ui16]) // ERROR "index bounds check elided"
use(s[i32])
use(a1[i32])
@@ -128,11 +128,11 @@ func main() {
use(s[ui%999])
use(a1[ui%999])
- use(a1k[ui%999]) // ERROR "index bounds check elided"
- use(a100k[ui%999]) // ERROR "index bounds check elided"
+ use(a1k[ui%999]) // ERROR "index bounds check elided"
+ use(a100k[ui%999]) // ERROR "index bounds check elided"
use(p1[ui%999])
- use(p1k[ui%999]) // ERROR "index bounds check elided"
- use(p100k[ui%999]) // ERROR "index bounds check elided"
+ use(p1k[ui%999]) // ERROR "index bounds check elided"
+ use(p100k[ui%999]) // ERROR "index bounds check elided"
use(s[i%1000])
use(a1[i%1000])
@@ -144,11 +144,11 @@ func main() {
use(s[ui%1000])
use(a1[ui%1000])
- use(a1k[ui%1000]) // ERROR "index bounds check elided"
- use(a100k[ui%1000]) // ERROR "index bounds check elided"
+ use(a1k[ui%1000]) // ERROR "index bounds check elided"
+ use(a100k[ui%1000]) // ERROR "index bounds check elided"
use(p1[ui%1000])
- use(p1k[ui%1000]) // ERROR "index bounds check elided"
- use(p100k[ui%1000]) // ERROR "index bounds check elided"
+ use(p1k[ui%1000]) // ERROR "index bounds check elided"
+ use(p100k[ui%1000]) // ERROR "index bounds check elided"
use(s[i%1001])
use(a1[i%1001])
@@ -161,45 +161,45 @@ func main() {
use(s[ui%1001])
use(a1[ui%1001])
use(a1k[ui%1001])
- use(a100k[ui%1001]) // ERROR "index bounds check elided"
+ use(a100k[ui%1001]) // ERROR "index bounds check elided"
use(p1[ui%1001])
use(p1k[ui%1001])
- use(p100k[ui%1001]) // ERROR "index bounds check elided"
+ use(p100k[ui%1001]) // ERROR "index bounds check elided"
// Bitwise and truncates the maximum value to the mask value.
// The result (for a positive mask) cannot be negative, so elision
// applies to both signed and unsigned indexes.
use(s[i&999])
use(a1[i&999])
- use(a1k[i&999]) // ERROR "index bounds check elided"
- use(a100k[i&999]) // ERROR "index bounds check elided"
+ use(a1k[i&999]) // ERROR "index bounds check elided"
+ use(a100k[i&999]) // ERROR "index bounds check elided"
use(p1[i&999])
- use(p1k[i&999]) // ERROR "index bounds check elided"
- use(p100k[i&999]) // ERROR "index bounds check elided"
+ use(p1k[i&999]) // ERROR "index bounds check elided"
+ use(p100k[i&999]) // ERROR "index bounds check elided"
use(s[ui&999])
use(a1[ui&999])
- use(a1k[ui&999]) // ERROR "index bounds check elided"
- use(a100k[ui&999]) // ERROR "index bounds check elided"
+ use(a1k[ui&999]) // ERROR "index bounds check elided"
+ use(a100k[ui&999]) // ERROR "index bounds check elided"
use(p1[ui&999])
- use(p1k[ui&999]) // ERROR "index bounds check elided"
- use(p100k[ui&999]) // ERROR "index bounds check elided"
+ use(p1k[ui&999]) // ERROR "index bounds check elided"
+ use(p100k[ui&999]) // ERROR "index bounds check elided"
use(s[i&1000])
use(a1[i&1000])
use(a1k[i&1000])
- use(a100k[i&1000]) // ERROR "index bounds check elided"
+ use(a100k[i&1000]) // ERROR "index bounds check elided"
use(p1[i&1000])
use(p1k[i&1000])
- use(p100k[i&1000]) // ERROR "index bounds check elided"
+ use(p100k[i&1000]) // ERROR "index bounds check elided"
use(s[ui&1000])
use(a1[ui&1000])
use(a1k[ui&1000])
- use(a100k[ui&1000]) // ERROR "index bounds check elided"
+ use(a100k[ui&1000]) // ERROR "index bounds check elided"
use(p1[ui&1000])
use(p1k[ui&1000])
- use(p100k[ui&1000]) // ERROR "index bounds check elided"
+ use(p100k[ui&1000]) // ERROR "index bounds check elided"
// Right shift cuts the effective number of bits in the index,
// but only for unsigned (signed stays negative).
@@ -214,10 +214,10 @@ func main() {
use(s[ui32>>22])
use(a1[ui32>>22])
use(a1k[ui32>>22])
- use(a100k[ui32>>22]) // ERROR "index bounds check elided"
+ use(a100k[ui32>>22]) // ERROR "index bounds check elided"
use(p1[ui32>>22])
use(p1k[ui32>>22])
- use(p100k[ui32>>22]) // ERROR "index bounds check elided"
+ use(p100k[ui32>>22]) // ERROR "index bounds check elided"
use(s[i32>>23])
use(a1[i32>>23])
@@ -229,11 +229,11 @@ func main() {
use(s[ui32>>23])
use(a1[ui32>>23])
- use(a1k[ui32>>23]) // ERROR "index bounds check elided"
- use(a100k[ui32>>23]) // ERROR "index bounds check elided"
+ use(a1k[ui32>>23]) // ERROR "index bounds check elided"
+ use(a100k[ui32>>23]) // ERROR "index bounds check elided"
use(p1[ui32>>23])
- use(p1k[ui32>>23]) // ERROR "index bounds check elided"
- use(p100k[ui32>>23]) // ERROR "index bounds check elided"
+ use(p1k[ui32>>23]) // ERROR "index bounds check elided"
+ use(p100k[ui32>>23]) // ERROR "index bounds check elided"
// Division cuts the range like right shift does.
use(s[i/1e6])
@@ -263,7 +263,7 @@ func main() {
use(p1[ui/1e7])
}
-var sum int
+var sum int
func use(x int) {
sum += x
diff --git a/test/chancap.go b/test/chancap.go
index b08478a13..9675e38bd 100644
--- a/test/chancap.go
+++ b/test/chancap.go
@@ -42,11 +42,10 @@ func main() {
shouldPanic("makechan: size out of range", func() { _ = make(T, n) })
shouldPanic("makechan: size out of range", func() { _ = make(T, int64(n)) })
if ptrSize == 8 {
- n = 1 << 20
- n <<= 20
- shouldPanic("makechan: size out of range", func() { _ = make(T, n) })
- n <<= 20
- shouldPanic("makechan: size out of range", func() { _ = make(T, n) })
+ var n2 int64 = 1 << 50
+ shouldPanic("makechan: size out of range", func() { _ = make(T, int(n2)) })
+ n2 = 1<<63 - 1
+ shouldPanic("makechan: size out of range", func() { _ = make(T, int(n2)) })
} else {
n = 1<<31 - 1
shouldPanic("makechan: size out of range", func() { _ = make(T, n) })
diff --git a/test/closure3.dir/main.go b/test/closure3.dir/main.go
index 436434316..e382ad980 100644
--- a/test/closure3.dir/main.go
+++ b/test/closure3.dir/main.go
@@ -15,12 +15,12 @@ func main() {
if x := func() int { // ERROR "can inline main.func1"
return 1
}(); x != 1 { // ERROR "inlining call to main.func1"
- panic("x != 1")
+ ppanic("x != 1")
}
if x := func() int { // ERROR "can inline main.func2" "func literal does not escape"
return 1
}; x() != 1 { // ERROR "inlining call to main.func2"
- panic("x() != 1")
+ ppanic("x() != 1")
}
}
@@ -28,12 +28,12 @@ func main() {
if y := func(x int) int { // ERROR "can inline main.func3"
return x + 2
}(40); y != 42 { // ERROR "inlining call to main.func3"
- panic("y != 42")
+ ppanic("y != 42")
}
if y := func(x int) int { // ERROR "can inline main.func4" "func literal does not escape"
return x + 2
}; y(40) != 42 { // ERROR "inlining call to main.func4"
- panic("y(40) != 42")
+ ppanic("y(40) != 42")
}
}
@@ -45,7 +45,7 @@ func main() {
return x + 1
}
if y(40) != 41 {
- panic("y(40) != 41")
+ ppanic("y(40) != 41")
}
}
@@ -58,7 +58,7 @@ func main() {
return x + 1
}
if y(40) != 41 {
- panic("y(40) != 41")
+ ppanic("y(40) != 41")
}
}()
}
@@ -71,7 +71,7 @@ func main() {
return x + 1
}, 42
if y(40) != 41 {
- panic("y(40) != 41")
+ ppanic("y(40) != 41")
}
}
@@ -84,7 +84,7 @@ func main() {
return x + 1
}, 42
if y(40) != 41 {
- panic("y(40) != 41")
+ ppanic("y(40) != 41")
}
}()
}
@@ -93,13 +93,13 @@ func main() {
y := func(x int) int { // ERROR "can inline main.func11" "func literal does not escape"
return x + 2
}
- y, sink = func() (func(int)int, int) { // ERROR "func literal does not escape"
+ y, sink = func() (func(int) int, int) { // ERROR "func literal does not escape"
return func(x int) int { // ERROR "can inline main.func12" "func literal escapes"
return x + 1
}, 42
}()
if y(40) != 41 {
- panic("y(40) != 41")
+ ppanic("y(40) != 41")
}
}
@@ -114,7 +114,7 @@ func main() {
}, 42
}()
if y(40) != 41 {
- panic("y(40) != 41")
+ ppanic("y(40) != 41")
}
}()
}
@@ -123,11 +123,11 @@ func main() {
y := func(x int) int { // ERROR "can inline main.func14" "func literal does not escape"
return x + 2
}
- y, ok = map[int]func(int)int { // ERROR "does not escape"
- 0: func (x int) int { return x + 1 }, // ERROR "can inline main.func15" "func literal escapes"
+ y, ok = map[int]func(int) int{ // ERROR "does not escape"
+ 0: func(x int) int { return x + 1 }, // ERROR "can inline main.func15" "func literal escapes"
}[0]
if y(40) != 41 {
- panic("y(40) != 41")
+ ppanic("y(40) != 41")
}
}
@@ -136,11 +136,11 @@ func main() {
y := func(x int) int { // ERROR "can inline main.func16.1" "func literal does not escape"
return x + 2
}
- y, ok = map[int]func(int) int{// ERROR "does not escape"
+ y, ok = map[int]func(int) int{ // ERROR "does not escape"
0: func(x int) int { return x + 1 }, // ERROR "can inline main.func16.2" "func literal escapes"
}[0]
if y(40) != 41 {
- panic("y(40) != 41")
+ ppanic("y(40) != 41")
}
}()
}
@@ -149,11 +149,11 @@ func main() {
y := func(x int) int { // ERROR "can inline main.func17" "func literal does not escape"
return x + 2
}
- y, ok = interface{}(func (x int) int { // ERROR "can inline main.func18" "does not escape"
+ y, ok = interface{}(func(x int) int { // ERROR "can inline main.func18" "does not escape"
return x + 1
- }).(func(int)int)
+ }).(func(int) int)
if y(40) != 41 {
- panic("y(40) != 41")
+ ppanic("y(40) != 41")
}
}
@@ -166,7 +166,7 @@ func main() {
return x + 1
}).(func(int) int)
if y(40) != 41 {
- panic("y(40) != 41")
+ ppanic("y(40) != 41")
}
}()
}
@@ -176,12 +176,12 @@ func main() {
if y := func() int { // ERROR "can inline main.func20"
return x
}(); y != 42 { // ERROR "inlining call to main.func20"
- panic("y != 42")
+ ppanic("y != 42")
}
if y := func() int { // ERROR "can inline main.func21" "func literal does not escape"
return x
}; y() != 42 { // ERROR "inlining call to main.func21"
- panic("y() != 42")
+ ppanic("y() != 42")
}
}
@@ -192,14 +192,14 @@ func main() {
return x + y
}() // ERROR "inlining call to main.func22.1"
}(1); z != 43 {
- panic("z != 43")
+ ppanic("z != 43")
}
if z := func(y int) int { // ERROR "func literal does not escape"
return func() int { // ERROR "can inline main.func23.1"
return x + y
}() // ERROR "inlining call to main.func23.1"
}; z(1) != 43 {
- panic("z(1) != 43")
+ ppanic("z(1) != 43")
}
}
@@ -211,7 +211,7 @@ func main() {
}() // ERROR "inlining call to main.func24" "&a does not escape"
}()
if a != 2 {
- panic("a != 2")
+ ppanic("a != 2")
}
}
@@ -222,11 +222,11 @@ func main() {
b = 3
}() // ERROR "inlining call to main.func25.1" "&b does not escape"
if b != 3 {
- panic("b != 3")
+ ppanic("b != 3")
}
}(b)
if b != 2 {
- panic("b != 2")
+ ppanic("b != 2")
}
}
@@ -236,12 +236,12 @@ func main() {
c = 4
func() { // ERROR "func literal does not escape"
if c != 4 {
- panic("c != 4")
+ ppanic("c != 4")
}
}()
}()
if c != 4 {
- panic("c != 4")
+ ppanic("c != 4")
}
}
@@ -256,7 +256,7 @@ func main() {
}(10) // ERROR "inlining call to main.func27.1.1"
}(100)
}(1000); r != 2350 {
- panic("r != 2350")
+ ppanic("r != 2350")
}
}
@@ -274,10 +274,15 @@ func main() {
return a + c
}(100) + b
}(1000); r != 2350 {
- panic("r != 2350")
+ ppanic("r != 2350")
}
if a != 2000 {
- panic("a != 2000")
+ ppanic("a != 2000")
}
}
}
+
+//go:noinline
+func ppanic(s string) { // ERROR "leaking param: s"
+ panic(s)
+}
diff --git a/test/closure4.go b/test/closure4.go
new file mode 100644
index 000000000..ec4e0a18e
--- /dev/null
+++ b/test/closure4.go
@@ -0,0 +1,21 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that calling a nil func causes a proper panic.
+
+package main
+
+func main() {
+ defer func() {
+ err := recover()
+ if err == nil {
+ panic("panic expected")
+ }
+ }()
+
+ var f func()
+ f()
+}
diff --git a/test/codegen/README b/test/codegen/README
new file mode 100644
index 000000000..298d807bd
--- /dev/null
+++ b/test/codegen/README
@@ -0,0 +1,147 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+The codegen directory contains code generation tests for the gc
+compiler.
+
+
+- Introduction
+
+The test harness compiles Go code inside files in this directory and
+then matches the generated assembly (the output of `go tool compile -S`)
+against a set of regexps specified in comments that follow a special
+syntax (described below). The test driver is implemented as a step of
+the top-level test/run.go suite, called "asmcheck".
+
+The codegen tests run during all.bash, but can also be run in
+isolation by using
+
+ $ ../bin/go run run.go -v codegen
+
+in the top-level test directory.
+
+The test harness compiles the tests with the same go toolchain that is
+used to run run.go. After writing tests for a newly added codegen
+transformation, it can be useful to first run the test harness with a
+toolchain from a released Go version (and verify that the new tests
+fail), and then re-runnig the tests using the devel toolchain.
+
+
+- Regexps comments syntax
+
+Instructions to match are specified inside plain comments that start
+with an architecture tag, followed by a colon and a quoted Go-style
+regexp to be matched. For example, the following test:
+
+ func Sqrt(x float64) float64 {
+ // amd64:"SQRTSD"
+ // arm64:"FSQRTD"
+ return math.Sqrt(x)
+ }
+
+verifies that math.Sqrt calls are intrinsified to a SQRTSD instruction
+on amd64, and to a FSQRTD instruction on arm64.
+
+It is possible to put multiple architectures checks into the same
+line, as:
+
+ // amd64:"SQRTSD" arm64:"FSQRTD"
+
+although this form should be avoided when doing so would make the
+regexps line excessively long and difficult to read.
+
+Comments that are on their own line will be matched against the first
+subsequent non-comment line. Inline comments are also supported; the
+regexp will be matched against the code found on the same line:
+
+ func Sqrt(x float64) float64 {
+ return math.Sqrt(x) // arm:"SQRTD"
+ }
+
+It's possible to specify a comma-separated list of regexps to be
+matched. For example, the following test:
+
+ func TZ8(n uint8) int {
+ // amd64:"BSFQ","ORQ\t\\$256"
+ return bits.TrailingZeros8(n)
+ }
+
+verifies that the code generated for a bits.TrailingZeros8 call on
+amd64 contains both a "BSFQ" instruction and an "ORQ $256".
+
+Note how the ORQ regex includes a tab char (\t). In the Go assembly
+syntax, operands are separated from opcodes by a tabulation.
+
+Regexps can be quoted using either " or `. Special characters must be
+escaped accordingly. Both of these are accepted, and equivalent:
+
+ // amd64:"ADDQ\t\\$3"
+ // amd64:`ADDQ\t\$3`
+
+and they'll match this assembly line:
+
+ ADDQ $3
+
+Negative matches can be specified using a - before the quoted regexp.
+For example:
+
+ func MoveSmall() {
+ x := [...]byte{1, 2, 3, 4, 5, 6, 7}
+ copy(x[1:], x[:]) // arm64:-".*memmove"
+ }
+
+verifies that NO memmove call is present in the assembly generated for
+the copy() line.
+
+- Architecture specifiers
+
+There are three different ways to specify on which architecture a test
+should be run:
+
+* Specify only the architecture (eg: "amd64"). This indicates that the
+ check should be run on all the supported architecture variants. For
+ instance, arm checks will be run against all supported GOARM
+ variations (5,6,7).
+* Specify both the architecture and a variant, separated by a slash
+ (eg: "arm/7"). This means that the check will be run only on that
+ specific variant.
+* Specify the operating system, the architecture and the variant,
+ separated by slashes (eg: "plan9/386/sse2", "plan9/amd64/"). This is
+ needed in the rare case that you need to do a codegen test affected
+ by a specific operating system; by default, tests are compiled only
+ targeting linux.
+
+
+- Remarks, and Caveats
+
+-- Write small test functions
+
+As a general guideline, test functions should be small, to avoid
+possible interactions between unrelated lines of code that may be
+introduced, for example, by the compiler's optimization passes.
+
+Any given line of Go code could get assigned more instructions that it
+may appear from reading the source. In particular, matching all MOV
+instructions should be avoided; the compiler may add them for
+unrelated reasons and this may render the test ineffective.
+
+-- Line matching logic
+
+Regexps are always matched from the start of the instructions line.
+This means, for example, that the "MULQ" regexp is equivalent to
+"^MULQ" (^ representing the start of the line), and it will NOT match
+the following assembly line:
+
+ IMULQ $99, AX
+
+To force a match at any point of the line, ".*MULQ" should be used.
+
+For the same reason, a negative regexp like -"memmove" is not enough
+to make sure that no memmove call is included in the assembly. A
+memmove call looks like this:
+
+ CALL runtime.memmove(SB)
+
+To make sure that the "memmove" symbol does not appear anywhere in the
+assembly, the negative regexp to be used is -".*memmove".
diff --git a/test/codegen/arithmetic.go b/test/codegen/arithmetic.go
new file mode 100644
index 000000000..f358020f5
--- /dev/null
+++ b/test/codegen/arithmetic.go
@@ -0,0 +1,184 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+// This file contains codegen tests related to arithmetic
+// simplifications and optimizations on integer types.
+// For codegen tests on float types, see floats.go.
+
+// ----------------- //
+// Subtraction //
+// ----------------- //
+
+func SubMem(arr []int, b int) int {
+ // 386:`SUBL\s[A-Z]+,\s8\([A-Z]+\)`
+ arr[2] -= b
+ // 386:`SUBL\s[A-Z]+,\s12\([A-Z]+\)`
+ arr[3] -= b
+ // 386:"SUBL\t4"
+ // amd64:"SUBQ\t8"
+ return arr[0] - arr[1]
+}
+
+// -------------------- //
+// Multiplication //
+// -------------------- //
+
+func Pow2Muls(n1, n2 int) (int, int) {
+ // amd64:"SHLQ\t[$]5",-"IMULQ"
+ // 386:"SHLL\t[$]5",-"IMULL"
+ // arm:"SLL\t[$]5",-"MUL"
+ // arm64:"LSL\t[$]5",-"MUL"
+ a := n1 * 32
+
+ // amd64:"SHLQ\t[$]6",-"IMULQ"
+ // 386:"SHLL\t[$]6",-"IMULL"
+ // arm:"SLL\t[$]6",-"MUL"
+ // arm64:"LSL\t[$]6",-"MUL"
+ b := -64 * n2
+
+ return a, b
+}
+
+func Mul_96(n int) int {
+ // amd64:`SHLQ\t[$]5`,`LEAQ\t\(.*\)\(.*\*2\),`
+ return n * 96
+}
+
+// Multiplications merging tests
+
+func MergeMuls1(n int) int {
+ // amd64:"IMUL3Q\t[$]46"
+ // 386:"IMUL3L\t[$]46"
+ return 15*n + 31*n // 46n
+}
+
+func MergeMuls2(n int) int {
+ // amd64:"IMUL3Q\t[$]23","ADDQ\t[$]29"
+ // 386:"IMUL3L\t[$]23","ADDL\t[$]29"
+ return 5*n + 7*(n+1) + 11*(n+2) // 23n + 29
+}
+
+func MergeMuls3(a, n int) int {
+ // amd64:"ADDQ\t[$]19",-"IMULQ\t[$]19"
+ // 386:"ADDL\t[$]19",-"IMULL\t[$]19"
+ return a*n + 19*n // (a+19)n
+}
+
+func MergeMuls4(n int) int {
+ // amd64:"IMUL3Q\t[$]14"
+ // 386:"IMUL3L\t[$]14"
+ return 23*n - 9*n // 14n
+}
+
+func MergeMuls5(a, n int) int {
+ // amd64:"ADDQ\t[$]-19",-"IMULQ\t[$]19"
+ // 386:"ADDL\t[$]-19",-"IMULL\t[$]19"
+ return a*n - 19*n // (a-19)n
+}
+
+// -------------- //
+// Division //
+// -------------- //
+
+func Pow2Divs(n1 uint, n2 int) (uint, int) {
+ // 386:"SHRL\t[$]5",-"DIVL"
+ // amd64:"SHRQ\t[$]5",-"DIVQ"
+ // arm:"SRL\t[$]5",-".*udiv"
+ // arm64:"LSR\t[$]5",-"UDIV"
+ a := n1 / 32 // unsigned
+
+ // amd64:"SARQ\t[$]6",-"IDIVQ"
+ // 386:"SARL\t[$]6",-"IDIVL"
+ // arm:"SRA\t[$]6",-".*udiv"
+ // arm64:"ASR\t[$]6",-"SDIV"
+ b := n2 / 64 // signed
+
+ return a, b
+}
+
+// Check that constant divisions get turned into MULs
+func ConstDivs(n1 uint, n2 int) (uint, int) {
+ // amd64:"MOVQ\t[$]-1085102592571150095","MULQ",-"DIVQ"
+ a := n1 / 17 // unsigned
+
+ // amd64:"MOVQ\t[$]-1085102592571150095","IMULQ",-"IDIVQ"
+ b := n2 / 17 // signed
+
+ return a, b
+}
+
+func Pow2Mods(n1 uint, n2 int) (uint, int) {
+ // 386:"ANDL\t[$]31",-"DIVL"
+ // amd64:"ANDQ\t[$]31",-"DIVQ"
+ // arm:"AND\t[$]31",-".*udiv"
+ // arm64:"AND\t[$]31",-"UDIV"
+ a := n1 % 32 // unsigned
+
+ // 386:-"IDIVL"
+ // amd64:-"IDIVQ"
+ // arm:-".*udiv"
+ // arm64:-"REM"
+ b := n2 % 64 // signed
+
+ return a, b
+}
+
+// Check that constant modulo divs get turned into MULs
+func ConstMods(n1 uint, n2 int) (uint, int) {
+ // amd64:"MOVQ\t[$]-1085102592571150095","MULQ",-"DIVQ"
+ a := n1 % 17 // unsigned
+
+ // amd64:"MOVQ\t[$]-1085102592571150095","IMULQ",-"IDIVQ"
+ b := n2 % 17 // signed
+
+ return a, b
+}
+
+// Check that len() and cap() calls divided by powers of two are
+// optimized into shifts and ands
+
+func LenDiv1(a []int) int {
+ // 386:"SHRL\t[$]10"
+ // amd64:"SHRQ\t[$]10"
+ return len(a) / 1024
+}
+
+func LenDiv2(s string) int {
+ // 386:"SHRL\t[$]11"
+ // amd64:"SHRQ\t[$]11"
+ return len(s) / (4097 >> 1)
+}
+
+func LenMod1(a []int) int {
+ // 386:"ANDL\t[$]1023"
+ // amd64:"ANDQ\t[$]1023"
+ return len(a) % 1024
+}
+
+func LenMod2(s string) int {
+ // 386:"ANDL\t[$]2047"
+ // amd64:"ANDQ\t[$]2047"
+ return len(s) % (4097 >> 1)
+}
+
+func CapDiv(a []int) int {
+ // 386:"SHRL\t[$]12"
+ // amd64:"SHRQ\t[$]12"
+ return cap(a) / ((1 << 11) + 2048)
+}
+
+func CapMod(a []int) int {
+ // 386:"ANDL\t[$]4095"
+ // amd64:"ANDQ\t[$]4095"
+ return cap(a) % ((1 << 11) + 2048)
+}
+
+func AddMul(x int) int {
+ // amd64:"LEAQ\t1"
+ return 2*x + 1
+}
diff --git a/test/codegen/bitfield.go b/test/codegen/bitfield.go
new file mode 100644
index 000000000..08788f144
--- /dev/null
+++ b/test/codegen/bitfield.go
@@ -0,0 +1,232 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+// This file contains codegen tests related to bit field
+// insertion/extraction simplifications/optimizations.
+
+func extr1(x, x2 uint64) uint64 {
+ return x<<7 + x2>>57 // arm64:"EXTR\t[$]57,"
+}
+
+func extr2(x, x2 uint64) uint64 {
+ return x<<7 | x2>>57 // arm64:"EXTR\t[$]57,"
+}
+
+func extr3(x, x2 uint64) uint64 {
+ return x<<7 ^ x2>>57 // arm64:"EXTR\t[$]57,"
+}
+
+func extr4(x, x2 uint32) uint32 {
+ return x<<7 + x2>>25 // arm64:"EXTRW\t[$]25,"
+}
+
+func extr5(x, x2 uint32) uint32 {
+ return x<<7 | x2>>25 // arm64:"EXTRW\t[$]25,"
+}
+
+func extr6(x, x2 uint32) uint32 {
+ return x<<7 ^ x2>>25 // arm64:"EXTRW\t[$]25,"
+}
+
+// check 32-bit shift masking
+func mask32(x uint32) uint32 {
+ return (x << 29) >> 29 // arm64:"AND\t[$]7, R[0-9]+",-"LSR",-"LSL"
+}
+
+// check 16-bit shift masking
+func mask16(x uint16) uint16 {
+ return (x << 14) >> 14 // arm64:"AND\t[$]3, R[0-9]+",-"LSR",-"LSL"
+}
+
+// check 8-bit shift masking
+func mask8(x uint8) uint8 {
+ return (x << 7) >> 7 // arm64:"AND\t[$]1, R[0-9]+",-"LSR",-"LSL"
+}
+
+func maskshift(x uint64) uint64 {
+ // arm64:"AND\t[$]4095, R[0-9]+",-"LSL",-"LSR",-"UBFIZ",-"UBFX"
+ return ((x << 5) & (0xfff << 5)) >> 5
+}
+
+// bitfield ops
+// bfi
+func bfi1(x, y uint64) uint64 {
+ // arm64:"BFI\t[$]4, R[0-9]+, [$]12",-"LSL",-"LSR",-"AND"
+ return ((x & 0xfff) << 4) | (y & 0xffffffffffff000f)
+}
+
+func bfi2(x, y uint64) uint64 {
+ // arm64:"BFI\t[$]12, R[0-9]+, [$]40",-"LSL",-"LSR",-"AND"
+ return (x << 24 >> 12) | (y & 0xfff0000000000fff)
+}
+
+// bfxil
+func bfxil1(x, y uint64) uint64 {
+ // arm64:"BFXIL\t[$]5, R[0-9]+, [$]12",-"LSL",-"LSR",-"AND"
+ return ((x >> 5) & 0xfff) | (y & 0xfffffffffffff000)
+}
+
+func bfxil2(x, y uint64) uint64 {
+ // arm64:"BFXIL\t[$]12, R[0-9]+, [$]40",-"LSL",-"LSR",-"AND"
+ return (x << 12 >> 24) | (y & 0xffffff0000000000)
+}
+
+// sbfiz
+func sbfiz1(x int64) int64 {
+ // arm64:"SBFIZ\t[$]1, R[0-9]+, [$]60",-"LSL",-"ASR"
+ return (x << 4) >> 3
+}
+
+func sbfiz2(x int32) int64 {
+ return int64(x << 3) // arm64:"SBFIZ\t[$]3, R[0-9]+, [$]29",-"LSL"
+}
+
+func sbfiz3(x int16) int64 {
+ return int64(x << 3) // arm64:"SBFIZ\t[$]3, R[0-9]+, [$]13",-"LSL"
+}
+
+func sbfiz4(x int8) int64 {
+ return int64(x << 3) // arm64:"SBFIZ\t[$]3, R[0-9]+, [$]5",-"LSL"
+}
+
+func sbfiz5(x int32) int32 {
+ // arm64:"SBFIZ\t[$]1, R[0-9]+, [$]28",-"LSL",-"ASR"
+ return (x << 4) >> 3
+}
+
+// sbfx
+func sbfx1(x int64) int64 {
+ return (x << 3) >> 4 // arm64:"SBFX\t[$]1, R[0-9]+, [$]60",-"LSL",-"ASR"
+}
+
+func sbfx2(x int64) int64 {
+ return (x << 60) >> 60 // arm64:"SBFX\tZR, R[0-9]+, [$]4",-"LSL",-"ASR"
+}
+
+func sbfx3(x int32) int64 {
+ return int64(x) >> 3 // arm64:"SBFX\t[$]3, R[0-9]+, [$]29",-"ASR"
+}
+
+func sbfx4(x int16) int64 {
+ return int64(x) >> 3 // arm64:"SBFX\t[$]3, R[0-9]+, [$]13",-"ASR"
+}
+
+func sbfx5(x int8) int64 {
+ return int64(x) >> 3 // arm64:"SBFX\t[$]3, R[0-9]+, [$]5",-"ASR"
+}
+
+func sbfx6(x int32) int32 {
+ return (x << 3) >> 4 // arm64:"SBFX\t[$]1, R[0-9]+, [$]28",-"LSL",-"ASR"
+}
+
+// ubfiz
+func ubfiz1(x uint64) uint64 {
+ // arm64:"UBFIZ\t[$]3, R[0-9]+, [$]12",-"LSL",-"AND"
+ return (x & 0xfff) << 3
+}
+
+func ubfiz2(x uint64) uint64 {
+ // arm64:"UBFIZ\t[$]4, R[0-9]+, [$]12",-"LSL",-"AND"
+ return (x << 4) & 0xfff0
+}
+
+func ubfiz3(x uint32) uint64 {
+ return uint64(x+1) << 3 // arm64:"UBFIZ\t[$]3, R[0-9]+, [$]32",-"LSL"
+}
+
+func ubfiz4(x uint16) uint64 {
+ return uint64(x+1) << 3 // arm64:"UBFIZ\t[$]3, R[0-9]+, [$]16",-"LSL"
+}
+
+func ubfiz5(x uint8) uint64 {
+ return uint64(x+1) << 3 // arm64:"UBFIZ\t[$]3, R[0-9]+, [$]8",-"LSL"
+}
+
+func ubfiz6(x uint64) uint64 {
+ // arm64:"UBFIZ\t[$]1, R[0-9]+, [$]60",-"LSL",-"LSR"
+ return (x << 4) >> 3
+}
+
+func ubfiz7(x uint32) uint32 {
+ // arm64:"UBFIZ\t[$]1, R[0-9]+, [$]28",-"LSL",-"LSR"
+ return (x << 4) >> 3
+}
+
+func ubfiz8(x uint64) uint64 {
+ // arm64:"UBFIZ\t[$]1, R[0-9]+, [$]20",-"LSL",-"LSR"
+ return ((x & 0xfffff) << 4) >> 3
+}
+
+func ubfiz9(x uint64) uint64 {
+ // arm64:"UBFIZ\t[$]5, R[0-9]+, [$]13",-"LSL",-"LSR",-"AND"
+ return ((x << 3) & 0xffff) << 2
+}
+
+func ubfiz10(x uint64) uint64 {
+ // arm64:"UBFIZ\t[$]7, R[0-9]+, [$]12",-"LSL",-"LSR",-"AND"
+ return ((x << 5) & (0xfff << 5)) << 2
+}
+
+// ubfx
+func ubfx1(x uint64) uint64 {
+ // arm64:"UBFX\t[$]25, R[0-9]+, [$]10",-"LSR",-"AND"
+ return (x >> 25) & 1023
+}
+
+func ubfx2(x uint64) uint64 {
+ // arm64:"UBFX\t[$]4, R[0-9]+, [$]8",-"LSR",-"AND"
+ return (x & 0x0ff0) >> 4
+}
+
+func ubfx3(x uint32) uint64 {
+ return uint64(x >> 15) // arm64:"UBFX\t[$]15, R[0-9]+, [$]17",-"LSR"
+}
+
+func ubfx4(x uint16) uint64 {
+ return uint64(x >> 9) // arm64:"UBFX\t[$]9, R[0-9]+, [$]7",-"LSR"
+}
+
+func ubfx5(x uint8) uint64 {
+ return uint64(x >> 3) // arm64:"UBFX\t[$]3, R[0-9]+, [$]5",-"LSR"
+}
+
+func ubfx6(x uint64) uint64 {
+ return (x << 1) >> 2 // arm64:"UBFX\t[$]1, R[0-9]+, [$]62",-"LSL",-"LSR"
+}
+
+func ubfx7(x uint32) uint32 {
+ return (x << 1) >> 2 // arm64:"UBFX\t[$]1, R[0-9]+, [$]30",-"LSL",-"LSR"
+}
+
+func ubfx8(x uint64) uint64 {
+ // arm64:"UBFX\t[$]1, R[0-9]+, [$]12",-"LSL",-"LSR",-"AND"
+ return ((x << 1) >> 2) & 0xfff
+}
+
+func ubfx9(x uint64) uint64 {
+ // arm64:"UBFX\t[$]4, R[0-9]+, [$]11",-"LSL",-"LSR",-"AND"
+ return ((x >> 3) & 0xfff) >> 1
+}
+
+func ubfx10(x uint64) uint64 {
+ // arm64:"UBFX\t[$]5, R[0-9]+, [$]56",-"LSL",-"LSR"
+ return ((x >> 2) << 5) >> 8
+}
+
+func ubfx11(x uint64) uint64 {
+ // arm64:"UBFX\t[$]1, R[0-9]+, [$]19",-"LSL",-"LSR"
+ return ((x & 0xfffff) << 3) >> 4
+}
+
+// Check that we don't emit comparisons for constant shifts.
+//go:nosplit
+func shift_no_cmp(x int) int {
+ // arm64:`LSL\t[$]17`,-`CMP`
+ // mips64:`SLLV\t[$]17`,-`SGT`
+ return x << 17
+}
diff --git a/test/codegen/bits.go b/test/codegen/bits.go
new file mode 100644
index 000000000..9de2201cb
--- /dev/null
+++ b/test/codegen/bits.go
@@ -0,0 +1,292 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+/************************************
+ * 64-bit instructions
+ ************************************/
+
+func bitcheck64_constleft(a uint64) (n int) {
+ // amd64:"BTQ\t[$]63"
+ if a&(1<<63) != 0 {
+ return 1
+ }
+ // amd64:"BTQ\t[$]60"
+ if a&(1<<60) != 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]0"
+ if a&(1<<0) != 0 {
+ return 1
+ }
+ return 0
+}
+
+func bitcheck64_constright(a [8]uint64) (n int) {
+ // amd64:"BTQ\t[$]63"
+ if (a[0]>>63)&1 != 0 {
+ return 1
+ }
+ // amd64:"BTQ\t[$]63"
+ if a[1]>>63 != 0 {
+ return 1
+ }
+ // amd64:"BTQ\t[$]63"
+ if a[2]>>63 == 0 {
+ return 1
+ }
+ // amd64:"BTQ\t[$]60"
+ if (a[3]>>60)&1 == 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]1"
+ if (a[4]>>1)&1 == 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]0"
+ if (a[5]>>0)&1 == 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]7"
+ if (a[6]>>5)&4 == 0 {
+ return 1
+ }
+ return 0
+}
+
+func bitcheck64_var(a, b uint64) (n int) {
+ // amd64:"BTQ"
+ if a&(1<<(b&63)) != 0 {
+ return 1
+ }
+ // amd64:"BTQ",-"BT.\t[$]0"
+ if (b>>(a&63))&1 != 0 {
+ return 1
+ }
+ return 0
+}
+
+func bitcheck64_mask(a uint64) (n int) {
+ // amd64:"BTQ\t[$]63"
+ if a&0x8000000000000000 != 0 {
+ return 1
+ }
+ // amd64:"BTQ\t[$]59"
+ if a&0x800000000000000 != 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]0"
+ if a&0x1 != 0 {
+ return 1
+ }
+ return 0
+}
+
+func biton64(a, b uint64) (n uint64) {
+ // amd64:"BTSQ"
+ n += b | (1 << (a & 63))
+
+ // amd64:"BTSQ\t[$]63"
+ n += a | (1 << 63)
+
+ // amd64:"BTSQ\t[$]60"
+ n += a | (1 << 60)
+
+ // amd64:"ORQ\t[$]1"
+ n += a | (1 << 0)
+
+ return n
+}
+
+func bitoff64(a, b uint64) (n uint64) {
+ // amd64:"BTRQ"
+ n += b &^ (1 << (a & 63))
+
+ // amd64:"BTRQ\t[$]63"
+ n += a &^ (1 << 63)
+
+ // amd64:"BTRQ\t[$]60"
+ n += a &^ (1 << 60)
+
+ // amd64:"ANDQ\t[$]-2"
+ n += a &^ (1 << 0)
+
+ return n
+}
+
+func bitcompl64(a, b uint64) (n uint64) {
+ // amd64:"BTCQ"
+ n += b ^ (1 << (a & 63))
+
+ // amd64:"BTCQ\t[$]63"
+ n += a ^ (1 << 63)
+
+ // amd64:"BTCQ\t[$]60"
+ n += a ^ (1 << 60)
+
+ // amd64:"XORQ\t[$]1"
+ n += a ^ (1 << 0)
+
+ return n
+}
+
+/************************************
+ * 32-bit instructions
+ ************************************/
+
+func bitcheck32_constleft(a uint32) (n int) {
+ // amd64:"BTL\t[$]31"
+ if a&(1<<31) != 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]28"
+ if a&(1<<28) != 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]0"
+ if a&(1<<0) != 0 {
+ return 1
+ }
+ return 0
+}
+
+func bitcheck32_constright(a [8]uint32) (n int) {
+ // amd64:"BTL\t[$]31"
+ if (a[0]>>31)&1 != 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]31"
+ if a[1]>>31 != 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]31"
+ if a[2]>>31 == 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]28"
+ if (a[3]>>28)&1 == 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]1"
+ if (a[4]>>1)&1 == 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]0"
+ if (a[5]>>0)&1 == 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]7"
+ if (a[6]>>5)&4 == 0 {
+ return 1
+ }
+ return 0
+}
+
+func bitcheck32_var(a, b uint32) (n int) {
+ // amd64:"BTL"
+ if a&(1<<(b&31)) != 0 {
+ return 1
+ }
+ // amd64:"BTL",-"BT.\t[$]0"
+ if (b>>(a&31))&1 != 0 {
+ return 1
+ }
+ return 0
+}
+
+func bitcheck32_mask(a uint32) (n int) {
+ // amd64:"BTL\t[$]31"
+ if a&0x80000000 != 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]27"
+ if a&0x8000000 != 0 {
+ return 1
+ }
+ // amd64:"BTL\t[$]0"
+ if a&0x1 != 0 {
+ return 1
+ }
+ return 0
+}
+
+func biton32(a, b uint32) (n uint32) {
+ // amd64:"BTSL"
+ n += b | (1 << (a & 31))
+
+ // amd64:"BTSL\t[$]31"
+ n += a | (1 << 31)
+
+ // amd64:"BTSL\t[$]28"
+ n += a | (1 << 28)
+
+ // amd64:"ORL\t[$]1"
+ n += a | (1 << 0)
+
+ return n
+}
+
+func bitoff32(a, b uint32) (n uint32) {
+ // amd64:"BTRL"
+ n += b &^ (1 << (a & 31))
+
+ // amd64:"BTRL\t[$]31"
+ n += a &^ (1 << 31)
+
+ // amd64:"BTRL\t[$]28"
+ n += a &^ (1 << 28)
+
+ // amd64:"ANDL\t[$]-2"
+ n += a &^ (1 << 0)
+
+ return n
+}
+
+func bitcompl32(a, b uint32) (n uint32) {
+ // amd64:"BTCL"
+ n += b ^ (1 << (a & 31))
+
+ // amd64:"BTCL\t[$]31"
+ n += a ^ (1 << 31)
+
+ // amd64:"BTCL\t[$]28"
+ n += a ^ (1 << 28)
+
+ // amd64:"XORL\t[$]1"
+ n += a ^ (1 << 0)
+
+ return n
+}
+
+// Check AND masking on arm64 (Issue #19857)
+
+func and_mask_1(a uint64) uint64 {
+ // arm64:`AND\t`
+ return a & ((1 << 63) - 1)
+}
+
+func and_mask_2(a uint64) uint64 {
+ // arm64:`AND\t`
+ return a & (1 << 63)
+}
+
+// Check generation of arm64 BIC/EON/ORN instructions
+
+func op_bic(x, y uint32) uint32 {
+ // arm64:`BIC\t`,-`AND`
+ return x &^ y
+}
+
+func op_eon(x, y uint32) uint32 {
+ // arm64:`EON\t`,-`XOR`
+ return x ^ ^y
+}
+
+func op_orn(x, y uint32) uint32 {
+ // arm64:`ORN\t`,-`ORR`
+ return x | ^y
+}
diff --git a/test/codegen/comparisons.go b/test/codegen/comparisons.go
new file mode 100644
index 000000000..2f010bcba
--- /dev/null
+++ b/test/codegen/comparisons.go
@@ -0,0 +1,149 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+import "unsafe"
+
+// This file contains code generation tests related to the comparison
+// operators.
+
+// -------------- //
+// Equality //
+// -------------- //
+
+// Check that compare to constant string use 2/4/8 byte compares
+
+func CompareString1(s string) bool {
+ // amd64:`CMPW\t\(.*\), [$]`
+ // arm64:`MOVHU\t\(.*\), [R]`,`CMPW\t[$]`
+ // ppc64le:`MOVHZ\t\(.*\), [R]`,`CMPW\t.*, [$]`
+ // s390x:`MOVHBR\t\(.*\), [R]`,`CMPW\t.*, [$]`
+ return s == "xx"
+}
+
+func CompareString2(s string) bool {
+ // amd64:`CMPL\t\(.*\), [$]`
+ // arm64:`MOVWU\t\(.*\), [R]`,`CMPW\t.*, [R]`
+ // ppc64le:`MOVWZ\t\(.*\), [R]`,`CMPW\t.*, [R]`
+ // s390x:`MOVWBR\t\(.*\), [R]`,`CMPW\t.*, [$]`
+ return s == "xxxx"
+}
+
+func CompareString3(s string) bool {
+ // amd64:`CMPQ\t\(.*\), [A-Z]`
+ // arm64:-`CMPW\t`
+ // ppc64le:-`CMPW\t`
+ // s390x:-`CMPW\t`
+ return s == "xxxxxxxx"
+}
+
+// Check that arrays compare use 2/4/8 byte compares
+
+func CompareArray1(a, b [2]byte) bool {
+ // amd64:`CMPW\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ // arm64:-`MOVBU\t`
+ // ppc64le:-`MOVBZ\t`
+ // s390x:-`MOVBZ\t`
+ return a == b
+}
+
+func CompareArray2(a, b [3]uint16) bool {
+ // amd64:`CMPL\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ // amd64:`CMPW\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ return a == b
+}
+
+func CompareArray3(a, b [3]int16) bool {
+ // amd64:`CMPL\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ // amd64:`CMPW\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ return a == b
+}
+
+func CompareArray4(a, b [12]int8) bool {
+ // amd64:`CMPQ\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ // amd64:`CMPL\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ return a == b
+}
+
+func CompareArray5(a, b [15]byte) bool {
+ // amd64:`CMPQ\t""[.+_a-z0-9]+\(SP\), [A-Z]`
+ return a == b
+}
+
+// This was a TODO in mapaccess1_faststr
+func CompareArray6(a, b unsafe.Pointer) bool {
+ // amd64:`CMPL\t\(.*\), [A-Z]`
+ // arm64:`MOVWU\t\(.*\), [R]`,`CMPW\t.*, [R]`
+ // ppc64le:`MOVWZ\t\(.*\), [R]`,`CMPW\t.*, [R]`
+ // s390x:`MOVWBR\t\(.*\), [R]`,`CMPW\t.*, [R]`
+ return *((*[4]byte)(a)) != *((*[4]byte)(b))
+}
+
+// -------------- //
+// Ordering //
+// -------------- //
+
+// Test that LEAQ/ADDQconst are folded into SETx ops
+
+func CmpFold(x uint32) bool {
+ // amd64:`SETHI\t.*\(SP\)`
+ return x > 4
+}
+
+// Test that direct comparisons with memory are generated when
+// possible
+
+func CmpMem1(p int, q *int) bool {
+ // amd64:`CMPQ\t\(.*\), [A-Z]`
+ return p < *q
+}
+
+func CmpMem2(p *int, q int) bool {
+ // amd64:`CMPQ\t\(.*\), [A-Z]`
+ return *p < q
+}
+
+func CmpMem3(p *int) bool {
+ // amd64:`CMPQ\t\(.*\), [$]7`
+ return *p < 7
+}
+
+func CmpMem4(p *int) bool {
+ // amd64:`CMPQ\t\(.*\), [$]7`
+ return 7 < *p
+}
+
+func CmpMem5(p **int) {
+ // amd64:`CMPL\truntime.writeBarrier\(SB\), [$]0`
+ *p = nil
+}
+
+// Check tbz/tbnz are generated when comparing against zero on arm64
+
+func CmpZero1(a int32, ptr *int) {
+ if a < 0 { // arm64:"TBZ"
+ *ptr = 0
+ }
+}
+
+func CmpZero2(a int64, ptr *int) {
+ if a < 0 { // arm64:"TBZ"
+ *ptr = 0
+ }
+}
+
+func CmpZero3(a int32, ptr *int) {
+ if a >= 0 { // arm64:"TBNZ"
+ *ptr = 0
+ }
+}
+
+func CmpZero4(a int64, ptr *int) {
+ if a >= 0 { // arm64:"TBNZ"
+ *ptr = 0
+ }
+}
diff --git a/test/codegen/condmove.go b/test/codegen/condmove.go
new file mode 100644
index 000000000..32039c16a
--- /dev/null
+++ b/test/codegen/condmove.go
@@ -0,0 +1,182 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+func cmovint(c int) int {
+ x := c + 4
+ if x < 0 {
+ x = 182
+ }
+ // amd64:"CMOVQLT"
+ // arm64:"CSEL\tLT"
+ return x
+}
+
+func cmovchan(x, y chan int) chan int {
+ if x != y {
+ x = y
+ }
+ // amd64:"CMOVQNE"
+ // arm64:"CSEL\tNE"
+ return x
+}
+
+func cmovuintptr(x, y uintptr) uintptr {
+ if x < y {
+ x = -y
+ }
+ // amd64:"CMOVQCS"
+ // arm64:"CSEL\tLO"
+ return x
+}
+
+func cmov32bit(x, y uint32) uint32 {
+ if x < y {
+ x = -y
+ }
+ // amd64:"CMOVLCS"
+ // arm64:"CSEL\tLO"
+ return x
+}
+
+func cmov16bit(x, y uint16) uint16 {
+ if x < y {
+ x = -y
+ }
+ // amd64:"CMOVWCS"
+ // arm64:"CSEL\tLO"
+ return x
+}
+
+// Floating point comparison. For EQ/NE, we must
+// generate special code to handle NaNs.
+func cmovfloateq(x, y float64) int {
+ a := 128
+ if x == y {
+ a = 256
+ }
+ // amd64:"CMOVQNE","CMOVQPC"
+ // arm64:"CSEL\tEQ"
+ return a
+}
+
+func cmovfloatne(x, y float64) int {
+ a := 128
+ if x != y {
+ a = 256
+ }
+ // amd64:"CMOVQNE","CMOVQPS"
+ // arm64:"CSEL\tNE"
+ return a
+}
+
+//go:noinline
+func frexp(f float64) (frac float64, exp int) {
+ return 1.0, 4
+}
+
+//go:noinline
+func ldexp(frac float64, exp int) float64 {
+ return 1.0
+}
+
+// Generate a CMOV with a floating comparison and integer move.
+func cmovfloatint2(x, y float64) float64 {
+ yfr, yexp := 4.0, 5
+
+ r := x
+ for r >= y {
+ rfr, rexp := frexp(r)
+ if rfr < yfr {
+ rexp = rexp - 1
+ }
+ // amd64:"CMOVQHI"
+ // arm64:"CSEL\tGT"
+ r = r - ldexp(y, (rexp-yexp))
+ }
+ return r
+}
+
+func cmovloaded(x [4]int, y int) int {
+ if x[2] != 0 {
+ y = x[2]
+ } else {
+ y = y >> 2
+ }
+ // amd64:"CMOVQNE"
+ // arm64:"CSEL\tNE"
+ return y
+}
+
+func cmovuintptr2(x, y uintptr) uintptr {
+ a := x * 2
+ if a == 0 {
+ a = 256
+ }
+ // amd64:"CMOVQEQ"
+ // arm64:"CSEL\tEQ"
+ return a
+}
+
+// Floating point CMOVs are not supported by amd64/arm64
+func cmovfloatmove(x, y int) float64 {
+ a := 1.0
+ if x <= y {
+ a = 2.0
+ }
+ // amd64:-"CMOV"
+ // arm64:-"CSEL"
+ return a
+}
+
+// On amd64, the following patterns trigger comparison inversion.
+// Test that we correctly invert the CMOV condition
+var gsink int64
+var gusink uint64
+
+func cmovinvert1(x, y int64) int64 {
+ if x < gsink {
+ y = -y
+ }
+ // amd64:"CMOVQGT"
+ return y
+}
+func cmovinvert2(x, y int64) int64 {
+ if x <= gsink {
+ y = -y
+ }
+ // amd64:"CMOVQGE"
+ return y
+}
+func cmovinvert3(x, y int64) int64 {
+ if x == gsink {
+ y = -y
+ }
+ // amd64:"CMOVQEQ"
+ return y
+}
+func cmovinvert4(x, y int64) int64 {
+ if x != gsink {
+ y = -y
+ }
+ // amd64:"CMOVQNE"
+ return y
+}
+func cmovinvert5(x, y uint64) uint64 {
+ if x > gusink {
+ y = -y
+ }
+ // amd64:"CMOVQCS"
+ return y
+}
+func cmovinvert6(x, y uint64) uint64 {
+ if x >= gusink {
+ y = -y
+ }
+ // amd64:"CMOVQLS"
+ return y
+}
diff --git a/test/codegen/copy.go b/test/codegen/copy.go
new file mode 100644
index 000000000..5c3837bc7
--- /dev/null
+++ b/test/codegen/copy.go
@@ -0,0 +1,80 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+import "runtime"
+
+// Check small copies are replaced with moves.
+
+func movesmall4() {
+ x := [...]byte{1, 2, 3, 4}
+ // 386:-".*memmove"
+ // amd64:-".*memmove"
+ // arm:-".*memmove"
+ // arm64:-".*memmove"
+ copy(x[1:], x[:])
+}
+
+func movesmall7() {
+ x := [...]byte{1, 2, 3, 4, 5, 6, 7}
+ // 386:-".*memmove"
+ // amd64:-".*memmove"
+ // arm64:-".*memmove"
+ copy(x[1:], x[:])
+}
+
+func movesmall16() {
+ x := [...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
+ // amd64:-".*memmove"
+ copy(x[1:], x[:])
+}
+
+var x [256]byte
+
+// Check that large disjoint copies are replaced with moves.
+
+func moveDisjointStack() {
+ var s [256]byte
+ // s390x:-".*memmove"
+ copy(s[:], x[:])
+ runtime.KeepAlive(&s)
+}
+
+func moveDisjointArg(b *[256]byte) {
+ var s [256]byte
+ // s390x:-".*memmove"
+ copy(s[:], b[:])
+ runtime.KeepAlive(&s)
+}
+
+func moveDisjointNoOverlap(a *[256]byte) {
+ // s390x:-".*memmove"
+ copy(a[:], a[128:])
+}
+
+// Check that no branches are generated when the pointers are [not] equal.
+
+func ptrEqual() {
+ // amd64:-"JEQ",-"JNE"
+ // ppc64le:-"BEQ",-"BNE"
+ // s390x:-"BEQ",-"BNE"
+ copy(x[:], x[:])
+}
+
+func ptrOneOffset() {
+ // amd64:-"JEQ",-"JNE"
+ // ppc64le:-"BEQ",-"BNE"
+ // s390x:-"BEQ",-"BNE"
+ copy(x[1:], x[:])
+}
+
+func ptrBothOffset() {
+ // amd64:-"JEQ",-"JNE"
+ // ppc64le:-"BEQ",-"BNE"
+ // s390x:-"BEQ",-"BNE"
+ copy(x[1:], x[2:])
+}
diff --git a/test/codegen/floats.go b/test/codegen/floats.go
new file mode 100644
index 000000000..e0e4d973a
--- /dev/null
+++ b/test/codegen/floats.go
@@ -0,0 +1,99 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+// This file contains codegen tests related to arithmetic
+// simplifications and optimizations on float types.
+// For codegen tests on integer types, see arithmetic.go.
+
+// --------------------- //
+// Strength-reduce //
+// --------------------- //
+
+func Mul2(f float64) float64 {
+ // 386/sse2:"ADDSD",-"MULSD"
+ // 386/387:"FADDDP",-"FMULDP"
+ // amd64:"ADDSD",-"MULSD"
+ // arm/7:"ADDD",-"MULD"
+ // arm64:"FADDD",-"FMULD"
+ return f * 2.0
+}
+
+func DivPow2(f1, f2, f3 float64) (float64, float64, float64) {
+ // 386/sse2:"MULSD",-"DIVSD"
+ // 386/387:"FMULDP",-"FDIVDP"
+ // amd64:"MULSD",-"DIVSD"
+ // arm/7:"MULD",-"DIVD"
+ // arm64:"FMULD",-"FDIVD"
+ x := f1 / 16.0
+
+ // 386/sse2:"MULSD",-"DIVSD"
+ // 386/387:"FMULDP",-"FDIVDP"
+ // amd64:"MULSD",-"DIVSD"
+ // arm/7:"MULD",-"DIVD"
+ // arm64:"FMULD",-"FDIVD"
+ y := f2 / 0.125
+
+ // 386/sse2:"ADDSD",-"DIVSD",-"MULSD"
+ // 386/387:"FADDDP",-"FDIVDP",-"FMULDP"
+ // amd64:"ADDSD",-"DIVSD",-"MULSD"
+ // arm/7:"ADDD",-"MULD",-"DIVD"
+ // arm64:"FADDD",-"FMULD",-"FDIVD"
+ z := f3 / 0.5
+
+ return x, y, z
+}
+
+// ----------- //
+// Fused //
+// ----------- //
+
+func FusedAdd32(x, y, z float32) float32 {
+ // s390x:"FMADDS\t"
+ // ppc64le:"FMADDS\t"
+ return x*y + z
+}
+
+func FusedSub32(x, y, z float32) float32 {
+ // s390x:"FMSUBS\t"
+ // ppc64le:"FMSUBS\t"
+ return x*y - z
+}
+
+func FusedAdd64(x, y, z float64) float64 {
+ // s390x:"FMADD\t"
+ // ppc64le:"FMADD\t"
+ return x*y + z
+}
+
+func FusedSub64(x, y, z float64) float64 {
+ // s390x:"FMSUB\t"
+ // ppc64le:"FMSUB\t"
+ return x*y - z
+}
+
+// ---------------- //
+// Non-floats //
+// ---------------- //
+
+// We should make sure that the compiler doesn't generate floating point
+// instructions for non-float operations on Plan 9, because floating point
+// operations are not allowed in the note handler.
+
+func ArrayZero() [16]byte {
+ // amd64:"MOVUPS"
+ // plan9/amd64/:-"MOVUPS"
+ var a [16]byte
+ return a
+}
+
+func ArrayCopy(a [16]byte) (b [16]byte) {
+ // amd64:"MOVUPS"
+ // plan9/amd64/:-"MOVUPS"
+ b = a
+ return
+}
diff --git a/test/codegen/issue22703.go b/test/codegen/issue22703.go
new file mode 100644
index 000000000..0201de653
--- /dev/null
+++ b/test/codegen/issue22703.go
@@ -0,0 +1,535 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+type I interface {
+ foo000()
+ foo001()
+ foo002()
+ foo003()
+ foo004()
+ foo005()
+ foo006()
+ foo007()
+ foo008()
+ foo009()
+ foo010()
+ foo011()
+ foo012()
+ foo013()
+ foo014()
+ foo015()
+ foo016()
+ foo017()
+ foo018()
+ foo019()
+ foo020()
+ foo021()
+ foo022()
+ foo023()
+ foo024()
+ foo025()
+ foo026()
+ foo027()
+ foo028()
+ foo029()
+ foo030()
+ foo031()
+ foo032()
+ foo033()
+ foo034()
+ foo035()
+ foo036()
+ foo037()
+ foo038()
+ foo039()
+ foo040()
+ foo041()
+ foo042()
+ foo043()
+ foo044()
+ foo045()
+ foo046()
+ foo047()
+ foo048()
+ foo049()
+ foo050()
+ foo051()
+ foo052()
+ foo053()
+ foo054()
+ foo055()
+ foo056()
+ foo057()
+ foo058()
+ foo059()
+ foo060()
+ foo061()
+ foo062()
+ foo063()
+ foo064()
+ foo065()
+ foo066()
+ foo067()
+ foo068()
+ foo069()
+ foo070()
+ foo071()
+ foo072()
+ foo073()
+ foo074()
+ foo075()
+ foo076()
+ foo077()
+ foo078()
+ foo079()
+ foo080()
+ foo081()
+ foo082()
+ foo083()
+ foo084()
+ foo085()
+ foo086()
+ foo087()
+ foo088()
+ foo089()
+ foo090()
+ foo091()
+ foo092()
+ foo093()
+ foo094()
+ foo095()
+ foo096()
+ foo097()
+ foo098()
+ foo099()
+ foo100()
+ foo101()
+ foo102()
+ foo103()
+ foo104()
+ foo105()
+ foo106()
+ foo107()
+ foo108()
+ foo109()
+ foo110()
+ foo111()
+ foo112()
+ foo113()
+ foo114()
+ foo115()
+ foo116()
+ foo117()
+ foo118()
+ foo119()
+ foo120()
+ foo121()
+ foo122()
+ foo123()
+ foo124()
+ foo125()
+ foo126()
+ foo127()
+ foo128()
+ foo129()
+ foo130()
+ foo131()
+ foo132()
+ foo133()
+ foo134()
+ foo135()
+ foo136()
+ foo137()
+ foo138()
+ foo139()
+ foo140()
+ foo141()
+ foo142()
+ foo143()
+ foo144()
+ foo145()
+ foo146()
+ foo147()
+ foo148()
+ foo149()
+ foo150()
+ foo151()
+ foo152()
+ foo153()
+ foo154()
+ foo155()
+ foo156()
+ foo157()
+ foo158()
+ foo159()
+ foo160()
+ foo161()
+ foo162()
+ foo163()
+ foo164()
+ foo165()
+ foo166()
+ foo167()
+ foo168()
+ foo169()
+ foo170()
+ foo171()
+ foo172()
+ foo173()
+ foo174()
+ foo175()
+ foo176()
+ foo177()
+ foo178()
+ foo179()
+ foo180()
+ foo181()
+ foo182()
+ foo183()
+ foo184()
+ foo185()
+ foo186()
+ foo187()
+ foo188()
+ foo189()
+ foo190()
+ foo191()
+ foo192()
+ foo193()
+ foo194()
+ foo195()
+ foo196()
+ foo197()
+ foo198()
+ foo199()
+ foo200()
+ foo201()
+ foo202()
+ foo203()
+ foo204()
+ foo205()
+ foo206()
+ foo207()
+ foo208()
+ foo209()
+ foo210()
+ foo211()
+ foo212()
+ foo213()
+ foo214()
+ foo215()
+ foo216()
+ foo217()
+ foo218()
+ foo219()
+ foo220()
+ foo221()
+ foo222()
+ foo223()
+ foo224()
+ foo225()
+ foo226()
+ foo227()
+ foo228()
+ foo229()
+ foo230()
+ foo231()
+ foo232()
+ foo233()
+ foo234()
+ foo235()
+ foo236()
+ foo237()
+ foo238()
+ foo239()
+ foo240()
+ foo241()
+ foo242()
+ foo243()
+ foo244()
+ foo245()
+ foo246()
+ foo247()
+ foo248()
+ foo249()
+ foo250()
+ foo251()
+ foo252()
+ foo253()
+ foo254()
+ foo255()
+ foo256()
+ foo257()
+ foo258()
+ foo259()
+ foo260()
+ foo261()
+ foo262()
+ foo263()
+ foo264()
+ foo265()
+ foo266()
+ foo267()
+ foo268()
+ foo269()
+ foo270()
+ foo271()
+ foo272()
+ foo273()
+ foo274()
+ foo275()
+ foo276()
+ foo277()
+ foo278()
+ foo279()
+ foo280()
+ foo281()
+ foo282()
+ foo283()
+ foo284()
+ foo285()
+ foo286()
+ foo287()
+ foo288()
+ foo289()
+ foo290()
+ foo291()
+ foo292()
+ foo293()
+ foo294()
+ foo295()
+ foo296()
+ foo297()
+ foo298()
+ foo299()
+ foo300()
+ foo301()
+ foo302()
+ foo303()
+ foo304()
+ foo305()
+ foo306()
+ foo307()
+ foo308()
+ foo309()
+ foo310()
+ foo311()
+ foo312()
+ foo313()
+ foo314()
+ foo315()
+ foo316()
+ foo317()
+ foo318()
+ foo319()
+ foo320()
+ foo321()
+ foo322()
+ foo323()
+ foo324()
+ foo325()
+ foo326()
+ foo327()
+ foo328()
+ foo329()
+ foo330()
+ foo331()
+ foo332()
+ foo333()
+ foo334()
+ foo335()
+ foo336()
+ foo337()
+ foo338()
+ foo339()
+ foo340()
+ foo341()
+ foo342()
+ foo343()
+ foo344()
+ foo345()
+ foo346()
+ foo347()
+ foo348()
+ foo349()
+ foo350()
+ foo351()
+ foo352()
+ foo353()
+ foo354()
+ foo355()
+ foo356()
+ foo357()
+ foo358()
+ foo359()
+ foo360()
+ foo361()
+ foo362()
+ foo363()
+ foo364()
+ foo365()
+ foo366()
+ foo367()
+ foo368()
+ foo369()
+ foo370()
+ foo371()
+ foo372()
+ foo373()
+ foo374()
+ foo375()
+ foo376()
+ foo377()
+ foo378()
+ foo379()
+ foo380()
+ foo381()
+ foo382()
+ foo383()
+ foo384()
+ foo385()
+ foo386()
+ foo387()
+ foo388()
+ foo389()
+ foo390()
+ foo391()
+ foo392()
+ foo393()
+ foo394()
+ foo395()
+ foo396()
+ foo397()
+ foo398()
+ foo399()
+ foo400()
+ foo401()
+ foo402()
+ foo403()
+ foo404()
+ foo405()
+ foo406()
+ foo407()
+ foo408()
+ foo409()
+ foo410()
+ foo411()
+ foo412()
+ foo413()
+ foo414()
+ foo415()
+ foo416()
+ foo417()
+ foo418()
+ foo419()
+ foo420()
+ foo421()
+ foo422()
+ foo423()
+ foo424()
+ foo425()
+ foo426()
+ foo427()
+ foo428()
+ foo429()
+ foo430()
+ foo431()
+ foo432()
+ foo433()
+ foo434()
+ foo435()
+ foo436()
+ foo437()
+ foo438()
+ foo439()
+ foo440()
+ foo441()
+ foo442()
+ foo443()
+ foo444()
+ foo445()
+ foo446()
+ foo447()
+ foo448()
+ foo449()
+ foo450()
+ foo451()
+ foo452()
+ foo453()
+ foo454()
+ foo455()
+ foo456()
+ foo457()
+ foo458()
+ foo459()
+ foo460()
+ foo461()
+ foo462()
+ foo463()
+ foo464()
+ foo465()
+ foo466()
+ foo467()
+ foo468()
+ foo469()
+ foo470()
+ foo471()
+ foo472()
+ foo473()
+ foo474()
+ foo475()
+ foo476()
+ foo477()
+ foo478()
+ foo479()
+ foo480()
+ foo481()
+ foo482()
+ foo483()
+ foo484()
+ foo485()
+ foo486()
+ foo487()
+ foo488()
+ foo489()
+ foo490()
+ foo491()
+ foo492()
+ foo493()
+ foo494()
+ foo495()
+ foo496()
+ foo497()
+ foo498()
+ foo499()
+ foo500()
+ foo501()
+ foo502()
+ foo503()
+ foo504()
+ foo505()
+ foo506()
+ foo507()
+ foo508()
+ foo509()
+ foo510()
+ foo511()
+}
+
+// Nil checks before calling interface methods.
+// We need it only when the offset is large.
+
+func callMethodSmallOffset(i I) {
+ // amd64:-"TESTB"
+ i.foo001()
+}
+
+func callMethodLargeOffset(i I) {
+ // amd64:"TESTB"
+ i.foo511()
+}
diff --git a/test/codegen/mapaccess.go b/test/codegen/mapaccess.go
new file mode 100644
index 000000000..35620e741
--- /dev/null
+++ b/test/codegen/mapaccess.go
@@ -0,0 +1,462 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+// These tests check that mapaccess calls are not used.
+// Issues #23661 and #24364.
+
+func mapCompoundAssignmentInt8() {
+ m := make(map[int8]int8, 0)
+ var k int8 = 0
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] += 67
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] -= 123
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] *= 45
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] |= 78
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] ^= 89
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] <<= 9
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] >>= 10
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k]++
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k]--
+}
+
+func mapCompoundAssignmentInt32() {
+ m := make(map[int32]int32, 0)
+ var k int32 = 0
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] += 67890
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] -= 123
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] *= 456
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] |= 78
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] ^= 89
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] <<= 9
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] >>= 10
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k]++
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k]--
+}
+
+func mapCompoundAssignmentInt64() {
+ m := make(map[int64]int64, 0)
+ var k int64 = 0
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] += 67890
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] -= 123
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] *= 456
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] |= 78
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] ^= 89
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] <<= 9
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] >>= 10
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k]++
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k]--
+}
+
+func mapCompoundAssignmentComplex128() {
+ m := make(map[complex128]complex128, 0)
+ var k complex128 = 0
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] += 67890
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] -= 123
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] *= 456
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k]++
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k]--
+}
+
+func mapCompoundAssignmentString() {
+ m := make(map[string]string, 0)
+ var k string = "key"
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] += "value"
+}
+
+var sinkAppend bool
+
+// TODO: optimization is not applied because of mapslow flag.
+func mapAppendAssignmentInt8() {
+ m := make(map[int8][]int8, 0)
+ var k int8 = 0
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(m[k], 1)
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(m[k], 1, 2, 3)
+
+ a := []int8{7, 8, 9, 0}
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(m[k], a...)
+
+ // Exceptions
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(a, m[k]...)
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ sinkAppend, m[k] = !sinkAppend, append(m[k], 99)
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(m[k+1], 100)
+}
+
+func mapAppendAssignmentInt32() {
+ m := make(map[int32][]int32, 0)
+ var k int32 = 0
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] = append(m[k], 1)
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] = append(m[k], 1, 2, 3)
+
+ a := []int32{7, 8, 9, 0}
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] = append(m[k], a...)
+
+ // Exceptions
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(a, m[k]...)
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ sinkAppend, m[k] = !sinkAppend, append(m[k], 99)
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(m[k+1], 100)
+}
+
+func mapAppendAssignmentInt64() {
+ m := make(map[int64][]int64, 0)
+ var k int64 = 0
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] = append(m[k], 1)
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] = append(m[k], 1, 2, 3)
+
+ a := []int64{7, 8, 9, 0}
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] = append(m[k], a...)
+
+ // Exceptions
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(a, m[k]...)
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ sinkAppend, m[k] = !sinkAppend, append(m[k], 99)
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(m[k+1], 100)
+}
+
+// TODO: optimization is not applied because of mapslow flag.
+func mapAppendAssignmentComplex128() {
+ m := make(map[complex128][]complex128, 0)
+ var k complex128 = 0
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(m[k], 1)
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(m[k], 1, 2, 3)
+
+ a := []complex128{7, 8, 9, 0}
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(m[k], a...)
+
+ // Exceptions
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(a, m[k]...)
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ sinkAppend, m[k] = !sinkAppend, append(m[k], 99)
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(m[k+1], 100)
+}
+
+func mapAppendAssignmentString() {
+ m := make(map[string][]string, 0)
+ var k string = "key"
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] = append(m[k], "1")
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] = append(m[k], "1", "2", "3")
+
+ a := []string{"7", "8", "9", "0"}
+
+ // 386:-".*mapaccess"
+ // amd64:-".*mapaccess"
+ // arm:-".*mapaccess"
+ // arm64:-".*mapaccess"
+ m[k] = append(m[k], a...)
+
+ // Exceptions
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(a, m[k]...)
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ sinkAppend, m[k] = !sinkAppend, append(m[k], "99")
+
+ // 386:".*mapaccess"
+ // amd64:".*mapaccess"
+ // arm:".*mapaccess"
+ // arm64:".*mapaccess"
+ m[k] = append(m[k+"1"], "100")
+}
diff --git a/test/codegen/maps.go b/test/codegen/maps.go
new file mode 100644
index 000000000..d16771589
--- /dev/null
+++ b/test/codegen/maps.go
@@ -0,0 +1,95 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+// This file contains code generation tests related to the handling of
+// map types.
+
+// ------------------- //
+// Access Const //
+// ------------------- //
+
+// Direct use of constants in fast map access calls (Issue #19015).
+
+func AccessInt1(m map[int]int) int {
+ // amd64:"MOVQ\t[$]5"
+ return m[5]
+}
+
+func AccessInt2(m map[int]int) bool {
+ // amd64:"MOVQ\t[$]5"
+ _, ok := m[5]
+ return ok
+}
+
+func AccessString1(m map[string]int) int {
+ // amd64:`.*"abc"`
+ return m["abc"]
+}
+
+func AccessString2(m map[string]int) bool {
+ // amd64:`.*"abc"`
+ _, ok := m["abc"]
+ return ok
+}
+
+// ------------------- //
+// Map Clear //
+// ------------------- //
+
+// Optimization of map clear idiom (Issue #20138).
+
+func MapClearReflexive(m map[int]int) {
+ // amd64:`.*runtime\.mapclear`
+ // amd64:-`.*runtime\.mapiterinit`
+ for k := range m {
+ delete(m, k)
+ }
+}
+
+func MapClearIndirect(m map[int]int) {
+ s := struct{ m map[int]int }{m: m}
+ // amd64:`.*runtime\.mapclear`
+ // amd64:-`.*runtime\.mapiterinit`
+ for k := range s.m {
+ delete(s.m, k)
+ }
+}
+
+func MapClearPointer(m map[*byte]int) {
+ // amd64:`.*runtime\.mapclear`
+ // amd64:-`.*runtime\.mapiterinit`
+ for k := range m {
+ delete(m, k)
+ }
+}
+
+func MapClearNotReflexive(m map[float64]int) {
+ // amd64:`.*runtime\.mapiterinit`
+ // amd64:-`.*runtime\.mapclear`
+ for k := range m {
+ delete(m, k)
+ }
+}
+
+func MapClearInterface(m map[interface{}]int) {
+ // amd64:`.*runtime\.mapiterinit`
+ // amd64:-`.*runtime\.mapclear`
+ for k := range m {
+ delete(m, k)
+ }
+}
+
+func MapClearSideEffect(m map[int]int) int {
+ k := 0
+ // amd64:`.*runtime\.mapiterinit`
+ // amd64:-`.*runtime\.mapclear`
+ for k = range m {
+ delete(m, k)
+ }
+ return k
+}
diff --git a/test/codegen/math.go b/test/codegen/math.go
new file mode 100644
index 000000000..1ecba2684
--- /dev/null
+++ b/test/codegen/math.go
@@ -0,0 +1,146 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+import "math"
+
+var sink64 [8]float64
+
+func approx(x float64) {
+ // s390x:"FIDBR\t[$]6"
+ // arm64:"FRINTPD"
+ // ppc64le:"FRIP"
+ sink64[0] = math.Ceil(x)
+
+ // s390x:"FIDBR\t[$]7"
+ // arm64:"FRINTMD"
+ // ppc64le:"FRIM"
+ sink64[1] = math.Floor(x)
+
+ // s390x:"FIDBR\t[$]1"
+ // arm64:"FRINTAD"
+ // ppc64le:"FRIN"
+ sink64[2] = math.Round(x)
+
+ // s390x:"FIDBR\t[$]5"
+ // arm64:"FRINTZD"
+ // ppc64le:"FRIZ"
+ sink64[3] = math.Trunc(x)
+
+ // s390x:"FIDBR\t[$]4"
+ sink64[4] = math.RoundToEven(x)
+}
+
+func sqrt(x float64) float64 {
+ // amd64:"SQRTSD"
+ // 386/387:"FSQRT" 386/sse2:"SQRTSD"
+ // arm64:"FSQRTD"
+ // arm/7:"SQRTD"
+ // mips/hardfloat:"SQRTD" mips/softfloat:-"SQRTD"
+ // mips64/hardfloat:"SQRTD" mips64/softfloat:-"SQRTD"
+ return math.Sqrt(x)
+}
+
+// Check that it's using integer registers
+func abs(x, y float64) {
+ // amd64:"BTRQ\t[$]63"
+ // s390x:"LPDFR\t",-"MOVD\t" (no integer load/store)
+ // ppc64le:"FABS\t"
+ sink64[0] = math.Abs(x)
+
+ // amd64:"BTRQ\t[$]63","PXOR" (TODO: this should be BTSQ)
+ // s390x:"LNDFR\t",-"MOVD\t" (no integer load/store)
+ // ppc64le:"FNABS\t"
+ sink64[1] = -math.Abs(y)
+}
+
+// Check that it's using integer registers
+func abs32(x float32) float32 {
+ // s390x:"LPDFR",-"LDEBR",-"LEDBR" (no float64 conversion)
+ return float32(math.Abs(float64(x)))
+}
+
+// Check that it's using integer registers
+func copysign(a, b, c float64) {
+ // amd64:"BTRQ\t[$]63","SHRQ\t[$]63","SHLQ\t[$]63","ORQ"
+ // s390x:"CPSDR",-"MOVD" (no integer load/store)
+ // ppc64le:"FCPSGN"
+ sink64[0] = math.Copysign(a, b)
+
+ // amd64:"BTSQ\t[$]63"
+ // s390x:"LNDFR\t",-"MOVD\t" (no integer load/store)
+ // ppc64le:"FCPSGN"
+ sink64[1] = math.Copysign(c, -1)
+
+ // Like math.Copysign(c, -1), but with integer operations. Useful
+ // for platforms that have a copysign opcode to see if it's detected.
+ // s390x:"LNDFR\t",-"MOVD\t" (no integer load/store)
+ sink64[2] = math.Float64frombits(math.Float64bits(a) | 1<<63)
+
+ // amd64:-"SHLQ\t[$]1",-"SHRQ\t[$]1","SHRQ\t[$]63","SHLQ\t[$]63","ORQ"
+ // s390x:"CPSDR\t",-"MOVD\t" (no integer load/store)
+ // ppc64le:"FCPSGN"
+ sink64[3] = math.Copysign(-1, c)
+}
+
+func fromFloat64(f64 float64) uint64 {
+ // amd64:"MOVQ\tX.*, [^X].*"
+ return math.Float64bits(f64+1) + 1
+}
+
+func fromFloat32(f32 float32) uint32 {
+ // amd64:"MOVL\tX.*, [^X].*"
+ return math.Float32bits(f32+1) + 1
+}
+
+func toFloat64(u64 uint64) float64 {
+ // amd64:"MOVQ\t[^X].*, X.*"
+ return math.Float64frombits(u64+1) + 1
+}
+
+func toFloat32(u32 uint32) float32 {
+ // amd64:"MOVL\t[^X].*, X.*"
+ return math.Float32frombits(u32+1) + 1
+}
+
+// Test that comparisons with constants converted to float
+// are evaluated at compile-time
+
+func constantCheck64() bool {
+ // amd64:"MOVB\t[$]0",-"FCMP",-"MOVB\t[$]1"
+ // s390x:"MOV(B|BZ|D)\t[$]0,",-"FCMPU",-"MOV(B|BZ|D)\t[$]1,"
+ return 0.5 == float64(uint32(1)) || 1.5 > float64(uint64(1<<63)) || math.NaN() == math.NaN()
+}
+
+func constantCheck32() bool {
+ // amd64:"MOVB\t[$]1",-"FCMP",-"MOVB\t[$]0"
+ // s390x:"MOV(B|BZ|D)\t[$]1,",-"FCMPU",-"MOV(B|BZ|D)\t[$]0,"
+ return float32(0.5) <= float32(int64(1)) && float32(1.5) >= float32(int32(-1<<31)) && float32(math.NaN()) != float32(math.NaN())
+}
+
+// Test that integer constants are converted to floating point constants
+// at compile-time
+
+func constantConvert32(x float32) float32 {
+ // amd64:"MOVSS\t[$]f32.3f800000\\(SB\\)"
+ // s390x:"FMOVS\t[$]f32.3f800000\\(SB\\)"
+ // ppc64le:"FMOVS\t[$]f32.3f800000\\(SB\\)"
+ if x > math.Float32frombits(0x3f800000) {
+ return -x
+ }
+ return x
+}
+
+func constantConvertInt32(x uint32) uint32 {
+ // amd64:-"MOVSS"
+ // s390x:-"FMOVS"
+ // ppc64le:-"FMOVS"
+ if x > math.Float32bits(1) {
+ return -x
+ }
+ return x
+}
diff --git a/test/codegen/mathbits.go b/test/codegen/mathbits.go
new file mode 100644
index 000000000..85c54ea61
--- /dev/null
+++ b/test/codegen/mathbits.go
@@ -0,0 +1,269 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+import "math/bits"
+
+// ----------------------- //
+// bits.LeadingZeros //
+// ----------------------- //
+
+func LeadingZeros(n uint) int {
+ // amd64:"BSRQ"
+ // s390x:"FLOGR"
+ // arm:"CLZ" arm64:"CLZ"
+ // mips:"CLZ"
+ return bits.LeadingZeros(n)
+}
+
+func LeadingZeros64(n uint64) int {
+ // amd64:"BSRQ"
+ // s390x:"FLOGR"
+ // arm:"CLZ" arm64:"CLZ"
+ // mips:"CLZ"
+ return bits.LeadingZeros64(n)
+}
+
+func LeadingZeros32(n uint32) int {
+ // amd64:"BSRQ","LEAQ",-"CMOVQEQ"
+ // s390x:"FLOGR"
+ // arm:"CLZ" arm64:"CLZ"
+ // mips:"CLZ"
+ return bits.LeadingZeros32(n)
+}
+
+func LeadingZeros16(n uint16) int {
+ // amd64:"BSRL","LEAL",-"CMOVQEQ"
+ // s390x:"FLOGR"
+ // arm:"CLZ" arm64:"CLZ"
+ // mips:"CLZ"
+ return bits.LeadingZeros16(n)
+}
+
+func LeadingZeros8(n uint8) int {
+ // amd64:"BSRL","LEAL",-"CMOVQEQ"
+ // s390x:"FLOGR"
+ // arm:"CLZ" arm64:"CLZ"
+ // mips:"CLZ"
+ return bits.LeadingZeros8(n)
+}
+
+// --------------- //
+// bits.Len* //
+// --------------- //
+
+func Len(n uint) int {
+ // amd64:"BSRQ"
+ // s390x:"FLOGR"
+ // arm:"CLZ" arm64:"CLZ"
+ // mips:"CLZ"
+ return bits.Len(n)
+}
+
+func Len64(n uint64) int {
+ // amd64:"BSRQ"
+ // s390x:"FLOGR"
+ // arm:"CLZ" arm64:"CLZ"
+ // mips:"CLZ"
+ return bits.Len64(n)
+}
+
+func Len32(n uint32) int {
+ // amd64:"BSRQ","LEAQ",-"CMOVQEQ"
+ // s390x:"FLOGR"
+ // arm:"CLZ" arm64:"CLZ"
+ // mips:"CLZ"
+ return bits.Len32(n)
+}
+
+func Len16(n uint16) int {
+ // amd64:"BSRL","LEAL",-"CMOVQEQ"
+ // s390x:"FLOGR"
+ // arm:"CLZ" arm64:"CLZ"
+ // mips:"CLZ"
+ return bits.Len16(n)
+}
+
+func Len8(n uint8) int {
+ // amd64:"BSRL","LEAL",-"CMOVQEQ"
+ // s390x:"FLOGR"
+ // arm:"CLZ" arm64:"CLZ"
+ // mips:"CLZ"
+ return bits.Len8(n)
+}
+
+// -------------------- //
+// bits.OnesCount //
+// -------------------- //
+
+func OnesCount(n uint) int {
+ // amd64:"POPCNTQ",".*support_popcnt"
+ // arm64:"VCNT","VUADDLV"
+ return bits.OnesCount(n)
+}
+
+func OnesCount64(n uint64) int {
+ // amd64:"POPCNTQ",".*support_popcnt"
+ // arm64:"VCNT","VUADDLV"
+ return bits.OnesCount64(n)
+}
+
+func OnesCount32(n uint32) int {
+ // amd64:"POPCNTL",".*support_popcnt"
+ // arm64:"VCNT","VUADDLV"
+ return bits.OnesCount32(n)
+}
+
+func OnesCount16(n uint16) int {
+ // amd64:"POPCNTL",".*support_popcnt"
+ // arm64:"VCNT","VUADDLV"
+ return bits.OnesCount16(n)
+}
+
+// ----------------------- //
+// bits.ReverseBytes //
+// ----------------------- //
+
+func ReverseBytes(n uint) uint {
+ // amd64:"BSWAPQ"
+ // s390x:"MOVDBR"
+ // arm64:"REV"
+ return bits.ReverseBytes(n)
+}
+
+func ReverseBytes64(n uint64) uint64 {
+ // amd64:"BSWAPQ"
+ // s390x:"MOVDBR"
+ // arm64:"REV"
+ return bits.ReverseBytes64(n)
+}
+
+func ReverseBytes32(n uint32) uint32 {
+ // amd64:"BSWAPL"
+ // s390x:"MOVWBR"
+ // arm64:"REVW"
+ return bits.ReverseBytes32(n)
+}
+
+func ReverseBytes16(n uint16) uint16 {
+ // amd64:"ROLW"
+ return bits.ReverseBytes16(n)
+}
+
+// --------------------- //
+// bits.RotateLeft //
+// --------------------- //
+
+func RotateLeft64(n uint64) uint64 {
+ // amd64:"ROLQ"
+ // arm64:"ROR"
+ // ppc64:"ROTL"
+ return bits.RotateLeft64(n, 37)
+}
+
+func RotateLeft32(n uint32) uint32 {
+ // amd64:"ROLL" 386:"ROLL"
+ // arm64:"RORW"
+ // ppc64:"ROTLW"
+ return bits.RotateLeft32(n, 9)
+}
+
+func RotateLeft16(n uint16) uint16 {
+ // amd64:"ROLW" 386:"ROLW"
+ return bits.RotateLeft16(n, 5)
+}
+
+func RotateLeft8(n uint8) uint8 {
+ // amd64:"ROLB" 386:"ROLB"
+ return bits.RotateLeft8(n, 5)
+}
+
+// ------------------------ //
+// bits.TrailingZeros //
+// ------------------------ //
+
+func TrailingZeros(n uint) int {
+ // amd64:"BSFQ","MOVL\t\\$64","CMOVQEQ"
+ // s390x:"FLOGR"
+ return bits.TrailingZeros(n)
+}
+
+func TrailingZeros64(n uint64) int {
+ // amd64:"BSFQ","MOVL\t\\$64","CMOVQEQ"
+ // s390x:"FLOGR"
+ return bits.TrailingZeros64(n)
+}
+
+func TrailingZeros32(n uint32) int {
+ // amd64:"BTSQ\\t\\$32","BSFQ"
+ // s390x:"FLOGR","MOVWZ"
+ return bits.TrailingZeros32(n)
+}
+
+func TrailingZeros16(n uint16) int {
+ // amd64:"BSFL","BTSL\\t\\$16"
+ // s390x:"FLOGR","OR\t\\$65536"
+ return bits.TrailingZeros16(n)
+}
+
+func TrailingZeros8(n uint8) int {
+ // amd64:"BSFL","BTSL\\t\\$8"
+ // s390x:"FLOGR","OR\t\\$256"
+ return bits.TrailingZeros8(n)
+}
+
+// IterateBitsNN checks special handling of TrailingZerosNN when the input is known to be non-zero.
+
+func IterateBits(n uint) int {
+ i := 0
+ for n != 0 {
+ // amd64:"BSFQ",-"CMOVEQ"
+ i += bits.TrailingZeros(n)
+ n &= n - 1
+ }
+ return i
+}
+
+func IterateBits64(n uint64) int {
+ i := 0
+ for n != 0 {
+ // amd64:"BSFQ",-"CMOVEQ"
+ i += bits.TrailingZeros64(n)
+ n &= n - 1
+ }
+ return i
+}
+
+func IterateBits32(n uint32) int {
+ i := 0
+ for n != 0 {
+ // amd64:"BSFL",-"BTSQ"
+ i += bits.TrailingZeros32(n)
+ n &= n - 1
+ }
+ return i
+}
+
+func IterateBits16(n uint16) int {
+ i := 0
+ for n != 0 {
+ // amd64:"BSFL",-"BTSL"
+ i += bits.TrailingZeros16(n)
+ n &= n - 1
+ }
+ return i
+}
+
+func IterateBits8(n uint8) int {
+ i := 0
+ for n != 0 {
+ // amd64:"BSFL",-"BTSL"
+ i += bits.TrailingZeros8(n)
+ n &= n - 1
+ }
+ return i
+}
diff --git a/test/codegen/memcombine.go b/test/codegen/memcombine.go
new file mode 100644
index 000000000..0db366250
--- /dev/null
+++ b/test/codegen/memcombine.go
@@ -0,0 +1,580 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+import (
+ "encoding/binary"
+ "runtime"
+)
+
+var sink64 uint64
+var sink32 uint32
+var sink16 uint16
+
+// ------------- //
+// Loading //
+// ------------- //
+
+func load_le64(b []byte) {
+ // amd64:`MOVQ\s\(.*\),`
+ // s390x:`MOVDBR\s\(.*\),`
+ // arm64:`MOVD\s\(R[0-9]+\),`,-`MOV[BHW]`
+ // ppc64le:`MOVD\s`,-`MOV[BHW]Z`
+ sink64 = binary.LittleEndian.Uint64(b)
+}
+
+func load_le64_idx(b []byte, idx int) {
+ // amd64:`MOVQ\s\(.*\)\(.*\*1\),`
+ // s390x:`MOVDBR\s\(.*\)\(.*\*1\),`
+ // arm64:`MOVD\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[BHW]`
+ // ppc64le:`MOVD\s`,-`MOV[BHW]Z\s`
+ sink64 = binary.LittleEndian.Uint64(b[idx:])
+}
+
+func load_le32(b []byte) {
+ // amd64:`MOVL\s\(.*\),` 386:`MOVL\s\(.*\),`
+ // s390x:`MOVWBR\s\(.*\),`
+ // arm64:`MOVWU\s\(R[0-9]+\),`,-`MOV[BH]`
+ // ppc64le:`MOVWZ\s`
+ sink32 = binary.LittleEndian.Uint32(b)
+}
+
+func load_le32_idx(b []byte, idx int) {
+ // amd64:`MOVL\s\(.*\)\(.*\*1\),` 386:`MOVL\s\(.*\)\(.*\*1\),`
+ // s390x:`MOVWBR\s\(.*\)\(.*\*1\),`
+ // arm64:`MOVWU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[BH]`
+ // ppc64le:`MOVWZ\s`
+ sink32 = binary.LittleEndian.Uint32(b[idx:])
+}
+
+func load_le16(b []byte) {
+ // amd64:`MOVWLZX\s\(.*\),`
+ // ppc64le:`MOVHZ\s`
+ // arm64:`MOVHU\s\(R[0-9]+\),`,-`MOVB`
+ sink16 = binary.LittleEndian.Uint16(b)
+}
+
+func load_le16_idx(b []byte, idx int) {
+ // amd64:`MOVWLZX\s\(.*\),`
+ // ppc64le:`MOVHZ\s`
+ // arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOVB`
+ sink16 = binary.LittleEndian.Uint16(b[idx:])
+}
+
+func load_be64(b []byte) {
+ // amd64:`BSWAPQ`
+ // s390x:`MOVD\s\(.*\),`
+ // arm64:`REV`,`MOVD\s\(R[0-9]+\),`,-`MOV[BHW]`,-`REVW`,-`REV16W`
+ // ppc64le:`MOVDBR`
+ sink64 = binary.BigEndian.Uint64(b)
+}
+
+func load_be64_idx(b []byte, idx int) {
+ // amd64:`BSWAPQ`
+ // s390x:`MOVD\s\(.*\)\(.*\*1\),`
+ // arm64:`REV`,`MOVD\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[WHB]`,-`REVW`,-`REV16W`
+ // ppc64le:`MOVDBR`
+ sink64 = binary.BigEndian.Uint64(b[idx:])
+}
+
+func load_be32(b []byte) {
+ // amd64:`BSWAPL`
+ // s390x:`MOVWZ\s\(.*\),`
+ // arm64:`REVW`,`MOVWU\s\(R[0-9]+\),`,-`MOV[BH]`,-`REV16W`
+ // ppc64le:`MOVWBR`
+ sink32 = binary.BigEndian.Uint32(b)
+}
+
+func load_be32_idx(b []byte, idx int) {
+ // amd64:`BSWAPL`
+ // s390x:`MOVWZ\s\(.*\)\(.*\*1\),`
+ // arm64:`REVW`,`MOVWU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOV[HB]`,-`REV16W`
+ // ppc64le:`MOVWBR`
+ sink32 = binary.BigEndian.Uint32(b[idx:])
+}
+
+func load_be16(b []byte) {
+ // amd64:`ROLW\s\$8`
+ // arm64:`REV16W`,`MOVHU\s\(R[0-9]+\),`,-`MOVB`
+ // ppc64le:`MOVHBR`
+ sink16 = binary.BigEndian.Uint16(b)
+}
+
+func load_be16_idx(b []byte, idx int) {
+ // amd64:`ROLW\s\$8`
+ // arm64:`REV16W`,`MOVHU\s\(R[0-9]+\)\(R[0-9]+\),`,-`MOVB`
+ // ppc64le:`MOVHBR`
+ sink16 = binary.BigEndian.Uint16(b[idx:])
+}
+
+func load_le_byte2_uint16(s []byte) uint16 {
+ // arm64:`MOVHU\t\(R[0-9]+\)`,-`ORR`,-`MOVB`
+ return uint16(s[0]) | uint16(s[1])<<8
+}
+
+func load_le_byte2_uint16_inv(s []byte) uint16 {
+ // arm64:`MOVHU\t\(R[0-9]+\)`,-`ORR`,-`MOVB`
+ return uint16(s[1])<<8 | uint16(s[0])
+}
+
+func load_le_byte4_uint32(s []byte) uint32 {
+ // arm64:`MOVWU\t\(R[0-9]+\)`,-`ORR`,-`MOV[BH]`
+ return uint32(s[0]) | uint32(s[1])<<8 | uint32(s[2])<<16 | uint32(s[3])<<24
+}
+
+func load_le_byte4_uint32_inv(s []byte) uint32 {
+ // arm64:`MOVWU\t\(R[0-9]+\)`,-`ORR`,-`MOV[BH]`
+ return uint32(s[3])<<24 | uint32(s[2])<<16 | uint32(s[1])<<8 | uint32(s[0])
+}
+
+func load_le_byte8_uint64(s []byte) uint64 {
+ // arm64:`MOVD\t\(R[0-9]+\)`,-`ORR`,-`MOV[BHW]`
+ return uint64(s[0]) | uint64(s[1])<<8 | uint64(s[2])<<16 | uint64(s[3])<<24 | uint64(s[4])<<32 | uint64(s[5])<<40 | uint64(s[6])<<48 | uint64(s[7])<<56
+}
+
+func load_le_byte8_uint64_inv(s []byte) uint64 {
+ // arm64:`MOVD\t\(R[0-9]+\)`,-`ORR`,-`MOV[BHW]`
+ return uint64(s[7])<<56 | uint64(s[6])<<48 | uint64(s[5])<<40 | uint64(s[4])<<32 | uint64(s[3])<<24 | uint64(s[2])<<16 | uint64(s[1])<<8 | uint64(s[0])
+}
+
+func load_be_byte2_uint16(s []byte) uint16 {
+ // arm64:`MOVHU\t\(R[0-9]+\)`,`REV16W`,-`ORR`,-`MOVB`
+ return uint16(s[0])<<8 | uint16(s[1])
+}
+
+func load_be_byte2_uint16_inv(s []byte) uint16 {
+ // arm64:`MOVHU\t\(R[0-9]+\)`,`REV16W`,-`ORR`,-`MOVB`
+ return uint16(s[1]) | uint16(s[0])<<8
+}
+
+func load_be_byte4_uint32(s []byte) uint32 {
+ // arm64:`MOVWU\t\(R[0-9]+\)`,`REVW`,-`ORR`,-`REV16W`,-`MOV[BH]`
+ return uint32(s[0])<<24 | uint32(s[1])<<16 | uint32(s[2])<<8 | uint32(s[3])
+}
+
+func load_be_byte4_uint32_inv(s []byte) uint32 {
+ // arm64:`MOVWU\t\(R[0-9]+\)`,`REVW`,-`ORR`,-`REV16W`,-`MOV[BH]`
+ return uint32(s[3]) | uint32(s[2])<<8 | uint32(s[1])<<16 | uint32(s[0])<<24
+}
+
+func load_be_byte8_uint64(s []byte) uint64 {
+ // arm64:`MOVD\t\(R[0-9]+\)`,`REV`,-`ORR`,-`REVW`,-`REV16W`,-`MOV[BHW]`
+ return uint64(s[0])<<56 | uint64(s[1])<<48 | uint64(s[2])<<40 | uint64(s[3])<<32 | uint64(s[4])<<24 | uint64(s[5])<<16 | uint64(s[6])<<8 | uint64(s[7])
+}
+
+func load_be_byte8_uint64_inv(s []byte) uint64 {
+ // arm64:`MOVD\t\(R[0-9]+\)`,`REV`,-`ORR`,-`REVW`,-`REV16W`,-`MOV[BHW]`
+ return uint64(s[7]) | uint64(s[6])<<8 | uint64(s[5])<<16 | uint64(s[4])<<24 | uint64(s[3])<<32 | uint64(s[2])<<40 | uint64(s[1])<<48 | uint64(s[0])<<56
+}
+
+func load_le_byte2_uint16_idx(s []byte, idx int) uint16 {
+ // arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+\)`,-`ORR`,-`MOVB`
+ return uint16(s[idx]) | uint16(s[idx+1])<<8
+}
+
+func load_le_byte2_uint16_idx_inv(s []byte, idx int) uint16 {
+ // arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+\)`,-`ORR`,-`MOVB`
+ return uint16(s[idx+1])<<8 | uint16(s[idx])
+}
+
+func load_le_byte4_uint32_idx(s []byte, idx int) uint32 {
+ // arm64:`MOVWU\s\(R[0-9]+\)\(R[0-9]+\)`,-`ORR`,-`MOV[BH]`
+ return uint32(s[idx]) | uint32(s[idx+1])<<8 | uint32(s[idx+2])<<16 | uint32(s[idx+3])<<24
+}
+
+func load_le_byte4_uint32_idx_inv(s []byte, idx int) uint32 {
+ // arm64:`MOVWU\s\(R[0-9]+\)\(R[0-9]+\)`,-`ORR`,-`MOV[BH]`
+ return uint32(s[idx+3])<<24 | uint32(s[idx+2])<<16 | uint32(s[idx+1])<<8 | uint32(s[idx])
+}
+
+func load_le_byte8_uint64_idx(s []byte, idx int) uint64 {
+ // arm64:`MOVD\s\(R[0-9]+\)\(R[0-9]+\)`,-`ORR`,-`MOV[BHW]`
+ return uint64(s[idx]) | uint64(s[idx+1])<<8 | uint64(s[idx+2])<<16 | uint64(s[idx+3])<<24 | uint64(s[idx+4])<<32 | uint64(s[idx+5])<<40 | uint64(s[idx+6])<<48 | uint64(s[idx+7])<<56
+}
+
+func load_le_byte8_uint64_idx_inv(s []byte, idx int) uint64 {
+ // arm64:`MOVD\s\(R[0-9]+\)\(R[0-9]+\)`,-`ORR`,-`MOV[BHW]`
+ return uint64(s[idx+7])<<56 | uint64(s[idx+6])<<48 | uint64(s[idx+5])<<40 | uint64(s[idx+4])<<32 | uint64(s[idx+3])<<24 | uint64(s[idx+2])<<16 | uint64(s[idx+1])<<8 | uint64(s[idx])
+}
+
+func load_be_byte2_uint16_idx(s []byte, idx int) uint16 {
+ // arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+\)`,`REV16W`,-`ORR`,-`MOVB`
+ return uint16(s[idx])<<8 | uint16(s[idx+1])
+}
+
+func load_be_byte2_uint16_idx_inv(s []byte, idx int) uint16 {
+ // arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+\)`,`REV16W`,-`ORR`,-`MOVB`
+ return uint16(s[idx+1]) | uint16(s[idx])<<8
+}
+
+func load_be_byte4_uint32_idx(s []byte, idx int) uint32 {
+ // arm64:`MOVWU\s\(R[0-9]+\)\(R[0-9]+\)`,`REVW`,-`ORR`,-`MOV[BH]`,-`REV16W`
+ return uint32(s[idx])<<24 | uint32(s[idx+1])<<16 | uint32(s[idx+2])<<8 | uint32(s[idx+3])
+}
+
+func load_be_byte8_uint64_idx(s []byte, idx int) uint64 {
+ // arm64:`MOVD\s\(R[0-9]+\)\(R[0-9]+\)`,`REV`,-`ORR`,-`MOV[BHW]`,-`REVW`,-`REV16W`
+ return uint64(s[idx])<<56 | uint64(s[idx+1])<<48 | uint64(s[idx+2])<<40 | uint64(s[idx+3])<<32 | uint64(s[idx+4])<<24 | uint64(s[idx+5])<<16 | uint64(s[idx+6])<<8 | uint64(s[idx+7])
+}
+
+func load_le_byte2_uint16_idx2(s []byte, idx int) uint16 {
+ // arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+<<1\)`,-`ORR`,-`MOVB`
+ return uint16(s[idx<<1]) | uint16(s[(idx<<1)+1])<<8
+}
+
+func load_le_byte2_uint16_idx2_inv(s []byte, idx int) uint16 {
+ // arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+<<1\)`,-`ORR`,-`MOVB`
+ return uint16(s[(idx<<1)+1])<<8 | uint16(s[idx<<1])
+}
+
+func load_le_byte4_uint32_idx4(s []byte, idx int) uint32 {
+ // arm64:`MOVWU\s\(R[0-9]+\)\(R[0-9]+<<2\)`,-`ORR`,-`MOV[BH]`
+ return uint32(s[idx<<2]) | uint32(s[(idx<<2)+1])<<8 | uint32(s[(idx<<2)+2])<<16 | uint32(s[(idx<<2)+3])<<24
+}
+
+func load_le_byte4_uint32_idx4_inv(s []byte, idx int) uint32 {
+ // arm64:`MOVWU\s\(R[0-9]+\)\(R[0-9]+<<2\)`,-`ORR`,-`MOV[BH]`
+ return uint32(s[(idx<<2)+3])<<24 | uint32(s[(idx<<2)+2])<<16 | uint32(s[(idx<<2)+1])<<8 | uint32(s[idx<<2])
+}
+
+func load_le_byte8_uint64_idx8(s []byte, idx int) uint64 {
+ // arm64:`MOVD\s\(R[0-9]+\)\(R[0-9]+<<3\)`,-`ORR`,-`MOV[BHW]`
+ return uint64(s[idx<<3]) | uint64(s[(idx<<3)+1])<<8 | uint64(s[(idx<<3)+2])<<16 | uint64(s[(idx<<3)+3])<<24 | uint64(s[(idx<<3)+4])<<32 | uint64(s[(idx<<3)+5])<<40 | uint64(s[(idx<<3)+6])<<48 | uint64(s[(idx<<3)+7])<<56
+}
+
+func load_le_byte8_uint64_idx8_inv(s []byte, idx int) uint64 {
+ // arm64:`MOVD\s\(R[0-9]+\)\(R[0-9]+<<3\)`,-`ORR`,-`MOV[BHW]`
+ return uint64(s[(idx<<3)+7])<<56 | uint64(s[(idx<<3)+6])<<48 | uint64(s[(idx<<3)+5])<<40 | uint64(s[(idx<<3)+4])<<32 | uint64(s[(idx<<3)+3])<<24 | uint64(s[(idx<<3)+2])<<16 | uint64(s[(idx<<3)+1])<<8 | uint64(s[idx<<3])
+}
+
+func load_be_byte2_uint16_idx2(s []byte, idx int) uint16 {
+ // arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+<<1\)`,`REV16W`,-`ORR`,-`MOVB`
+ return uint16(s[idx<<1])<<8 | uint16(s[(idx<<1)+1])
+}
+
+func load_be_byte2_uint16_idx2_inv(s []byte, idx int) uint16 {
+ // arm64:`MOVHU\s\(R[0-9]+\)\(R[0-9]+<<1\)`,`REV16W`,-`ORR`,-`MOVB`
+ return uint16(s[(idx<<1)+1]) | uint16(s[idx<<1])<<8
+}
+
+func load_be_byte4_uint32_idx4(s []byte, idx int) uint32 {
+ // arm64:`MOVWU\s\(R[0-9]+\)\(R[0-9]+<<2\)`,`REVW`,-`ORR`,-`MOV[BH]`,-`REV16W`
+ return uint32(s[idx<<2])<<24 | uint32(s[(idx<<2)+1])<<16 | uint32(s[(idx<<2)+2])<<8 | uint32(s[(idx<<2)+3])
+}
+
+func load_be_byte8_uint64_idx8(s []byte, idx int) uint64 {
+ // arm64:`MOVD\s\(R[0-9]+\)\(R[0-9]+<<3\)`,`REV`,-`ORR`,-`MOV[BHW]`,-`REVW`,-`REV16W`
+ return uint64(s[idx<<3])<<56 | uint64(s[(idx<<3)+1])<<48 | uint64(s[(idx<<3)+2])<<40 | uint64(s[(idx<<3)+3])<<32 | uint64(s[(idx<<3)+4])<<24 | uint64(s[(idx<<3)+5])<<16 | uint64(s[(idx<<3)+6])<<8 | uint64(s[(idx<<3)+7])
+}
+
+// Check load combining across function calls.
+
+func fcall_byte(a, b byte) (byte, byte) {
+ return fcall_byte(fcall_byte(a, b)) // amd64:`MOVW`
+}
+
+func fcall_uint16(a, b uint16) (uint16, uint16) {
+ return fcall_uint16(fcall_uint16(a, b)) // amd64:`MOVL`
+}
+
+func fcall_uint32(a, b uint32) (uint32, uint32) {
+ return fcall_uint32(fcall_uint32(a, b)) // amd64:`MOVQ`
+}
+
+// We want to merge load+op in the first function, but not in the
+// second. See Issue 19595.
+func load_op_merge(p, q *int) {
+ x := *p
+ *q += x // amd64:`ADDQ\t\(`
+}
+func load_op_no_merge(p, q *int) {
+ x := *p
+ for i := 0; i < 10; i++ {
+ *q += x // amd64:`ADDQ\t[A-Z]`
+ }
+}
+
+// Make sure offsets are folded into loads and stores.
+func offsets_fold(_, a [20]byte) (b [20]byte) {
+ // arm64:`MOVD\t""\.a\+[0-9]+\(FP\), R[0-9]+`,`MOVD\tR[0-9]+, ""\.b\+[0-9]+\(FP\)`
+ b = a
+ return
+}
+
+// Make sure we don't put pointers in SSE registers across safe
+// points.
+
+func safe_point(p, q *[2]*int) {
+ a, b := p[0], p[1] // amd64:-`MOVUPS`
+ runtime.GC()
+ q[0], q[1] = a, b // amd64:-`MOVUPS`
+}
+
+// ------------- //
+// Storing //
+// ------------- //
+
+func store_le64(b []byte) {
+ // amd64:`MOVQ\s.*\(.*\)$`,-`SHR.`
+ // arm64:`MOVD`,-`MOV[WBH]`
+ // ppc64le:`MOVD\s`,-`MOV[BHW]\s`
+ binary.LittleEndian.PutUint64(b, sink64)
+}
+
+func store_le64_idx(b []byte, idx int) {
+ // amd64:`MOVQ\s.*\(.*\)\(.*\*1\)$`,-`SHR.`
+ // arm64:`MOVD\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BHW]`
+ // ppc64le:`MOVD\s`,-`MOV[BHW]\s`
+ binary.LittleEndian.PutUint64(b[idx:], sink64)
+}
+
+func store_le32(b []byte) {
+ // amd64:`MOVL\s`
+ // arm64:`MOVW`,-`MOV[BH]`
+ // ppc64le:`MOVW\s`
+ binary.LittleEndian.PutUint32(b, sink32)
+}
+
+func store_le32_idx(b []byte, idx int) {
+ // amd64:`MOVL\s`
+ // arm64:`MOVW\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BH]`
+ // ppc64le:`MOVW\s`
+ binary.LittleEndian.PutUint32(b[idx:], sink32)
+}
+
+func store_le16(b []byte) {
+ // amd64:`MOVW\s`
+ // arm64:`MOVH`,-`MOVB`
+ // ppc64le:`MOVH\s`
+ binary.LittleEndian.PutUint16(b, sink16)
+}
+
+func store_le16_idx(b []byte, idx int) {
+ // amd64:`MOVW\s`
+ // arm64:`MOVH\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOVB`
+ // ppc64le:`MOVH\s`
+ binary.LittleEndian.PutUint16(b[idx:], sink16)
+}
+
+func store_be64(b []byte) {
+ // amd64:`BSWAPQ`,-`SHR.`
+ // arm64:`MOVD`,`REV`,-`MOV[WBH]`,-`REVW`,-`REV16W`
+ // ppc64le:`MOVDBR`
+ binary.BigEndian.PutUint64(b, sink64)
+}
+
+func store_be64_idx(b []byte, idx int) {
+ // amd64:`BSWAPQ`,-`SHR.`
+ // arm64:`REV`,`MOVD\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BHW]`,-`REV16W`,-`REVW`
+ // ppc64le:`MOVDBR`
+ binary.BigEndian.PutUint64(b[idx:], sink64)
+}
+
+func store_be32(b []byte) {
+ // amd64:`BSWAPL`,-`SHR.`
+ // arm64:`MOVW`,`REVW`,-`MOV[BH]`,-`REV16W`
+ // ppc64le:`MOVWBR`
+ binary.BigEndian.PutUint32(b, sink32)
+}
+
+func store_be32_idx(b []byte, idx int) {
+ // amd64:`BSWAPL`,-`SHR.`
+ // arm64:`REVW`,`MOVW\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOV[BH]`,-`REV16W`
+ // ppc64le:`MOVWBR`
+ binary.BigEndian.PutUint32(b[idx:], sink32)
+}
+
+func store_be16(b []byte) {
+ // amd64:`ROLW\s\$8`,-`SHR.`
+ // arm64:`MOVH`,`REV16W`,-`MOVB`
+ // ppc64le:`MOVHBR`
+ binary.BigEndian.PutUint16(b, sink16)
+}
+
+func store_be16_idx(b []byte, idx int) {
+ // amd64:`ROLW\s\$8`,-`SHR.`
+ // arm64:`MOVH\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,`REV16W`,-`MOVB`
+ // ppc64le:`MOVHBR`
+ binary.BigEndian.PutUint16(b[idx:], sink16)
+}
+
+func store_le_byte_2(b []byte, val uint16) {
+ _ = b[2]
+ // arm64:`MOVH\sR[0-9]+,\s1\(R[0-9]+\)`,-`MOVB`
+ b[1], b[2] = byte(val), byte(val>>8)
+}
+
+func store_le_byte_4(b []byte, val uint32) {
+ _ = b[4]
+ // arm64:`MOVW\sR[0-9]+,\s1\(R[0-9]+\)`,-`MOVB`,-`MOVH`
+ b[1], b[2], b[3], b[4] = byte(val), byte(val>>8), byte(val>>16), byte(val>>24)
+}
+
+func store_le_byte_8(b []byte, val uint64) {
+ _ = b[8]
+ // arm64:`MOVD\sR[0-9]+,\s1\(R[0-9]+\)`,-`MOVB`,-`MOVH`,-`MOVW`
+ b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8] = byte(val), byte(val>>8), byte(val>>16), byte(val>>24), byte(val>>32), byte(val>>40), byte(val>>48), byte(val>>56)
+}
+
+func store_be_byte_2(b []byte, val uint16) {
+ _ = b[2]
+ // arm64:`REV16W`,`MOVH\sR[0-9]+,\s1\(R[0-9]+\)`,-`MOVB`
+ b[1], b[2] = byte(val>>8), byte(val)
+}
+
+func store_be_byte_4(b []byte, val uint32) {
+ _ = b[4]
+ // arm64:`REVW`,`MOVW\sR[0-9]+,\s1\(R[0-9]+\)`,-`MOVB`,-`MOVH`,-`REV16W`
+ b[1], b[2], b[3], b[4] = byte(val>>24), byte(val>>16), byte(val>>8), byte(val)
+}
+
+func store_be_byte_8(b []byte, val uint64) {
+ _ = b[8]
+ // arm64:`REV`,`MOVD\sR[0-9]+,\s1\(R[0-9]+\)`,-`MOVB`,-`MOVH`,-`MOVW`,-`REV16W`,-`REVW`
+ b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8] = byte(val>>56), byte(val>>48), byte(val>>40), byte(val>>32), byte(val>>24), byte(val>>16), byte(val>>8), byte(val)
+}
+
+func store_le_byte_2_idx(b []byte, idx int, val uint16) {
+ _, _ = b[idx+0], b[idx+1]
+ // arm64:`MOVH\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOVB`
+ b[idx+1], b[idx+0] = byte(val>>8), byte(val)
+}
+
+func store_le_byte_4_idx(b []byte, idx int, val uint32) {
+ _, _, _, _ = b[idx+0], b[idx+1], b[idx+2], b[idx+3]
+ // arm64:`MOVW\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOVB`,-`MOVH`
+ b[idx+3], b[idx+2], b[idx+1], b[idx+0] = byte(val>>24), byte(val>>16), byte(val>>8), byte(val)
+}
+
+func store_be_byte_2_idx(b []byte, idx int, val uint16) {
+ _, _ = b[idx+0], b[idx+1]
+ // arm64:`REV16W`,`MOVH\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOVB`
+ b[idx+0], b[idx+1] = byte(val>>8), byte(val)
+}
+
+func store_be_byte_4_idx(b []byte, idx int, val uint32) {
+ _, _, _, _ = b[idx+0], b[idx+1], b[idx+2], b[idx+3]
+ // arm64:`REVW`,`MOVW\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOVB`,-`MOVH`,-`REV16W`
+ b[idx+0], b[idx+1], b[idx+2], b[idx+3] = byte(val>>24), byte(val>>16), byte(val>>8), byte(val)
+}
+
+func store_be_byte_2_idx2(b []byte, idx int, val uint16) {
+ _, _ = b[(idx<<1)+0], b[(idx<<1)+1]
+ // arm64:`REV16W`,`MOVH\sR[0-9]+,\s\(R[0-9]+\)\(R[0-9]+<<1\)`,-`MOVB`
+ b[(idx<<1)+0], b[(idx<<1)+1] = byte(val>>8), byte(val)
+}
+
+// ------------- //
+// Zeroing //
+// ------------- //
+
+// Check that zero stores are combined into larger stores
+
+func zero_byte_2(b1, b2 []byte) {
+ // bounds checks to guarantee safety of writes below
+ _, _ = b1[1], b2[1]
+ b1[0], b1[1] = 0, 0 // arm64:"MOVH\tZR",-"MOVB"
+ b2[1], b2[0] = 0, 0 // arm64:"MOVH\tZR",-"MOVB"
+}
+
+func zero_byte_4(b1, b2 []byte) {
+ _, _ = b1[3], b2[3]
+ b1[0], b1[1], b1[2], b1[3] = 0, 0, 0, 0 // arm64:"MOVW\tZR",-"MOVB",-"MOVH"
+ b2[2], b2[3], b2[1], b2[0] = 0, 0, 0, 0 // arm64:"MOVW\tZR",-"MOVB",-"MOVH"
+}
+
+func zero_byte_8(b []byte) {
+ _ = b[7]
+ b[0], b[1], b[2], b[3] = 0, 0, 0, 0
+ b[4], b[5], b[6], b[7] = 0, 0, 0, 0 // arm64:"MOVD\tZR",-"MOVB",-"MOVH",-"MOVW"
+}
+
+func zero_byte_16(b []byte) {
+ _ = b[15]
+ b[0], b[1], b[2], b[3] = 0, 0, 0, 0
+ b[4], b[5], b[6], b[7] = 0, 0, 0, 0
+ b[8], b[9], b[10], b[11] = 0, 0, 0, 0
+ b[12], b[13], b[14], b[15] = 0, 0, 0, 0 // arm64:"STP",-"MOVB",-"MOVH",-"MOVW"
+}
+
+/* TODO: enable them when corresponding optimization are implemented
+func zero_byte_4_idx(b []byte, idx int) {
+ // arm64: `MOVW\sZR,\s\(R[0-9]+\)\(R[0-9]+<<2\)`,-`MOV[BH]`
+ b[(idx<<2)+0] = 0
+ b[(idx<<2)+1] = 0
+ b[(idx<<2)+2] = 0
+ b[(idx<<2)+3] = 0
+}
+
+func zero_byte_8_idx(b []byte, idx int) {
+ // arm64: `MOVD\sZR,\s\(R[0-9]+\)\(R[0-9]+<<3\)`,-`MOV[BHW]`
+ b[(idx<<3)+0] = 0
+ b[(idx<<3)+1] = 0
+ b[(idx<<3)+2] = 0
+ b[(idx<<3)+3] = 0
+ b[(idx<<3)+4] = 0
+ b[(idx<<3)+5] = 0
+ b[(idx<<3)+6] = 0
+ b[(idx<<3)+7] = 0
+}
+*/
+
+func zero_byte_30(a *[30]byte) {
+ *a = [30]byte{} // arm64:"STP",-"MOVB",-"MOVH",-"MOVW"
+}
+
+func zero_byte_39(a *[39]byte) {
+ *a = [39]byte{} // arm64:"MOVD",-"MOVB",-"MOVH",-"MOVW"
+}
+
+func zero_byte_2_idx(b []byte, idx int) {
+ _, _ = b[idx+0], b[idx+1]
+ // arm64:`MOVH\sZR,\s\(R[0-9]+\)\(R[0-9]+\)`,-`MOVB`
+ b[idx+0], b[idx+1] = 0, 0
+}
+
+func zero_byte_2_idx2(b []byte, idx int) {
+ _, _ = b[(idx<<1)+0], b[(idx<<1)+1]
+ // arm64:`MOVH\sZR,\s\(R[0-9]+\)\(R[0-9]+<<1\)`,-`MOVB`
+ b[(idx<<1)+0], b[(idx<<1)+1] = 0, 0
+}
+
+func zero_uint16_2(h1, h2 []uint16) {
+ _, _ = h1[1], h2[1]
+ h1[0], h1[1] = 0, 0 // arm64:"MOVW\tZR",-"MOVB",-"MOVH"
+ h2[1], h2[0] = 0, 0 // arm64:"MOVW\tZR",-"MOVB",-"MOVH"
+}
+
+func zero_uint16_4(h1, h2 []uint16) {
+ _, _ = h1[3], h2[3]
+ h1[0], h1[1], h1[2], h1[3] = 0, 0, 0, 0 // arm64:"MOVD\tZR",-"MOVB",-"MOVH",-"MOVW"
+ h2[2], h2[3], h2[1], h2[0] = 0, 0, 0, 0 // arm64:"MOVD\tZR",-"MOVB",-"MOVH",-"MOVW"
+}
+
+func zero_uint16_8(h []uint16) {
+ _ = h[7]
+ h[0], h[1], h[2], h[3] = 0, 0, 0, 0
+ h[4], h[5], h[6], h[7] = 0, 0, 0, 0 // arm64:"STP",-"MOVB",-"MOVH"
+}
+
+func zero_uint32_2(w1, w2 []uint32) {
+ _, _ = w1[1], w2[1]
+ w1[0], w1[1] = 0, 0 // arm64:"MOVD\tZR",-"MOVB",-"MOVH",-"MOVW"
+ w2[1], w2[0] = 0, 0 // arm64:"MOVD\tZR",-"MOVB",-"MOVH",-"MOVW"
+}
+
+func zero_uint32_4(w1, w2 []uint32) {
+ _, _ = w1[3], w2[3]
+ w1[0], w1[1], w1[2], w1[3] = 0, 0, 0, 0 // arm64:"STP",-"MOVB",-"MOVH"
+ w2[2], w2[3], w2[1], w2[0] = 0, 0, 0, 0 // arm64:"STP",-"MOVB",-"MOVH"
+}
+
+func zero_uint64_2(d1, d2 []uint64) {
+ _, _ = d1[1], d2[1]
+ d1[0], d1[1] = 0, 0 // arm64:"STP",-"MOVB",-"MOVH"
+ d2[1], d2[0] = 0, 0 // arm64:"STP",-"MOVB",-"MOVH"
+}
diff --git a/test/codegen/rotate.go b/test/codegen/rotate.go
new file mode 100644
index 000000000..5812e1c0b
--- /dev/null
+++ b/test/codegen/rotate.go
@@ -0,0 +1,160 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+// ------------------- //
+// const rotates //
+// ------------------- //
+
+func rot64(x uint64) uint64 {
+ var a uint64
+
+ // amd64:"ROLQ\t[$]7"
+ // arm64:"ROR\t[$]57"
+ // s390x:"RLLG\t[$]7"
+ // ppc64le:"ROTL\t[$]7"
+ a += x<<7 | x>>57
+
+ // amd64:"ROLQ\t[$]8"
+ // arm64:"ROR\t[$]56"
+ // s390x:"RLLG\t[$]8"
+ // ppc64le:"ROTL\t[$]8"
+ a += x<<8 + x>>56
+
+ // amd64:"ROLQ\t[$]9"
+ // arm64:"ROR\t[$]55"
+ // s390x:"RLLG\t[$]9"
+ // ppc64le:"ROTL\t[$]9"
+ a += x<<9 ^ x>>55
+
+ return a
+}
+
+func rot32(x uint32) uint32 {
+ var a uint32
+
+ // amd64:"ROLL\t[$]7"
+ // arm:"MOVW\tR\\d+@>25"
+ // arm64:"RORW\t[$]25"
+ // s390x:"RLL\t[$]7"
+ // ppc64le:"ROTLW\t[$]7"
+ a += x<<7 | x>>25
+
+ // amd64:`ROLL\t[$]8`
+ // arm:"MOVW\tR\\d+@>24"
+ // arm64:"RORW\t[$]24"
+ // s390x:"RLL\t[$]8"
+ // ppc64le:"ROTLW\t[$]8"
+ a += x<<8 + x>>24
+
+ // amd64:"ROLL\t[$]9"
+ // arm:"MOVW\tR\\d+@>23"
+ // arm64:"RORW\t[$]23"
+ // s390x:"RLL\t[$]9"
+ // ppc64le:"ROTLW\t[$]9"
+ a += x<<9 ^ x>>23
+
+ return a
+}
+
+func rot16(x uint16) uint16 {
+ var a uint16
+
+ // amd64:"ROLW\t[$]7"
+ a += x<<7 | x>>9
+
+ // amd64:`ROLW\t[$]8`
+ a += x<<8 + x>>8
+
+ // amd64:"ROLW\t[$]9"
+ a += x<<9 ^ x>>7
+
+ return a
+}
+
+func rot8(x uint8) uint8 {
+ var a uint8
+
+ // amd64:"ROLB\t[$]5"
+ a += x<<5 | x>>3
+
+ // amd64:`ROLB\t[$]6`
+ a += x<<6 + x>>2
+
+ // amd64:"ROLB\t[$]7"
+ a += x<<7 ^ x>>1
+
+ return a
+}
+
+// ----------------------- //
+// non-const rotates //
+// ----------------------- //
+
+func rot64nc(x uint64, z uint) uint64 {
+ var a uint64
+
+ z &= 63
+
+ // amd64:"ROLQ"
+ // ppc64le:"ROTL"
+ a += x<<z | x>>(64-z)
+
+ // amd64:"RORQ"
+ a += x>>z | x<<(64-z)
+
+ return a
+}
+
+func rot32nc(x uint32, z uint) uint32 {
+ var a uint32
+
+ z &= 31
+
+ // amd64:"ROLL"
+ // ppc64le:"ROTLW"
+ a += x<<z | x>>(32-z)
+
+ // amd64:"RORL"
+ a += x>>z | x<<(32-z)
+
+ return a
+}
+
+func rot16nc(x uint16, z uint) uint16 {
+ var a uint16
+
+ z &= 15
+
+ // amd64:"ROLW"
+ a += x<<z | x>>(16-z)
+
+ // amd64:"RORW"
+ a += x>>z | x<<(16-z)
+
+ return a
+}
+
+func rot8nc(x uint8, z uint) uint8 {
+ var a uint8
+
+ z &= 7
+
+ // amd64:"ROLB"
+ a += x<<z | x>>(8-z)
+
+ // amd64:"RORB"
+ a += x>>z | x<<(8-z)
+
+ return a
+}
+
+// Issue 18254: rotate after inlining
+func f32(x uint32) uint32 {
+ // amd64:"ROLL\t[$]7"
+ return rot32nc(x, 7)
+}
diff --git a/test/codegen/shift.go b/test/codegen/shift.go
new file mode 100644
index 000000000..93fa82886
--- /dev/null
+++ b/test/codegen/shift.go
@@ -0,0 +1,99 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+// ------------------ //
+// masked shifts //
+// ------------------ //
+
+func lshMask64x64(v int64, s uint64) int64 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v << (s&63)
+}
+
+func rshMask64Ux64(v uint64, s uint64) uint64 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v >> (s&63)
+}
+
+func rshMask64x64(v int64, s uint64) int64 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v >> (s&63)
+}
+
+func lshMask32x64(v int32, s uint64) int32 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v << (s&63)
+}
+
+func rshMask32Ux64(v uint32, s uint64) uint32 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v >> (s&63)
+}
+
+func rshMask32x64(v int32, s uint64) int32 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v >> (s&63)
+}
+
+func lshMask64x32(v int64, s uint32) int64 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v << (s&63)
+}
+
+func rshMask64Ux32(v uint64, s uint32) uint64 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v >> (s&63)
+}
+
+func rshMask64x32(v int64, s uint32) int64 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v >> (s&63)
+}
+
+func lshMask64x32Ext(v int64, s int32) int64 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v << uint(s&63)
+}
+
+func rshMask64Ux32Ext(v uint64, s int32) uint64 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v >> uint(s&63)
+}
+
+func rshMask64x32Ext(v int64, s int32) int64 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v >> uint(s&63)
+}
+
+// ------------------ //
+// bounded shifts //
+// ------------------ //
+
+func lshGuarded64(v int64, s uint) int64 {
+ if s < 64 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v >> s
+ }
+ panic("shift too large")
+}
+
+func rshGuarded64U(v uint64, s uint) uint64 {
+ if s < 64 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v >> s
+ }
+ panic("shift too large")
+}
+
+func rshGuarded64(v int64, s uint) int64 {
+ if s < 64 {
+ // s390x:-".*AND",-".*MOVDGE"
+ return v << s
+ }
+ panic("shift too large")
+}
diff --git a/test/codegen/slices.go b/test/codegen/slices.go
new file mode 100644
index 000000000..15dbcee73
--- /dev/null
+++ b/test/codegen/slices.go
@@ -0,0 +1,63 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+// This file contains code generation tests related to the handling of
+// slice types.
+
+// ------------------ //
+// Clear //
+// ------------------ //
+
+// Issue #5373 optimize memset idiom
+
+func SliceClear(s []int) []int {
+ // amd64:`.*memclrNoHeapPointers`
+ for i := range s {
+ s[i] = 0
+ }
+ return s
+}
+
+func SliceClearPointers(s []*int) []*int {
+ // amd64:`.*memclrHasPointers`
+ for i := range s {
+ s[i] = nil
+ }
+ return s
+}
+
+// ------------------ //
+// Extension //
+// ------------------ //
+
+// Issue #21266 - avoid makeslice in append(x, make([]T, y)...)
+
+func SliceExtensionConst(s []int) []int {
+ // amd64:`.*runtime\.memclrNoHeapPointers`
+ // amd64:-`.*runtime\.makeslice`
+ // amd64:-`.*runtime\.panicmakeslicelen`
+ return append(s, make([]int, 1<<2)...)
+}
+
+func SliceExtensionPointer(s []*int, l int) []*int {
+ // amd64:`.*runtime\.memclrHasPointers`
+ // amd64:-`.*runtime\.makeslice`
+ return append(s, make([]*int, l)...)
+}
+
+func SliceExtensionVar(s []byte, l int) []byte {
+ // amd64:`.*runtime\.memclrNoHeapPointers`
+ // amd64:-`.*runtime\.makeslice`
+ return append(s, make([]byte, l)...)
+}
+
+func SliceExtensionInt64(s []int, l64 int64) []int {
+ // 386:`.*runtime\.makeslice`
+ // 386:-`.*runtime\.memclr`
+ return append(s, make([]int, l64)...)
+}
diff --git a/test/codegen/stack.go b/test/codegen/stack.go
new file mode 100644
index 000000000..7e12dbc0e
--- /dev/null
+++ b/test/codegen/stack.go
@@ -0,0 +1,95 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+import "runtime"
+
+// This file contains code generation tests related to the use of the
+// stack.
+
+// Check that stack stores are optimized away.
+
+// 386:"TEXT\t.*, [$]0-"
+// amd64:"TEXT\t.*, [$]0-"
+// arm:"TEXT\t.*, [$]-4-"
+// arm64:"TEXT\t.*, [$]-8-"
+// mips:"TEXT\t.*, [$]-4-"
+// ppc64le:"TEXT\t.*, [$]0-"
+// s390x:"TEXT\t.*, [$]0-"
+func StackStore() int {
+ var x int
+ return *(&x)
+}
+
+type T struct {
+ A, B, C, D int // keep exported fields
+ x, y, z int // reset unexported fields
+}
+
+// Check that large structs are cleared directly (issue #24416).
+
+// 386:"TEXT\t.*, [$]0-"
+// amd64:"TEXT\t.*, [$]0-"
+// arm:"TEXT\t.*, [$]0-" (spills return address)
+// arm64:"TEXT\t.*, [$]-8-"
+// mips:"TEXT\t.*, [$]-4-"
+// ppc64le:"TEXT\t.*, [$]0-"
+// s390x:"TEXT\t.*, [$]0-"
+func ZeroLargeStruct(x *T) {
+ t := T{}
+ *x = t
+}
+
+// Check that structs are partially initialised directly (issue #24386).
+
+// Notes:
+// - 386 fails due to spilling a register
+// amd64:"TEXT\t.*, [$]0-"
+// arm:"TEXT\t.*, [$]0-" (spills return address)
+// arm64:"TEXT\t.*, [$]-8-"
+// ppc64le:"TEXT\t.*, [$]0-"
+// s390x:"TEXT\t.*, [$]0-"
+// Note: that 386 currently has to spill a register.
+func KeepWanted(t *T) {
+ *t = T{A: t.A, B: t.B, C: t.C, D: t.D}
+}
+
+// Check that small array operations avoid using the stack (issue #15925).
+
+// Notes:
+// - 386 fails due to spilling a register
+// - arm & mips fail due to softfloat calls
+// amd64:"TEXT\t.*, [$]0-"
+// arm64:"TEXT\t.*, [$]-8-"
+// ppc64le:"TEXT\t.*, [$]0-"
+// s390x:"TEXT\t.*, [$]0-"
+func ArrayAdd64(a, b [4]float64) [4]float64 {
+ return [4]float64{a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]}
+}
+
+// Check that small array initialization avoids using the stack.
+
+// 386:"TEXT\t.*, [$]0-"
+// amd64:"TEXT\t.*, [$]0-"
+// arm:"TEXT\t.*, [$]0-" (spills return address)
+// arm64:"TEXT\t.*, [$]-8-"
+// mips:"TEXT\t.*, [$]-4-"
+// ppc64le:"TEXT\t.*, [$]0-"
+// s390x:"TEXT\t.*, [$]0-"
+func ArrayInit(i, j int) [4]int {
+ return [4]int{i, 0, j, 0}
+}
+
+// Check that assembly output has matching offset and base register
+// (issue #21064).
+
+func check_asmout(a, b int) int {
+ runtime.GC() // use some frame
+ // amd64:`.*b\+24\(SP\)`
+ // arm:`.*b\+4\(FP\)`
+ return b
+}
diff --git a/test/codegen/strings.go b/test/codegen/strings.go
new file mode 100644
index 000000000..ccb6bd427
--- /dev/null
+++ b/test/codegen/strings.go
@@ -0,0 +1,15 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+// This file contains code generation tests related to the handling of
+// string types.
+
+func CountRunes(s string) int { // Issue #24923
+ // amd64:`.*countrunes`
+ return len([]rune(s))
+}
diff --git a/test/codegen/structs.go b/test/codegen/structs.go
new file mode 100644
index 000000000..b81ad67c4
--- /dev/null
+++ b/test/codegen/structs.go
@@ -0,0 +1,46 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+// This file contains code generation tests related to the handling of
+// struct types.
+
+// ------------- //
+// Zeroing //
+// ------------- //
+
+type Z1 struct {
+ a, b, c int
+}
+
+func Zero1(t *Z1) { // Issue #18370
+ // amd64:`XORPS\tX., X`,`MOVUPS\tX., \(.*\)`,`MOVQ\t\$0, 16\(.*\)`
+ *t = Z1{}
+}
+
+type Z2 struct {
+ a, b, c *int
+}
+
+func Zero2(t *Z2) {
+ // amd64:`XORPS\tX., X`,`MOVUPS\tX., \(.*\)`,`MOVQ\t\$0, 16\(.*\)`
+ // amd64:`.*runtime[.]gcWriteBarrier\(SB\)`
+ *t = Z2{}
+}
+
+// ------------------ //
+// Initializing //
+// ------------------ //
+
+type I1 struct {
+ a, b, c, d int
+}
+
+func Init1(p *I1) { // Issue #18872
+ // amd64:`MOVQ\t[$]1`,`MOVQ\t[$]2`,`MOVQ\t[$]3`,`MOVQ\t[$]4`
+ *p = I1{1, 2, 3, 4}
+}
diff --git a/test/const1.go b/test/const1.go
index 58bddee7e..62abe4145 100644
--- a/test/const1.go
+++ b/test/const1.go
@@ -90,5 +90,5 @@ func main() {
const ptr = nil // ERROR "const.*nil"
const _ = string([]byte(nil)) // ERROR "is not a? ?constant"
const _ = uintptr(unsafe.Pointer((*int)(nil))) // ERROR "is not a? ?constant"
-const _ = unsafe.Pointer((*int)(nil)) // ERROR "cannot be nil|invalid constant type"
-const _ = (*int)(nil) // ERROR "cannot be nil|invalid constant type"
+const _ = unsafe.Pointer((*int)(nil)) // ERROR "cannot be nil|invalid constant type|is not a constant"
+const _ = (*int)(nil) // ERROR "cannot be nil|invalid constant type|is not a constant"
diff --git a/test/deferprint.go b/test/deferprint.go
index 3dc08542c..b74677ac5 100644
--- a/test/deferprint.go
+++ b/test/deferprint.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/escape4.go b/test/escape4.go
index 22a37c1d0..0fe330539 100644
--- a/test/escape4.go
+++ b/test/escape4.go
@@ -34,8 +34,8 @@ func f1() {
func f2() {} // ERROR "can inline f2"
-// No inline for panic, recover.
-func f3() { panic(1) }
+// No inline for recover; panic now allowed to inline.
+func f3() { panic(1) } // ERROR "can inline f3"
func f4() { recover() }
func f5() *byte {
diff --git a/test/escape5.go b/test/escape5.go
index 7d6ef554a..03283a37f 100644
--- a/test/escape5.go
+++ b/test/escape5.go
@@ -163,3 +163,68 @@ func f13() {
f12(&x) // ERROR "&x does not escape"
runtime.KeepAlive(&x) // ERROR "&x does not escape"
}
+
+// Test for issue 24305 (passing to unnamed receivers does not escape).
+type U int
+
+func (*U) M() {}
+func (_ *U) N() {}
+
+func _() {
+ var u U
+ u.M() // ERROR "u does not escape"
+ u.N() // ERROR "u does not escape"
+}
+
+// Issue 24730: taking address in a loop causes unnecessary escape
+type T24730 struct {
+ x [64]byte
+}
+
+func (t *T24730) g() { // ERROR "t does not escape"
+ y := t.x[:] // ERROR "t\.x does not escape"
+ for i := range t.x[:] { // ERROR "t\.x does not escape"
+ y = t.x[:] // ERROR "t\.x does not escape"
+ y[i] = 1
+ }
+
+ var z *byte
+ for i := range t.x[:] { // ERROR "t\.x does not escape"
+ z = &t.x[i] // ERROR "t\.x\[i\] does not escape"
+ *z = 2
+ }
+}
+
+// Issue 15730: copy causes unnecessary escape
+
+var sink []byte
+var sink2 []int
+var sink3 []*int
+
+func f15730a(args ...interface{}) { // ERROR "args does not escape"
+ for _, arg := range args {
+ switch a := arg.(type) {
+ case string:
+ copy(sink, a)
+ }
+ }
+}
+
+func f15730b(args ...interface{}) { // ERROR "args does not escape"
+ for _, arg := range args {
+ switch a := arg.(type) {
+ case []int:
+ copy(sink2, a)
+ }
+ }
+}
+
+func f15730c(args ...interface{}) { // ERROR "leaking param content: args"
+ for _, arg := range args {
+ switch a := arg.(type) {
+ case []*int:
+ // copy pointerful data should cause escape
+ copy(sink3, a)
+ }
+ }
+}
diff --git a/test/escape_array.go b/test/escape_array.go
index 0204c690c..c2c3e2c85 100644
--- a/test/escape_array.go
+++ b/test/escape_array.go
@@ -120,3 +120,10 @@ func doesMakeSlice(x *string, y *string) { // ERROR "leaking param: x" "leaking
b := make([]*string, 65537) // ERROR "make\(\[\]\*string, 65537\) escapes to heap"
b[0] = y
}
+
+func nonconstArray() {
+ n := 32
+ s1 := make([]int, n) // ERROR "make\(\[\]int, n\) escapes to heap"
+ s2 := make([]int, 0, n) // ERROR "make\(\[\]int, 0, n\) escapes to heap"
+ _, _ = s1, s2
+}
diff --git a/test/escape_because.go b/test/escape_because.go
index 7d349b7a1..c7548fc67 100644
--- a/test/escape_because.go
+++ b/test/escape_because.go
@@ -118,6 +118,13 @@ func transmit(b []byte) []byte { // ERROR "from ~r1 \(return\) at escape_because
return b
}
+func f14() {
+ n := 32
+ s1 := make([]int, n) // ERROR "make\(\[\]int, n\) escapes to heap" "from make\(\[\]int, n\) \(non-constant size\)"
+ s2 := make([]int, 0, n) // ERROR "make\(\[\]int, 0, n\) escapes to heap" "from make\(\[\]int, 0, n\) \(non-constant size\)"
+ _, _ = s1, s2
+}
+
// The list below is all of the why-escapes messages seen building the escape analysis tests.
/*
for i in escape*go ; do echo compile $i; go build -gcflags '-l -m -m' $i >& `basename $i .go`.log ; done
@@ -134,51 +141,40 @@ appended to slice
appendee slice
arg to ...
arg to recursive call
-array literal element
array-element-equals
-assign-pair
-assign-pair-dot-type
-assign-pair-func-call
+array literal element
assigned
assigned to top level variable
-call part
+assign-pair-dot-type
+assign-pair-func-call
captured by a closure
-closure-var
-converted
-copied slice
-defer func
-defer func ...
-defer func arg
+captured by called closure
dot
-dot of pointer
dot-equals
+dot of pointer
fixed-array-index-of
-go func
-go func ...
go func arg
indirection
interface-converted
key of map put
map literal key
map literal value
+non-constant size
+panic
parameter to indirect call
+passed-to-and-returned-from-call
passed to call[argument content escapes]
passed to call[argument escapes]
-passed-to-and-returned-from-call
pointer literal
-range
range-deref
receiver in indirect call
return
returned from recursive function
-send
-slice
slice-element-equals
slice-literal-element
star-dot-equals
star-equals
struct literal element
-switch case
too large for stack
value of map put
*/
@@ -191,7 +187,6 @@ assign-pair-mapr
assign-pair-receive
call receiver
map index
-panic
pointer literal [assign]
slice literal element
*/
diff --git a/test/fixedbugs/bug206.go b/test/fixedbugs/bug206.go
index c2382acf1..91efa3ff7 100644
--- a/test/fixedbugs/bug206.go
+++ b/test/fixedbugs/bug206.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug248.dir/bug1.go b/test/fixedbugs/bug248.dir/bug1.go
index 78433f504..f1db77d2f 100644
--- a/test/fixedbugs/bug248.dir/bug1.go
+++ b/test/fixedbugs/bug248.dir/bug1.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file
-package p
+package q
type T struct {
X, Y int
diff --git a/test/fixedbugs/bug248.dir/bug2.go b/test/fixedbugs/bug248.dir/bug2.go
index ba547d64a..c0fdecfdb 100644
--- a/test/fixedbugs/bug248.dir/bug2.go
+++ b/test/fixedbugs/bug248.dir/bug2.go
@@ -2,19 +2,20 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file
-package main
+package s
import (
p0 "./bug0"
p1 "./bug1"
-
- "reflect"
- "strings"
)
+// both p0.T and p1.T are struct { X, Y int }.
+
var v0 p0.T
var v1 p1.T
+// interfaces involving the two
+
type I0 interface {
M(p0.T)
}
@@ -23,83 +24,50 @@ type I1 interface {
M(p1.T)
}
+// t0 satisfies I0 and p0.I
type t0 int
func (t0) M(p0.T) {}
+// t1 satisfies I1 and p1.I
type t1 float64
func (t1) M(p1.T) {}
+// check static interface assignments
var i0 I0 = t0(0) // ok
var i1 I1 = t1(0) // ok
+var i2 I0 = t1(0) // ERROR "does not implement|incompatible"
+var i3 I1 = t0(0) // ERROR "does not implement|incompatible"
+
var p0i p0.I = t0(0) // ok
var p1i p1.I = t1(0) // ok
-func main() {
- // check that reflect paths are correct,
- // meaning that reflect data for v0, v1 didn't get confused.
-
- // path is full (rooted) path name. check suffix for gc, prefix for gccgo
- if s := reflect.TypeOf(v0).PkgPath(); !strings.HasSuffix(s, "/bug0") && !strings.HasPrefix(s, "bug0") {
- println("bad v0 path", len(s), s)
- panic("fail")
- }
- if s := reflect.TypeOf(v1).PkgPath(); !strings.HasSuffix(s, "/bug1") && !strings.HasPrefix(s, "bug1") {
- println("bad v1 path", s)
- panic("fail")
- }
-
- // check that dynamic interface check doesn't get confused
- var i interface{} = t0(0)
- if _, ok := i.(I1); ok {
- println("used t0 as i1")
- panic("fail")
- }
- if _, ok := i.(p1.I); ok {
- println("used t0 as p1.I")
- panic("fail")
- }
-
- i = t1(1)
- if _, ok := i.(I0); ok {
- println("used t1 as i0")
- panic("fail")
- }
- if _, ok := i.(p0.I); ok {
- println("used t1 as p0.I")
- panic("fail")
- }
-
- // check that type switch works.
- // the worry is that if p0.T and p1.T have the same hash,
- // the binary search will handle one of them incorrectly.
- for j := 0; j < 3; j++ {
- switch j {
- case 0:
- i = p0.T{}
- case 1:
- i = p1.T{}
- case 2:
- i = 3.14
- }
- switch i.(type) {
- case p0.T:
- if j != 0 {
- println("type switch p0.T")
- panic("fail")
- }
- case p1.T:
- if j != 1 {
- println("type switch p1.T")
- panic("fail")
- }
- default:
- if j != 2 {
- println("type switch default", j)
- panic("fail")
- }
- }
- }
+var p0i1 p0.I = t1(0) // ERROR "does not implement|incompatible"
+var p0i2 p1.I = t0(0) // ERROR "does not implement|incompatible"
+
+func foobar() {
+ // check that cannot assign one to the other,
+ // but can convert.
+ v0 = v1 // ERROR "assign"
+ v1 = v0 // ERROR "assign"
+
+ v0 = p0.T(v1)
+ v1 = p1.T(v0)
+
+ i0 = i1 // ERROR "cannot use|incompatible"
+ i1 = i0 // ERROR "cannot use|incompatible"
+ p0i = i1 // ERROR "cannot use|incompatible"
+ p1i = i0 // ERROR "cannot use|incompatible"
+ i0 = p1i // ERROR "cannot use|incompatible"
+ i1 = p0i // ERROR "cannot use|incompatible"
+ p0i = p1i // ERROR "cannot use|incompatible"
+ p1i = p0i // ERROR "cannot use|incompatible"
+
+ i0 = p0i
+ p0i = i0
+
+ i1 = p1i
+ p1i = i1
}
diff --git a/test/fixedbugs/bug248.dir/bug3.go b/test/fixedbugs/bug248.dir/bug3.go
index 4a56c5cc8..ba547d64a 100644
--- a/test/fixedbugs/bug248.dir/bug3.go
+++ b/test/fixedbugs/bug248.dir/bug3.go
@@ -7,15 +7,14 @@ package main
import (
p0 "./bug0"
p1 "./bug1"
-)
-// both p0.T and p1.T are struct { X, Y int }.
+ "reflect"
+ "strings"
+)
var v0 p0.T
var v1 p1.T
-// interfaces involving the two
-
type I0 interface {
M(p0.T)
}
@@ -24,50 +23,83 @@ type I1 interface {
M(p1.T)
}
-// t0 satisfies I0 and p0.I
type t0 int
func (t0) M(p0.T) {}
-// t1 satisfies I1 and p1.I
type t1 float64
func (t1) M(p1.T) {}
-// check static interface assignments
var i0 I0 = t0(0) // ok
var i1 I1 = t1(0) // ok
-var i2 I0 = t1(0) // ERROR "does not implement|incompatible"
-var i3 I1 = t0(0) // ERROR "does not implement|incompatible"
-
var p0i p0.I = t0(0) // ok
var p1i p1.I = t1(0) // ok
-var p0i1 p0.I = t1(0) // ERROR "does not implement|incompatible"
-var p0i2 p1.I = t0(0) // ERROR "does not implement|incompatible"
-
func main() {
- // check that cannot assign one to the other,
- // but can convert.
- v0 = v1 // ERROR "assign"
- v1 = v0 // ERROR "assign"
-
- v0 = p0.T(v1)
- v1 = p1.T(v0)
-
- i0 = i1 // ERROR "cannot use|incompatible"
- i1 = i0 // ERROR "cannot use|incompatible"
- p0i = i1 // ERROR "cannot use|incompatible"
- p1i = i0 // ERROR "cannot use|incompatible"
- i0 = p1i // ERROR "cannot use|incompatible"
- i1 = p0i // ERROR "cannot use|incompatible"
- p0i = p1i // ERROR "cannot use|incompatible"
- p1i = p0i // ERROR "cannot use|incompatible"
-
- i0 = p0i
- p0i = i0
-
- i1 = p1i
- p1i = i1
+ // check that reflect paths are correct,
+ // meaning that reflect data for v0, v1 didn't get confused.
+
+ // path is full (rooted) path name. check suffix for gc, prefix for gccgo
+ if s := reflect.TypeOf(v0).PkgPath(); !strings.HasSuffix(s, "/bug0") && !strings.HasPrefix(s, "bug0") {
+ println("bad v0 path", len(s), s)
+ panic("fail")
+ }
+ if s := reflect.TypeOf(v1).PkgPath(); !strings.HasSuffix(s, "/bug1") && !strings.HasPrefix(s, "bug1") {
+ println("bad v1 path", s)
+ panic("fail")
+ }
+
+ // check that dynamic interface check doesn't get confused
+ var i interface{} = t0(0)
+ if _, ok := i.(I1); ok {
+ println("used t0 as i1")
+ panic("fail")
+ }
+ if _, ok := i.(p1.I); ok {
+ println("used t0 as p1.I")
+ panic("fail")
+ }
+
+ i = t1(1)
+ if _, ok := i.(I0); ok {
+ println("used t1 as i0")
+ panic("fail")
+ }
+ if _, ok := i.(p0.I); ok {
+ println("used t1 as p0.I")
+ panic("fail")
+ }
+
+ // check that type switch works.
+ // the worry is that if p0.T and p1.T have the same hash,
+ // the binary search will handle one of them incorrectly.
+ for j := 0; j < 3; j++ {
+ switch j {
+ case 0:
+ i = p0.T{}
+ case 1:
+ i = p1.T{}
+ case 2:
+ i = 3.14
+ }
+ switch i.(type) {
+ case p0.T:
+ if j != 0 {
+ println("type switch p0.T")
+ panic("fail")
+ }
+ case p1.T:
+ if j != 1 {
+ println("type switch p1.T")
+ panic("fail")
+ }
+ default:
+ if j != 2 {
+ println("type switch default", j)
+ panic("fail")
+ }
+ }
+ }
}
diff --git a/test/fixedbugs/bug248.go b/test/fixedbugs/bug248.go
index 173b46fd8..93d2fdb67 100644
--- a/test/fixedbugs/bug248.go
+++ b/test/fixedbugs/bug248.go
@@ -1,53 +1,12 @@
-// +build !nacl,!plan9,!windows
-// run
+// +build !nacl,!js,!plan9
+// errorcheckandrundir -1
// Copyright 2009 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
+package ignored
-import (
- "fmt"
- "os"
- "os/exec"
- "path/filepath"
-)
-
-func main() {
- // TODO: If we get rid of errchk, re-enable this test on Windows.
- errchk, err := filepath.Abs("errchk")
- check(err)
-
- err = os.Chdir(filepath.Join("fixedbugs", "bug248.dir"))
- check(err)
-
- run("go", "tool", "compile", "bug0.go")
- run("go", "tool", "compile", "bug1.go")
- run("go", "tool", "compile", "bug2.go")
- run(errchk, "go", "tool", "compile", "-e", "bug3.go")
- run("go", "tool", "link", "bug2.o")
- run(fmt.Sprintf(".%ca.out", filepath.Separator))
-
- os.Remove("bug0.o")
- os.Remove("bug1.o")
- os.Remove("bug2.o")
- os.Remove("a.out")
-}
-
-func run(name string, args ...string) {
- cmd := exec.Command(name, args...)
- out, err := cmd.CombinedOutput()
- if err != nil {
- fmt.Println(string(out))
- fmt.Println(err)
- os.Exit(1)
- }
-}
-
-func check(err error) {
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-}
+// Compile: bug0.go, bug1.go
+// Compile and errorCheck: bug2.go
+// Link and run: bug3.go
diff --git a/test/fixedbugs/bug273.go b/test/fixedbugs/bug273.go
index c04f2116c..7305c6063 100644
--- a/test/fixedbugs/bug273.go
+++ b/test/fixedbugs/bug273.go
@@ -8,13 +8,15 @@
package main
+import "unsafe"
+
var bug = false
var minus1 = -1
var five = 5
-var big int64 = 10 | 1<<32
+var big int64 = 10 | 1<<40
-type block [1<<19]byte
+type block [1 << 19]byte
var g1 []block
@@ -48,9 +50,10 @@ func bigcap() {
g1 = make([]block, 10, big)
}
-type cblock [1<<16-1]byte
+type cblock [1<<16 - 1]byte
var g4 chan cblock
+
func badchancap() {
g4 = make(chan cblock, minus1)
}
@@ -60,7 +63,8 @@ func bigchancap() {
}
func overflowchan() {
- g4 = make(chan cblock, 1<<30)
+ const ptrSize = unsafe.Sizeof(uintptr(0))
+ g4 = make(chan cblock, 1<<(30*(ptrSize/4)))
}
func main() {
diff --git a/test/fixedbugs/bug302.go b/test/fixedbugs/bug302.go
index e4de25d5d..c763b8778 100644
--- a/test/fixedbugs/bug302.go
+++ b/test/fixedbugs/bug302.go
@@ -1,4 +1,4 @@
-// +build !nacl
+// +build !nacl,!js
// run
// Copyright 2010 The Go Authors. All rights reserved.
diff --git a/test/fixedbugs/bug328.go b/test/fixedbugs/bug328.go
index 180af05fd..57043f30a 100644
--- a/test/fixedbugs/bug328.go
+++ b/test/fixedbugs/bug328.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug345.dir/main.go b/test/fixedbugs/bug345.dir/main.go
index 6e4fdf4e2..b77a2fad5 100644
--- a/test/fixedbugs/bug345.dir/main.go
+++ b/test/fixedbugs/bug345.dir/main.go
@@ -6,8 +6,9 @@ package main
import (
"bufio"
- "./io"
goio "io"
+
+ "./io"
)
func main() {
@@ -22,7 +23,7 @@ func main() {
// main.go:27: cannot use &x (type *"io".SectionReader) as type *"/Users/rsc/g/go/test/fixedbugs/bug345.dir/io".SectionReader in function argument
var w io.Writer
- bufio.NewWriter(w) // ERROR "test/io|has incompatible type"
+ bufio.NewWriter(w) // ERROR "[\w.]+[^.]/io|has incompatible type"
var x goio.SectionReader
- io.SR(&x) // ERROR "test/io|has incompatible type"
+ io.SR(&x) // ERROR "[\w.]+[^.]/io|has incompatible type"
}
diff --git a/test/fixedbugs/bug345.go b/test/fixedbugs/bug345.go
index dcf62f059..b974a61ff 100644
--- a/test/fixedbugs/bug345.go
+++ b/test/fixedbugs/bug345.go
@@ -1,45 +1,10 @@
-// +build !nacl,!plan9,!windows
-// run
+// +build !windows
+// errorcheckdir -n
// Copyright 2011 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
+package ignored
-import (
- "fmt"
- "os"
- "os/exec"
- "path/filepath"
-)
-
-func main() {
- // TODO: If we get rid of errchk, re-enable this test on Plan 9 and Windows.
- errchk, err := filepath.Abs("errchk")
- check(err)
-
- err = os.Chdir(filepath.Join(".", "fixedbugs", "bug345.dir"))
- check(err)
-
- run("go", "tool", "compile", "io.go")
- run(errchk, "go", "tool", "compile", "-e", "main.go")
- os.Remove("io.o")
-}
-
-func run(name string, args ...string) {
- cmd := exec.Command(name, args...)
- out, err := cmd.CombinedOutput()
- if err != nil {
- fmt.Println(string(out))
- fmt.Println(err)
- os.Exit(1)
- }
-}
-
-func check(err error) {
- if err != nil {
- fmt.Println(err)
- os.Exit(1)
- }
-}
+// TODO(ysmolsky): Fix golang.org/issue/25693 to enable on Windows.
diff --git a/test/fixedbugs/bug369.go b/test/fixedbugs/bug369.go
index 60162ab1c..e2a114773 100644
--- a/test/fixedbugs/bug369.go
+++ b/test/fixedbugs/bug369.go
@@ -1,4 +1,4 @@
-// +build !nacl,!windows
+// +build !nacl,!js,!windows
// run
// Copyright 2011 The Go Authors. All rights reserved.
diff --git a/test/fixedbugs/bug409.go b/test/fixedbugs/bug409.go
index 9e08a8e67..e8546361a 100644
--- a/test/fixedbugs/bug409.go
+++ b/test/fixedbugs/bug409.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/bug429_run.go b/test/fixedbugs/bug429_run.go
index 284033d1f..c6a02aae5 100644
--- a/test/fixedbugs/bug429_run.go
+++ b/test/fixedbugs/bug429_run.go
@@ -1,4 +1,4 @@
-// +build !nacl
+// +build !nacl,!js
// run
// Copyright 2014 The Go Authors. All rights reserved.
diff --git a/test/fixedbugs/issue10958.go b/test/fixedbugs/issue10958.go
index 2b7669413..52487fb9b 100644
--- a/test/fixedbugs/issue10958.go
+++ b/test/fixedbugs/issue10958.go
@@ -1,4 +1,4 @@
-// +build !nacl,disabled_see_issue_18589
+// +build !nacl,!js,disabled_see_issue_18589
// buildrun -t 10 -gcflags=-d=ssa/insert_resched_checks/on,ssa/check/on
// Copyright 2016 The Go Authors. All rights reserved.
diff --git a/test/fixedbugs/issue11656.go b/test/fixedbugs/issue11656.go
index c04a66202..451ae6348 100644
--- a/test/fixedbugs/issue11656.go
+++ b/test/fixedbugs/issue11656.go
@@ -9,6 +9,9 @@
// doesn't go into the Go runtime.
// +build !windows
+// wasm does not work, because the linear memory is not executable.
+// +build !wasm
+
package main
import (
diff --git a/test/fixedbugs/issue11771.go b/test/fixedbugs/issue11771.go
index d91fc5d96..99d7060d4 100644
--- a/test/fixedbugs/issue11771.go
+++ b/test/fixedbugs/issue11771.go
@@ -1,4 +1,4 @@
-// +build !nacl
+// +build !nacl,!js
// run
// Copyright 2015 The Go Authors. All rights reserved.
diff --git a/test/fixedbugs/issue12621.go b/test/fixedbugs/issue12621.go
new file mode 100644
index 000000000..379a362d7
--- /dev/null
+++ b/test/fixedbugs/issue12621.go
@@ -0,0 +1,20 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issues 12576 and 12621: Negative untyped floating point constants
+// with small magnitude round to 0, not negative zero.
+
+package main
+
+import "math"
+
+var m = -1e-10000
+
+func main() {
+ if math.Signbit(m) {
+ panic(m)
+ }
+}
diff --git a/test/fixedbugs/issue14321.go b/test/fixedbugs/issue14321.go
new file mode 100644
index 000000000..058008c38
--- /dev/null
+++ b/test/fixedbugs/issue14321.go
@@ -0,0 +1,33 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that error message reports _ambiguous_ method.
+
+package p
+
+type A struct{
+ H int
+}
+
+func (A) F() {}
+func (A) G() {}
+
+type B struct{
+ G int
+ H int
+}
+
+func (B) F() {}
+
+type C struct {
+ A
+ B
+}
+
+var _ = C.F // ERROR "ambiguous selector"
+var _ = C.G // ERROR "ambiguous selector"
+var _ = C.H // ERROR "ambiguous selector"
+var _ = C.I // ERROR "no method I"
diff --git a/test/fixedbugs/issue14636.go b/test/fixedbugs/issue14636.go
index 7d1b60624..6b342e402 100644
--- a/test/fixedbugs/issue14636.go
+++ b/test/fixedbugs/issue14636.go
@@ -1,4 +1,4 @@
-// +build !nacl,!android,!darwin darwin,!arm
+// +build !nacl,!js,!android,!darwin darwin,!arm
// run
// Copyright 2016 The Go Authors. All rights reserved.
diff --git a/test/fixedbugs/issue15747.go b/test/fixedbugs/issue15747.go
index decabc754..c7ef96d58 100644
--- a/test/fixedbugs/issue15747.go
+++ b/test/fixedbugs/issue15747.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -live -d=eagerwb
+// errorcheck -0 -live
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -7,10 +7,6 @@
// Issue 15747: liveness analysis was marking heap-escaped params live too much,
// and worse was using the wrong bitmap bits to do so.
-// TODO(austin): This expects function calls to the write barrier, so
-// we enable the legacy eager write barrier. Fix this once the
-// buffered write barrier works on all arches.
-
package p
var global *[]byte
@@ -21,14 +17,14 @@ type T struct{ M string }
var b bool
-func f1(q *Q, xx []byte) interface{} { // ERROR "live at call to newobject: xx$" "live at call to writebarrierptr: &xx$" "live at entry to f1: xx$"
+func f1(q *Q, xx []byte) interface{} { // ERROR "live at call to newobject: xx$" "live at entry to f1: xx$"
// xx was copied from the stack to the heap on the previous line:
// xx was live for the first two prints but then it switched to &xx
// being live. We should not see plain xx again.
if b {
- global = &xx // ERROR "live at call to writebarrierptr: &xx$"
+ global = &xx
}
- xx, _, err := f2(xx, 5) // ERROR "live at call to f2: &xx$" "live at call to writebarrierptr: err.data err.type$"
+ xx, _, err := f2(xx, 5) // ERROR "live at call to f2: &xx$"
if err != nil {
return err
}
@@ -38,7 +34,7 @@ func f1(q *Q, xx []byte) interface{} { // ERROR "live at call to newobject: xx$"
//go:noinline
func f2(d []byte, n int) (odata, res []byte, e interface{}) { // ERROR "live at entry to f2: d$"
if n > len(d) {
- return d, nil, &T{M: "hello"} // ERROR "live at call to newobject: d" "live at call to writebarrierptr: d"
+ return d, nil, &T{M: "hello"} // ERROR "live at call to newobject: d"
}
res = d[:n]
odata = d[n:]
diff --git a/test/fixedbugs/issue16037_run.go b/test/fixedbugs/issue16037_run.go
index 23fff5925..d05e3f7f3 100644
--- a/test/fixedbugs/issue16037_run.go
+++ b/test/fixedbugs/issue16037_run.go
@@ -1,4 +1,4 @@
-// +build !nacl,!android
+// +build !nacl,!js,!android
// run
// Copyright 2016 The Go Authors. All rights reserved.
diff --git a/test/fixedbugs/issue18640.go b/test/fixedbugs/issue18640.go
index c4f948b70..60abd31f7 100644
--- a/test/fixedbugs/issue18640.go
+++ b/test/fixedbugs/issue18640.go
@@ -11,12 +11,20 @@ type (
b struct {
*a
}
+)
+type (
c struct {
*d
}
d = c
+)
+// The compiler reports an incorrect (non-alias related)
+// type cycle here (via dowith()). Disabled for now.
+// See issue #25838.
+/*
+type (
e = f
f = g
g = []h
@@ -24,3 +32,16 @@ type (
i = j
j = e
)
+*/
+
+type (
+ a1 struct{ *b1 }
+ b1 = c1
+ c1 struct{ *b1 }
+)
+
+type (
+ a2 struct{ b2 }
+ b2 = c2
+ c2 struct{ *b2 }
+)
diff --git a/test/fixedbugs/issue18902.go b/test/fixedbugs/issue18902.go
deleted file mode 100644
index 78c92187e..000000000
--- a/test/fixedbugs/issue18902.go
+++ /dev/null
@@ -1,141 +0,0 @@
-// run
-// +build !nacl
-
-// Copyright 2016 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.
-
-// Runs a build -S to capture the assembly language
-// output, checks that the line numbers associated with
-// the stream of instructions do not change "too much".
-// The changes that fixes this (that reduces the amount
-// of change) does so by treating register spill, reload,
-// copy, and rematerializations as being "unimportant" and
-// just assigns them the line numbers of whatever "real"
-// instructions preceded them.
-
-// nacl is excluded because this runs a compiler.
-
-package main
-
-import (
- "bufio"
- "bytes"
- "fmt"
- "os"
- "os/exec"
- "strconv"
- "strings"
-)
-
-// updateEnv modifies env to ensure that key=val
-func updateEnv(env *[]string, key, val string) {
- if val != "" {
- var found bool
- key = key + "="
- for i, kv := range *env {
- if strings.HasPrefix(kv, key) {
- (*env)[i] = key + val
- found = true
- break
- }
- }
- if !found {
- *env = append(*env, key+val)
- }
- }
-}
-
-func main() {
- testarch := os.Getenv("TESTARCH") // Targets other platform in test compilation.
- debug := os.Getenv("TESTDEBUG") != "" // Output the relevant assembly language.
-
- cmd := exec.Command("go", "tool", "compile", "-S", "fixedbugs/issue18902b.go")
- var buf bytes.Buffer
- cmd.Stdout = &buf
- cmd.Stderr = &buf
- cmd.Env = os.Environ()
-
- if testarch != "" {
- updateEnv(&cmd.Env, "GOARCH", testarch)
- updateEnv(&cmd.Env, "GOOS", "linux") // Simplify multi-arch testing
- }
-
- err := cmd.Run()
- if err != nil {
- fmt.Printf("%s\n%s", err, buf.Bytes())
- return
- }
- begin := "\"\".(*gcSortBuf).flush" // Text at beginning of relevant dissassembly.
- s := buf.String()
- i := strings.Index(s, begin)
- if i < 0 {
- fmt.Printf("Failed to find expected symbol %s in output\n%s\n", begin, s)
- return
- }
- s = s[i:]
- r := strings.NewReader(s)
- scanner := bufio.NewScanner(r)
- first := true // The first line after the begin text will be skipped
- beforeLineNumber := "issue18902b.go:" // Text preceding line number in each line.
- lbln := len(beforeLineNumber)
-
- var scannedCount, changes, sumdiffs float64
-
- prevVal := 0
- for scanner.Scan() {
- line := scanner.Text()
- if first {
- first = false
- continue
- }
- i = strings.Index(line, beforeLineNumber)
- if i < 0 {
- // Done reading lines
- const minLines = 150
- if scannedCount <= minLines { // When test was written, 251 lines observed on amd64; arm64 now obtains 184
- fmt.Printf("Scanned only %d lines, was expecting more than %d\n", int(scannedCount), minLines)
- return
- }
- // Note: when test was written, before changes=92, after=50 (was 62 w/o rematerialization NoXPos in *Value.copyInto())
- // and before sumdiffs=784, after=180 (was 446 w/o rematerialization NoXPos in *Value.copyInto())
- // Set the dividing line between pass and fail at the midpoint.
- // Normalize against instruction count in case we unroll loops, etc.
- if changes/scannedCount >= (50+92)/(2*scannedCount) || sumdiffs/scannedCount >= (180+784)/(2*scannedCount) {
- fmt.Printf("Line numbers change too much, # of changes=%.f, sumdiffs=%.f, # of instructions=%.f\n", changes, sumdiffs, scannedCount)
- }
- return
- }
- scannedCount++
- i += lbln
- lineVal, err := strconv.Atoi(line[i : i+3])
- if err != nil {
- fmt.Printf("Expected 3-digit line number after %s in %s\n", beforeLineNumber, line)
- }
- if prevVal == 0 {
- prevVal = lineVal
- }
- diff := lineVal - prevVal
- if diff < 0 {
- diff = -diff
- }
- if diff != 0 {
- changes++
- sumdiffs += float64(diff)
- }
- // If things change too much, set environment variable TESTDEBUG to help figure out what's up.
- // The "before" behavior can be recreated in DebugFriendlySetPosFrom (currently in gc/ssa.go)
- // by inserting unconditional
- // s.SetPos(v.Pos)
- // at the top of the function.
-
- if debug {
- fmt.Printf("%d %.f %.f %s\n", lineVal, changes, sumdiffs, line)
- }
- prevVal = lineVal
- }
- if err := scanner.Err(); err != nil {
- fmt.Println("Reading standard input:", err)
- return
- }
-}
diff --git a/test/fixedbugs/issue18902b.go b/test/fixedbugs/issue18902b.go
deleted file mode 100644
index 2e43e9f32..000000000
--- a/test/fixedbugs/issue18902b.go
+++ /dev/null
@@ -1,161 +0,0 @@
-// skip
-
-// Copyright 2016 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 foo
-
-import (
- "unsafe"
-)
-
-type gcMaxTreeNodeVal uint64
-
-var work struct {
- full uint64 // lock-free list of full blocks workbuf
- empty uint64 // lock-free list of empty blocks workbuf
- pad0 [64]uint8 // prevents false-sharing between full/empty and nproc/nwait
- bytesMarked uint64
- markrootNext uint32 // next markroot job
- markrootJobs uint32 // number of markroot jobs
- nproc uint32
- tstart int64
- nwait uint32
- ndone uint32
-}
-
-type gcShardQueue1 struct {
- partial *workbuf
- full *workbuf
- n uintptr
- maxTree gcMaxTreeNodeVal
-}
-type gcShardQueue struct {
- gcShardQueue1
- pad [64 - unsafe.Sizeof(gcShardQueue1{})]byte
-}
-
-const gcSortBufPointers = (64 << 10) / 8
-
-type gcSortBuf struct {
- buf *gcSortArray
- tmp *gcSortArray
- n uintptr
-}
-
-//go:notinheap
-type gcSortArray [gcSortBufPointers]uintptr
-
-const (
- _DebugGC = 0
- _ConcurrentSweep = true
- _FinBlockSize = 4 * 1024
- sweepMinHeapDistance = 1024 * 1024
- gcShardShift = 2 + 20
- gcShardBytes = 1 << gcShardShift
-)
-
-//go:notinheap
-type mheap struct {
- shardQueues []gcShardQueue
- _ uint32 // align uint64 fields on 32-bit for atomics
- pagesInUse uint64 // pages of spans in stats _MSpanInUse; R/W with mheap.lock
- spanBytesAlloc uint64 // bytes of spans allocated this cycle; updated atomically
- pagesSwept uint64 // pages swept this cycle; updated atomically
- sweepPagesPerByte float64 // proportional sweep ratio; written with lock, read without
- largefree uint64 // bytes freed for large objects (>maxsmallsize)
- nlargefree uint64 // number of frees for large objects (>maxsmallsize)
- nsmallfree [67]uint64 // number of frees for small objects (<=maxsmallsize)
- bitmap uintptr // Points to one byte past the end of the bitmap
- bitmap_mapped uintptr
- arena_start uintptr
- arena_used uintptr // always mHeap_Map{Bits,Spans} before updating
- arena_end uintptr
- arena_reserved bool
-}
-
-var mheap_ mheap
-
-type lfnode struct {
- next uint64
- pushcnt uintptr
-}
-type workbufhdr struct {
- node lfnode // must be first
- next *workbuf
- nobj int
-}
-
-//go:notinheap
-type workbuf struct {
- workbufhdr
- obj [(2048 - unsafe.Sizeof(workbufhdr{})) / 8]uintptr
-}
-
-//go:noinline
-func (b *workbuf) checkempty() {
- if b.nobj != 0 {
- b.nobj = 0
- }
-}
-func putempty(b *workbuf) {
- b.checkempty()
- lfstackpush(&work.empty, &b.node)
-}
-
-//go:noinline
-func lfstackpush(head *uint64, node *lfnode) {
-}
-
-//go:noinline
-func (q *gcShardQueue) add(qidx uintptr, ptrs []uintptr, spare *workbuf) *workbuf {
- return spare
-}
-
-func (b *gcSortBuf) flush() {
- if b.n == 0 {
- return
- }
- const sortDigitBits = 11
- buf, tmp := b.buf[:b.n], b.tmp[:b.n]
- moreBits := true
- for shift := uint(gcShardShift); moreBits; shift += sortDigitBits {
- const k = 1 << sortDigitBits
- var pos [k]uint16
- nshift := shift + sortDigitBits
- nbits := buf[0] >> nshift
- moreBits = false
- for _, v := range buf {
- pos[(v>>shift)%k]++
- moreBits = moreBits || v>>nshift != nbits
- }
- var sum uint16
- for i, count := range &pos {
- pos[i] = sum
- sum += count
- }
- for _, v := range buf {
- digit := (v >> shift) % k
- tmp[pos[digit]] = v
- pos[digit]++
- }
- buf, tmp = tmp, buf
- }
- start := mheap_.arena_start
- i0 := 0
- shard0 := (buf[0] - start) / gcShardBytes
- var spare *workbuf
- for i, p := range buf {
- shard := (p - start) / gcShardBytes
- if shard != shard0 {
- spare = mheap_.shardQueues[shard0].add(shard0, buf[i0:i], spare)
- i0, shard0 = i, shard
- }
- }
- spare = mheap_.shardQueues[shard0].add(shard0, buf[i0:], spare)
- b.n = 0
- if spare != nil {
- putempty(spare)
- }
-}
diff --git a/test/fixedbugs/issue18911.dir/a.go b/test/fixedbugs/issue18911.dir/a.go
new file mode 100644
index 000000000..d2221e761
--- /dev/null
+++ b/test/fixedbugs/issue18911.dir/a.go
@@ -0,0 +1,7 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+var X interface{} = struct{ x int }{}
diff --git a/test/fixedbugs/issue18911.dir/b.go b/test/fixedbugs/issue18911.dir/b.go
new file mode 100644
index 000000000..da2388b88
--- /dev/null
+++ b/test/fixedbugs/issue18911.dir/b.go
@@ -0,0 +1,21 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+import "strings"
+
+func main() {
+ defer func() {
+ p, ok := recover().(error)
+ if ok && strings.Contains(p.Error(), "different packages") {
+ return
+ }
+ panic(p)
+ }()
+
+ // expected to fail and report two identical looking (but different) types
+ _ = a.X.(struct{ x int })
+}
diff --git a/test/fixedbugs/issue18911.go b/test/fixedbugs/issue18911.go
new file mode 100644
index 000000000..8bf34a382
--- /dev/null
+++ b/test/fixedbugs/issue18911.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignore
diff --git a/test/fixedbugs/issue19182.go b/test/fixedbugs/issue19182.go
index 3a90ff4b2..e1f3ffb47 100644
--- a/test/fixedbugs/issue19182.go
+++ b/test/fixedbugs/issue19182.go
@@ -1,4 +1,5 @@
// run
+// +build !js
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/issue19359.go b/test/fixedbugs/issue19359.go
index 4717d1365..cc3ecc84f 100644
--- a/test/fixedbugs/issue19359.go
+++ b/test/fixedbugs/issue19359.go
@@ -28,10 +28,64 @@ func del(m map[interface{}]interface{}, key interface{}) (err error) {
return nil
}
+func addInt(m map[interface{}]int, key interface{}) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = fmt.Errorf("addInt failed: %v", r)
+ }
+ }()
+ m[key] += 2018
+ return nil
+}
+
+func addStr(m map[interface{}]string, key interface{}) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = fmt.Errorf("addStr failed: %v", r)
+ }
+ }()
+ m[key] += "hello, go"
+ return nil
+}
+
+func appendInt(m map[interface{}][]int, key interface{}) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = fmt.Errorf("appendInt failed: %v", r)
+ }
+ }()
+ m[key] = append(m[key], 2018)
+ return nil
+}
+
+func appendStr(m map[interface{}][]string, key interface{}) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ err = fmt.Errorf("addStr failed: %v", r)
+ }
+ }()
+ m[key] = append(m[key], "hello, go")
+ return nil
+}
+
func main() {
m := make(map[interface{}]interface{})
set(m, []int{1, 2, 3})
set(m, "abc") // used to throw
del(m, []int{1, 2, 3})
del(m, "abc") // used to throw
+
+ mi := make(map[interface{}]int)
+ addInt(mi, []int{1, 2, 3})
+ addInt(mi, "abc") // used to throw
+
+ ms := make(map[interface{}]string)
+ addStr(ms, []int{1, 2, 3})
+ addStr(ms, "abc") // used to throw
+
+ mia := make(map[interface{}][]int)
+ appendInt(mia, []int{1, 2, 3})
+
+ msa := make(map[interface{}][]string)
+ appendStr(msa, "abc") // used to throw
}
diff --git a/test/fixedbugs/issue19658.go b/test/fixedbugs/issue19658.go
index 91cb88658..b2539629d 100644
--- a/test/fixedbugs/issue19658.go
+++ b/test/fixedbugs/issue19658.go
@@ -1,4 +1,4 @@
-// +build !nacl
+// +build !nacl,!js
// run
// Copyright 2017 The Go Authors. All rights reserved.
diff --git a/test/fixedbugs/issue20250.go b/test/fixedbugs/issue20250.go
index 525192a46..6fc861a8d 100644
--- a/test/fixedbugs/issue20250.go
+++ b/test/fixedbugs/issue20250.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -live -l -d=compilelater,eagerwb
+// errorcheck -0 -live -l -d=compilelater
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -8,10 +8,6 @@
// due to propagation of addrtaken to outer variables for
// closure variables.
-// TODO(austin): This expects function calls to the write barrier, so
-// we enable the legacy eager write barrier. Fix this once the
-// buffered write barrier works on all arches.
-
package p
type T struct {
@@ -21,7 +17,7 @@ type T struct {
func f(a T) { // ERROR "live at entry to f: a"
var e interface{}
func() { // ERROR "live at entry to f.func1: a &e"
- e = a.s // ERROR "live at call to convT2Estring: a &e" "live at call to writebarrierptr: a"
+ e = a.s // ERROR "live at call to convT2Estring: a &e"
}() // ERROR "live at call to f.func1: e$"
// Before the fix, both a and e were live at the previous line.
_ = e
diff --git a/test/fixedbugs/issue20529.go b/test/fixedbugs/issue20529.go
index cd0c23da0..669064c2e 100644
--- a/test/fixedbugs/issue20529.go
+++ b/test/fixedbugs/issue20529.go
@@ -13,6 +13,9 @@
package p
+import "runtime"
+
func f() { // ERROR "stack frame too large"
- _ = [][]int{1e9: []int{}}
+ x := [][]int{1e9: []int{}}
+ runtime.KeepAlive(x)
}
diff --git a/test/fixedbugs/issue20780.go b/test/fixedbugs/issue20780.go
new file mode 100644
index 000000000..a31e031b7
--- /dev/null
+++ b/test/fixedbugs/issue20780.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// We have a limit of 1GB for stack frames.
+// Make sure we include the callee args section.
+// (The dispatch wrapper which implements (*S).f
+// copies the return value from f to a stack temp, then
+// from that stack temp to the return value of (*S).f.
+// It uses ~800MB for each section.)
+
+package main
+
+type S struct {
+ i interface {
+ f() [800e6]byte
+ }
+}
diff --git a/test/fixedbugs/issue20923.go b/test/fixedbugs/issue20923.go
new file mode 100644
index 000000000..5fd1ad8a4
--- /dev/null
+++ b/test/fixedbugs/issue20923.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 20923: gccgo failed to compile parenthesized select case expressions.
+
+package p
+
+func F(c chan bool) {
+ select {
+ case (<-c):
+ case _ = (<-c):
+ case _, _ = (<-c):
+ case (c) <- true:
+ default:
+ }
+}
diff --git a/test/fixedbugs/issue21221.go b/test/fixedbugs/issue21221.go
new file mode 100644
index 000000000..bd5a4b550
--- /dev/null
+++ b/test/fixedbugs/issue21221.go
@@ -0,0 +1,18 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "unsafe"
+
+func main() {
+ if unsafe.Pointer(uintptr(0)) != unsafe.Pointer(nil) {
+ panic("fail")
+ }
+ if (*int)(unsafe.Pointer(uintptr(0))) != (*int)(nil) {
+ panic("fail")
+ }
+}
diff --git a/test/fixedbugs/issue21317.go b/test/fixedbugs/issue21317.go
index ae0e0b55f..530694af1 100644
--- a/test/fixedbugs/issue21317.go
+++ b/test/fixedbugs/issue21317.go
@@ -21,7 +21,7 @@ import (
)
func main() {
- if runtime.Compiler != "gc" || runtime.GOOS == "nacl" {
+ if runtime.Compiler != "gc" || runtime.GOOS == "nacl" || runtime.GOOS == "js" {
return
}
diff --git a/test/fixedbugs/issue21887.go b/test/fixedbugs/issue21887.go
index 9e3e91fcd..73c3f4359 100644
--- a/test/fixedbugs/issue21887.go
+++ b/test/fixedbugs/issue21887.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/issue22305.go b/test/fixedbugs/issue22305.go
new file mode 100644
index 000000000..ec432f9ae
--- /dev/null
+++ b/test/fixedbugs/issue22305.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 22305: gccgo failed to compile this file.
+
+package main
+
+var F func() [0]func()
+var i = 2
+var B = F()[i]
+
+func main() {}
diff --git a/test/fixedbugs/issue22660.go b/test/fixedbugs/issue22660.go
index 48686fefe..b2282ea66 100644
--- a/test/fixedbugs/issue22660.go
+++ b/test/fixedbugs/issue22660.go
@@ -19,7 +19,7 @@ import (
)
func main() {
- if runtime.GOOS == "nacl" {
+ if runtime.GOOS == "nacl" || runtime.GOOS == "js" {
return // no file system available on builders
}
diff --git a/test/fixedbugs/issue22662.go b/test/fixedbugs/issue22662.go
new file mode 100644
index 000000000..a1f00bfac
--- /dev/null
+++ b/test/fixedbugs/issue22662.go
@@ -0,0 +1,46 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify effect of various line directives.
+// TODO: check columns
+
+package main
+
+import (
+ "fmt"
+ "runtime"
+)
+
+func check(file string, line int) {
+ _, f, l, ok := runtime.Caller(1)
+ if !ok {
+ panic("runtime.Caller(1) failed")
+ }
+ if f != file || l != line {
+ panic(fmt.Sprintf("got %s:%d; want %s:%d", f, l, file, line))
+ }
+}
+
+func main() {
+//-style line directives
+//line :1
+ check("??", 1) // no file specified
+//line foo.go:1
+ check("foo.go", 1)
+//line bar.go:10:20
+ check("bar.go", 10)
+//line :11:22
+ check("bar.go", 11) // no file, but column specified => keep old filename
+
+/*-style line directives */
+/*line :1*/ check("??", 1) // no file specified
+/*line foo.go:1*/ check("foo.go", 1)
+/*line bar.go:10:20*/ check("bar.go", 10)
+/*line :11:22*/ check("bar.go", 11) // no file, but column specified => keep old filename
+
+ /*line :10*/ check("??", 10); /*line foo.go:20*/ check("foo.go", 20); /*line :30:1*/ check("foo.go", 30)
+ check("foo.go", 31)
+}
diff --git a/test/fixedbugs/issue22662b.go b/test/fixedbugs/issue22662b.go
new file mode 100644
index 000000000..3594c0f4e
--- /dev/null
+++ b/test/fixedbugs/issue22662b.go
@@ -0,0 +1,65 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify the impact of line directives on error positions and position formatting.
+
+package main
+
+import (
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "runtime"
+ "strings"
+)
+
+// Each of these tests is expected to fail (missing package clause)
+// at the position determined by the preceeding line directive.
+var tests = []struct {
+ src, pos string
+}{
+ {"//line :10\n", ":10:"}, // no filename means no filename
+ {"//line :10:4\n", "filename:10:4"}, // no filename means use existing filename
+ {"//line foo.go:10\n", "foo.go:10:"}, // no column means don't print a column
+ {"//line foo.go:10:4\n", "foo.go:10:4:"}, // column means print a column
+ {"//line foo.go:10:4\n\n", "foo.go:11:1:"}, // relative columns start at 1 after newline
+
+ {"/*line :10*/", ":10:"},
+ {"/*line :10:4*/", "filename:10:4"},
+ {"/*line foo.go:10*/", "foo.go:10:"},
+ {"/*line foo.go:10:4*/", "foo.go:10:4:"},
+ {"/*line foo.go:10:4*/\n", "foo.go:11:1:"},
+}
+
+func main() {
+ if runtime.GOOS == "nacl" || runtime.GOOS == "js" {
+ return // can not exec go tool
+ }
+
+ f, err := ioutil.TempFile("", "issue22662b.go")
+ if err != nil {
+ log.Fatal(err)
+ }
+ f.Close()
+ defer os.Remove(f.Name())
+
+ for _, test := range tests {
+ if err := ioutil.WriteFile(f.Name(), []byte(test.src), 0660); err != nil {
+ log.Fatal(err)
+ }
+
+ out, err := exec.Command("go", "tool", "compile", f.Name()).CombinedOutput()
+ if err == nil {
+ log.Fatalf("expected compiling\n---\n%s\n---\nto fail", test.src)
+ }
+
+ errmsg := strings.Replace(string(out), f.Name(), "filename", -1) // use "filename" instead of actual (long) filename
+ if !strings.HasPrefix(errmsg, test.pos) {
+ log.Fatalf("%q: got %q; want position %q", test.src, errmsg, test.pos)
+ }
+ }
+}
diff --git a/test/fixedbugs/issue22683.go b/test/fixedbugs/issue22683.go
index a59a0edaf..47c7f6513 100644
--- a/test/fixedbugs/issue22683.go
+++ b/test/fixedbugs/issue22683.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/issue22822.go b/test/fixedbugs/issue22822.go
new file mode 100644
index 000000000..e449ddb18
--- /dev/null
+++ b/test/fixedbugs/issue22822.go
@@ -0,0 +1,16 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that calling a function shadowing a built-in provides a good
+// error message.
+
+package main
+
+func F() {
+ slice := []int{1, 2, 3}
+ len := int(2)
+ println(len(slice)) // ERROR "cannot call non-function len .type int., declared at"
+}
diff --git a/test/fixedbugs/issue22881.go b/test/fixedbugs/issue22881.go
index 61e99a288..645f2d4b8 100644
--- a/test/fixedbugs/issue22881.go
+++ b/test/fixedbugs/issue22881.go
@@ -13,7 +13,7 @@ import "fmt"
func main() {
for i, f := range []func(map[int]int){
- f0, f1, f2, f3, f4, f5, f6, f7,
+ f0, f1, f2, f3, f4, f5, f6, f7, f8,
} {
m := map[int]int{}
func() { // wrapper to scope the defer.
@@ -27,6 +27,23 @@ func main() {
fmt.Printf("map insert happened, case f%d\n", i)
}
}
+
+ // Append slice.
+ for i, f := range []func(map[int][]int){
+ fa0, fa1, fa2, fa3,
+ } {
+ m := map[int][]int{}
+ func() { // wrapper to scope the defer.
+ defer func() {
+ recover()
+ }()
+ f(m) // Will panic. Shouldn't modify m.
+ fmt.Printf("RHS didn't panic, case fa%d\n", i)
+ }()
+ if len(m) != 0 {
+ fmt.Printf("map insert happened, case fa%d\n", i)
+ }
+ }
}
func f0(m map[int]int) {
@@ -69,4 +86,32 @@ func f7(m map[int]int) {
m[0] = a[0]
}
+func f8(m map[int]int) {
+ var z int
+ m[0] %= z
+}
+
+func fa0(m map[int][]int) {
+ var p *int
+ m[0] = append(m[0], *p)
+}
+
+func fa1(m map[int][]int) {
+ var p *int
+ sink, m[0] = !sink, append(m[0], *p)
+}
+
+func fa2(m map[int][]int) {
+ var p *int
+ m[0], _ = append(m[0], 0), *p
+}
+
+func fa3(m map[int][]int) {
+ // OSLICE has similar in-place-reassignment
+ // optimizations as OAPPEND, but we need to make sure
+ // to *not* optimize them, because we can't guarantee
+ // the slice indices are within bounds.
+ m[0] = m[0][:1]
+}
+
var sink bool
diff --git a/test/fixedbugs/issue23094.go b/test/fixedbugs/issue23094.go
new file mode 100644
index 000000000..415556f30
--- /dev/null
+++ b/test/fixedbugs/issue23094.go
@@ -0,0 +1,11 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that the array is reported in correct notation.
+
+package p
+
+var a [len(a)]int // ERROR "\[len\(a\)\]int"
diff --git a/test/fixedbugs/issue23116.go b/test/fixedbugs/issue23116.go
new file mode 100644
index 000000000..1737fee2c
--- /dev/null
+++ b/test/fixedbugs/issue23116.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(x interface{}) {
+ switch x.(type) {
+ }
+
+ switch t := x.(type) { // ERROR "declared and not used"
+ }
+}
diff --git a/test/fixedbugs/issue23188.go b/test/fixedbugs/issue23188.go
new file mode 100644
index 000000000..c22434069
--- /dev/null
+++ b/test/fixedbugs/issue23188.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test order of evaluation of index operations.
+
+package main
+
+func main() {
+ arr := []int{1, 2}
+
+ // The spec says that in an assignment statement the operands
+ // of all index expressions and pointer indirections on the
+ // left, and the expressions on the right, are evaluated in
+ // the usual order. The usual order means function calls and
+ // channel operations are done first. Then the assignments are
+ // carried out one at a time. The operands of an index
+ // expression include both the array and the index. So this
+ // evaluates as
+ // tmp1 := arr
+ // tmp2 := len(arr) - 1
+ // tmp3 := len(arr)
+ // arr = arr[:tmp3-1]
+ // tmp1[tmp2] = 3
+ arr, arr[len(arr)-1] = arr[:len(arr)-1], 3
+
+ if len(arr) != 1 || arr[0] != 1 || arr[:2][1] != 3 {
+ panic(arr)
+ }
+}
diff --git a/test/fixedbugs/issue23298.go b/test/fixedbugs/issue23298.go
new file mode 100644
index 000000000..be00a8ec6
--- /dev/null
+++ b/test/fixedbugs/issue23298.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type T string
+
+var (
+ t = T("T")
+ r = []rune(t)
+)
diff --git a/test/fixedbugs/issue23414.go b/test/fixedbugs/issue23414.go
new file mode 100644
index 000000000..7ef3d831f
--- /dev/null
+++ b/test/fixedbugs/issue23414.go
@@ -0,0 +1,13 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var x struct{}
+
+func f() bool {
+ return x == x && x == x
+}
diff --git a/test/fixedbugs/issue23489.go b/test/fixedbugs/issue23489.go
new file mode 100644
index 000000000..1e64af190
--- /dev/null
+++ b/test/fixedbugs/issue23489.go
@@ -0,0 +1,20 @@
+// 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.
+
+// Caused gccgo to issue a spurious compilation error.
+
+package main
+
+type T struct{}
+
+func (*T) Foo() {}
+
+type P = *T
+
+func main() {
+ var p P
+ p.Foo()
+}
diff --git a/test/fixedbugs/issue23504.go b/test/fixedbugs/issue23504.go
new file mode 100644
index 000000000..77f318414
--- /dev/null
+++ b/test/fixedbugs/issue23504.go
@@ -0,0 +1,15 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f() {
+ var B bool
+ B2 := (B || B && !B) && !B
+ B3 := B2 || B
+ for (B3 || B2) && !B2 && B {
+ }
+}
diff --git a/test/fixedbugs/issue23521.go b/test/fixedbugs/issue23521.go
new file mode 100644
index 000000000..159e03238
--- /dev/null
+++ b/test/fixedbugs/issue23521.go
@@ -0,0 +1,43 @@
+// errorcheck -0 -m
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 23521: improve early DCE for if without explicit else.
+
+package p
+
+//go:noinline
+func nonleaf() {}
+
+const truth = true
+
+func f() int { // ERROR "can inline f"
+ if truth {
+ return 0
+ }
+ // If everything below is removed, as it should,
+ // function f should be inlineable.
+ nonleaf()
+ for {
+ panic("")
+ }
+}
+
+func g() int { // ERROR "can inline g"
+ return f() // ERROR "inlining call to f"
+}
+
+func f2() int { // ERROR "can inline f2"
+ if !truth {
+ nonleaf()
+ } else {
+ return 0
+ }
+ panic("")
+}
+
+func g2() int { // ERROR "can inline g2"
+ return f2() // ERROR "inlining call to f2"
+}
diff --git a/test/fixedbugs/issue23545.go b/test/fixedbugs/issue23545.go
index 24485c11c..d97f64af5 100644
--- a/test/fixedbugs/issue23545.go
+++ b/test/fixedbugs/issue23545.go
@@ -4,12 +4,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// +build gccgo
-
// Issue 23545: gccgo didn't lower array comparison to
// proper equality function in some case.
-// TODO: build only on gccgo for now, as it hits issue
-// #23546.
package main
diff --git a/test/fixedbugs/issue23546.go b/test/fixedbugs/issue23546.go
new file mode 100644
index 000000000..818f0cd6b
--- /dev/null
+++ b/test/fixedbugs/issue23546.go
@@ -0,0 +1,22 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 23546: type..eq function not generated when
+// DWARF is disabled.
+
+package main
+
+func main() {
+ use(f() == f())
+}
+
+func f() [2]interface{} {
+ var out [2]interface{}
+ return out
+}
+
+//go:noinline
+func use(bool) {}
diff --git a/test/fixedbugs/issue23586.go b/test/fixedbugs/issue23586.go
new file mode 100644
index 000000000..c2d4c9ffb
--- /dev/null
+++ b/test/fixedbugs/issue23586.go
@@ -0,0 +1,24 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that we type-check deferred/go functions even
+// if they are not called (a common error). Specifically,
+// we don't want to see errors such as import or variable
+// declared but not used.
+
+package p
+
+import (
+ "fmt"
+ "math"
+)
+
+func f() {
+ var i int
+ defer func() { fmt.Println() } // ERROR "must be function call"
+ go func() { _ = math.Sin(0) } // ERROR "must be function call"
+ go func() { _ = i} // ERROR "must be function call"
+}
diff --git a/test/fixedbugs/issue23587.go b/test/fixedbugs/issue23587.go
new file mode 100644
index 000000000..bd5df2775
--- /dev/null
+++ b/test/fixedbugs/issue23587.go
@@ -0,0 +1,12 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(x int) {
+ _ = ~x // ERROR "invalid character"
+ _ = x ~ x // ERROR "invalid character" "unexpected x at end of statement"
+}
diff --git a/test/fixedbugs/issue23609.go b/test/fixedbugs/issue23609.go
new file mode 100644
index 000000000..7c17a98d3
--- /dev/null
+++ b/test/fixedbugs/issue23609.go
@@ -0,0 +1,27 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type t1 struct {
+ t1f1 int
+ t1f2 int
+}
+type t2 struct {
+ t2f1 int
+ t2f2 int
+ t1
+}
+type t3 struct {
+ t3f1 int
+ t2
+}
+
+var (
+ _ = t2{t1f1: 600} // ERROR "cannot use promoted field t1.t1f1 in struct literal of type t2"
+ _ = t3{t1f2: 800} // ERROR "cannot use promoted field t2.t1.t1f2 in struct literal of type t3"
+ _ = t3{t2f1: 900} // ERROR "cannot use promoted field t2.t2f1 in struct literal of type t3"
+)
diff --git a/test/fixedbugs/issue23664.go b/test/fixedbugs/issue23664.go
new file mode 100644
index 000000000..1925ebffe
--- /dev/null
+++ b/test/fixedbugs/issue23664.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify error messages for incorrect if/switch headers.
+
+package p
+
+func f() {
+ if f() true { // ERROR "unexpected true, expecting {"
+ }
+
+ switch f() true { // ERROR "unexpected true, expecting {"
+ }
+}
diff --git a/test/fixedbugs/issue23732.go b/test/fixedbugs/issue23732.go
new file mode 100644
index 000000000..be17bf4f6
--- /dev/null
+++ b/test/fixedbugs/issue23732.go
@@ -0,0 +1,42 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 23732: Give better details about which struct
+// initializer has the wrong number of values.
+
+package main
+
+type Foo struct {
+ A int
+ B int
+ C interface{}
+ Bar
+}
+
+type Bar struct {
+ A string
+}
+
+func main() {
+ _ = Foo{
+ 1,
+ 2,
+ 3, // ERROR "too few values in Foo literal"
+ }
+
+ _ = Foo{
+ 1,
+ 2,
+ 3,
+ Bar{"A", "B"}, // ERROR "too many values in Bar literal"
+ }
+
+ _ = Foo{
+ 1,
+ 2,
+ Bar{"A", "B"}, // ERROR "too many values in Bar literal" "too few values in Foo literal"
+ }
+}
diff --git a/test/fixedbugs/issue23823.go b/test/fixedbugs/issue23823.go
new file mode 100644
index 000000000..2f802d098
--- /dev/null
+++ b/test/fixedbugs/issue23823.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type I1 = interface {
+ I2
+}
+
+type I2 interface { // ERROR "invalid recursive type"
+ I1
+}
diff --git a/test/fixedbugs/issue23912.go b/test/fixedbugs/issue23912.go
new file mode 100644
index 000000000..05ffd6be2
--- /dev/null
+++ b/test/fixedbugs/issue23912.go
@@ -0,0 +1,30 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// A couple of aliases cases that gccgo incorrectly gave errors for.
+
+package p
+
+func F1() {
+ type E = struct{}
+ type X struct{}
+ var x X
+ var y E = x
+ _ = y
+}
+
+func F2() {
+ type E = struct{}
+ type S []E
+ type T []struct{}
+ type X struct{}
+ var x X
+ s := S{E{}}
+ t := T{struct{}{}}
+ _ = append(s, x)
+ _ = append(s, t[0])
+ _ = append(s, t...)
+}
diff --git a/test/fixedbugs/issue24120.go b/test/fixedbugs/issue24120.go
new file mode 100644
index 000000000..6c7d871b7
--- /dev/null
+++ b/test/fixedbugs/issue24120.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+var F func(int)
+
+func G() {
+ if F(func() int { return 1 }()); false {
+ }
+}
diff --git a/test/fixedbugs/issue24159.go b/test/fixedbugs/issue24159.go
new file mode 100644
index 000000000..9397bdc84
--- /dev/null
+++ b/test/fixedbugs/issue24159.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type intAlias = int
+
+func f() {
+ switch interface{}(nil) {
+ case uint8(0):
+ case byte(0): // ERROR "duplicate case"
+ case int32(0):
+ case rune(0): // ERROR "duplicate case"
+ case int(0):
+ case intAlias(0): // ERROR "duplicate case"
+ }
+}
diff --git a/test/fixedbugs/issue24173.go b/test/fixedbugs/issue24173.go
new file mode 100644
index 000000000..4c19e05ef
--- /dev/null
+++ b/test/fixedbugs/issue24173.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type arrayAlias = [10]int
+type mapAlias = map[int]int
+type sliceAlias = []int
+type structAlias = struct{}
+
+func Exported() {
+ _ = arrayAlias{}
+ _ = mapAlias{}
+ _ = sliceAlias{}
+ _ = structAlias{}
+}
diff --git a/test/fixedbugs/issue24187.go b/test/fixedbugs/issue24187.go
new file mode 100644
index 000000000..45fc92971
--- /dev/null
+++ b/test/fixedbugs/issue24187.go
@@ -0,0 +1,33 @@
+// +build amd64p32
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "unsafe"
+)
+
+func main() {
+ b := make([]byte, 128)
+ for i := range b {
+ b[i] = 1
+ }
+ if bytes.IndexByte(b, 0) != -1 {
+ panic("found 0")
+ }
+ for i := range b {
+ b[i] = 0
+ c := b
+ *(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&c)) + unsafe.Sizeof(uintptr(0)))) = 1<<31 - 1
+ if bytes.IndexByte(c, 0) != i {
+ panic(fmt.Sprintf("missing 0 at %d\n", i))
+ }
+ b[i] = 1
+ }
+}
diff --git a/test/fixedbugs/issue24339.go b/test/fixedbugs/issue24339.go
new file mode 100644
index 000000000..0670becdf
--- /dev/null
+++ b/test/fixedbugs/issue24339.go
@@ -0,0 +1,20 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Use a diffent line number for each token so we can
+// check that the error message appears at the correct
+// position.
+var _ = struct{}{ /*line :20:1*/foo /*line :21:1*/: /*line :22:1*/0 }
+
+
+
+
+
+
+
+// ERROR "unknown field 'foo'" \ No newline at end of file
diff --git a/test/fixedbugs/issue24419.go b/test/fixedbugs/issue24419.go
new file mode 100644
index 000000000..73b7783e0
--- /dev/null
+++ b/test/fixedbugs/issue24419.go
@@ -0,0 +1,51 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "bytes"
+ "strings"
+)
+
+func growstack(n int) {
+ if n > 0 {
+ growstack(n - 1)
+ }
+}
+
+func main() {
+ c := make(chan struct{})
+ go compare(c)
+ go equal(c)
+ go indexByte(c)
+ go indexByteString(c)
+ <-c
+ <-c
+ <-c
+ <-c
+}
+
+func compare(c chan struct{}) {
+ defer bytes.Compare(nil, nil)
+ growstack(10000)
+ c <- struct{}{}
+}
+func equal(c chan struct{}) {
+ defer bytes.Equal(nil, nil)
+ growstack(10000)
+ c <- struct{}{}
+}
+func indexByte(c chan struct{}) {
+ defer bytes.IndexByte(nil, 0)
+ growstack(10000)
+ c <- struct{}{}
+}
+func indexByteString(c chan struct{}) {
+ defer strings.IndexByte("", 0)
+ growstack(10000)
+ c <- struct{}{}
+}
diff --git a/test/fixedbugs/issue24449.go b/test/fixedbugs/issue24449.go
new file mode 100644
index 000000000..b23664510
--- /dev/null
+++ b/test/fixedbugs/issue24449.go
@@ -0,0 +1,62 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import (
+ "sync/atomic"
+)
+
+var cnt32 int32
+
+//go:noinline
+func test32(a, b []int) bool {
+ // Try to generate flag value, issue atomic
+ // adds and then re-use the flag value to see if
+ // the atomic add has clobbered them.
+ atomic.AddInt32(&cnt32, 1)
+ if len(a) == len(b) {
+ atomic.AddInt32(&cnt32, 2)
+ }
+ atomic.AddInt32(&cnt32, 4)
+ if len(a) >= len(b) {
+ atomic.AddInt32(&cnt32, 8)
+ }
+ if len(a) <= len(b) {
+ atomic.AddInt32(&cnt32, 16)
+ }
+ return atomic.LoadInt32(&cnt32) == 31
+}
+
+var cnt64 int64
+
+//go:noinline
+func test64(a, b []int) bool {
+ // Try to generate flag value, issue atomic
+ // adds and then re-use the flag value to see if
+ // the atomic add has clobbered them.
+ atomic.AddInt64(&cnt64, 1)
+ if len(a) == len(b) {
+ atomic.AddInt64(&cnt64, 2)
+ }
+ atomic.AddInt64(&cnt64, 4)
+ if len(a) >= len(b) {
+ atomic.AddInt64(&cnt64, 8)
+ }
+ if len(a) <= len(b) {
+ atomic.AddInt64(&cnt64, 16)
+ }
+ return atomic.LoadInt64(&cnt64) == 31
+}
+
+func main() {
+ if !test32([]int{}, []int{}) {
+ panic("test32")
+ }
+ if !test64([]int{}, []int{}) {
+ panic("test64")
+ }
+}
diff --git a/test/fixedbugs/issue24470.go b/test/fixedbugs/issue24470.go
new file mode 100644
index 000000000..d0e5e23fa
--- /dev/null
+++ b/test/fixedbugs/issue24470.go
@@ -0,0 +1,15 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Verify that we get "use of .(type) outside type switch"
+// before any other (misleading) errors. Test case from issue.
+
+package p
+
+func f(i interface{}) {
+ if x, ok := i.(type); ok { // ERROR "outside type switch"
+ }
+}
diff --git a/test/fixedbugs/issue24503.go b/test/fixedbugs/issue24503.go
new file mode 100644
index 000000000..933ce70db
--- /dev/null
+++ b/test/fixedbugs/issue24503.go
@@ -0,0 +1,28 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 24503: Handle == and != of addresses taken of symbols consistently.
+
+package main
+
+func test() string {
+ type test struct{}
+ o1 := test{}
+ o2 := test{}
+ if &o1 == &o2 {
+ return "equal"
+ }
+ if &o1 != &o2 {
+ return "unequal"
+ }
+ return "failed"
+}
+
+func main() {
+ if test() == "failed" {
+ panic("expected either 'equal' or 'unequal'")
+ }
+}
diff --git a/test/fixedbugs/issue24547.go b/test/fixedbugs/issue24547.go
new file mode 100644
index 000000000..47d94a9f9
--- /dev/null
+++ b/test/fixedbugs/issue24547.go
@@ -0,0 +1,46 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// When computing method sets with shadowed methods, make sure we
+// compute whether a method promotion involved a pointer traversal
+// based on the promoted method, not the shadowed method.
+
+package main
+
+import (
+ "bytes"
+ "fmt"
+)
+
+type mystruct struct {
+ f int
+}
+
+func (t mystruct) String() string {
+ return "FAIL"
+}
+
+func main() {
+ type deep struct {
+ mystruct
+ }
+ s := struct {
+ deep
+ *bytes.Buffer
+ }{
+ deep{},
+ bytes.NewBufferString("ok"),
+ }
+
+ if got := s.String(); got != "ok" {
+ panic(got)
+ }
+
+ var i fmt.Stringer = s
+ if got := i.String(); got != "ok" {
+ panic(got)
+ }
+}
diff --git a/test/fixedbugs/issue24651a.go b/test/fixedbugs/issue24651a.go
new file mode 100644
index 000000000..5f63635a2
--- /dev/null
+++ b/test/fixedbugs/issue24651a.go
@@ -0,0 +1,24 @@
+//errorcheck -0 -race -m -m
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+//go:norace
+func Foo(x int) int { // ERROR "cannot inline Foo: marked go:norace with -race compilation$"
+ return x * (x + 1) * (x + 2)
+}
+
+func Bar(x int) int { // ERROR "can inline Bar as: func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$"
+ return x * (x + 1) * (x + 2)
+}
+
+var x = 5
+
+//go:noinline Provide a clean, constant reason for not inlining main
+func main() { // ERROR "cannot inline main: marked go:noinline$"
+ println("Foo(", x, ")=", Foo(x))
+ println("Bar(", x, ")=", Bar(x)) // ERROR "inlining call to Bar func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$"
+}
diff --git a/test/fixedbugs/issue24651b.go b/test/fixedbugs/issue24651b.go
new file mode 100644
index 000000000..2420f61fa
--- /dev/null
+++ b/test/fixedbugs/issue24651b.go
@@ -0,0 +1,24 @@
+//errorcheck -0 -m -m
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+//go:norace
+func Foo(x int) int { // ERROR "can inline Foo as: func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$"
+ return x * (x + 1) * (x + 2)
+}
+
+func Bar(x int) int { // ERROR "can inline Bar as: func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$"
+ return x * (x + 1) * (x + 2)
+}
+
+var x = 5
+
+//go:noinline Provide a clean, constant reason for not inlining main
+func main() { // ERROR "cannot inline main: marked go:noinline$"
+ println("Foo(", x, ")=", Foo(x)) // ERROR "inlining call to Foo func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$"
+ println("Bar(", x, ")=", Bar(x)) // ERROR "inlining call to Bar func\(int\) int { return x \* \(x \+ 1\) \* \(x \+ 2\) }$"
+}
diff --git a/test/fixedbugs/issue24693.dir/a.go b/test/fixedbugs/issue24693.dir/a.go
new file mode 100644
index 000000000..8a845ed86
--- /dev/null
+++ b/test/fixedbugs/issue24693.dir/a.go
@@ -0,0 +1,11 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type T struct{}
+
+func (T) m() { println("FAIL") }
+
+type I interface{ m() }
diff --git a/test/fixedbugs/issue24693.dir/b.go b/test/fixedbugs/issue24693.dir/b.go
new file mode 100644
index 000000000..15ffa4f7c
--- /dev/null
+++ b/test/fixedbugs/issue24693.dir/b.go
@@ -0,0 +1,38 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+type T struct{ a.T }
+
+func (T) m() { println("ok") }
+
+// The compiler used to not pay attention to package for non-exported
+// methods when statically constructing itabs. The consequence of this
+// was that the call to b.F1(b.T{}) in c.go would create an itab using
+// a.T.m instead of b.T.m.
+func F1(i interface{ m() }) { i.m() }
+
+// The interface method calling convention depends on interface method
+// sets being sorted in the same order across compilation units. In
+// the test case below, at the call to b.F2(b.T{}) in c.go, the
+// interface method set is sorted as { a.m(); b.m() }.
+//
+// However, while compiling package b, its package path is set to "",
+// so the code produced for F2 uses { b.m(); a.m() } as the method set
+// order. So again, it ends up calling the wrong method.
+//
+// Also, this function is marked noinline because it's critical to the
+// test that the interface method call happen in this compilation
+// unit, and the itab construction happens in c.go.
+//
+//go:noinline
+func F2(i interface {
+ m()
+ a.I // embeds m() from package a
+}) {
+ i.m()
+}
diff --git a/test/fixedbugs/issue24693.dir/c.go b/test/fixedbugs/issue24693.dir/c.go
new file mode 100644
index 000000000..8c6e27b14
--- /dev/null
+++ b/test/fixedbugs/issue24693.dir/c.go
@@ -0,0 +1,12 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./b"
+
+func main() {
+ b.F1(b.T{})
+ b.F2(b.T{})
+}
diff --git a/test/fixedbugs/issue24693.go b/test/fixedbugs/issue24693.go
new file mode 100644
index 000000000..3da6a81af
--- /dev/null
+++ b/test/fixedbugs/issue24693.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/fixedbugs/issue24693.out b/test/fixedbugs/issue24693.out
new file mode 100644
index 000000000..79ebd0860
--- /dev/null
+++ b/test/fixedbugs/issue24693.out
@@ -0,0 +1,2 @@
+ok
+ok
diff --git a/test/fixedbugs/issue24761.dir/a.go b/test/fixedbugs/issue24761.dir/a.go
new file mode 100644
index 000000000..1aa2317bd
--- /dev/null
+++ b/test/fixedbugs/issue24761.dir/a.go
@@ -0,0 +1,15 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type T2 struct{}
+
+func (t *T2) M2(a, b float64) {
+ variadic(a, b)
+}
+
+func variadic(points ...float64) {
+ println(points)
+}
diff --git a/test/fixedbugs/issue24761.dir/b.go b/test/fixedbugs/issue24761.dir/b.go
new file mode 100644
index 000000000..dd3d543a0
--- /dev/null
+++ b/test/fixedbugs/issue24761.dir/b.go
@@ -0,0 +1,11 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+type T1 struct {
+ *a.T2
+}
diff --git a/test/fixedbugs/issue24761.go b/test/fixedbugs/issue24761.go
new file mode 100644
index 000000000..4b97663c3
--- /dev/null
+++ b/test/fixedbugs/issue24761.go
@@ -0,0 +1,7 @@
+// compiledir -c=4
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/fixedbugs/issue24763.go b/test/fixedbugs/issue24763.go
new file mode 100644
index 000000000..623ab489e
--- /dev/null
+++ b/test/fixedbugs/issue24763.go
@@ -0,0 +1,21 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ var s uint
+ var x = interface{}(1<<s + 1<<s) // compiler must not crash here
+ if x.(int) != 2 {
+ panic("x not int or not 2")
+ }
+
+ var y interface{}
+ y = 1<<s + 1 // compiler must not crash here
+ if y.(int) != 2 {
+ panic("y not int or not 2")
+ }
+}
diff --git a/test/fixedbugs/issue24799.go b/test/fixedbugs/issue24799.go
new file mode 100644
index 000000000..c805c86dd
--- /dev/null
+++ b/test/fixedbugs/issue24799.go
@@ -0,0 +1,58 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Loads of 8 byte go.strings cannot use DS relocation
+// in case the alignment is not a multiple of 4.
+
+package main
+
+import (
+ "fmt"
+)
+
+type Level string
+
+// The following are all go.strings. A link time error can
+// occur if an 8 byte load is used to load a go.string that is
+// not aligned to 4 bytes due to the type of relocation that
+// is generated for the instruction. A fix was made to avoid
+// generating an instruction with DS relocation for go.strings
+// since their alignment is not known until link time.
+
+// This problem only affects go.string since other types have
+// correct alignment.
+
+const (
+ LevelBad Level = "badvals"
+ LevelNone Level = "No"
+ LevelMetadata Level = "Metadata"
+ LevelRequest Level = "Request"
+ LevelRequestResponse Level = "RequestResponse"
+)
+
+func ordLevel(l Level) int {
+ switch l {
+ case LevelMetadata:
+ return 1
+ case LevelRequest:
+ return 2
+ case LevelRequestResponse:
+ return 3
+ default:
+ return 0
+ }
+}
+
+//go:noinline
+func test(l Level) {
+ if ordLevel(l) < ordLevel(LevelMetadata) {
+ fmt.Printf("OK\n")
+ }
+}
+
+func main() {
+ test(LevelMetadata)
+}
diff --git a/test/fixedbugs/issue24801.dir/a.go b/test/fixedbugs/issue24801.dir/a.go
new file mode 100644
index 000000000..58e6240d8
--- /dev/null
+++ b/test/fixedbugs/issue24801.dir/a.go
@@ -0,0 +1,9 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type main int
+
+var X main
diff --git a/test/fixedbugs/issue24801.dir/main.go b/test/fixedbugs/issue24801.dir/main.go
new file mode 100644
index 000000000..5c7db7b4d
--- /dev/null
+++ b/test/fixedbugs/issue24801.dir/main.go
@@ -0,0 +1,11 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "./a"
+
+func main() {
+ a.X = 1
+}
diff --git a/test/fixedbugs/issue24801.go b/test/fixedbugs/issue24801.go
new file mode 100644
index 000000000..9b05db8ea
--- /dev/null
+++ b/test/fixedbugs/issue24801.go
@@ -0,0 +1,5 @@
+// compiledir
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
diff --git a/test/fixedbugs/issue24817.go b/test/fixedbugs/issue24817.go
new file mode 100644
index 000000000..ba2a138ed
--- /dev/null
+++ b/test/fixedbugs/issue24817.go
@@ -0,0 +1,64 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check all ways to compare a non-constant string to the empty string.
+
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+var (
+ s = "abc"
+ e = ""
+ failed bool
+)
+
+func main() {
+ want(true, "" < s, `"" < s`)
+ want(false, s < "", `s < ""`)
+ want(false, "" < e, `"" < e`)
+ want(false, e < "", `e < ""`)
+
+ want(true, "" <= s, `"" <= s`)
+ want(false, s <= "", `s <= ""`)
+ want(true, "" <= e, `"" <= e`)
+ want(true, e <= "", `e <= ""`)
+
+ want(false, "" > s, `"" > s`)
+ want(true, s > "", `s > ""`)
+ want(false, "" > e, `"" > e`)
+ want(false, e > "", `e > ""`)
+
+ want(false, "" >= s, `"" >= s`)
+ want(true, s >= "", `s >= ""`)
+ want(true, "" >= e, `"" >= e`)
+ want(true, e >= "", `e >= ""`)
+
+ want(false, "" == s, `"" == s`)
+ want(false, s == "", `s == ""`)
+ want(true, "" == e, `"" == e`)
+ want(true, e == "", `e == ""`)
+
+ want(true, "" != s, `"" != s`)
+ want(true, s != "", `s != ""`)
+ want(false, "" != e, `"" != e`)
+ want(false, e != "", `e != ""`)
+
+ if failed {
+ os.Exit(1)
+ }
+}
+
+//go:noinline
+func want(b bool, have bool, msg string) {
+ if b != have {
+ fmt.Println(msg)
+ failed = true
+ }
+}
diff --git a/test/fixedbugs/issue24937.go b/test/fixedbugs/issue24937.go
new file mode 100644
index 000000000..7d8460f61
--- /dev/null
+++ b/test/fixedbugs/issue24937.go
@@ -0,0 +1,15 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ x := []byte{'a'}
+ switch string(x) {
+ case func() string { x[0] = 'b'; return "b" }():
+ panic("FAIL")
+ }
+}
diff --git a/test/fixedbugs/issue24939.go b/test/fixedbugs/issue24939.go
new file mode 100644
index 000000000..26530e95b
--- /dev/null
+++ b/test/fixedbugs/issue24939.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type T interface {
+ M(P)
+}
+
+type M interface {
+ F() P
+}
+
+type P = interface {
+ I() M
+}
+
+func main() {}
diff --git a/test/fixedbugs/issue25006.go b/test/fixedbugs/issue25006.go
new file mode 100644
index 000000000..570fdca5c
--- /dev/null
+++ b/test/fixedbugs/issue25006.go
@@ -0,0 +1,30 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func spin() {
+ var i int
+ var b bool
+
+ switch 1 {
+ case 0:
+ i = 1
+ }
+ switch 1 {
+ case i:
+ default:
+ i = 1
+ b = !b && (b && !b) && b
+ }
+ switch false {
+ case false:
+ i = 3 + -i
+ switch 0 {
+ case 1 - i:
+ }
+ }
+}
diff --git a/test/fixedbugs/issue25055.dir/a.go b/test/fixedbugs/issue25055.dir/a.go
new file mode 100644
index 000000000..7fea195e2
--- /dev/null
+++ b/test/fixedbugs/issue25055.dir/a.go
@@ -0,0 +1,7 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+var A chan *interface{}
diff --git a/test/fixedbugs/issue25055.dir/b.go b/test/fixedbugs/issue25055.dir/b.go
new file mode 100644
index 000000000..01efeae3e
--- /dev/null
+++ b/test/fixedbugs/issue25055.dir/b.go
@@ -0,0 +1,9 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+var _ = <-a.A
diff --git a/test/fixedbugs/issue25055.go b/test/fixedbugs/issue25055.go
new file mode 100644
index 000000000..0e15a8e71
--- /dev/null
+++ b/test/fixedbugs/issue25055.go
@@ -0,0 +1,7 @@
+// compiledir -c=2
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/fixedbugs/issue25101.go b/test/fixedbugs/issue25101.go
new file mode 100644
index 000000000..4fd6bed92
--- /dev/null
+++ b/test/fixedbugs/issue25101.go
@@ -0,0 +1,16 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Indexed export format must not crash when writing
+// the anonymous parameter for m.
+
+package p
+
+var x interface {
+ m(int)
+}
+
+var M = x.m
diff --git a/test/fixedbugs/issue25322.go b/test/fixedbugs/issue25322.go
new file mode 100644
index 000000000..ee4ff53e2
--- /dev/null
+++ b/test/fixedbugs/issue25322.go
@@ -0,0 +1,23 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Missing zero extension when converting a float32
+// to a uint64.
+
+package main
+
+import (
+ "fmt"
+ "math"
+)
+
+func Foo(v float32) {
+ fmt.Printf("%x\n", uint64(math.Float32bits(v)))
+}
+
+func main() {
+ Foo(2.0)
+}
diff --git a/test/fixedbugs/issue25322.out b/test/fixedbugs/issue25322.out
new file mode 100644
index 000000000..52f3f6a74
--- /dev/null
+++ b/test/fixedbugs/issue25322.out
@@ -0,0 +1 @@
+40000000
diff --git a/test/fixedbugs/issue25507.go b/test/fixedbugs/issue25507.go
new file mode 100644
index 000000000..8dcbae16a
--- /dev/null
+++ b/test/fixedbugs/issue25507.go
@@ -0,0 +1,29 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// We have a limit of 1GB for stack frames.
+// Test that we extend that limit to include large argument/return areas.
+// Argument/return areas are part of the parent frame, not the frame itself,
+// so they need to be handled separately.
+
+package main
+
+// >1GB to trigger failure, <2GB to work on 32-bit platforms.
+type large struct {
+ b [1500000000]byte
+}
+
+func (x large) f1() int { // ERROR "stack frame too large"
+ return 5
+}
+
+func f2(x large) int { // ERROR "stack frame too large"
+ return 5
+}
+
+func f3() (x large, i int) { // ERROR "stack frame too large"
+ return
+}
diff --git a/test/fixedbugs/issue25516.go b/test/fixedbugs/issue25516.go
new file mode 100644
index 000000000..8326ef953
--- /dev/null
+++ b/test/fixedbugs/issue25516.go
@@ -0,0 +1,26 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure dead write barriers are handled correctly.
+
+package main
+
+func f(p **int) {
+ // The trick here is to eliminate the block containing the write barrier,
+ // but only after the write barrier branches are inserted.
+ // This requires some delicate code.
+ i := 0
+ var b []bool
+ var s string
+ for true {
+ if b[i] {
+ var a []string
+ s = a[len(s)]
+ i = 0
+ }
+ *p = nil
+ }
+}
diff --git a/test/fixedbugs/issue25727.go b/test/fixedbugs/issue25727.go
new file mode 100644
index 000000000..9b7c804a0
--- /dev/null
+++ b/test/fixedbugs/issue25727.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "net/http"
+
+var s = http.Server{}
+var _ = s.doneChan // ERROR "s.doneChan undefined .cannot refer to unexported field or method doneChan.$"
+var _ = s.DoneChan // ERROR "s.DoneChan undefined .type http.Server has no field or method DoneChan.$"
+var _ = http.Server{tlsConfig: nil} // ERROR "unknown field 'tlsConfig' in struct literal.+ .but does have TLSConfig.$"
+var _ = http.Server{DoneChan: nil} // ERROR "unknown field 'DoneChan' in struct literal of type http.Server$"
+
+type foo struct {
+ bar int
+}
+
+var _ = &foo{bAr: 10} // ERROR "unknown field 'bAr' in struct literal.+ .but does have bar.$"
diff --git a/test/fixedbugs/issue25741.go b/test/fixedbugs/issue25741.go
new file mode 100644
index 000000000..c76e97594
--- /dev/null
+++ b/test/fixedbugs/issue25741.go
@@ -0,0 +1,14 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+var s []int
+
+func main() {
+ i := -1
+ s[i] = 0
+}
diff --git a/test/fixedbugs/issue25776.go b/test/fixedbugs/issue25776.go
new file mode 100644
index 000000000..e05c0bce4
--- /dev/null
+++ b/test/fixedbugs/issue25776.go
@@ -0,0 +1,99 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+const (
+ Upper = true
+ blas_Upper = 121
+ badTriangle = "bad triangle"
+)
+
+// Triangular represents a triangular matrix. Triangular matrices are always square.
+type Triangular interface {
+ // Triangular returns the number of rows/columns in the matrix and its
+ // orientation.
+ Tryangle() (mmmm int, kynd bool)
+ Triangle() (mmmm int, kynd bool)
+}
+
+// blas64_Triangular represents a triangular matrix using the conventional storage scheme.
+type blas64_Triangular struct {
+ Stride int
+ Uplo int
+}
+
+// TriDense represents an upper or lower triangular matrix in dense storage
+// format.
+type TriDense struct {
+ mat blas64_Triangular
+}
+
+func NewTriDense() *TriDense {
+ return &TriDense{
+ mat: blas64_Triangular{
+ Stride: 3,
+ Uplo: blas_Upper,
+ },
+ }
+}
+
+func (t *TriDense) isUpper() bool {
+ return isUpperUplo(t.mat.Uplo)
+}
+
+func (t *TriDense) triKind() bool {
+ return isUpperUplo(t.mat.Uplo)
+}
+
+func isUpperUplo(u int) bool {
+ switch u {
+ case blas_Upper:
+ return true
+ default:
+ panic(badTriangle)
+ }
+}
+
+func (t *TriDense) IsZero() bool {
+ return t.mat.Stride == 0
+}
+
+//go:noinline
+func (t *TriDense) ScaleTri(f float64, a Triangular) {
+ n, kind := a.Triangle()
+ if kind == false {
+ println("ScaleTri n, kind=", n, ", ", kind, " (FAIL, expected true)")
+ }
+}
+
+//go:noinline
+func (t *TriDense) ScaleTry(f float64, a Triangular) {
+ n, kind := a.Tryangle()
+ if kind == false {
+ println("ScaleTry n, kind=", n, ", ", kind, " (FAIL, expected true)")
+ }
+}
+
+// Triangle failed (before fix)
+func (t *TriDense) Triangle() (nnnn int, kind bool) {
+ return 3, !t.IsZero() && t.triKind()
+}
+
+// Tryangle works -- difference is not-named output parameters.
+func (t *TriDense) Tryangle() (int, bool) {
+ return 3, !t.IsZero() && t.triKind()
+}
+
+func main() {
+ ta := NewTriDense()
+ n, kind := ta.Triangle()
+ if kind == false {
+ println(" main n, kind=", n, ", ", kind, " (FAIL, expected true)")
+ }
+ ta.ScaleTri(1, ta)
+ ta.ScaleTry(1, ta)
+}
diff --git a/test/fixedbugs/issue25958.go b/test/fixedbugs/issue25958.go
new file mode 100644
index 000000000..ba7ee8223
--- /dev/null
+++ b/test/fixedbugs/issue25958.go
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// Verify that the "must be receive" error for "case done:" appears
+// on the line of the case clause, not the line of the done declaration.
+
+func f(done chan struct{}) {
+ select {
+ case done: // ERROR "must be receive", "not used"
+ case (chan struct{})(done): // ERROR "must be receive"
+ }
+}
diff --git a/test/fixedbugs/issue25966.go b/test/fixedbugs/issue25966.go
new file mode 100644
index 000000000..7b5f2a7e4
--- /dev/null
+++ b/test/fixedbugs/issue25966.go
@@ -0,0 +1,24 @@
+// compile -N
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 25966: liveness code complains autotmp live on
+// function entry.
+
+package p
+
+var F = []func(){
+ func() func() { return (func())(nil) }(),
+}
+
+var A = []int{}
+
+type ss struct {
+ string
+ float64
+ i int
+}
+
+var V = A[ss{}.i]
diff --git a/test/fixedbugs/issue25984.dir/p.go b/test/fixedbugs/issue25984.dir/p.go
new file mode 100644
index 000000000..306d6a489
--- /dev/null
+++ b/test/fixedbugs/issue25984.dir/p.go
@@ -0,0 +1,15 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type m struct {
+ link *m
+}
+
+var head *m
+
+func F(m *int) bool {
+ return head != nil
+}
diff --git a/test/fixedbugs/issue25984.dir/q.go b/test/fixedbugs/issue25984.dir/q.go
new file mode 100644
index 000000000..64d25870b
--- /dev/null
+++ b/test/fixedbugs/issue25984.dir/q.go
@@ -0,0 +1,11 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package q
+
+import "./p"
+
+func G() {
+ p.F(nil)
+}
diff --git a/test/fixedbugs/issue25984.go b/test/fixedbugs/issue25984.go
new file mode 100644
index 000000000..128cf9d06
--- /dev/null
+++ b/test/fixedbugs/issue25984.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/fixedbugs/issue25993.go b/test/fixedbugs/issue25993.go
new file mode 100644
index 000000000..3253cd82f
--- /dev/null
+++ b/test/fixedbugs/issue25993.go
@@ -0,0 +1,21 @@
+// compile -d=ssa/check/on
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 25993: SSA check fails on ARM.
+
+package p
+
+func f() {
+ var x int
+ var B0 bool
+ B0 = !B0 || B0
+ if B0 && B0 {
+ x = -1
+ }
+ var AI []int
+ var AB []bool
+ _ = AI[x] > 0 && AB[x]
+}
diff --git a/test/fixedbugs/issue26024.go b/test/fixedbugs/issue26024.go
new file mode 100644
index 000000000..78877b21f
--- /dev/null
+++ b/test/fixedbugs/issue26024.go
@@ -0,0 +1,28 @@
+// compile
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package r
+
+// f compiles into code where no stores remain in the two successors
+// of a write barrier block; i.e., they are empty. Pre-fix, this
+// results in an unexpected input to markUnsafePoints, that expects to
+// see a pair of non-empty plain blocks.
+func f() {
+ var i int
+ var s string
+ for len(s) < len(s) {
+ i++
+ s = "a"
+ }
+ var b bool
+ var sa []string
+ for true {
+ sa = []string{""}
+ for b || i == 0 {
+ }
+ b = !b
+ _ = sa
+ }
+}
diff --git a/test/fixedbugs/issue26043.go b/test/fixedbugs/issue26043.go
new file mode 100644
index 000000000..fe32947b0
--- /dev/null
+++ b/test/fixedbugs/issue26043.go
@@ -0,0 +1,32 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This program results in a loop inferred to increment
+// j by 0, causing bounds check elimination to attempt
+// something%0, which panics (in the bug).
+
+package q
+
+func f() {
+ var s1 string
+ var b bool
+ if b {
+ b = !b
+ s1 += "a"
+ }
+
+ var s2 string
+ var i, j int
+ if (s1 <= "") || (s2 >= "") {
+ j = len(s1[:6])
+ } else {
+ i = len("b")
+ }
+
+ for j < 0 {
+ j += i
+ }
+}
diff --git a/test/fixedbugs/issue26094.go b/test/fixedbugs/issue26094.go
new file mode 100644
index 000000000..7af8fac6b
--- /dev/null
+++ b/test/fixedbugs/issue26094.go
@@ -0,0 +1,49 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "strings"
+
+var X interface{}
+
+type T struct{}
+
+func scopes() {
+ p, ok := recover().(error)
+ if ok && strings.Contains(p.Error(), "different scopes") {
+ return
+ }
+ panic(p)
+}
+
+func F1() {
+ type T struct{}
+ X = T{}
+}
+
+func F2() {
+ type T struct{}
+ defer scopes()
+ _ = X.(T)
+}
+
+func F3() {
+ defer scopes()
+ _ = X.(T)
+}
+
+func F4() {
+ X = T{}
+}
+
+func main() {
+ F1() // set X to F1's T
+ F2() // check that X is not F2's T
+ F3() // check that X is not package T
+ F4() // set X to package T
+ F2() // check that X is not F2's T
+}
diff --git a/test/fixedbugs/issue26097.go b/test/fixedbugs/issue26097.go
new file mode 100644
index 000000000..eedd6bacd
--- /dev/null
+++ b/test/fixedbugs/issue26097.go
@@ -0,0 +1,47 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+//go:noinline
+func cmovClobberAX64(v1, v2 int64, x1, x2 float64) int64 {
+ r := v1
+ if x1 == x2 {
+ r = v2
+ }
+ return r
+}
+
+//go:noinline
+func cmovClobberAX32(v1, v2 int32, x1, x2 float64) int32 {
+ r := v1
+ if x1 == x2 {
+ r = v2
+ }
+ return r
+}
+
+//go:noinline
+func cmovClobberAX16(v1, v2 int16, x1, x2 float64) int16 {
+ r := v1
+ if x1 == x2 {
+ r = v2
+ }
+ return r
+}
+
+func main() {
+ if cmovClobberAX16(1, 2, 4.0, 5.0) != 1 {
+ panic("CMOVQEQF causes incorrect code")
+ }
+ if cmovClobberAX32(1, 2, 4.0, 5.0) != 1 {
+ panic("CMOVQEQF causes incorrect code")
+ }
+ if cmovClobberAX64(1, 2, 4.0, 5.0) != 1 {
+ panic("CMOVQEQF causes incorrect code")
+ }
+
+}
diff --git a/test/fixedbugs/issue26105.go b/test/fixedbugs/issue26105.go
new file mode 100644
index 000000000..88a5f162f
--- /dev/null
+++ b/test/fixedbugs/issue26105.go
@@ -0,0 +1,25 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Triggers a bug in writebarrier, which inserts one
+// between (first block) OpAddr x and (second block) a VarDef x,
+// which are then in the wrong order and unable to be
+// properly scheduled.
+
+package q
+
+var S interface{}
+
+func F(n int) {
+ fun := func(x int) int {
+ S = 1
+ return n
+ }
+ i := fun(([]int{})[n])
+
+ var fc [2]chan int
+ S = (([1][2]chan int{fc})[i][i])
+}
diff --git a/test/fixedbugs/issue26116.go b/test/fixedbugs/issue26116.go
new file mode 100644
index 000000000..8a6348181
--- /dev/null
+++ b/test/fixedbugs/issue26116.go
@@ -0,0 +1,18 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+ s := []int{0, 1, 2}
+ i := 1
+ for i > 0 && s[i] != 2 {
+ i++
+ }
+ if i != 2 {
+ panic("loop didn't run")
+ }
+}
diff --git a/test/fixedbugs/issue26120.go b/test/fixedbugs/issue26120.go
new file mode 100644
index 000000000..94bf7d9cb
--- /dev/null
+++ b/test/fixedbugs/issue26120.go
@@ -0,0 +1,23 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26120: INDEX of 1-element but non-SSAable array
+// is mishandled when building SSA.
+
+package p
+
+type T [1]struct {
+ f []int
+ i, j int
+}
+
+func F() {
+ var v T
+ f := func() T {
+ return v
+ }
+ _ = []int{}[f()[0].i]
+}
diff --git a/test/fixedbugs/issue26153.go b/test/fixedbugs/issue26153.go
new file mode 100644
index 000000000..53f53cf8a
--- /dev/null
+++ b/test/fixedbugs/issue26153.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26153. The write to ps was incorrectly
+// removed by the dead auto elimination pass.
+
+package main
+
+const hello = "hello world"
+
+func main() {
+ var s string
+ mangle(&s)
+ if s != hello {
+ panic("write incorrectly elided")
+ }
+}
+
+//go:noinline
+func mangle(ps *string) {
+ if ps == nil {
+ var s string
+ ps = &s
+ }
+ *ps = hello
+}
diff --git a/test/fixedbugs/issue26163.go b/test/fixedbugs/issue26163.go
new file mode 100644
index 000000000..3f3d77859
--- /dev/null
+++ b/test/fixedbugs/issue26163.go
@@ -0,0 +1,17 @@
+// compile -N -d=softfloat
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26163: dead store generated in late opt messes
+// up store chain calculation.
+
+package p
+
+var i int
+var A = ([]*int{})[i]
+
+var F func(float64, complex128) int
+var C chan complex128
+var B = F(1, 1+(<-C))
diff --git a/test/fixedbugs/issue26248.go b/test/fixedbugs/issue26248.go
new file mode 100644
index 000000000..2f04e4822
--- /dev/null
+++ b/test/fixedbugs/issue26248.go
@@ -0,0 +1,39 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26248: gccgo miscompiles interface field expression.
+// In G().M where G returns an interface, G() is evaluated twice.
+
+package main
+
+type I interface {
+ M()
+}
+
+type T struct{}
+
+func (T) M() {}
+
+var g = 0
+
+//go:noinline
+func G() I {
+ g++
+ return T{}
+}
+
+//go:noinline
+func Use(interface{}) {}
+
+func main() {
+ x := G().M
+ Use(x)
+
+ if g != 1 {
+ println("want 1, got", g)
+ panic("FAIL")
+ }
+}
diff --git a/test/fixedbugs/issue26335.go b/test/fixedbugs/issue26335.go
new file mode 100644
index 000000000..a97b4b6c7
--- /dev/null
+++ b/test/fixedbugs/issue26335.go
@@ -0,0 +1,32 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// gccgo mishandled passing a struct with an empty field through
+// reflect.Value.Call.
+
+package main
+
+import (
+ "reflect"
+)
+
+type Empty struct {
+ f1, f2 *byte
+ empty struct{}
+}
+
+func F(e Empty, s []string) {
+ if len(s) != 1 || s[0] != "hi" {
+ panic("bad slice")
+ }
+}
+
+func main() {
+ reflect.ValueOf(F).Call([]reflect.Value{
+ reflect.ValueOf(Empty{}),
+ reflect.ValueOf([]string{"hi"}),
+ })
+}
diff --git a/test/fixedbugs/issue26340.go b/test/fixedbugs/issue26340.go
new file mode 100644
index 000000000..f973ce223
--- /dev/null
+++ b/test/fixedbugs/issue26340.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// gccgo did not permit omitting the type of a composite literal
+// element when one of the middle omitted types was a pointer type.
+
+package p
+
+type S []T
+type T struct { x int }
+
+var _ = map[string]*S{
+ "a": {
+ { 1 },
+ },
+}
+
+var _ = [1]*S{ { {1}, } }
diff --git a/test/fixedbugs/issue26341.dir/a.go b/test/fixedbugs/issue26341.dir/a.go
new file mode 100644
index 000000000..4fd23c796
--- /dev/null
+++ b/test/fixedbugs/issue26341.dir/a.go
@@ -0,0 +1,11 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type k int
+
+func (k) F() {}
+
+type M map[k]int
diff --git a/test/fixedbugs/issue26341.dir/b.go b/test/fixedbugs/issue26341.dir/b.go
new file mode 100644
index 000000000..30b8c25a5
--- /dev/null
+++ b/test/fixedbugs/issue26341.dir/b.go
@@ -0,0 +1,13 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func f() {
+ for k := range (a.M{}) {
+ k.F()
+ }
+}
diff --git a/test/fixedbugs/issue26341.go b/test/fixedbugs/issue26341.go
new file mode 100644
index 000000000..128cf9d06
--- /dev/null
+++ b/test/fixedbugs/issue26341.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored
diff --git a/test/fixedbugs/issue26407.go b/test/fixedbugs/issue26407.go
new file mode 100644
index 000000000..aa8e79c1e
--- /dev/null
+++ b/test/fixedbugs/issue26407.go
@@ -0,0 +1,58 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26407: ensure that stack variables which have
+// had their address taken and then used in a comparison,
+// but are otherwise unused, are cleared.
+
+package main
+
+func main() {
+ poison()
+ test()
+}
+
+//go:noinline
+func poison() {
+ // initialise the stack with invalid pointers
+ var large [256]uintptr
+ for i := range large {
+ large[i] = 1
+ }
+ use(large[:])
+}
+
+//go:noinline
+func test() {
+ a := 2
+ x := &a
+ if x != compare(&x) {
+ panic("not possible")
+ }
+}
+
+//go:noinline
+func compare(x **int) *int {
+ var y *int
+ if x == &y {
+ panic("not possible")
+ }
+ // grow the stack to trigger a check for invalid pointers
+ grow()
+ if x == &y {
+ panic("not possible")
+ }
+ return *x
+}
+
+//go:noinline
+func grow() {
+ var large [1 << 16]uintptr
+ use(large[:])
+}
+
+//go:noinline
+func use(_ []uintptr) { }
diff --git a/test/fixedbugs/issue26416.go b/test/fixedbugs/issue26416.go
new file mode 100644
index 000000000..bc37fd9d3
--- /dev/null
+++ b/test/fixedbugs/issue26416.go
@@ -0,0 +1,27 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type t1 struct {
+ t1f1 int
+ t1f2 int
+}
+type t2 struct {
+ t2f1 int
+ t2f2 int
+ *t1
+}
+type t3 struct {
+ t3f1 int
+ *t2
+}
+
+var (
+ _ = t2{t1f1: 600} // ERROR "cannot use promoted field t1.t1f1 in struct literal of type t2"
+ _ = t3{t1f2: 800} // ERROR "cannot use promoted field t2.t1.t1f2 in struct literal of type t3"
+ _ = t3{t2f1: 900} // ERROR "cannot use promoted field t2.t2f1 in struct literal of type t3"
+)
diff --git a/test/fixedbugs/issue26426.go b/test/fixedbugs/issue26426.go
new file mode 100644
index 000000000..4f2a452fa
--- /dev/null
+++ b/test/fixedbugs/issue26426.go
@@ -0,0 +1,29 @@
+//run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+//go:noinline
+func f(p *int, v int, q1, q2 *int, r *bool) {
+ x := *r
+ if x {
+ *q1 = 1
+ }
+ *p = *p + v // This must clobber flags. Otherwise we keep x in a flags register.
+ if x {
+ *q2 = 1
+ }
+}
+
+func main() {
+ var p int
+ var q1, q2 int
+ var b bool
+ f(&p, 1, &q1, &q2, &b)
+ if q1 != 0 || q2 != 0 {
+ panic("bad")
+ }
+}
diff --git a/test/fixedbugs/issue26438.go b/test/fixedbugs/issue26438.go
new file mode 100644
index 000000000..d44da21eb
--- /dev/null
+++ b/test/fixedbugs/issue26438.go
@@ -0,0 +1,26 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26438: arm64 backend may use 64-bit TST for
+// "if uint32(a)&uint32(b) == 0", which should be
+// 32-bit TSTW
+
+package main
+
+//go:noinline
+func tstw(a, b uint64) uint64 {
+ if uint32(a)&uint32(b) == 0 {
+ return 100
+ } else {
+ return 200
+ }
+}
+
+func main() {
+ if tstw(0xff00000000, 0xaa00000000) == 200 {
+ panic("impossible")
+ }
+}
diff --git a/test/fixedbugs/issue26495.go b/test/fixedbugs/issue26495.go
new file mode 100644
index 000000000..11ea36017
--- /dev/null
+++ b/test/fixedbugs/issue26495.go
@@ -0,0 +1,36 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Issue 26495: gccgo produces incorrect order of evaluation
+// for expressions involving &&, || subexpressions.
+
+package main
+
+var i int
+
+func checkorder(order int) {
+ if i != order {
+ panic("FAIL: wrong evaluation order")
+ }
+ i++
+}
+
+func A() bool { checkorder(1); return true }
+func B() bool { checkorder(2); return true }
+func C() bool { checkorder(5); return false }
+func D() bool { panic("FAIL: D should not be called") }
+func E() int { checkorder(3); return 0 }
+func F() int { checkorder(0); return 0 }
+func G(bool) int { checkorder(9); return 0 }
+func H(int, bool, int) int { checkorder(7); return 0 }
+func I(int) bool { checkorder(8); return true }
+func J() int { checkorder(4); return 0 }
+func K() int { checkorder(6); return 0 }
+func L() int { checkorder(10); return 0 }
+
+func main() {
+ _ = F() + G(A() && B() && I(E()+H(J(), C() && D(), K()))) + L()
+}
diff --git a/test/fixedbugs/issue4085b.go b/test/fixedbugs/issue4085b.go
index b91bbd748..6bf315fcc 100644
--- a/test/fixedbugs/issue4085b.go
+++ b/test/fixedbugs/issue4085b.go
@@ -21,13 +21,12 @@ func main() {
shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
var t *byte
if unsafe.Sizeof(t) == 8 {
- n = 1 << 20
- n <<= 20
- shouldPanic("len out of range", func() { _ = make(T, n) })
- shouldPanic("cap out of range", func() { _ = make(T, 0, n) })
- n <<= 20
- shouldPanic("len out of range", func() { _ = make(T, n) })
- shouldPanic("cap out of range", func() { _ = make(T, 0, n) })
+ var n2 int64 = 1 << 50
+ shouldPanic("len out of range", func() { _ = make(T, int(n2)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int(n2)) })
+ n2 = 1<<63 - 1
+ shouldPanic("len out of range", func() { _ = make(T, int(n2)) })
+ shouldPanic("cap out of range", func() { _ = make(T, 0, int(n2)) })
} else {
n = 1<<31 - 1
shouldPanic("len out of range", func() { _ = make(T, n) })
@@ -35,6 +34,12 @@ func main() {
shouldPanic("len out of range", func() { _ = make(T, int64(n)) })
shouldPanic("cap out of range", func() { _ = make(T, 0, int64(n)) })
}
+
+ // Test make in append panics since the gc compiler optimizes makes in appends.
+ shouldPanic("len out of range", func() { _ = append(T{}, make(T, n)...) })
+ shouldPanic("cap out of range", func() { _ = append(T{}, make(T, 0, n)...) })
+ shouldPanic("len out of range", func() { _ = append(T{}, make(T, int64(n))...) })
+ shouldPanic("cap out of range", func() { _ = append(T{}, make(T, 0, int64(n))...) })
}
func shouldPanic(str string, f func()) {
diff --git a/test/fixedbugs/issue6899.go b/test/fixedbugs/issue6899.go
index f98f551b3..d7f857802 100644
--- a/test/fixedbugs/issue6899.go
+++ b/test/fixedbugs/issue6899.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/fixedbugs/issue9355.go b/test/fixedbugs/issue9355.go
index 10f8c7306..9657e6449 100644
--- a/test/fixedbugs/issue9355.go
+++ b/test/fixedbugs/issue9355.go
@@ -16,7 +16,7 @@ import (
)
func main() {
- if runtime.Compiler != "gc" || runtime.GOOS == "nacl" {
+ if runtime.Compiler != "gc" || runtime.GOOS == "nacl" || runtime.GOOS == "js" {
return
}
diff --git a/test/fixedbugs/issue9604b.go b/test/fixedbugs/issue9604b.go
index ebbd205ba..d32116b85 100644
--- a/test/fixedbugs/issue9604b.go
+++ b/test/fixedbugs/issue9604b.go
@@ -4,6 +4,9 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// terribly slow on wasm
+// +build !wasm
+
package main
import (
diff --git a/test/fixedbugs/issue9862_run.go b/test/fixedbugs/issue9862_run.go
index be22f4058..299e80954 100644
--- a/test/fixedbugs/issue9862_run.go
+++ b/test/fixedbugs/issue9862_run.go
@@ -1,4 +1,4 @@
-// +build !nacl
+// +build !nacl,!js
// run
// Copyright 2015 The Go Authors. All rights reserved.
diff --git a/test/gc2.go b/test/gc2.go
index 31b36d8a0..2f8eb9b70 100644
--- a/test/gc2.go
+++ b/test/gc2.go
@@ -1,4 +1,4 @@
-// +build !nacl
+// +build !nacl,!js
// run
// Copyright 2011 The Go Authors. All rights reserved.
diff --git a/test/gcgort.go b/test/gcgort.go
new file mode 100644
index 000000000..973e79659
--- /dev/null
+++ b/test/gcgort.go
@@ -0,0 +1,1850 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test independent goroutines modifying a comprehensive
+// variety of vars during aggressive garbage collection.
+
+// The point is to catch GC regressions like fixedbugs/issue22781.go
+
+package main
+
+import (
+ "errors"
+ "runtime"
+ "runtime/debug"
+ "sync"
+)
+
+const (
+ goroutines = 8
+ allocs = 8
+ mods = 8
+
+ length = 9
+)
+
+func main() {
+ debug.SetGCPercent(1)
+ var wg sync.WaitGroup
+ for i := 0; i < goroutines; i++ {
+ for _, t := range types {
+ err := t.valid()
+ if err != nil {
+ panic(err)
+ }
+ wg.Add(1)
+ go func(f modifier) {
+ var wg2 sync.WaitGroup
+ for j := 0; j < allocs; j++ {
+ wg2.Add(1)
+ go func() {
+ f.t()
+ wg2.Done()
+ }()
+ wg2.Add(1)
+ go func() {
+ f.pointerT()
+ wg2.Done()
+ }()
+ wg2.Add(1)
+ go func() {
+ f.arrayT()
+ wg2.Done()
+ }()
+ wg2.Add(1)
+ go func() {
+ f.sliceT()
+ wg2.Done()
+ }()
+ wg2.Add(1)
+ go func() {
+ f.mapT()
+ wg2.Done()
+ }()
+ wg2.Add(1)
+ go func() {
+ f.mapPointerKeyT()
+ wg2.Done()
+ }()
+ wg2.Add(1)
+ go func() {
+ f.chanT()
+ wg2.Done()
+ }()
+ wg2.Add(1)
+ go func() {
+ f.interfaceT()
+ wg2.Done()
+ }()
+ }
+ wg2.Wait()
+ wg.Done()
+ }(t)
+ }
+ }
+ wg.Wait()
+}
+
+type modifier struct {
+ name string
+ t func()
+ pointerT func()
+ arrayT func()
+ sliceT func()
+ mapT func()
+ mapPointerKeyT func()
+ chanT func()
+ interfaceT func()
+}
+
+func (a modifier) valid() error {
+ switch {
+ case a.name == "":
+ return errors.New("modifier without name")
+ case a.t == nil:
+ return errors.New(a.name + " missing t")
+ case a.pointerT == nil:
+ return errors.New(a.name + " missing pointerT")
+ case a.arrayT == nil:
+ return errors.New(a.name + " missing arrayT")
+ case a.sliceT == nil:
+ return errors.New(a.name + " missing sliceT")
+ case a.mapT == nil:
+ return errors.New(a.name + " missing mapT")
+ case a.mapPointerKeyT == nil:
+ return errors.New(a.name + " missing mapPointerKeyT")
+ case a.chanT == nil:
+ return errors.New(a.name + " missing chanT")
+ case a.interfaceT == nil:
+ return errors.New(a.name + " missing interfaceT")
+ default:
+ return nil
+ }
+}
+
+var types = []modifier{
+ modifier{
+ name: "bool",
+ t: func() {
+ var a bool
+ for i := 0; i < mods; i++ {
+ a = !a
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *bool { return new(bool) }()
+ for i := 0; i < mods; i++ {
+ *a = !*a
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]bool{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j] = !a[j]
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]bool, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j] = !a[j]
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[bool]bool)
+ for i := 0; i < mods; i++ {
+ a[false] = !a[false]
+ a[true] = !a[true]
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*bool]bool)
+ for i := 0; i < length; i++ {
+ a[new(bool)] = false
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, v := range a {
+ a[k] = !v
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan bool)
+ for i := 0; i < mods; i++ {
+ go func() { a <- false }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(bool(false))
+ for i := 0; i < mods; i++ {
+ a = !a.(bool)
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "uint8",
+ t: func() {
+ var u uint8
+ for i := 0; i < mods; i++ {
+ u++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *uint8 { return new(uint8) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]uint8{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]uint8, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[uint8]uint8)
+ for i := 0; i < length; i++ {
+ a[uint8(i)] = uint8(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*uint8]uint8)
+ for i := 0; i < length; i++ {
+ a[new(uint8)] = uint8(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan uint8)
+ for i := 0; i < mods; i++ {
+ go func() { a <- uint8(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(uint8(0))
+ for i := 0; i < mods; i++ {
+ a = a.(uint8) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "uint16",
+ t: func() {
+ var u uint16
+ for i := 0; i < mods; i++ {
+ u++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *uint16 { return new(uint16) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]uint16{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]uint16, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[uint16]uint16)
+ for i := 0; i < length; i++ {
+ a[uint16(i)] = uint16(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*uint16]uint16)
+ for i := 0; i < length; i++ {
+ a[new(uint16)] = uint16(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan uint16)
+ for i := 0; i < mods; i++ {
+ go func() { a <- uint16(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(uint16(0))
+ for i := 0; i < mods; i++ {
+ a = a.(uint16) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "uint32",
+ t: func() {
+ var u uint32
+ for i := 0; i < mods; i++ {
+ u++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *uint32 { return new(uint32) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]uint32{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]uint32, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[uint32]uint32)
+ for i := 0; i < length; i++ {
+ a[uint32(i)] = uint32(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*uint32]uint32)
+ for i := 0; i < length; i++ {
+ a[new(uint32)] = uint32(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan uint32)
+ for i := 0; i < mods; i++ {
+ go func() { a <- uint32(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(uint32(0))
+ for i := 0; i < mods; i++ {
+ a = a.(uint32) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "uint64",
+ t: func() {
+ var u uint64
+ for i := 0; i < mods; i++ {
+ u++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *uint64 { return new(uint64) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]uint64{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]uint64, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[uint64]uint64)
+ for i := 0; i < length; i++ {
+ a[uint64(i)] = uint64(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*uint64]uint64)
+ for i := 0; i < length; i++ {
+ a[new(uint64)] = uint64(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan uint64)
+ for i := 0; i < mods; i++ {
+ go func() { a <- uint64(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(uint64(0))
+ for i := 0; i < mods; i++ {
+ a = a.(uint64) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "int8",
+ t: func() {
+ var u int8
+ for i := 0; i < mods; i++ {
+ u++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *int8 { return new(int8) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]int8{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]int8, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[int8]int8)
+ for i := 0; i < length; i++ {
+ a[int8(i)] = int8(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*int8]int8)
+ for i := 0; i < length; i++ {
+ a[new(int8)] = int8(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan int8)
+ for i := 0; i < mods; i++ {
+ go func() { a <- int8(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(int8(0))
+ for i := 0; i < mods; i++ {
+ a = a.(int8) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "int16",
+ t: func() {
+ var u int16
+ for i := 0; i < mods; i++ {
+ u++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *int16 { return new(int16) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]int16{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]int16, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[int16]int16)
+ for i := 0; i < length; i++ {
+ a[int16(i)] = int16(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*int16]int16)
+ for i := 0; i < length; i++ {
+ a[new(int16)] = int16(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan int16)
+ for i := 0; i < mods; i++ {
+ go func() { a <- int16(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(int16(0))
+ for i := 0; i < mods; i++ {
+ a = a.(int16) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "int32",
+ t: func() {
+ var u int32
+ for i := 0; i < mods; i++ {
+ u++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *int32 { return new(int32) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]int32{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]int32, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[int32]int32)
+ for i := 0; i < length; i++ {
+ a[int32(i)] = int32(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*int32]int32)
+ for i := 0; i < length; i++ {
+ a[new(int32)] = int32(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan int32)
+ for i := 0; i < mods; i++ {
+ go func() { a <- int32(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(int32(0))
+ for i := 0; i < mods; i++ {
+ a = a.(int32) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "int64",
+ t: func() {
+ var u int64
+ for i := 0; i < mods; i++ {
+ u++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *int64 { return new(int64) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]int64{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]int64, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[int64]int64)
+ for i := 0; i < length; i++ {
+ a[int64(i)] = int64(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*int64]int64)
+ for i := 0; i < length; i++ {
+ a[new(int64)] = int64(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan int64)
+ for i := 0; i < mods; i++ {
+ go func() { a <- int64(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(int64(0))
+ for i := 0; i < mods; i++ {
+ a = a.(int64) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "float32",
+ t: func() {
+ u := float32(1.01)
+ for i := 0; i < mods; i++ {
+ u *= 1.01
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *float32 { return new(float32) }()
+ *a = 1.01
+ for i := 0; i < mods; i++ {
+ *a *= 1.01
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]float32{}
+ for i := 0; i < length; i++ {
+ a[i] = float32(1.01)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j] *= 1.01
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]float32, length)
+ for i := 0; i < length; i++ {
+ a[i] = float32(1.01)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j] *= 1.01
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[float32]float32)
+ for i := 0; i < length; i++ {
+ a[float32(i)] = float32(i) + 0.01
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k] *= 1.01
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*float32]float32)
+ for i := 0; i < length; i++ {
+ a[new(float32)] = float32(i) + 0.01
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k] *= 1.01
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan float32)
+ for i := 0; i < mods; i++ {
+ go func() { a <- float32(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(float32(0))
+ for i := 0; i < mods; i++ {
+ a = a.(float32) * 1.01
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "float64",
+ t: func() {
+ u := float64(1.01)
+ for i := 0; i < mods; i++ {
+ u *= 1.01
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *float64 { return new(float64) }()
+ *a = 1.01
+ for i := 0; i < mods; i++ {
+ *a *= 1.01
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]float64{}
+ for i := 0; i < length; i++ {
+ a[i] = float64(1.01)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j] *= 1.01
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]float64, length)
+ for i := 0; i < length; i++ {
+ a[i] = float64(1.01)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j] *= 1.01
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[float64]float64)
+ for i := 0; i < length; i++ {
+ a[float64(i)] = float64(i) + 0.01
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k] *= 1.01
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*float64]float64)
+ for i := 0; i < length; i++ {
+ a[new(float64)] = float64(i) + 0.01
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k] *= 1.01
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan float64)
+ for i := 0; i < mods; i++ {
+ go func() { a <- float64(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(float64(0))
+ for i := 0; i < mods; i++ {
+ a = a.(float64) * 1.01
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "complex64",
+ t: func() {
+ c := complex64(complex(float32(1.01), float32(1.01)))
+ for i := 0; i < mods; i++ {
+ c = complex(real(c)*1.01, imag(c)*1.01)
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *complex64 { return new(complex64) }()
+ *a = complex64(complex(float32(1.01), float32(1.01)))
+ for i := 0; i < mods; i++ {
+ *a *= complex(real(*a)*1.01, imag(*a)*1.01)
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]complex64{}
+ for i := 0; i < length; i++ {
+ a[i] = complex64(complex(float32(1.01), float32(1.01)))
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j] *= complex(real(a[j])*1.01, imag(a[j])*1.01)
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]complex64, length)
+ for i := 0; i < length; i++ {
+ a[i] = complex64(complex(float32(1.01), float32(1.01)))
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j] *= complex(real(a[j])*1.01, imag(a[j])*1.01)
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[complex64]complex64)
+ for i := 0; i < length; i++ {
+ a[complex64(complex(float32(i), float32(i)))] = complex64(complex(float32(i), float32(i))) + 0.01
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k] *= complex(real(a[k])*1.01, imag(a[k])*1.01)
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*complex64]complex64)
+ for i := 0; i < length; i++ {
+ a[new(complex64)] = complex64(complex(float32(i), float32(i))) + 0.01
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k] *= complex(real(a[k])*1.01, imag(a[k])*1.01)
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan complex64)
+ for i := 0; i < mods; i++ {
+ go func() { a <- complex64(complex(float32(i), float32(i))) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(complex64(complex(float32(1.01), float32(1.01))))
+ for i := 0; i < mods; i++ {
+ a = a.(complex64) * complex(real(a.(complex64))*1.01, imag(a.(complex64))*1.01)
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "complex128",
+ t: func() {
+ c := complex128(complex(float64(1.01), float64(1.01)))
+ for i := 0; i < mods; i++ {
+ c = complex(real(c)*1.01, imag(c)*1.01)
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *complex128 { return new(complex128) }()
+ *a = complex128(complex(float64(1.01), float64(1.01)))
+ for i := 0; i < mods; i++ {
+ *a *= complex(real(*a)*1.01, imag(*a)*1.01)
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]complex128{}
+ for i := 0; i < length; i++ {
+ a[i] = complex128(complex(float64(1.01), float64(1.01)))
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j] *= complex(real(a[j])*1.01, imag(a[j])*1.01)
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]complex128, length)
+ for i := 0; i < length; i++ {
+ a[i] = complex128(complex(float64(1.01), float64(1.01)))
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j] *= complex(real(a[j])*1.01, imag(a[j])*1.01)
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[complex128]complex128)
+ for i := 0; i < length; i++ {
+ a[complex128(complex(float64(i), float64(i)))] = complex128(complex(float64(i), float64(i))) + 0.01
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k] *= complex(real(a[k])*1.01, imag(a[k])*1.01)
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*complex128]complex128)
+ for i := 0; i < length; i++ {
+ a[new(complex128)] = complex128(complex(float64(i), float64(i))) + 0.01
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k] *= complex(real(a[k])*1.01, imag(a[k])*1.01)
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan complex128)
+ for i := 0; i < mods; i++ {
+ go func() { a <- complex128(complex(float64(i), float64(i))) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(complex128(complex(float64(1.01), float64(1.01))))
+ for i := 0; i < mods; i++ {
+ a = a.(complex128) * complex(real(a.(complex128))*1.01, imag(a.(complex128))*1.01)
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "byte",
+ t: func() {
+ var a byte
+ for i := 0; i < mods; i++ {
+ a++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *byte { return new(byte) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]byte{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]byte, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[byte]byte)
+ for i := 0; i < length; i++ {
+ a[byte(i)] = byte(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*byte]byte)
+ for i := 0; i < length; i++ {
+ a[new(byte)] = byte(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan byte)
+ for i := 0; i < mods; i++ {
+ go func() { a <- byte(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(byte(0))
+ for i := 0; i < mods; i++ {
+ a = a.(byte) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "rune",
+ t: func() {
+ var a rune
+ for i := 0; i < mods; i++ {
+ a++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *rune { return new(rune) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]rune{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]rune, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[rune]rune)
+ for i := 0; i < length; i++ {
+ a[rune(i)] = rune(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*rune]rune)
+ for i := 0; i < length; i++ {
+ a[new(rune)] = rune(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan rune)
+ for i := 0; i < mods; i++ {
+ go func() { a <- rune(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(rune(0))
+ for i := 0; i < mods; i++ {
+ a = a.(rune) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "uint",
+ t: func() {
+ var a uint
+ for i := 0; i < mods; i++ {
+ a++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *uint { return new(uint) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]uint{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]uint, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[uint]uint)
+ for i := 0; i < length; i++ {
+ a[uint(i)] = uint(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*uint]uint)
+ for i := 0; i < length; i++ {
+ a[new(uint)] = uint(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan uint)
+ for i := 0; i < mods; i++ {
+ go func() { a <- uint(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(uint(0))
+ for i := 0; i < mods; i++ {
+ a = a.(uint) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "int",
+ t: func() {
+ var a int
+ for i := 0; i < mods; i++ {
+ a++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *int { return new(int) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]int{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]int, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[int]int)
+ for i := 0; i < length; i++ {
+ a[int(i)] = int(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*int]int)
+ for i := 0; i < length; i++ {
+ a[new(int)] = int(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan int)
+ for i := 0; i < mods; i++ {
+ go func() { a <- int(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(int(0))
+ for i := 0; i < mods; i++ {
+ a = a.(int) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "uintptr",
+ t: func() {
+ var a uintptr
+ for i := 0; i < mods; i++ {
+ a++
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ a := func() *uintptr { return new(uintptr) }()
+ for i := 0; i < mods; i++ {
+ *a++
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]uintptr{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]uintptr, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j]++
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[uintptr]uintptr)
+ for i := 0; i < length; i++ {
+ a[uintptr(i)] = uintptr(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*uintptr]uintptr)
+ for i := 0; i < length; i++ {
+ a[new(uintptr)] = uintptr(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k]++
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan uintptr)
+ for i := 0; i < mods; i++ {
+ go func() { a <- uintptr(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(uintptr(0))
+ for i := 0; i < mods; i++ {
+ a = a.(uintptr) + 1
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "string",
+ t: func() {
+ var s string
+ f := func(a string) string { return a }
+ for i := 0; i < mods; i++ {
+ s = str(i)
+ s = f(s)
+ }
+ },
+ pointerT: func() {
+ a := func() *string { return new(string) }()
+ for i := 0; i < mods; i++ {
+ *a = str(i)
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]string{}
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j] = str(i)
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]string, length)
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j] = str(i)
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[string]string)
+ for i := 0; i < length; i++ {
+ a[string(i)] = str(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k] = str(i)
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*string]string)
+ for i := 0; i < length; i++ {
+ a[new(string)] = str(i)
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for k, _ := range a {
+ a[k] = str(i)
+ runtime.Gosched()
+ }
+ }
+ },
+ chanT: func() {
+ a := make(chan string)
+ for i := 0; i < mods; i++ {
+ go func() { a <- str(i) }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(str(0))
+ f := func(a string) string { return a }
+ for i := 0; i < mods; i++ {
+ a = str(i)
+ a = f(a.(string))
+ runtime.Gosched()
+ }
+ },
+ },
+ modifier{
+ name: "structT",
+ t: func() {
+ s := newStructT()
+ for i := 0; i < mods; i++ {
+ s.u8++
+ s.u16++
+ s.u32++
+ s.u64++
+ s.i8++
+ s.i16++
+ s.i32++
+ s.i64++
+ s.f32 *= 1.01
+ s.f64 *= 1.01
+ s.c64 = complex(real(s.c64)*1.01, imag(s.c64)*1.01)
+ s.c128 = complex(real(s.c128)*1.01, imag(s.c128)*1.01)
+ s.b++
+ s.r++
+ s.u++
+ s.in++
+ s.uip++
+ s.s = str(i)
+ runtime.Gosched()
+ }
+ },
+ pointerT: func() {
+ s := func() *structT {
+ t := newStructT()
+ return &t
+ }()
+ for i := 0; i < mods; i++ {
+ s.u8++
+ s.u16++
+ s.u32++
+ s.u64++
+ s.i8++
+ s.i16++
+ s.i32++
+ s.i64++
+ s.f32 *= 1.01
+ s.f64 *= 1.01
+ s.c64 = complex(real(s.c64)*1.01, imag(s.c64)*1.01)
+ s.c128 = complex(real(s.c128)*1.01, imag(s.c128)*1.01)
+ s.b++
+ s.r++
+ s.u++
+ s.in++
+ s.uip++
+ s.s = str(i)
+ runtime.Gosched()
+ }
+ },
+ arrayT: func() {
+ a := [length]structT{}
+ for i := 0; i < len(a); i++ {
+ a[i] = newStructT()
+ }
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j].u8++
+ a[j].u16++
+ a[j].u32++
+ a[j].u64++
+ a[j].i8++
+ a[j].i16++
+ a[j].i32++
+ a[j].i64++
+ a[j].f32 *= 1.01
+ a[j].f64 *= 1.01
+ a[j].c64 = complex(real(a[j].c64)*1.01, imag(a[j].c64)*1.01)
+ a[j].c128 = complex(real(a[j].c128)*1.01, imag(a[j].c128)*1.01)
+ a[j].b++
+ a[j].r++
+ a[j].u++
+ a[j].in++
+ a[j].uip++
+ a[j].s = str(i)
+ runtime.Gosched()
+ }
+ }
+ },
+ sliceT: func() {
+ a := make([]structT, length)
+ for i := 0; i < len(a); i++ {
+ a[i] = newStructT()
+ }
+ for i := 0; i < mods; i++ {
+ for j := 0; j < len(a); j++ {
+ a[j].u8++
+ a[j].u16++
+ a[j].u32++
+ a[j].u64++
+ a[j].i8++
+ a[j].i16++
+ a[j].i32++
+ a[j].i64++
+ a[j].f32 *= 1.01
+ a[j].f64 *= 1.01
+ a[j].c64 = complex(real(a[j].c64)*1.01, imag(a[j].c64)*1.01)
+ a[j].c128 = complex(real(a[j].c128)*1.01, imag(a[j].c128)*1.01)
+ a[j].b++
+ a[j].r++
+ a[j].u++
+ a[j].in++
+ a[j].uip++
+ a[j].s = str(i)
+ runtime.Gosched()
+ }
+ }
+ },
+ mapT: func() {
+ a := make(map[structT]structT)
+ for i := 0; i < length; i++ {
+ m := newStructT()
+ m.in = i
+ a[m] = newStructT()
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for j, _ := range a {
+ m := a[j]
+ m.u8++
+ m.u16++
+ m.u32++
+ m.u64++
+ m.i8++
+ m.i16++
+ m.i32++
+ m.i64++
+ m.f32 *= 1.01
+ m.f64 *= 1.01
+ m.c64 = complex(real(a[j].c64)*1.01, imag(a[j].c64)*1.01)
+ m.c128 = complex(real(a[j].c128)*1.01, imag(a[j].c128)*1.01)
+ m.b++
+ m.r++
+ m.u++
+ m.in++
+ m.uip++
+ m.s = str(i)
+ a[j] = m
+ runtime.Gosched()
+ }
+ runtime.Gosched()
+ }
+ },
+ mapPointerKeyT: func() {
+ a := make(map[*structT]structT)
+ f := func() *structT {
+ m := newStructT()
+ return &m
+ }
+ for i := 0; i < length; i++ {
+ m := f()
+ m.in = i
+ a[m] = newStructT()
+ runtime.Gosched()
+ }
+ for i := 0; i < mods; i++ {
+ for j, _ := range a {
+ m := a[j]
+ m.u8++
+ m.u16++
+ m.u32++
+ m.u64++
+ m.i8++
+ m.i16++
+ m.i32++
+ m.i64++
+ m.f32 *= 1.01
+ m.f64 *= 1.01
+ m.c64 = complex(real(a[j].c64)*1.01, imag(a[j].c64)*1.01)
+ m.c128 = complex(real(a[j].c128)*1.01, imag(a[j].c128)*1.01)
+ m.b++
+ m.r++
+ m.u++
+ m.in++
+ m.uip++
+ m.s = str(i)
+ a[j] = m
+ runtime.Gosched()
+ }
+ runtime.Gosched()
+ }
+ },
+ chanT: func() {
+ a := make(chan structT)
+ for i := 0; i < mods; i++ {
+ go func() { a <- newStructT() }()
+ <-a
+ runtime.Gosched()
+ }
+ },
+ interfaceT: func() {
+ a := interface{}(newStructT())
+ for i := 0; i < mods; i++ {
+ a = a.(structT)
+ runtime.Gosched()
+ }
+ },
+ },
+}
+
+type structT struct {
+ u8 uint8
+ u16 uint16
+ u32 uint32
+ u64 uint64
+ i8 int8
+ i16 int16
+ i32 int32
+ i64 int64
+ f32 float32
+ f64 float64
+ c64 complex64
+ c128 complex128
+ b byte
+ r rune
+ u uint
+ in int
+ uip uintptr
+ s string
+}
+
+func newStructT() structT {
+ return structT{
+ f32: 1.01,
+ f64: 1.01,
+ c64: complex(float32(1.01), float32(1.01)),
+ c128: complex(float64(1.01), float64(1.01)),
+ }
+}
+
+func str(in int) string {
+ switch in % 3 {
+ case 0:
+ return "Hello"
+ case 1:
+ return "world"
+ case 2:
+ return "!"
+ }
+ return "?"
+}
diff --git a/test/goprint.go b/test/goprint.go
index 0648c77e7..57eeac53a 100644
--- a/test/goprint.go
+++ b/test/goprint.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/helloworld.go b/test/helloworld.go
index 5025ec9bb..06851d13b 100644
--- a/test/helloworld.go
+++ b/test/helloworld.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/inline_big.go b/test/inline_big.go
new file mode 100644
index 000000000..c4af15b4e
--- /dev/null
+++ b/test/inline_big.go
@@ -0,0 +1,1029 @@
+// errorcheck -0 -m=2
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that we restrict inlining into very large functions.
+// See issue #26546.
+
+package foo
+
+func small(a []int) int { // ERROR "can inline small as:.*" "small a does not escape"
+ // Cost 16 body (need cost < 20).
+ // See cmd/compile/internal/gc/inl.go:inlineBigFunction*
+ return a[0] + a[1] + a[2] + a[3]
+}
+func medium(a []int) int { // ERROR "can inline medium as:.*" "medium a does not escape"
+ // Cost 32 body (need cost > 20 and cost < 80).
+ // See cmd/compile/internal/gc/inl.go:inlineBigFunction*
+ return a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7]
+}
+
+func f(a []int) int { // ERROR "cannot inline f:.*" "f a does not escape"
+ // Add lots of nodes to f's body. We need >5000.
+ // See cmd/compile/internal/gc/inl.go:inlineBigFunction*
+ a[0] = 0
+ a[1] = 0
+ a[2] = 0
+ a[3] = 0
+ a[4] = 0
+ a[5] = 0
+ a[6] = 0
+ a[7] = 0
+ a[8] = 0
+ a[9] = 0
+ a[10] = 0
+ a[11] = 0
+ a[12] = 0
+ a[13] = 0
+ a[14] = 0
+ a[15] = 0
+ a[16] = 0
+ a[17] = 0
+ a[18] = 0
+ a[19] = 0
+ a[20] = 0
+ a[21] = 0
+ a[22] = 0
+ a[23] = 0
+ a[24] = 0
+ a[25] = 0
+ a[26] = 0
+ a[27] = 0
+ a[28] = 0
+ a[29] = 0
+ a[30] = 0
+ a[31] = 0
+ a[32] = 0
+ a[33] = 0
+ a[34] = 0
+ a[35] = 0
+ a[36] = 0
+ a[37] = 0
+ a[38] = 0
+ a[39] = 0
+ a[40] = 0
+ a[41] = 0
+ a[42] = 0
+ a[43] = 0
+ a[44] = 0
+ a[45] = 0
+ a[46] = 0
+ a[47] = 0
+ a[48] = 0
+ a[49] = 0
+ a[50] = 0
+ a[51] = 0
+ a[52] = 0
+ a[53] = 0
+ a[54] = 0
+ a[55] = 0
+ a[56] = 0
+ a[57] = 0
+ a[58] = 0
+ a[59] = 0
+ a[60] = 0
+ a[61] = 0
+ a[62] = 0
+ a[63] = 0
+ a[64] = 0
+ a[65] = 0
+ a[66] = 0
+ a[67] = 0
+ a[68] = 0
+ a[69] = 0
+ a[70] = 0
+ a[71] = 0
+ a[72] = 0
+ a[73] = 0
+ a[74] = 0
+ a[75] = 0
+ a[76] = 0
+ a[77] = 0
+ a[78] = 0
+ a[79] = 0
+ a[80] = 0
+ a[81] = 0
+ a[82] = 0
+ a[83] = 0
+ a[84] = 0
+ a[85] = 0
+ a[86] = 0
+ a[87] = 0
+ a[88] = 0
+ a[89] = 0
+ a[90] = 0
+ a[91] = 0
+ a[92] = 0
+ a[93] = 0
+ a[94] = 0
+ a[95] = 0
+ a[96] = 0
+ a[97] = 0
+ a[98] = 0
+ a[99] = 0
+ a[100] = 0
+ a[101] = 0
+ a[102] = 0
+ a[103] = 0
+ a[104] = 0
+ a[105] = 0
+ a[106] = 0
+ a[107] = 0
+ a[108] = 0
+ a[109] = 0
+ a[110] = 0
+ a[111] = 0
+ a[112] = 0
+ a[113] = 0
+ a[114] = 0
+ a[115] = 0
+ a[116] = 0
+ a[117] = 0
+ a[118] = 0
+ a[119] = 0
+ a[120] = 0
+ a[121] = 0
+ a[122] = 0
+ a[123] = 0
+ a[124] = 0
+ a[125] = 0
+ a[126] = 0
+ a[127] = 0
+ a[128] = 0
+ a[129] = 0
+ a[130] = 0
+ a[131] = 0
+ a[132] = 0
+ a[133] = 0
+ a[134] = 0
+ a[135] = 0
+ a[136] = 0
+ a[137] = 0
+ a[138] = 0
+ a[139] = 0
+ a[140] = 0
+ a[141] = 0
+ a[142] = 0
+ a[143] = 0
+ a[144] = 0
+ a[145] = 0
+ a[146] = 0
+ a[147] = 0
+ a[148] = 0
+ a[149] = 0
+ a[150] = 0
+ a[151] = 0
+ a[152] = 0
+ a[153] = 0
+ a[154] = 0
+ a[155] = 0
+ a[156] = 0
+ a[157] = 0
+ a[158] = 0
+ a[159] = 0
+ a[160] = 0
+ a[161] = 0
+ a[162] = 0
+ a[163] = 0
+ a[164] = 0
+ a[165] = 0
+ a[166] = 0
+ a[167] = 0
+ a[168] = 0
+ a[169] = 0
+ a[170] = 0
+ a[171] = 0
+ a[172] = 0
+ a[173] = 0
+ a[174] = 0
+ a[175] = 0
+ a[176] = 0
+ a[177] = 0
+ a[178] = 0
+ a[179] = 0
+ a[180] = 0
+ a[181] = 0
+ a[182] = 0
+ a[183] = 0
+ a[184] = 0
+ a[185] = 0
+ a[186] = 0
+ a[187] = 0
+ a[188] = 0
+ a[189] = 0
+ a[190] = 0
+ a[191] = 0
+ a[192] = 0
+ a[193] = 0
+ a[194] = 0
+ a[195] = 0
+ a[196] = 0
+ a[197] = 0
+ a[198] = 0
+ a[199] = 0
+ a[200] = 0
+ a[201] = 0
+ a[202] = 0
+ a[203] = 0
+ a[204] = 0
+ a[205] = 0
+ a[206] = 0
+ a[207] = 0
+ a[208] = 0
+ a[209] = 0
+ a[210] = 0
+ a[211] = 0
+ a[212] = 0
+ a[213] = 0
+ a[214] = 0
+ a[215] = 0
+ a[216] = 0
+ a[217] = 0
+ a[218] = 0
+ a[219] = 0
+ a[220] = 0
+ a[221] = 0
+ a[222] = 0
+ a[223] = 0
+ a[224] = 0
+ a[225] = 0
+ a[226] = 0
+ a[227] = 0
+ a[228] = 0
+ a[229] = 0
+ a[230] = 0
+ a[231] = 0
+ a[232] = 0
+ a[233] = 0
+ a[234] = 0
+ a[235] = 0
+ a[236] = 0
+ a[237] = 0
+ a[238] = 0
+ a[239] = 0
+ a[240] = 0
+ a[241] = 0
+ a[242] = 0
+ a[243] = 0
+ a[244] = 0
+ a[245] = 0
+ a[246] = 0
+ a[247] = 0
+ a[248] = 0
+ a[249] = 0
+ a[250] = 0
+ a[251] = 0
+ a[252] = 0
+ a[253] = 0
+ a[254] = 0
+ a[255] = 0
+ a[256] = 0
+ a[257] = 0
+ a[258] = 0
+ a[259] = 0
+ a[260] = 0
+ a[261] = 0
+ a[262] = 0
+ a[263] = 0
+ a[264] = 0
+ a[265] = 0
+ a[266] = 0
+ a[267] = 0
+ a[268] = 0
+ a[269] = 0
+ a[270] = 0
+ a[271] = 0
+ a[272] = 0
+ a[273] = 0
+ a[274] = 0
+ a[275] = 0
+ a[276] = 0
+ a[277] = 0
+ a[278] = 0
+ a[279] = 0
+ a[280] = 0
+ a[281] = 0
+ a[282] = 0
+ a[283] = 0
+ a[284] = 0
+ a[285] = 0
+ a[286] = 0
+ a[287] = 0
+ a[288] = 0
+ a[289] = 0
+ a[290] = 0
+ a[291] = 0
+ a[292] = 0
+ a[293] = 0
+ a[294] = 0
+ a[295] = 0
+ a[296] = 0
+ a[297] = 0
+ a[298] = 0
+ a[299] = 0
+ a[300] = 0
+ a[301] = 0
+ a[302] = 0
+ a[303] = 0
+ a[304] = 0
+ a[305] = 0
+ a[306] = 0
+ a[307] = 0
+ a[308] = 0
+ a[309] = 0
+ a[310] = 0
+ a[311] = 0
+ a[312] = 0
+ a[313] = 0
+ a[314] = 0
+ a[315] = 0
+ a[316] = 0
+ a[317] = 0
+ a[318] = 0
+ a[319] = 0
+ a[320] = 0
+ a[321] = 0
+ a[322] = 0
+ a[323] = 0
+ a[324] = 0
+ a[325] = 0
+ a[326] = 0
+ a[327] = 0
+ a[328] = 0
+ a[329] = 0
+ a[330] = 0
+ a[331] = 0
+ a[332] = 0
+ a[333] = 0
+ a[334] = 0
+ a[335] = 0
+ a[336] = 0
+ a[337] = 0
+ a[338] = 0
+ a[339] = 0
+ a[340] = 0
+ a[341] = 0
+ a[342] = 0
+ a[343] = 0
+ a[344] = 0
+ a[345] = 0
+ a[346] = 0
+ a[347] = 0
+ a[348] = 0
+ a[349] = 0
+ a[350] = 0
+ a[351] = 0
+ a[352] = 0
+ a[353] = 0
+ a[354] = 0
+ a[355] = 0
+ a[356] = 0
+ a[357] = 0
+ a[358] = 0
+ a[359] = 0
+ a[360] = 0
+ a[361] = 0
+ a[362] = 0
+ a[363] = 0
+ a[364] = 0
+ a[365] = 0
+ a[366] = 0
+ a[367] = 0
+ a[368] = 0
+ a[369] = 0
+ a[370] = 0
+ a[371] = 0
+ a[372] = 0
+ a[373] = 0
+ a[374] = 0
+ a[375] = 0
+ a[376] = 0
+ a[377] = 0
+ a[378] = 0
+ a[379] = 0
+ a[380] = 0
+ a[381] = 0
+ a[382] = 0
+ a[383] = 0
+ a[384] = 0
+ a[385] = 0
+ a[386] = 0
+ a[387] = 0
+ a[388] = 0
+ a[389] = 0
+ a[390] = 0
+ a[391] = 0
+ a[392] = 0
+ a[393] = 0
+ a[394] = 0
+ a[395] = 0
+ a[396] = 0
+ a[397] = 0
+ a[398] = 0
+ a[399] = 0
+ a[400] = 0
+ a[401] = 0
+ a[402] = 0
+ a[403] = 0
+ a[404] = 0
+ a[405] = 0
+ a[406] = 0
+ a[407] = 0
+ a[408] = 0
+ a[409] = 0
+ a[410] = 0
+ a[411] = 0
+ a[412] = 0
+ a[413] = 0
+ a[414] = 0
+ a[415] = 0
+ a[416] = 0
+ a[417] = 0
+ a[418] = 0
+ a[419] = 0
+ a[420] = 0
+ a[421] = 0
+ a[422] = 0
+ a[423] = 0
+ a[424] = 0
+ a[425] = 0
+ a[426] = 0
+ a[427] = 0
+ a[428] = 0
+ a[429] = 0
+ a[430] = 0
+ a[431] = 0
+ a[432] = 0
+ a[433] = 0
+ a[434] = 0
+ a[435] = 0
+ a[436] = 0
+ a[437] = 0
+ a[438] = 0
+ a[439] = 0
+ a[440] = 0
+ a[441] = 0
+ a[442] = 0
+ a[443] = 0
+ a[444] = 0
+ a[445] = 0
+ a[446] = 0
+ a[447] = 0
+ a[448] = 0
+ a[449] = 0
+ a[450] = 0
+ a[451] = 0
+ a[452] = 0
+ a[453] = 0
+ a[454] = 0
+ a[455] = 0
+ a[456] = 0
+ a[457] = 0
+ a[458] = 0
+ a[459] = 0
+ a[460] = 0
+ a[461] = 0
+ a[462] = 0
+ a[463] = 0
+ a[464] = 0
+ a[465] = 0
+ a[466] = 0
+ a[467] = 0
+ a[468] = 0
+ a[469] = 0
+ a[470] = 0
+ a[471] = 0
+ a[472] = 0
+ a[473] = 0
+ a[474] = 0
+ a[475] = 0
+ a[476] = 0
+ a[477] = 0
+ a[478] = 0
+ a[479] = 0
+ a[480] = 0
+ a[481] = 0
+ a[482] = 0
+ a[483] = 0
+ a[484] = 0
+ a[485] = 0
+ a[486] = 0
+ a[487] = 0
+ a[488] = 0
+ a[489] = 0
+ a[490] = 0
+ a[491] = 0
+ a[492] = 0
+ a[493] = 0
+ a[494] = 0
+ a[495] = 0
+ a[496] = 0
+ a[497] = 0
+ a[498] = 0
+ a[499] = 0
+ a[500] = 0
+ a[501] = 0
+ a[502] = 0
+ a[503] = 0
+ a[504] = 0
+ a[505] = 0
+ a[506] = 0
+ a[507] = 0
+ a[508] = 0
+ a[509] = 0
+ a[510] = 0
+ a[511] = 0
+ a[512] = 0
+ a[513] = 0
+ a[514] = 0
+ a[515] = 0
+ a[516] = 0
+ a[517] = 0
+ a[518] = 0
+ a[519] = 0
+ a[520] = 0
+ a[521] = 0
+ a[522] = 0
+ a[523] = 0
+ a[524] = 0
+ a[525] = 0
+ a[526] = 0
+ a[527] = 0
+ a[528] = 0
+ a[529] = 0
+ a[530] = 0
+ a[531] = 0
+ a[532] = 0
+ a[533] = 0
+ a[534] = 0
+ a[535] = 0
+ a[536] = 0
+ a[537] = 0
+ a[538] = 0
+ a[539] = 0
+ a[540] = 0
+ a[541] = 0
+ a[542] = 0
+ a[543] = 0
+ a[544] = 0
+ a[545] = 0
+ a[546] = 0
+ a[547] = 0
+ a[548] = 0
+ a[549] = 0
+ a[550] = 0
+ a[551] = 0
+ a[552] = 0
+ a[553] = 0
+ a[554] = 0
+ a[555] = 0
+ a[556] = 0
+ a[557] = 0
+ a[558] = 0
+ a[559] = 0
+ a[560] = 0
+ a[561] = 0
+ a[562] = 0
+ a[563] = 0
+ a[564] = 0
+ a[565] = 0
+ a[566] = 0
+ a[567] = 0
+ a[568] = 0
+ a[569] = 0
+ a[570] = 0
+ a[571] = 0
+ a[572] = 0
+ a[573] = 0
+ a[574] = 0
+ a[575] = 0
+ a[576] = 0
+ a[577] = 0
+ a[578] = 0
+ a[579] = 0
+ a[580] = 0
+ a[581] = 0
+ a[582] = 0
+ a[583] = 0
+ a[584] = 0
+ a[585] = 0
+ a[586] = 0
+ a[587] = 0
+ a[588] = 0
+ a[589] = 0
+ a[590] = 0
+ a[591] = 0
+ a[592] = 0
+ a[593] = 0
+ a[594] = 0
+ a[595] = 0
+ a[596] = 0
+ a[597] = 0
+ a[598] = 0
+ a[599] = 0
+ a[600] = 0
+ a[601] = 0
+ a[602] = 0
+ a[603] = 0
+ a[604] = 0
+ a[605] = 0
+ a[606] = 0
+ a[607] = 0
+ a[608] = 0
+ a[609] = 0
+ a[610] = 0
+ a[611] = 0
+ a[612] = 0
+ a[613] = 0
+ a[614] = 0
+ a[615] = 0
+ a[616] = 0
+ a[617] = 0
+ a[618] = 0
+ a[619] = 0
+ a[620] = 0
+ a[621] = 0
+ a[622] = 0
+ a[623] = 0
+ a[624] = 0
+ a[625] = 0
+ a[626] = 0
+ a[627] = 0
+ a[628] = 0
+ a[629] = 0
+ a[630] = 0
+ a[631] = 0
+ a[632] = 0
+ a[633] = 0
+ a[634] = 0
+ a[635] = 0
+ a[636] = 0
+ a[637] = 0
+ a[638] = 0
+ a[639] = 0
+ a[640] = 0
+ a[641] = 0
+ a[642] = 0
+ a[643] = 0
+ a[644] = 0
+ a[645] = 0
+ a[646] = 0
+ a[647] = 0
+ a[648] = 0
+ a[649] = 0
+ a[650] = 0
+ a[651] = 0
+ a[652] = 0
+ a[653] = 0
+ a[654] = 0
+ a[655] = 0
+ a[656] = 0
+ a[657] = 0
+ a[658] = 0
+ a[659] = 0
+ a[660] = 0
+ a[661] = 0
+ a[662] = 0
+ a[663] = 0
+ a[664] = 0
+ a[665] = 0
+ a[666] = 0
+ a[667] = 0
+ a[668] = 0
+ a[669] = 0
+ a[670] = 0
+ a[671] = 0
+ a[672] = 0
+ a[673] = 0
+ a[674] = 0
+ a[675] = 0
+ a[676] = 0
+ a[677] = 0
+ a[678] = 0
+ a[679] = 0
+ a[680] = 0
+ a[681] = 0
+ a[682] = 0
+ a[683] = 0
+ a[684] = 0
+ a[685] = 0
+ a[686] = 0
+ a[687] = 0
+ a[688] = 0
+ a[689] = 0
+ a[690] = 0
+ a[691] = 0
+ a[692] = 0
+ a[693] = 0
+ a[694] = 0
+ a[695] = 0
+ a[696] = 0
+ a[697] = 0
+ a[698] = 0
+ a[699] = 0
+ a[700] = 0
+ a[701] = 0
+ a[702] = 0
+ a[703] = 0
+ a[704] = 0
+ a[705] = 0
+ a[706] = 0
+ a[707] = 0
+ a[708] = 0
+ a[709] = 0
+ a[710] = 0
+ a[711] = 0
+ a[712] = 0
+ a[713] = 0
+ a[714] = 0
+ a[715] = 0
+ a[716] = 0
+ a[717] = 0
+ a[718] = 0
+ a[719] = 0
+ a[720] = 0
+ a[721] = 0
+ a[722] = 0
+ a[723] = 0
+ a[724] = 0
+ a[725] = 0
+ a[726] = 0
+ a[727] = 0
+ a[728] = 0
+ a[729] = 0
+ a[730] = 0
+ a[731] = 0
+ a[732] = 0
+ a[733] = 0
+ a[734] = 0
+ a[735] = 0
+ a[736] = 0
+ a[737] = 0
+ a[738] = 0
+ a[739] = 0
+ a[740] = 0
+ a[741] = 0
+ a[742] = 0
+ a[743] = 0
+ a[744] = 0
+ a[745] = 0
+ a[746] = 0
+ a[747] = 0
+ a[748] = 0
+ a[749] = 0
+ a[750] = 0
+ a[751] = 0
+ a[752] = 0
+ a[753] = 0
+ a[754] = 0
+ a[755] = 0
+ a[756] = 0
+ a[757] = 0
+ a[758] = 0
+ a[759] = 0
+ a[760] = 0
+ a[761] = 0
+ a[762] = 0
+ a[763] = 0
+ a[764] = 0
+ a[765] = 0
+ a[766] = 0
+ a[767] = 0
+ a[768] = 0
+ a[769] = 0
+ a[770] = 0
+ a[771] = 0
+ a[772] = 0
+ a[773] = 0
+ a[774] = 0
+ a[775] = 0
+ a[776] = 0
+ a[777] = 0
+ a[778] = 0
+ a[779] = 0
+ a[780] = 0
+ a[781] = 0
+ a[782] = 0
+ a[783] = 0
+ a[784] = 0
+ a[785] = 0
+ a[786] = 0
+ a[787] = 0
+ a[788] = 0
+ a[789] = 0
+ a[790] = 0
+ a[791] = 0
+ a[792] = 0
+ a[793] = 0
+ a[794] = 0
+ a[795] = 0
+ a[796] = 0
+ a[797] = 0
+ a[798] = 0
+ a[799] = 0
+ a[800] = 0
+ a[801] = 0
+ a[802] = 0
+ a[803] = 0
+ a[804] = 0
+ a[805] = 0
+ a[806] = 0
+ a[807] = 0
+ a[808] = 0
+ a[809] = 0
+ a[810] = 0
+ a[811] = 0
+ a[812] = 0
+ a[813] = 0
+ a[814] = 0
+ a[815] = 0
+ a[816] = 0
+ a[817] = 0
+ a[818] = 0
+ a[819] = 0
+ a[820] = 0
+ a[821] = 0
+ a[822] = 0
+ a[823] = 0
+ a[824] = 0
+ a[825] = 0
+ a[826] = 0
+ a[827] = 0
+ a[828] = 0
+ a[829] = 0
+ a[830] = 0
+ a[831] = 0
+ a[832] = 0
+ a[833] = 0
+ a[834] = 0
+ a[835] = 0
+ a[836] = 0
+ a[837] = 0
+ a[838] = 0
+ a[839] = 0
+ a[840] = 0
+ a[841] = 0
+ a[842] = 0
+ a[843] = 0
+ a[844] = 0
+ a[845] = 0
+ a[846] = 0
+ a[847] = 0
+ a[848] = 0
+ a[849] = 0
+ a[850] = 0
+ a[851] = 0
+ a[852] = 0
+ a[853] = 0
+ a[854] = 0
+ a[855] = 0
+ a[856] = 0
+ a[857] = 0
+ a[858] = 0
+ a[859] = 0
+ a[860] = 0
+ a[861] = 0
+ a[862] = 0
+ a[863] = 0
+ a[864] = 0
+ a[865] = 0
+ a[866] = 0
+ a[867] = 0
+ a[868] = 0
+ a[869] = 0
+ a[870] = 0
+ a[871] = 0
+ a[872] = 0
+ a[873] = 0
+ a[874] = 0
+ a[875] = 0
+ a[876] = 0
+ a[877] = 0
+ a[878] = 0
+ a[879] = 0
+ a[880] = 0
+ a[881] = 0
+ a[882] = 0
+ a[883] = 0
+ a[884] = 0
+ a[885] = 0
+ a[886] = 0
+ a[887] = 0
+ a[888] = 0
+ a[889] = 0
+ a[890] = 0
+ a[891] = 0
+ a[892] = 0
+ a[893] = 0
+ a[894] = 0
+ a[895] = 0
+ a[896] = 0
+ a[897] = 0
+ a[898] = 0
+ a[899] = 0
+ a[900] = 0
+ a[901] = 0
+ a[902] = 0
+ a[903] = 0
+ a[904] = 0
+ a[905] = 0
+ a[906] = 0
+ a[907] = 0
+ a[908] = 0
+ a[909] = 0
+ a[910] = 0
+ a[911] = 0
+ a[912] = 0
+ a[913] = 0
+ a[914] = 0
+ a[915] = 0
+ a[916] = 0
+ a[917] = 0
+ a[918] = 0
+ a[919] = 0
+ a[920] = 0
+ a[921] = 0
+ a[922] = 0
+ a[923] = 0
+ a[924] = 0
+ a[925] = 0
+ a[926] = 0
+ a[927] = 0
+ a[928] = 0
+ a[929] = 0
+ a[930] = 0
+ a[931] = 0
+ a[932] = 0
+ a[933] = 0
+ a[934] = 0
+ a[935] = 0
+ a[936] = 0
+ a[937] = 0
+ a[938] = 0
+ a[939] = 0
+ a[940] = 0
+ a[941] = 0
+ a[942] = 0
+ a[943] = 0
+ a[944] = 0
+ a[945] = 0
+ a[946] = 0
+ a[947] = 0
+ a[948] = 0
+ a[949] = 0
+ a[950] = 0
+ a[951] = 0
+ a[952] = 0
+ a[953] = 0
+ a[954] = 0
+ a[955] = 0
+ a[956] = 0
+ a[957] = 0
+ a[958] = 0
+ a[959] = 0
+ a[960] = 0
+ a[961] = 0
+ a[962] = 0
+ a[963] = 0
+ a[964] = 0
+ a[965] = 0
+ a[966] = 0
+ a[967] = 0
+ a[968] = 0
+ a[969] = 0
+ a[970] = 0
+ a[971] = 0
+ a[972] = 0
+ a[973] = 0
+ a[974] = 0
+ a[975] = 0
+ a[976] = 0
+ a[977] = 0
+ a[978] = 0
+ a[979] = 0
+ a[980] = 0
+ a[981] = 0
+ a[982] = 0
+ a[983] = 0
+ a[984] = 0
+ a[985] = 0
+ a[986] = 0
+ a[987] = 0
+ a[988] = 0
+ a[989] = 0
+ a[990] = 0
+ a[991] = 0
+ a[992] = 0
+ a[993] = 0
+ a[994] = 0
+ a[995] = 0
+ a[996] = 0
+ a[997] = 0
+ a[998] = 0
+ a[999] = 0
+ x := small(a) // ERROR "inlining call to small .*"
+ y := medium(a) // The crux of this test: medium is not inlined.
+ return x + y
+}
diff --git a/test/inline_variadic.go b/test/inline_variadic.go
index 6466c2b09..fcc1cff1e 100644
--- a/test/inline_variadic.go
+++ b/test/inline_variadic.go
@@ -1,10 +1,10 @@
-// errorcheck -0 -m -l=3
+// errorcheck -0 -m
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-// Test more aggressive inlining (-l=3 allows variadic functions)
+// Test inlining of variadic functions.
// See issue #18116.
package foo
diff --git a/test/ken/cplx0.go b/test/ken/cplx0.go
index 665e52a5f..5d78dc014 100644
--- a/test/ken/cplx0.go
+++ b/test/ken/cplx0.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/ken/string.go b/test/ken/string.go
index 6df8dc4dd..7bb3cabbc 100644
--- a/test/ken/string.go
+++ b/test/ken/string.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/linkmain_run.go b/test/linkmain_run.go
index 55de481a8..68d53e8ca 100644
--- a/test/linkmain_run.go
+++ b/test/linkmain_run.go
@@ -1,4 +1,4 @@
-// +build !nacl
+// +build !nacl,!js
// run
// Copyright 2014 The Go Authors. All rights reserved.
diff --git a/test/linkobj.go b/test/linkobj.go
index 8a86aa872..2902d23f4 100644
--- a/test/linkobj.go
+++ b/test/linkobj.go
@@ -1,4 +1,4 @@
-// +build !nacl
+// +build !nacl,!js
// run
// Copyright 2016 The Go Authors. All rights reserved.
diff --git a/test/linkx_run.go b/test/linkx_run.go
index cc249c9cf..ca9d31612 100644
--- a/test/linkx_run.go
+++ b/test/linkx_run.go
@@ -1,4 +1,4 @@
-// +build !nacl
+// +build !nacl,!js
// run
// Copyright 2014 The Go Authors. All rights reserved.
diff --git a/test/live.go b/test/live.go
index e54336ead..18611f511 100644
--- a/test/live.go
+++ b/test/live.go
@@ -141,7 +141,7 @@ var i9 interface{}
func f9() bool {
g8()
x := i9
- y := interface{}(str()) // ERROR "live at call to convT2Estring: .autotmp_[0-9]+ x.data x.type$" "live at call to str: x.data x.type$"
+ y := interface{}(str()) // ERROR "live at call to convT2Estring: .autotmp_[0-9]+ x.data$" "live at call to str: x.data$"
i9 = y // make y escape so the line above has to call convT2E
return x != y
}
@@ -163,10 +163,10 @@ var b bool
// this used to have a spurious "live at entry to f11a: ~r0"
func f11a() *int {
- select { // ERROR "live at call to newselect: .autotmp_[0-9]+$" "live at call to selectgo: .autotmp_[0-9]+$"
- case <-c: // ERROR "live at call to selectrecv: .autotmp_[0-9]+$"
+ select { // ERROR "live at call to selectgo: .autotmp_[0-9]+$"
+ case <-c:
return nil
- case <-c: // ERROR "live at call to selectrecv: .autotmp_[0-9]+$"
+ case <-c:
return nil
}
}
@@ -178,10 +178,10 @@ func f11b() *int {
// get to the bottom of the function.
// This used to have a spurious "live at call to printint: p".
printint(1) // nothing live here!
- select { // ERROR "live at call to newselect: .autotmp_[0-9]+$" "live at call to selectgo: .autotmp_[0-9]+$"
- case <-c: // ERROR "live at call to selectrecv: .autotmp_[0-9]+$"
+ select { // ERROR "live at call to selectgo: .autotmp_[0-9]+$"
+ case <-c:
return nil
- case <-c: // ERROR "live at call to selectrecv: .autotmp_[0-9]+$"
+ case <-c:
return nil
}
}
@@ -198,9 +198,9 @@ func f11c() *int {
// Unlike previous, the cases in this select fall through,
// so we can get to the println, so p is not dead.
printint(1) // ERROR "live at call to printint: p$"
- select { // ERROR "live at call to newselect: .autotmp_[0-9]+ p$" "live at call to selectgo: .autotmp_[0-9]+ p$"
- case <-c: // ERROR "live at call to selectrecv: .autotmp_[0-9]+ p$"
- case <-c: // ERROR "live at call to selectrecv: .autotmp_[0-9]+ p$"
+ select { // ERROR "live at call to selectgo: .autotmp_[0-9]+ p$"
+ case <-c:
+ case <-c:
}
}
println(*p)
@@ -553,7 +553,7 @@ func f34() {
}
func f35() {
- if m33[byteptr()] == 0 && m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+ if m33[byteptr()] == 0 && m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$" "f35: .autotmp_[0-9]+ \(type interface \{\}\) is ambiguously live$"
printnl()
return
}
@@ -561,7 +561,7 @@ func f35() {
}
func f36() {
- if m33[byteptr()] == 0 || m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+ if m33[byteptr()] == 0 || m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$" "f36: .autotmp_[0-9]+ \(type interface \{\}\) is ambiguously live$"
printnl()
return
}
@@ -569,7 +569,7 @@ func f36() {
}
func f37() {
- if (m33[byteptr()] == 0 || m33[byteptr()] == 0) && m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$"
+ if (m33[byteptr()] == 0 || m33[byteptr()] == 0) && m33[byteptr()] == 0 { // ERROR "live at call to mapaccess1: .autotmp_[0-9]+$" "f37: .autotmp_[0-9]+ \(type interface \{\}\) is ambiguously live$"
printnl()
return
}
@@ -589,14 +589,14 @@ func f38(b bool) {
// we care that the println lines have no live variables
// and therefore no output.
if b {
- select { // ERROR "live at call to newselect:( .autotmp_[0-9]+)+$" "live at call to selectgo:( .autotmp_[0-9]+)+$"
- case <-fc38(): // ERROR "live at call to selectrecv:( .autotmp_[0-9]+)+$"
+ select { // ERROR "live at call to selectgo:( .autotmp_[0-9]+)+$"
+ case <-fc38():
printnl()
- case fc38() <- *fi38(1): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "live at call to selectsend:( .autotmp_[0-9]+)+$"
+ case fc38() <- *fi38(1): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$"
printnl()
- case *fi38(2) = <-fc38(): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "live at call to selectrecv:( .autotmp_[0-9]+)+$"
+ case *fi38(2) = <-fc38(): // ERROR "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$"
printnl()
- case *fi38(3), *fb38() = <-fc38(): // ERROR "live at call to fb38:( .autotmp_[0-9]+)+$" "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$" "live at call to selectrecv:( .autotmp_[0-9]+)+$"
+ case *fi38(3), *fb38() = <-fc38(): // ERROR "live at call to fb38:( .autotmp_[0-9]+)+$" "live at call to fc38:( .autotmp_[0-9]+)+$" "live at call to fi38:( .autotmp_[0-9]+)+$"
printnl()
}
printnl()
diff --git a/test/live_syscall.go b/test/live_syscall.go
index 6d954653c..65a161c02 100644
--- a/test/live_syscall.go
+++ b/test/live_syscall.go
@@ -1,6 +1,6 @@
// errorcheck -0 -m -live
-// +build !windows
+// +build !windows,!js
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/locklinear.go b/test/locklinear.go
index 161912b65..54e40a543 100644
--- a/test/locklinear.go
+++ b/test/locklinear.go
@@ -125,6 +125,12 @@ func main() {
}
})
+ if runtime.GOARCH == "arm" && os.Getenv("GOARM") == "5" {
+ // lockmany reliably fails on the linux-arm-arm5spacemonkey
+ // builder. See https://golang.org/issue/24221.
+ return
+ }
+
checkLinear("lockmany", 1000, func(n int) {
locks := make([]sync.RWMutex, n*offset+1)
diff --git a/test/loopbce.go b/test/loopbce.go
index 857cf2442..b4bf79749 100644
--- a/test/loopbce.go
+++ b/test/loopbce.go
@@ -1,20 +1,20 @@
// +build amd64
-// errorcheck -0 -d=ssa/loopbce/debug=3
+// errorcheck -0 -d=ssa/prove/debug=1
package main
func f0a(a []int) int {
x := 0
- for i := range a { // ERROR "Induction variable with minimum 0 and increment 1$"
- x += a[i] // ERROR "Found redundant IsInBounds$"
+ for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ x += a[i] // ERROR "Proved IsInBounds$"
}
return x
}
func f0b(a []int) int {
x := 0
- for i := range a { // ERROR "Induction variable with minimum 0 and increment 1$"
- b := a[i:] // ERROR "Found redundant IsSliceInBounds$"
+ for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ b := a[i:] // ERROR "Proved IsSliceInBounds$"
x += b[0]
}
return x
@@ -22,8 +22,8 @@ func f0b(a []int) int {
func f0c(a []int) int {
x := 0
- for i := range a { // ERROR "Induction variable with minimum 0 and increment 1$"
- b := a[:i+1] // ERROR "Found redundant IsSliceInBounds \(len promoted to cap\)$"
+ for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ b := a[:i+1] // ERROR "Proved IsSliceInBounds$"
x += b[0]
}
return x
@@ -31,7 +31,7 @@ func f0c(a []int) int {
func f1(a []int) int {
x := 0
- for _, i := range a { // ERROR "Induction variable with minimum 0 and increment 1"
+ for _, i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
x += i
}
return x
@@ -39,47 +39,79 @@ func f1(a []int) int {
func f2(a []int) int {
x := 0
- for i := 1; i < len(a); i++ { // ERROR "Induction variable with minimum 1 and increment 1$"
- x += a[i] // ERROR "Found redundant IsInBounds$"
+ for i := 1; i < len(a); i++ { // ERROR "Induction variable: limits \[1,\?\), increment 1$"
+ x += a[i] // ERROR "Proved IsInBounds$"
}
return x
}
func f4(a [10]int) int {
x := 0
- for i := 0; i < len(a); i += 2 { // ERROR "Induction variable with minimum 0 and increment 2$"
- x += a[i] // ERROR "Found redundant IsInBounds$"
+ for i := 0; i < len(a); i += 2 { // ERROR "Induction variable: limits \[0,10\), increment 2$"
+ x += a[i] // ERROR "Proved IsInBounds$"
}
return x
}
func f5(a [10]int) int {
x := 0
- for i := -10; i < len(a); i += 2 { // ERROR "Induction variable with minimum -10 and increment 2$"
+ for i := -10; i < len(a); i += 2 { // ERROR "Induction variable: limits \[-10,10\), increment 2$"
x += a[i]
}
return x
}
func f6(a []int) {
- for i := range a { // ERROR "Induction variable with minimum 0 and increment 1$"
- b := a[0:i] // ERROR "Found redundant IsSliceInBounds \(len promoted to cap\)$"
+ for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ b := a[0:i] // ERROR "Proved IsSliceInBounds$"
f6(b)
}
}
func g0a(a string) int {
x := 0
- for i := 0; i < len(a); i++ { // ERROR "Induction variable with minimum 0 and increment 1$"
- x += int(a[i]) // ERROR "Found redundant IsInBounds$"
+ for i := 0; i < len(a); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ x += int(a[i]) // ERROR "Proved IsInBounds$"
}
return x
}
func g0b(a string) int {
x := 0
- for i := 0; len(a) > i; i++ { // ERROR "Induction variable with minimum 0 and increment 1$"
- x += int(a[i]) // ERROR "Found redundant IsInBounds$"
+ for i := 0; len(a) > i; i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ x += int(a[i]) // ERROR "Proved IsInBounds$"
+ }
+ return x
+}
+
+func g0c(a string) int {
+ x := 0
+ for i := len(a); i > 0; i-- { // ERROR "Induction variable: limits \(0,\?\], increment 1$"
+ x += int(a[i-1]) // ERROR "Proved IsInBounds$"
+ }
+ return x
+}
+
+func g0d(a string) int {
+ x := 0
+ for i := len(a); 0 < i; i-- { // ERROR "Induction variable: limits \(0,\?\], increment 1$"
+ x += int(a[i-1]) // ERROR "Proved IsInBounds$"
+ }
+ return x
+}
+
+func g0e(a string) int {
+ x := 0
+ for i := len(a) - 1; i >= 0; i-- { // ERROR "Induction variable: limits \[0,\?\], increment 1$"
+ x += int(a[i]) // ERROR "Proved IsInBounds$"
+ }
+ return x
+}
+
+func g0f(a string) int {
+ x := 0
+ for i := len(a) - 1; 0 <= i; i-- { // ERROR "Induction variable: limits \[0,\?\], increment 1$"
+ x += int(a[i]) // ERROR "Proved IsInBounds$"
}
return x
}
@@ -87,8 +119,8 @@ func g0b(a string) int {
func g1() int {
a := "evenlength"
x := 0
- for i := 0; i < len(a); i += 2 { // ERROR "Induction variable with minimum 0 and increment 2$"
- x += int(a[i]) // ERROR "Found redundant IsInBounds$"
+ for i := 0; i < len(a); i += 2 { // ERROR "Induction variable: limits \[0,10\), increment 2$"
+ x += int(a[i]) // ERROR "Proved IsInBounds$"
}
return x
}
@@ -96,9 +128,9 @@ func g1() int {
func g2() int {
a := "evenlength"
x := 0
- for i := 0; i < len(a); i += 2 { // ERROR "Induction variable with minimum 0 and increment 2$"
+ for i := 0; i < len(a); i += 2 { // ERROR "Induction variable: limits \[0,10\), increment 2$"
j := i
- if a[i] == 'e' { // ERROR "Found redundant IsInBounds$"
+ if a[i] == 'e' { // ERROR "Proved IsInBounds$"
j = j + 1
}
x += int(a[j])
@@ -108,97 +140,119 @@ func g2() int {
func g3a() {
a := "this string has length 25"
- for i := 0; i < len(a); i += 5 { // ERROR "Induction variable with minimum 0 and increment 5$"
- useString(a[i:]) // ERROR "Found redundant IsSliceInBounds$"
+ for i := 0; i < len(a); i += 5 { // ERROR "Induction variable: limits \[0,25\), increment 5$"
+ useString(a[i:]) // ERROR "Proved IsSliceInBounds$"
useString(a[:i+3])
}
}
func g3b(a string) {
- for i := 0; i < len(a); i++ { // ERROR "Induction variable with minimum 0 and increment 1$"
- useString(a[i+1:]) // ERROR "Found redundant IsSliceInBounds$"
+ for i := 0; i < len(a); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ useString(a[i+1:]) // ERROR "Proved IsSliceInBounds$"
}
}
func g3c(a string) {
- for i := 0; i < len(a); i++ { // ERROR "Induction variable with minimum 0 and increment 1$"
- useString(a[:i+1]) // ERROR "Found redundant IsSliceInBounds$"
+ for i := 0; i < len(a); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ useString(a[:i+1]) // ERROR "Proved IsSliceInBounds$"
}
}
func h1(a []byte) {
c := a[:128]
- for i := range c { // ERROR "Induction variable with minimum 0 and increment 1$"
- c[i] = byte(i) // ERROR "Found redundant IsInBounds$"
+ for i := range c { // ERROR "Induction variable: limits \[0,128\), increment 1$"
+ c[i] = byte(i) // ERROR "Proved IsInBounds$"
}
}
func h2(a []byte) {
- for i := range a[:128] { // ERROR "Induction variable with minimum 0 and increment 1$"
+ for i := range a[:128] { // ERROR "Induction variable: limits \[0,128\), increment 1$"
a[i] = byte(i)
}
}
func k0(a [100]int) [100]int {
- for i := 10; i < 90; i++ { // ERROR "Induction variable with minimum 10 and increment 1$"
+ for i := 10; i < 90; i++ { // ERROR "Induction variable: limits \[10,90\), increment 1$"
a[i-11] = i
- a[i-10] = i // ERROR "Found redundant \(IsInBounds ind 100\), ind < 80$"
- a[i-5] = i // ERROR "Found redundant \(IsInBounds ind 100\), ind < 85$"
- a[i] = i // ERROR "Found redundant \(IsInBounds ind 100\), ind < 90$"
- a[i+5] = i // ERROR "Found redundant \(IsInBounds ind 100\), ind < 95$"
- a[i+10] = i // ERROR "Found redundant \(IsInBounds ind 100\), ind < 100$"
+ a[i-10] = i // ERROR "Proved IsInBounds$"
+ a[i-5] = i // ERROR "Proved IsInBounds$"
+ a[i] = i // ERROR "Proved IsInBounds$"
+ a[i+5] = i // ERROR "Proved IsInBounds$"
+ a[i+10] = i // ERROR "Proved IsInBounds$"
a[i+11] = i
}
return a
}
func k1(a [100]int) [100]int {
- for i := 10; i < 90; i++ { // ERROR "Induction variable with minimum 10 and increment 1$"
+ for i := 10; i < 90; i++ { // ERROR "Induction variable: limits \[10,90\), increment 1$"
useSlice(a[:i-11])
- useSlice(a[:i-10]) // ERROR "Found redundant \(IsSliceInBounds ind 100\), ind < 80$"
- useSlice(a[:i-5]) // ERROR "Found redundant \(IsSliceInBounds ind 100\), ind < 85$"
- useSlice(a[:i]) // ERROR "Found redundant \(IsSliceInBounds ind 100\), ind < 90$"
- useSlice(a[:i+5]) // ERROR "Found redundant \(IsSliceInBounds ind 100\), ind < 95$"
- useSlice(a[:i+10]) // ERROR "Found redundant \(IsSliceInBounds ind 100\), ind < 100$"
- useSlice(a[:i+11]) // ERROR "Found redundant \(IsSliceInBounds ind 100\), ind < 101$"
+ useSlice(a[:i-10]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[:i-5]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[:i]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[:i+5]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[:i+10]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[:i+11]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[:i+12])
}
return a
}
func k2(a [100]int) [100]int {
- for i := 10; i < 90; i++ { // ERROR "Induction variable with minimum 10 and increment 1$"
+ for i := 10; i < 90; i++ { // ERROR "Induction variable: limits \[10,90\), increment 1$"
useSlice(a[i-11:])
- useSlice(a[i-10:]) // ERROR "Found redundant \(IsSliceInBounds ind 100\), ind < 80$"
- useSlice(a[i-5:]) // ERROR "Found redundant \(IsSliceInBounds ind 100\), ind < 85$"
- useSlice(a[i:]) // ERROR "Found redundant \(IsSliceInBounds ind 100\), ind < 90$"
- useSlice(a[i+5:]) // ERROR "Found redundant \(IsSliceInBounds ind 100\), ind < 95$"
- useSlice(a[i+10:]) // ERROR "Found redundant \(IsSliceInBounds ind 100\), ind < 100$"
- useSlice(a[i+11:]) // ERROR "Found redundant \(IsSliceInBounds ind 100\), ind < 101$"
+ useSlice(a[i-10:]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[i-5:]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[i:]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[i+5:]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[i+10:]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[i+11:]) // ERROR "Proved IsSliceInBounds$"
+ useSlice(a[i+12:])
}
return a
}
func k3(a [100]int) [100]int {
- for i := -10; i < 90; i++ { // ERROR "Induction variable with minimum -10 and increment 1$"
- a[i+10] = i // ERROR "Found redundant \(IsInBounds ind 100\), ind < 100$"
+ for i := -10; i < 90; i++ { // ERROR "Induction variable: limits \[-10,90\), increment 1$"
+ a[i+9] = i
+ a[i+10] = i // ERROR "Proved IsInBounds$"
+ a[i+11] = i
+ }
+ return a
+}
+
+func k3neg(a [100]int) [100]int {
+ for i := 89; i > -11; i-- { // ERROR "Induction variable: limits \(-11,89\], increment 1$"
+ a[i+9] = i
+ a[i+10] = i // ERROR "Proved IsInBounds$"
+ a[i+11] = i
+ }
+ return a
+}
+
+func k3neg2(a [100]int) [100]int {
+ for i := 89; i >= -10; i-- { // ERROR "Induction variable: limits \[-10,89\], increment 1$"
+ a[i+9] = i
+ a[i+10] = i // ERROR "Proved IsInBounds$"
+ a[i+11] = i
}
return a
}
func k4(a [100]int) [100]int {
min := (-1) << 63
- for i := min; i < min+50; i++ { // ERROR "Induction variable with minimum -9223372036854775808 and increment 1$"
- a[i-min] = i // ERROR "Found redundant \(IsInBounds ind 100\), ind < 50$"
+ for i := min; i < min+50; i++ { // ERROR "Induction variable: limits \[-9223372036854775808,-9223372036854775758\), increment 1$"
+ a[i-min] = i // ERROR "Proved IsInBounds$"
}
return a
}
func k5(a [100]int) [100]int {
max := (1 << 63) - 1
- for i := max - 50; i < max; i++ { // ERROR "Induction variable with minimum 9223372036854775757 and increment 1$"
- a[i-max+50] = i // ERROR "Found redundant \(IsInBounds ind 100\), ind < 50$"
- a[i-(max-70)] = i // ERROR "Found redundant \(IsInBounds ind 100\), ind < 70$"
+ for i := max - 50; i < max; i++ { // ERROR "Induction variable: limits \[9223372036854775757,9223372036854775807\), increment 1"
+ a[i-max+50] = i // ERROR "Proved IsInBounds$"
+ a[i-(max-70)] = i // ERROR "Proved IsInBounds$"
}
return a
}
@@ -220,14 +274,21 @@ func nobce1() {
}
func nobce2(a string) {
- for i := int64(0); i < int64(len(a)); i++ { // ERROR "Induction variable with minimum 0 and increment 1$"
- useString(a[i:]) // ERROR "Found redundant IsSliceInBounds$"
+ for i := int64(0); i < int64(len(a)); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ useString(a[i:]) // ERROR "Proved IsSliceInBounds$"
+ }
+ for i := int64(0); i < int64(len(a))-31337; i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ useString(a[i:]) // ERROR "Proved IsSliceInBounds$"
+ }
+ for i := int64(0); i < int64(len(a))+int64(-1<<63); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ useString(a[i:]) // ERROR "Proved IsSliceInBounds$"
}
- for i := int64(0); i < int64(len(a))-31337; i++ { // ERROR "Induction variable with minimum 0 and increment 1$"
- useString(a[i:]) // ERROR "Found redundant IsSliceInBounds$"
+ j := int64(len(a)) - 123
+ for i := int64(0); i < j+123+int64(-1<<63); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ useString(a[i:]) // ERROR "Proved IsSliceInBounds$"
}
- for i := int64(0); i < int64(len(a))+int64(-1<<63); i++ { // ERROR "Induction variable with minimum 0 and increment 1$"
- // tests an overflow of StringLen-MinInt64
+ for i := int64(0); i < j+122+int64(-1<<63); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ // len(a)-123+122+MinInt overflows when len(a) == 0, so a bound check is needed here
useString(a[i:])
}
}
@@ -235,12 +296,22 @@ func nobce2(a string) {
func nobce3(a [100]int64) [100]int64 {
min := int64((-1) << 63)
max := int64((1 << 63) - 1)
- for i := min; i < max; i++ { // ERROR "Induction variable with minimum -9223372036854775808 and increment 1$"
+ for i := min; i < max; i++ { // ERROR "Induction variable: limits \[-9223372036854775808,9223372036854775807\), increment 1$"
a[i] = i
}
return a
}
+func issue26116a(a []int) {
+ // There is no induction variable here. The comparison is in the wrong direction.
+ for i := 3; i > 6; i++ {
+ a[i] = 0
+ }
+ for i := 7; i < 3; i-- {
+ a[i] = 1
+ }
+}
+
//go:noinline
func useString(a string) {
}
diff --git a/test/makemap.go b/test/makemap.go
index 60983c0d4..d19e6c344 100644
--- a/test/makemap.go
+++ b/test/makemap.go
@@ -18,6 +18,12 @@ func main() {
sink = make(T, -1) // ERROR "negative size argument in make.*"
sink = make(T, uint64(1<<63)) // ERROR "size argument too large in make.*"
+ // Test that errors are emitted at call sites, not const declarations
+ const x = -1
+ sink = make(T, x) // ERROR "negative size argument in make.*"
+ const y = uint64(1 << 63)
+ sink = make(T, y) // ERROR "size argument too large in make.*"
+
sink = make(T, 0.5) // ERROR "constant 0.5 truncated to integer"
sink = make(T, 1.0)
sink = make(T, float32(1.0)) // ERROR "non-integer size argument in make.*"
diff --git a/test/mapclear.go b/test/mapclear.go
new file mode 100644
index 000000000..a29f30da7
--- /dev/null
+++ b/test/mapclear.go
@@ -0,0 +1,89 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Ensure that range loops over maps with delete statements
+// have the requisite side-effects.
+
+package main
+
+import (
+ "fmt"
+ "os"
+)
+
+func checkcleared() {
+ m := make(map[byte]int)
+ m[1] = 1
+ m[2] = 2
+ for k := range m {
+ delete(m, k)
+ }
+ l := len(m)
+ if want := 0; l != want {
+ fmt.Printf("len after map clear = %d want %d\n", l, want)
+ os.Exit(1)
+ }
+
+ m[0] = 0 // To have non empty map and avoid internal map code fast paths.
+ n := 0
+ for range m {
+ n++
+ }
+ if want := 1; n != want {
+ fmt.Printf("number of keys found = %d want %d\n", n, want)
+ os.Exit(1)
+ }
+}
+
+func checkloopvars() {
+ k := 0
+ m := make(map[int]int)
+ m[42] = 0
+ for k = range m {
+ delete(m, k)
+ }
+ if want := 42; k != want {
+ fmt.Printf("var after range with side-effect = %d want %d\n", k, want)
+ os.Exit(1)
+ }
+}
+
+func checksideeffects() {
+ var x int
+ f := func() int {
+ x++
+ return 0
+ }
+ m := make(map[int]int)
+ m[0] = 0
+ m[1] = 1
+ for k := range m {
+ delete(m, k+f())
+ }
+ if want := 2; x != want {
+ fmt.Printf("var after range with side-effect = %d want %d\n", x, want)
+ os.Exit(1)
+ }
+
+ var n int
+ m = make(map[int]int)
+ m[0] = 0
+ m[1] = 1
+ for k := range m {
+ delete(m, k)
+ n++
+ }
+ if want := 2; n != want {
+ fmt.Printf("counter for range with side-effect = %d want %d\n", n, want)
+ os.Exit(1)
+ }
+}
+
+func main() {
+ checkcleared()
+ checkloopvars()
+ checksideeffects()
+}
diff --git a/test/method7.go b/test/method7.go
index 72c88b377..15e123e85 100644
--- a/test/method7.go
+++ b/test/method7.go
@@ -45,10 +45,9 @@ func main() {
interface{ m1(string) }.m1(x, "d")
want += " m1(d)"
- // cannot link the call below - see #22444
- // g := struct{ T }.m2
- // g(struct{T}{})
- // want += " m2()"
+ g := struct{ T }.m2
+ g(struct{ T }{})
+ want += " m2()"
if got != want {
panic("got" + got + ", want" + want)
diff --git a/test/nilptr3.go b/test/nilptr3.go
index 9a96bb538..a22e60ef1 100644
--- a/test/nilptr3.go
+++ b/test/nilptr3.go
@@ -1,5 +1,7 @@
// errorcheck -0 -d=nil
+// +build !wasm
+
// Copyright 2013 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.
diff --git a/test/nilptr3_wasm.go b/test/nilptr3_wasm.go
new file mode 100644
index 000000000..9376d4209
--- /dev/null
+++ b/test/nilptr3_wasm.go
@@ -0,0 +1,270 @@
+// errorcheck -0 -d=nil
+
+// +build wasm
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that nil checks are removed.
+// Optimization is enabled.
+
+package p
+
+type Struct struct {
+ X int
+ Y float64
+}
+
+type BigStruct struct {
+ X int
+ Y float64
+ A [1 << 20]int
+ Z string
+}
+
+type Empty struct {
+}
+
+type Empty1 struct {
+ Empty
+}
+
+var (
+ intp *int
+ arrayp *[10]int
+ array0p *[0]int
+ bigarrayp *[1 << 26]int
+ structp *Struct
+ bigstructp *BigStruct
+ emptyp *Empty
+ empty1p *Empty1
+)
+
+func f1() {
+ _ = *intp // ERROR "generated nil check"
+
+ // This one should be removed but the block copy needs
+ // to be turned into its own pseudo-op in order to see
+ // the indirect.
+ _ = *arrayp // ERROR "generated nil check"
+
+ // 0-byte indirect doesn't suffice.
+ // we don't registerize globals, so there are no removed.* nil checks.
+ _ = *array0p // ERROR "generated nil check"
+ _ = *array0p // ERROR "removed nil check"
+
+ _ = *intp // ERROR "removed nil check"
+ _ = *arrayp // ERROR "removed nil check"
+ _ = *structp // ERROR "generated nil check"
+ _ = *emptyp // ERROR "generated nil check"
+ _ = *arrayp // ERROR "removed nil check"
+}
+
+func f2() {
+ var (
+ intp *int
+ arrayp *[10]int
+ array0p *[0]int
+ bigarrayp *[1 << 20]int
+ structp *Struct
+ bigstructp *BigStruct
+ emptyp *Empty
+ empty1p *Empty1
+ )
+
+ _ = *intp // ERROR "generated nil check"
+ _ = *arrayp // ERROR "generated nil check"
+ _ = *array0p // ERROR "generated nil check"
+ _ = *array0p // ERROR "removed.* nil check"
+ _ = *intp // ERROR "removed.* nil check"
+ _ = *arrayp // ERROR "removed.* nil check"
+ _ = *structp // ERROR "generated nil check"
+ _ = *emptyp // ERROR "generated nil check"
+ _ = *arrayp // ERROR "removed.* nil check"
+ _ = *bigarrayp // ERROR "generated nil check" ARM removed nil check before indirect!!
+ _ = *bigstructp // ERROR "generated nil check"
+ _ = *empty1p // ERROR "generated nil check"
+}
+
+func fx10k() *[10000]int
+
+var b bool
+
+func f3(x *[10000]int) {
+ // Using a huge type and huge offsets so the compiler
+ // does not expect the memory hardware to fault.
+ _ = x[9999] // ERROR "generated nil check"
+
+ for {
+ if x[9999] != 0 { // ERROR "removed nil check"
+ break
+ }
+ }
+
+ x = fx10k()
+ _ = x[9999] // ERROR "generated nil check"
+ if b {
+ _ = x[9999] // ERROR "removed.* nil check"
+ } else {
+ _ = x[9999] // ERROR "removed.* nil check"
+ }
+ _ = x[9999] // ERROR "removed nil check"
+
+ x = fx10k()
+ if b {
+ _ = x[9999] // ERROR "generated nil check"
+ } else {
+ _ = x[9999] // ERROR "generated nil check"
+ }
+ _ = x[9999] // ERROR "generated nil check"
+
+ fx10k()
+ // This one is a bit redundant, if we figured out that
+ // x wasn't going to change across the function call.
+ // But it's a little complex to do and in practice doesn't
+ // matter enough.
+ _ = x[9999] // ERROR "removed nil check"
+}
+
+func f3a() {
+ x := fx10k()
+ y := fx10k()
+ z := fx10k()
+ _ = &x[9] // ERROR "generated nil check"
+ y = z
+ _ = &x[9] // ERROR "removed.* nil check"
+ x = y
+ _ = &x[9] // ERROR "generated nil check"
+}
+
+func f3b() {
+ x := fx10k()
+ y := fx10k()
+ _ = &x[9] // ERROR "generated nil check"
+ y = x
+ _ = &x[9] // ERROR "removed.* nil check"
+ x = y
+ _ = &x[9] // ERROR "removed.* nil check"
+}
+
+func fx10() *[10]int
+
+func f4(x *[10]int) {
+ // Most of these have no checks because a real memory reference follows,
+ // and the offset is small enough that if x is nil, the address will still be
+ // in the first unmapped page of memory.
+
+ _ = x[9] // ERROR "generated nil check" // bug: would like to remove this check (but nilcheck and load are in different blocks)
+
+ for {
+ if x[9] != 0 { // ERROR "removed nil check"
+ break
+ }
+ }
+
+ x = fx10()
+ _ = x[9] // ERROR "generated nil check" // bug would like to remove before indirect
+ if b {
+ _ = x[9] // ERROR "removed nil check"
+ } else {
+ _ = x[9] // ERROR "removed nil check"
+ }
+ _ = x[9] // ERROR "removed nil check"
+
+ x = fx10()
+ if b {
+ _ = x[9] // ERROR "generated nil check" // bug would like to remove before indirect
+ } else {
+ _ = &x[9] // ERROR "generated nil check"
+ }
+ _ = x[9] // ERROR "generated nil check" // bug would like to remove before indirect
+
+ fx10()
+ _ = x[9] // ERROR "removed nil check"
+
+ x = fx10()
+ y := fx10()
+ _ = &x[9] // ERROR "generated nil check"
+ y = x
+ _ = &x[9] // ERROR "removed[a-z ]* nil check"
+ x = y
+ _ = &x[9] // ERROR "removed[a-z ]* nil check"
+}
+
+func f5(p *float32, q *float64, r *float32, s *float64) float64 {
+ x := float64(*p) // ERROR "generated nil check"
+ y := *q // ERROR "generated nil check"
+ *r = 7 // ERROR "generated nil check"
+ *s = 9 // ERROR "generated nil check"
+ return x + y
+}
+
+type T [29]byte
+
+func f6(p, q *T) {
+ x := *p // ERROR "generated nil check"
+ *q = x // ERROR "generated nil check"
+}
+
+func m1(m map[int][80]byte) byte {
+ v := m[3] // ERROR "removed nil check"
+ return v[5]
+}
+func m2(m map[int][800]byte) byte {
+ v := m[3] // ERROR "removed nil check"
+ return v[5]
+}
+func m3(m map[int][80]byte) (byte, bool) {
+ v, ok := m[3] // ERROR "removed nil check"
+ return v[5], ok
+}
+func m4(m map[int][800]byte) (byte, bool) {
+ v, ok := m[3] // ERROR "removed nil check"
+ return v[5], ok
+}
+func p1() byte {
+ p := new([100]byte)
+ return p[5] // ERROR "removed nil check"
+}
+
+// make sure not to do nil check for access of PAUTOHEAP
+//go:noinline
+func (p *Struct) m() {}
+func c1() {
+ var x Struct
+ func() { x.m() }() // ERROR "removed nil check"
+}
+
+type SS struct {
+ x byte
+}
+
+type TT struct {
+ SS
+}
+
+func f(t *TT) *byte {
+ // See issue 17242.
+ s := &t.SS // ERROR "removed nil check"
+ return &s.x // ERROR "generated nil check"
+}
+
+// make sure not to do nil check for newobject
+func f7() (*Struct, float64) {
+ t := new(Struct)
+ p := &t.Y // ERROR "removed nil check"
+ return t, *p // ERROR "removed nil check"
+}
+
+// make sure to remove nil check for memory move (issue #18003)
+func f8(t *[8]int) [8]int {
+ return *t // ERROR "generated nil check"
+}
+
+func f9() []int {
+ x := new([1]int)
+ x[0] = 1 // ERROR "removed nil check"
+ y := x[:] // ERROR "removed nil check"
+ return y
+}
diff --git a/test/nosplit.go b/test/nosplit.go
index e6cecebde..e6cd04e56 100644
--- a/test/nosplit.go
+++ b/test/nosplit.go
@@ -1,4 +1,4 @@
-// +build !nacl
+// +build !nacl,!js
// run
// Copyright 2014 The Go Authors. All rights reserved.
diff --git a/test/peano.go b/test/peano.go
index 745f5153f..1102a9724 100644
--- a/test/peano.go
+++ b/test/peano.go
@@ -9,6 +9,8 @@
package main
+import "runtime"
+
type Number *Number
// -------------------------------------
@@ -116,7 +118,11 @@ var results = [...]int{
}
func main() {
- for i := 0; i <= 9; i++ {
+ max := 9
+ if runtime.GOARCH == "wasm" {
+ max = 7 // stack size is limited
+ }
+ for i := 0; i <= max; i++ {
if f := count(fact(gen(i))); f != results[i] {
println("FAIL:", i, "!:", f, "!=", results[i])
panic(0)
diff --git a/test/print.go b/test/print.go
index b7f3db0a4..7718c735e 100644
--- a/test/print.go
+++ b/test/print.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/printbig.go b/test/printbig.go
index 5693c58d4..9e08c39ad 100644
--- a/test/printbig.go
+++ b/test/printbig.go
@@ -1,4 +1,4 @@
-// cmpout
+// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/prove.go b/test/prove.go
index e89ab3f8d..45cee9e8b 100644
--- a/test/prove.go
+++ b/test/prove.go
@@ -11,11 +11,11 @@ import "math"
func f0(a []int) int {
a[0] = 1
- a[0] = 1 // ERROR "Proved boolean IsInBounds$"
+ a[0] = 1 // ERROR "Proved IsInBounds$"
a[6] = 1
- a[6] = 1 // ERROR "Proved boolean IsInBounds$"
+ a[6] = 1 // ERROR "Proved IsInBounds$"
+ a[5] = 1 // ERROR "Proved IsInBounds$"
a[5] = 1 // ERROR "Proved IsInBounds$"
- a[5] = 1 // ERROR "Proved boolean IsInBounds$"
return 13
}
@@ -23,27 +23,27 @@ func f1(a []int) int {
if len(a) <= 5 {
return 18
}
- a[0] = 1 // ERROR "Proved non-negative bounds IsInBounds$"
- a[0] = 1 // ERROR "Proved boolean IsInBounds$"
+ a[0] = 1 // ERROR "Proved IsInBounds$"
+ a[0] = 1 // ERROR "Proved IsInBounds$"
a[6] = 1
- a[6] = 1 // ERROR "Proved boolean IsInBounds$"
+ a[6] = 1 // ERROR "Proved IsInBounds$"
+ a[5] = 1 // ERROR "Proved IsInBounds$"
a[5] = 1 // ERROR "Proved IsInBounds$"
- a[5] = 1 // ERROR "Proved boolean IsInBounds$"
return 26
}
func f1b(a []int, i int, j uint) int {
if i >= 0 && i < len(a) {
- return a[i] // ERROR "Proved non-negative bounds IsInBounds$"
+ return a[i] // ERROR "Proved IsInBounds$"
}
if i >= 10 && i < len(a) {
- return a[i] // ERROR "Proved non-negative bounds IsInBounds$"
+ return a[i] // ERROR "Proved IsInBounds$"
}
if i >= 10 && i < len(a) {
- return a[i] // ERROR "Proved non-negative bounds IsInBounds$"
+ return a[i] // ERROR "Proved IsInBounds$"
}
- if i >= 10 && i < len(a) { // todo: handle this case
- return a[i-10]
+ if i >= 10 && i < len(a) {
+ return a[i-10] // ERROR "Proved IsInBounds$"
}
if j < uint(len(a)) {
return a[j] // ERROR "Proved IsInBounds$"
@@ -62,9 +62,9 @@ func f1c(a []int, i int64) int {
}
func f2(a []int) int {
- for i := range a {
+ for i := range a { // ERROR "Induction variable: limits \[0,\?\), increment 1"
a[i+1] = i
- a[i+1] = i // ERROR "Proved boolean IsInBounds$"
+ a[i+1] = i // ERROR "Proved IsInBounds$"
}
return 34
}
@@ -84,15 +84,14 @@ func f4a(a, b, c int) int {
if a > b { // ERROR "Disproved Greater64$"
return 50
}
- if a < b { // ERROR "Proved boolean Less64$"
+ if a < b { // ERROR "Proved Less64$"
return 53
}
- if a == b { // ERROR "Disproved boolean Eq64$"
+ // We can't get to this point and prove knows that, so
+ // there's no message for the next (obvious) branch.
+ if a != a {
return 56
}
- if a > b { // ERROR "Disproved boolean Greater64$"
- return 59
- }
return 61
}
return 63
@@ -127,8 +126,8 @@ func f4c(a, b, c int) int {
func f4d(a, b, c int) int {
if a < b {
if a < c {
- if a < b { // ERROR "Proved boolean Less64$"
- if a < c { // ERROR "Proved boolean Less64$"
+ if a < b { // ERROR "Proved Less64$"
+ if a < c { // ERROR "Proved Less64$"
return 87
}
return 89
@@ -218,8 +217,8 @@ func f6e(a uint8) int {
func f7(a []int, b int) int {
if b < len(a) {
a[b] = 3
- if b < len(a) { // ERROR "Proved boolean Less64$"
- a[b] = 5 // ERROR "Proved boolean IsInBounds$"
+ if b < len(a) { // ERROR "Proved Less64$"
+ a[b] = 5 // ERROR "Proved IsInBounds$"
}
}
return 161
@@ -242,7 +241,7 @@ func f9(a, b bool) int {
if a {
return 1
}
- if a || b { // ERROR "Disproved boolean Arg$"
+ if a || b { // ERROR "Disproved Arg$"
return 2
}
return 3
@@ -260,22 +259,22 @@ func f10(a string) int {
func f11a(a []int, i int) {
useInt(a[i])
- useInt(a[i]) // ERROR "Proved boolean IsInBounds$"
+ useInt(a[i]) // ERROR "Proved IsInBounds$"
}
func f11b(a []int, i int) {
useSlice(a[i:])
- useSlice(a[i:]) // ERROR "Proved boolean IsSliceInBounds$"
+ useSlice(a[i:]) // ERROR "Proved IsSliceInBounds$"
}
func f11c(a []int, i int) {
useSlice(a[:i])
- useSlice(a[:i]) // ERROR "Proved boolean IsSliceInBounds$"
+ useSlice(a[:i]) // ERROR "Proved IsSliceInBounds$"
}
func f11d(a []int, i int) {
useInt(a[2*i+7])
- useInt(a[2*i+7]) // ERROR "Proved boolean IsInBounds$"
+ useInt(a[2*i+7]) // ERROR "Proved IsInBounds$"
}
func f12(a []int, b int) {
@@ -305,7 +304,7 @@ func f13a(a, b, c int, x bool) int {
}
}
if x {
- if a > 12 { // ERROR "Proved boolean Greater64$"
+ if a > 12 { // ERROR "Proved Greater64$"
return 5
}
}
@@ -327,7 +326,7 @@ func f13b(a int, x bool) int {
}
}
if x {
- if a == -9 { // ERROR "Proved boolean Eq64$"
+ if a == -9 { // ERROR "Proved Eq64$"
return 9
}
}
@@ -349,7 +348,7 @@ func f13b(a int, x bool) int {
func f13c(a int, x bool) int {
if a < 90 {
if x {
- if a < 90 { // ERROR "Proved boolean Less64$"
+ if a < 90 { // ERROR "Proved Less64$"
return 13
}
}
@@ -398,8 +397,7 @@ func f13e(a int) int {
func f13f(a int64) int64 {
if a > math.MaxInt64 {
- // Unreachable, but prove doesn't know that.
- if a == 0 {
+ if a == 0 { // ERROR "Disproved Eq64$"
return 1
}
}
@@ -450,7 +448,7 @@ func f14(p, q *int, a []int) {
j := *q
i2 := *p
useInt(a[i1+j])
- useInt(a[i2+j]) // ERROR "Proved boolean IsInBounds$"
+ useInt(a[i2+j]) // ERROR "Proved IsInBounds$"
}
func f15(s []int, x int) {
@@ -460,11 +458,238 @@ func f15(s []int, x int) {
func f16(s []int) []int {
if len(s) >= 10 {
- return s[:10] // ERROR "Proved non-negative bounds IsSliceInBounds$"
+ return s[:10] // ERROR "Proved IsSliceInBounds$"
}
return nil
}
+func f17(b []int) {
+ for i := 0; i < len(b); i++ { // ERROR "Induction variable: limits \[0,\?\), increment 1"
+ // This tests for i <= cap, which we can only prove
+ // using the derived relation between len and cap.
+ // This depends on finding the contradiction, since we
+ // don't query this condition directly.
+ useSlice(b[:i]) // ERROR "Proved IsSliceInBounds$"
+ }
+}
+
+func f18(b []int, x int, y uint) {
+ _ = b[x]
+ _ = b[y]
+
+ if x > len(b) { // ERROR "Disproved Greater64$"
+ return
+ }
+ if y > uint(len(b)) { // ERROR "Disproved Greater64U$"
+ return
+ }
+ if int(y) > len(b) { // ERROR "Disproved Greater64$"
+ return
+ }
+}
+
+func sm1(b []int, x int) {
+ // Test constant argument to slicemask.
+ useSlice(b[2:8]) // ERROR "Proved slicemask not needed$"
+ // Test non-constant argument with known limits.
+ if cap(b) > 10 {
+ useSlice(b[2:]) // ERROR "Proved slicemask not needed$"
+ }
+}
+
+func lim1(x, y, z int) {
+ // Test relations between signed and unsigned limits.
+ if x > 5 {
+ if uint(x) > 5 { // ERROR "Proved Greater64U$"
+ return
+ }
+ }
+ if y >= 0 && y < 4 {
+ if uint(y) > 4 { // ERROR "Disproved Greater64U$"
+ return
+ }
+ if uint(y) < 5 { // ERROR "Proved Less64U$"
+ return
+ }
+ }
+ if z < 4 {
+ if uint(z) > 4 { // Not provable without disjunctions.
+ return
+ }
+ }
+}
+
+// fence1–4 correspond to the four fence-post implications.
+
+func fence1(b []int, x, y int) {
+ // Test proofs that rely on fence-post implications.
+ if x+1 > y {
+ if x < y { // ERROR "Disproved Less64$"
+ return
+ }
+ }
+ if len(b) < cap(b) {
+ // This eliminates the growslice path.
+ b = append(b, 1) // ERROR "Disproved Greater64$"
+ }
+}
+
+func fence2(x, y int) {
+ if x-1 < y {
+ if x > y { // ERROR "Disproved Greater64$"
+ return
+ }
+ }
+}
+
+func fence3(b []int, x, y int64) {
+ if x-1 >= y {
+ if x <= y { // Can't prove because x may have wrapped.
+ return
+ }
+ }
+
+ if x != math.MinInt64 && x-1 >= y {
+ if x <= y { // ERROR "Disproved Leq64$"
+ return
+ }
+ }
+
+ if n := len(b); n > 0 {
+ b[n-1] = 0 // ERROR "Proved IsInBounds$"
+ }
+}
+
+func fence4(x, y int64) {
+ if x >= y+1 {
+ if x <= y {
+ return
+ }
+ }
+ if y != math.MaxInt64 && x >= y+1 {
+ if x <= y { // ERROR "Disproved Leq64$"
+ return
+ }
+ }
+}
+
+// Check transitive relations
+func trans1(x, y int64) {
+ if x > 5 {
+ if y > x {
+ if y > 2 { // ERROR "Proved Greater64"
+ return
+ }
+ } else if y == x {
+ if y > 5 { // ERROR "Proved Greater64"
+ return
+ }
+ }
+ }
+ if x >= 10 {
+ if y > x {
+ if y > 10 { // ERROR "Proved Greater64"
+ return
+ }
+ }
+ }
+}
+
+func trans2(a, b []int, i int) {
+ if len(a) != len(b) {
+ return
+ }
+
+ _ = a[i]
+ _ = b[i] // ERROR "Proved IsInBounds$"
+}
+
+func trans3(a, b []int, i int) {
+ if len(a) > len(b) {
+ return
+ }
+
+ _ = a[i]
+ _ = b[i] // ERROR "Proved IsInBounds$"
+}
+
+// Derived from nat.cmp
+func natcmp(x, y []uint) (r int) {
+ m := len(x)
+ n := len(y)
+ if m != n || m == 0 {
+ return
+ }
+
+ i := m - 1
+ for i > 0 && // ERROR "Induction variable: limits \(0,\?\], increment 1"
+ x[i] == // ERROR "Proved IsInBounds$"
+ y[i] { // ERROR "Proved IsInBounds$"
+ i--
+ }
+
+ switch {
+ case x[i] < // todo, cannot prove this because it's dominated by i<=0 || x[i]==y[i]
+ y[i]: // ERROR "Proved IsInBounds$"
+ r = -1
+ case x[i] > // ERROR "Proved IsInBounds$"
+ y[i]: // ERROR "Proved IsInBounds$"
+ r = 1
+ }
+ return
+}
+
+func suffix(s, suffix string) bool {
+ // todo, we're still not able to drop the bound check here in the general case
+ return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
+}
+
+func constsuffix(s string) bool {
+ return suffix(s, "abc") // ERROR "Proved IsSliceInBounds$"
+}
+
+// oforuntil tests the pattern created by OFORUNTIL blocks. These are
+// handled by addLocalInductiveFacts rather than findIndVar.
+func oforuntil(b []int) {
+ i := 0
+ if len(b) > i {
+ top:
+ println(b[i]) // ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$"
+ i++
+ if i < len(b) {
+ goto top
+ }
+ }
+}
+
+// The range tests below test the index variable of range loops.
+
+// range1 compiles to the "efficiently indexable" form of a range loop.
+func range1(b []int) {
+ for i, v := range b { // ERROR "Induction variable: limits \[0,\?\), increment 1$"
+ b[i] = v + 1 // ERROR "Proved IsInBounds$"
+ if i < len(b) { // ERROR "Proved Less64$"
+ println("x")
+ }
+ if i >= 0 { // ERROR "Proved Geq64$"
+ println("x")
+ }
+ }
+}
+
+// range2 elements are larger, so they use the general form of a range loop.
+func range2(b [][32]int) {
+ for i, v := range b {
+ b[i][0] = v[0] + 1 // ERROR "Induction variable: limits \[0,\?\), increment 1$" "Proved IsInBounds$"
+ if i < len(b) { // ERROR "Proved Less64$"
+ println("x")
+ }
+ if i >= 0 { // ERROR "Proved Geq64"
+ println("x")
+ }
+ }
+}
+
//go:noinline
func useInt(a int) {
}
diff --git a/test/retjmp.dir/a.s b/test/retjmp.dir/a.s
new file mode 100644
index 000000000..c67a06638
--- /dev/null
+++ b/test/retjmp.dir/a.s
@@ -0,0 +1,12 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+TEXT ·f(SB), 4, $8-0
+ CALL ·f1(SB)
+ RET ·f2(SB)
+ CALL ·unreachable(SB)
+
+TEXT ·leaf(SB), 4, $0-0
+ RET ·f3(SB)
+ JMP ·unreachable(SB)
diff --git a/test/retjmp.dir/main.go b/test/retjmp.dir/main.go
new file mode 100644
index 000000000..cb4bd018b
--- /dev/null
+++ b/test/retjmp.dir/main.go
@@ -0,0 +1,32 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func f()
+func leaf()
+
+var f1called, f2called, f3called bool
+
+func main() {
+ f()
+ if !f1called {
+ panic("f1 not called")
+ }
+ if !f2called {
+ panic("f2 not called")
+ }
+ leaf()
+ if !f3called {
+ panic("f3 not called")
+ }
+}
+
+func f1() { f1called = true }
+func f2() { f2called = true }
+func f3() { f3called = true }
+
+func unreachable() {
+ panic("unreachable function called")
+}
diff --git a/test/retjmp.go b/test/retjmp.go
new file mode 100644
index 000000000..778d90362
--- /dev/null
+++ b/test/retjmp.go
@@ -0,0 +1,9 @@
+// buildrundir
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that return jump works correctly in assembly code.
+
+package ignored
diff --git a/test/run.go b/test/run.go
index 22ec7576f..99ef79feb 100644
--- a/test/run.go
+++ b/test/run.go
@@ -5,9 +5,6 @@
// license that can be found in the LICENSE file.
// Run runs tests in the test directory.
-//
-// TODO(bradfitz): docs of some sort, once we figure out how we're changing
-// headers of files
package main
import (
@@ -52,7 +49,7 @@ var (
// dirs are the directories to look for *.go files in.
// TODO(bradfitz): just use all directories?
- dirs = []string{".", "ken", "chan", "interface", "syntax", "dwarf", "fixedbugs"}
+ dirs = []string{".", "ken", "chan", "interface", "syntax", "dwarf", "fixedbugs", "codegen"}
// ratec controls the max number of tests running at a time.
ratec chan bool
@@ -167,6 +164,22 @@ func toolPath(name string) string {
return p
}
+// goTool reports the path of the go tool to use to run the tests.
+// If possible, use the same Go used to run run.go, otherwise
+// fallback to the go version found in the PATH.
+func goTool() string {
+ var exeSuffix string
+ if runtime.GOOS == "windows" {
+ exeSuffix = ".exe"
+ }
+ path := filepath.Join(runtime.GOROOT(), "bin", "go"+exeSuffix)
+ if _, err := os.Stat(path); err == nil {
+ return path
+ }
+ // Just run "go" from PATH
+ return "go"
+}
+
func shardMatch(name string) bool {
if *shards == 0 {
return true
@@ -194,7 +207,7 @@ func goFiles(dir string) []string {
type runCmd func(...string) ([]byte, error)
func compileFile(runcmd runCmd, longname string, flags []string) (out []byte, err error) {
- cmd := []string{"go", "tool", "compile", "-e"}
+ cmd := []string{goTool(), "tool", "compile", "-e"}
cmd = append(cmd, flags...)
if *linkshared {
cmd = append(cmd, "-dynlink", "-installsuffix=dynlink")
@@ -203,8 +216,12 @@ func compileFile(runcmd runCmd, longname string, flags []string) (out []byte, er
return runcmd(cmd...)
}
-func compileInDir(runcmd runCmd, dir string, flags []string, names ...string) (out []byte, err error) {
- cmd := []string{"go", "tool", "compile", "-e", "-D", ".", "-I", "."}
+func compileInDir(runcmd runCmd, dir string, flags []string, localImports bool, names ...string) (out []byte, err error) {
+ cmd := []string{goTool(), "tool", "compile", "-e"}
+ if localImports {
+ // Set relative path for local imports and import search path to current dir.
+ cmd = append(cmd, "-D", ".", "-I", ".")
+ }
cmd = append(cmd, flags...)
if *linkshared {
cmd = append(cmd, "-dynlink", "-installsuffix=dynlink")
@@ -217,7 +234,7 @@ func compileInDir(runcmd runCmd, dir string, flags []string, names ...string) (o
func linkFile(runcmd runCmd, goname string) (err error) {
pfile := strings.Replace(goname, ".go", ".o", -1)
- cmd := []string{"go", "tool", "link", "-w", "-o", "a.exe", "-L", "."}
+ cmd := []string{goTool(), "tool", "link", "-w", "-o", "a.exe", "-L", "."}
if *linkshared {
cmd = append(cmd, "-linkshared", "-installsuffix=dynlink")
}
@@ -476,6 +493,7 @@ func (t *test) run() {
wantError := false
wantAuto := false
singlefilepkgs := false
+ localImports := true
f := strings.Fields(action)
if len(f) > 0 {
action = f[0]
@@ -484,11 +502,7 @@ func (t *test) run() {
// TODO: Clean up/simplify this switch statement.
switch action {
- case "rundircmpout":
- action = "rundir"
- case "cmpout":
- action = "run" // the run case already looks for <dir>/<test>.out files
- case "compile", "compiledir", "build", "builddir", "run", "buildrun", "runoutput", "rundir":
+ case "compile", "compiledir", "build", "builddir", "buildrundir", "run", "buildrun", "runoutput", "rundir", "asmcheck":
// nothing to do
case "errorcheckandrundir":
wantError = false // should be no error if also will run
@@ -511,10 +525,18 @@ func (t *test) run() {
// collect flags
for len(args) > 0 && strings.HasPrefix(args[0], "-") {
switch args[0] {
+ case "-1":
+ wantError = true
case "-0":
wantError = false
case "-s":
singlefilepkgs = true
+ case "-n":
+ // Do not set relative path for local imports to current dir,
+ // e.g. do not pass -D . -I . to the compiler.
+ // Used in fixedbugs/bug345.go to allow compilation and import of local pkg.
+ // See golang.org/issue/25635
+ localImports = false
case "-t": // timeout in seconds
args = args[1:]
var err error
@@ -593,9 +615,38 @@ func (t *test) run() {
default:
t.err = fmt.Errorf("unimplemented action %q", action)
+ case "asmcheck":
+ // Compile Go file and match the generated assembly
+ // against a set of regexps in comments.
+ ops := t.wantedAsmOpcodes(long)
+ for _, env := range ops.Envs() {
+ cmdline := []string{"build", "-gcflags", "-S"}
+ cmdline = append(cmdline, flags...)
+ cmdline = append(cmdline, long)
+ cmd := exec.Command(goTool(), cmdline...)
+ cmd.Env = append(os.Environ(), env.Environ()...)
+
+ var buf bytes.Buffer
+ cmd.Stdout, cmd.Stderr = &buf, &buf
+ if err := cmd.Run(); err != nil {
+ fmt.Println(env, "\n", cmd.Stderr)
+ t.err = err
+ return
+ }
+
+ t.err = t.asmCheck(buf.String(), long, env, ops[env])
+ if t.err != nil {
+ return
+ }
+ }
+ return
+
case "errorcheck":
+ // Compile Go file.
+ // Fail if wantError is true and compilation was successful and vice versa.
+ // Match errors produced by gc against errors in comments.
// TODO(gri) remove need for -C (disable printing of columns in error messages)
- cmdline := []string{"go", "tool", "compile", "-C", "-e", "-o", "a.o"}
+ cmdline := []string{goTool(), "tool", "compile", "-C", "-e", "-o", "a.o"}
// No need to add -dynlink even if linkshared if we're just checking for errors...
cmdline = append(cmdline, flags...)
cmdline = append(cmdline, long)
@@ -618,10 +669,11 @@ func (t *test) run() {
return
case "compile":
+ // Compile Go file.
_, t.err = compileFile(runcmd, long, flags)
case "compiledir":
- // Compile all files in the directory in lexicographic order.
+ // Compile all files in the directory as packages in lexicographic order.
longdir := filepath.Join(cwd, t.goDirName())
pkgs, err := goDirPackages(longdir, singlefilepkgs)
if err != nil {
@@ -629,24 +681,31 @@ func (t *test) run() {
return
}
for _, gofiles := range pkgs {
- _, t.err = compileInDir(runcmd, longdir, flags, gofiles...)
+ _, t.err = compileInDir(runcmd, longdir, flags, localImports, gofiles...)
if t.err != nil {
return
}
}
case "errorcheckdir", "errorcheckandrundir":
- // errorcheck all files in lexicographic order
- // useful for finding importing errors
+ // Compile and errorCheck all files in the directory as packages in lexicographic order.
+ // If errorcheckdir and wantError, compilation of the last package must fail.
+ // If errorcheckandrundir and wantError, compilation of the package prior the last must fail.
longdir := filepath.Join(cwd, t.goDirName())
pkgs, err := goDirPackages(longdir, singlefilepkgs)
if err != nil {
t.err = err
return
}
+ errPkg := len(pkgs) - 1
+ if wantError && action == "errorcheckandrundir" {
+ // The last pkg should compiled successfully and will be run in next case.
+ // Preceding pkg must return an error from compileInDir.
+ errPkg--
+ }
for i, gofiles := range pkgs {
- out, err := compileInDir(runcmd, longdir, flags, gofiles...)
- if i == len(pkgs)-1 {
+ out, err := compileInDir(runcmd, longdir, flags, localImports, gofiles...)
+ if i == errPkg {
if wantError && err == nil {
t.err = fmt.Errorf("compilation succeeded unexpectedly\n%s", out)
return
@@ -673,8 +732,10 @@ func (t *test) run() {
fallthrough
case "rundir":
- // Compile all files in the directory in lexicographic order.
- // then link as if the last file is the main package and run it
+ // Compile all files in the directory as packages in lexicographic order.
+ // In case of errorcheckandrundir, ignore failed compilation of the package before the last.
+ // Link as if the last file is the main package, run it.
+ // Verify the expected output.
longdir := filepath.Join(cwd, t.goDirName())
pkgs, err := goDirPackages(longdir, singlefilepkgs)
if err != nil {
@@ -682,8 +743,10 @@ func (t *test) run() {
return
}
for i, gofiles := range pkgs {
- _, err := compileInDir(runcmd, longdir, flags, gofiles...)
- if err != nil {
+ _, err := compileInDir(runcmd, longdir, flags, localImports, gofiles...)
+ // Allow this package compilation fail based on conditions below;
+ // its errors were checked in previous case.
+ if err != nil && !(wantError && action == "errorcheckandrundir" && i == len(pkgs)-2) {
t.err = err
return
}
@@ -709,14 +772,15 @@ func (t *test) run() {
}
case "build":
- _, err := runcmd("go", "build", goGcflags(), "-o", "a.exe", long)
+ // Build Go file.
+ _, err := runcmd(goTool(), "build", goGcflags(), "-o", "a.exe", long)
if err != nil {
t.err = err
}
- case "builddir":
+ case "builddir", "buildrundir":
// Build an executable from all the .go and .s files in a subdirectory.
- useTmp = true
+ // Run it and verify its output in the buildrundir case.
longdir := filepath.Join(cwd, t.goDirName())
files, dirErr := ioutil.ReadDir(longdir)
if dirErr != nil {
@@ -735,7 +799,7 @@ func (t *test) run() {
}
var objs []string
- cmd := []string{"go", "tool", "compile", "-e", "-D", ".", "-I", ".", "-o", "go.o"}
+ cmd := []string{goTool(), "tool", "compile", "-e", "-D", ".", "-I", ".", "-o", "go.o"}
if len(asms) > 0 {
cmd = append(cmd, "-asmhdr", "go_asm.h")
}
@@ -749,7 +813,7 @@ func (t *test) run() {
}
objs = append(objs, "go.o")
if len(asms) > 0 {
- cmd = []string{"go", "tool", "asm", "-e", "-I", ".", "-o", "asm.o"}
+ cmd = []string{goTool(), "tool", "asm", "-e", "-I", ".", "-o", "asm.o"}
for _, file := range asms {
cmd = append(cmd, filepath.Join(longdir, file.Name()))
}
@@ -760,24 +824,36 @@ func (t *test) run() {
}
objs = append(objs, "asm.o")
}
- cmd = []string{"go", "tool", "pack", "c", "all.a"}
+ cmd = []string{goTool(), "tool", "pack", "c", "all.a"}
cmd = append(cmd, objs...)
_, err = runcmd(cmd...)
if err != nil {
t.err = err
break
}
- cmd = []string{"go", "tool", "link", "all.a"}
+ cmd = []string{goTool(), "tool", "link", "-o", "a.exe", "all.a"}
_, err = runcmd(cmd...)
if err != nil {
t.err = err
break
}
+ if action == "buildrundir" {
+ cmd = append(findExecCmd(), filepath.Join(t.tempDir, "a.exe"))
+ out, err := runcmd(cmd...)
+ if err != nil {
+ t.err = err
+ break
+ }
+ if strings.Replace(string(out), "\r\n", "\n", -1) != t.expectedOutput() {
+ t.err = fmt.Errorf("incorrect output\n%s", out)
+ }
+ }
- case "buildrun": // build binary, then run binary, instead of go run. Useful for timeout tests where failure mode is infinite loop.
+ case "buildrun":
+ // Build an executable from Go file, then run it, verify its output.
+ // Useful for timeout tests where failure mode is infinite loop.
// TODO: not supported on NaCl
- useTmp = true
- cmd := []string{"go", "build", goGcflags(), "-o", "a.exe"}
+ cmd := []string{goTool(), "build", goGcflags(), "-o", "a.exe"}
if *linkshared {
cmd = append(cmd, "-linkshared")
}
@@ -801,6 +877,9 @@ func (t *test) run() {
}
case "run":
+ // Run Go file if no special go command flags are provided;
+ // otherwise build an executable and run it.
+ // Verify the output.
useTmp = false
var out []byte
var err error
@@ -813,12 +892,12 @@ func (t *test) run() {
// Because we run lots of trivial test programs,
// the time adds up.
pkg := filepath.Join(t.tempDir, "pkg.a")
- if _, err := runcmd("go", "tool", "compile", "-o", pkg, t.goFileName()); err != nil {
+ if _, err := runcmd(goTool(), "tool", "compile", "-o", pkg, t.goFileName()); err != nil {
t.err = err
return
}
exe := filepath.Join(t.tempDir, "test.exe")
- cmd := []string{"go", "tool", "link", "-s", "-w"}
+ cmd := []string{goTool(), "tool", "link", "-s", "-w"}
cmd = append(cmd, "-o", exe, pkg)
if _, err := runcmd(cmd...); err != nil {
t.err = err
@@ -826,7 +905,7 @@ func (t *test) run() {
}
out, err = runcmd(append([]string{exe}, args...)...)
} else {
- cmd := []string{"go", "run", goGcflags()}
+ cmd := []string{goTool(), "run", goGcflags()}
if *linkshared {
cmd = append(cmd, "-linkshared")
}
@@ -843,12 +922,14 @@ func (t *test) run() {
}
case "runoutput":
+ // Run Go file and write its output into temporary Go file.
+ // Run generated Go file and verify its output.
rungatec <- true
defer func() {
<-rungatec
}()
useTmp = false
- cmd := []string{"go", "run", goGcflags()}
+ cmd := []string{goTool(), "run", goGcflags()}
if *linkshared {
cmd = append(cmd, "-linkshared")
}
@@ -863,7 +944,7 @@ func (t *test) run() {
t.err = fmt.Errorf("write tempfile:%s", err)
return
}
- cmd = []string{"go", "run", goGcflags()}
+ cmd = []string{goTool(), "run", goGcflags()}
if *linkshared {
cmd = append(cmd, "-linkshared")
}
@@ -878,8 +959,10 @@ func (t *test) run() {
}
case "errorcheckoutput":
+ // Run Go file and write its output into temporary Go file.
+ // Compile and errorCheck generated Go file.
useTmp = false
- cmd := []string{"go", "run", goGcflags()}
+ cmd := []string{goTool(), "run", goGcflags()}
if *linkshared {
cmd = append(cmd, "-linkshared")
}
@@ -895,7 +978,7 @@ func (t *test) run() {
t.err = fmt.Errorf("write tempfile:%s", err)
return
}
- cmdline := []string{"go", "tool", "compile", "-e", "-o", "a.o"}
+ cmdline := []string{goTool(), "tool", "compile", "-e", "-o", "a.o"}
cmdline = append(cmdline, flags...)
cmdline = append(cmdline, tfile)
out, err = runcmd(cmdline...)
@@ -973,6 +1056,17 @@ func splitOutput(out string, wantAuto bool) []string {
return res
}
+// errorCheck matches errors in outStr against comments in source files.
+// For each line of the source files which should generate an error,
+// there should be a comment of the form // ERROR "regexp".
+// If outStr has an error for a line which has no such comment,
+// this function will report an error.
+// Likewise if outStr does not have an error for a line which has a comment,
+// or if the error message does not match the <regexp>.
+// The <regexp> syntax is Perl but its best to stick to egrep.
+//
+// Sources files are supplied as fullshort slice.
+// It consists of pairs: full path to source file and it's base name.
func (t *test) errorCheck(outStr string, wantAuto bool, fullshort ...string) (err error) {
defer func() {
if *verbose && err != nil {
@@ -1115,7 +1209,7 @@ func (t *test) updateErrors(out, file string) {
return
}
// Polish.
- exec.Command("go", "fmt", file).CombinedOutput()
+ exec.Command(goTool(), "fmt", file).CombinedOutput()
}
// matchPrefix reports whether s is of the form ^(.*/)?prefix(:|[),
@@ -1226,6 +1320,264 @@ func (t *test) wantedErrors(file, short string) (errs []wantedError) {
return
}
+const (
+ // Regexp to match a single opcode check: optionally begin with "-" (to indicate
+ // a negative check), followed by a string literal enclosed in "" or ``. For "",
+ // backslashes must be handled.
+ reMatchCheck = `-?(?:\x60[^\x60]*\x60|"(?:[^"\\]|\\.)*")`
+)
+
+var (
+ // Regexp to split a line in code and comment, trimming spaces
+ rxAsmComment = regexp.MustCompile(`^\s*(.*?)\s*(?:\/\/\s*(.+)\s*)?$`)
+
+ // Regexp to extract an architecture check: architecture name, followed by semi-colon,
+ // followed by a comma-separated list of opcode checks.
+ rxAsmPlatform = regexp.MustCompile(`(\w+)(/\w+)?(/\w*)?:(` + reMatchCheck + `(?:,` + reMatchCheck + `)*)`)
+
+ // Regexp to extract a single opcoded check
+ rxAsmCheck = regexp.MustCompile(reMatchCheck)
+
+ // List of all architecture variants. Key is the GOARCH architecture,
+ // value[0] is the variant-changing environment variable, and values[1:]
+ // are the supported variants.
+ archVariants = map[string][]string{
+ "386": {"GO386", "387", "sse2"},
+ "amd64": {},
+ "arm": {"GOARM", "5", "6", "7"},
+ "arm64": {},
+ "mips": {"GOMIPS", "hardfloat", "softfloat"},
+ "mips64": {"GOMIPS64", "hardfloat", "softfloat"},
+ "ppc64": {},
+ "ppc64le": {},
+ "s390x": {},
+ }
+)
+
+// wantedAsmOpcode is a single asmcheck check
+type wantedAsmOpcode struct {
+ fileline string // original source file/line (eg: "/path/foo.go:45")
+ line int // original source line
+ opcode *regexp.Regexp // opcode check to be performed on assembly output
+ negative bool // true if the check is supposed to fail rather than pass
+ found bool // true if the opcode check matched at least one in the output
+}
+
+// A build environment triplet separated by slashes (eg: linux/386/sse2).
+// The third field can be empty if the arch does not support variants (eg: "plan9/amd64/")
+type buildEnv string
+
+// Environ returns the environment it represents in cmd.Environ() "key=val" format
+// For instance, "linux/386/sse2".Environ() returns {"GOOS=linux", "GOARCH=386", "GO386=sse2"}
+func (b buildEnv) Environ() []string {
+ fields := strings.Split(string(b), "/")
+ if len(fields) != 3 {
+ panic("invalid buildEnv string: " + string(b))
+ }
+ env := []string{"GOOS=" + fields[0], "GOARCH=" + fields[1]}
+ if fields[2] != "" {
+ env = append(env, archVariants[fields[1]][0]+"="+fields[2])
+ }
+ return env
+}
+
+// asmChecks represents all the asmcheck checks present in a test file
+// The outer map key is the build triplet in which the checks must be performed.
+// The inner map key represent the source file line ("filename.go:1234") at which the
+// checks must be performed.
+type asmChecks map[buildEnv]map[string][]wantedAsmOpcode
+
+// Envs returns all the buildEnv in which at least one check is present
+func (a asmChecks) Envs() []buildEnv {
+ var envs []buildEnv
+ for e := range a {
+ envs = append(envs, e)
+ }
+ sort.Slice(envs, func(i, j int) bool {
+ return string(envs[i]) < string(envs[j])
+ })
+ return envs
+}
+
+func (t *test) wantedAsmOpcodes(fn string) asmChecks {
+ ops := make(asmChecks)
+
+ comment := ""
+ src, _ := ioutil.ReadFile(fn)
+ for i, line := range strings.Split(string(src), "\n") {
+ matches := rxAsmComment.FindStringSubmatch(line)
+ code, cmt := matches[1], matches[2]
+
+ // Keep comments pending in the comment variable until
+ // we find a line that contains some code.
+ comment += " " + cmt
+ if code == "" {
+ continue
+ }
+
+ // Parse and extract any architecture check from comments,
+ // made by one architecture name and multiple checks.
+ lnum := fn + ":" + strconv.Itoa(i+1)
+ for _, ac := range rxAsmPlatform.FindAllStringSubmatch(comment, -1) {
+ archspec, allchecks := ac[1:4], ac[4]
+
+ var arch, subarch, os string
+ switch {
+ case archspec[2] != "": // 3 components: "linux/386/sse2"
+ os, arch, subarch = archspec[0], archspec[1][1:], archspec[2][1:]
+ case archspec[1] != "": // 2 components: "386/sse2"
+ os, arch, subarch = "linux", archspec[0], archspec[1][1:]
+ default: // 1 component: "386"
+ os, arch, subarch = "linux", archspec[0], ""
+ }
+
+ if _, ok := archVariants[arch]; !ok {
+ log.Fatalf("%s:%d: unsupported architecture: %v", t.goFileName(), i+1, arch)
+ }
+
+ // Create the build environments corresponding the above specifiers
+ envs := make([]buildEnv, 0, 4)
+ if subarch != "" {
+ envs = append(envs, buildEnv(os+"/"+arch+"/"+subarch))
+ } else {
+ subarchs := archVariants[arch]
+ if len(subarchs) == 0 {
+ envs = append(envs, buildEnv(os+"/"+arch+"/"))
+ } else {
+ for _, sa := range archVariants[arch][1:] {
+ envs = append(envs, buildEnv(os+"/"+arch+"/"+sa))
+ }
+ }
+ }
+
+ for _, m := range rxAsmCheck.FindAllString(allchecks, -1) {
+ negative := false
+ if m[0] == '-' {
+ negative = true
+ m = m[1:]
+ }
+
+ rxsrc, err := strconv.Unquote(m)
+ if err != nil {
+ log.Fatalf("%s:%d: error unquoting string: %v", t.goFileName(), i+1, err)
+ }
+
+ // Compile the checks as regular expressions. Notice that we
+ // consider checks as matching from the beginning of the actual
+ // assembler source (that is, what is left on each line of the
+ // compile -S output after we strip file/line info) to avoid
+ // trivial bugs such as "ADD" matching "FADD". This
+ // doesn't remove genericity: it's still possible to write
+ // something like "F?ADD", but we make common cases simpler
+ // to get right.
+ oprx, err := regexp.Compile("^" + rxsrc)
+ if err != nil {
+ log.Fatalf("%s:%d: %v", t.goFileName(), i+1, err)
+ }
+
+ for _, env := range envs {
+ if ops[env] == nil {
+ ops[env] = make(map[string][]wantedAsmOpcode)
+ }
+ ops[env][lnum] = append(ops[env][lnum], wantedAsmOpcode{
+ negative: negative,
+ fileline: lnum,
+ line: i + 1,
+ opcode: oprx,
+ })
+ }
+ }
+ }
+ comment = ""
+ }
+
+ return ops
+}
+
+func (t *test) asmCheck(outStr string, fn string, env buildEnv, fullops map[string][]wantedAsmOpcode) (err error) {
+ // The assembly output contains the concatenated dump of multiple functions.
+ // the first line of each function begins at column 0, while the rest is
+ // indented by a tabulation. These data structures help us index the
+ // output by function.
+ functionMarkers := make([]int, 1)
+ lineFuncMap := make(map[string]int)
+
+ lines := strings.Split(outStr, "\n")
+ rxLine := regexp.MustCompile(fmt.Sprintf(`\((%s:\d+)\)\s+(.*)`, regexp.QuoteMeta(fn)))
+
+ for nl, line := range lines {
+ // Check if this line begins a function
+ if len(line) > 0 && line[0] != '\t' {
+ functionMarkers = append(functionMarkers, nl)
+ }
+
+ // Search if this line contains a assembly opcode (which is prefixed by the
+ // original source file/line in parenthesis)
+ matches := rxLine.FindStringSubmatch(line)
+ if len(matches) == 0 {
+ continue
+ }
+ srcFileLine, asm := matches[1], matches[2]
+
+ // Associate the original file/line information to the current
+ // function in the output; it will be useful to dump it in case
+ // of error.
+ lineFuncMap[srcFileLine] = len(functionMarkers) - 1
+
+ // If there are opcode checks associated to this source file/line,
+ // run the checks.
+ if ops, found := fullops[srcFileLine]; found {
+ for i := range ops {
+ if !ops[i].found && ops[i].opcode.FindString(asm) != "" {
+ ops[i].found = true
+ }
+ }
+ }
+ }
+ functionMarkers = append(functionMarkers, len(lines))
+
+ var failed []wantedAsmOpcode
+ for _, ops := range fullops {
+ for _, o := range ops {
+ // There's a failure if a negative match was found,
+ // or a positive match was not found.
+ if o.negative == o.found {
+ failed = append(failed, o)
+ }
+ }
+ }
+ if len(failed) == 0 {
+ return
+ }
+
+ // At least one asmcheck failed; report them
+ sort.Slice(failed, func(i, j int) bool {
+ return failed[i].line < failed[j].line
+ })
+
+ lastFunction := -1
+ var errbuf bytes.Buffer
+ fmt.Fprintln(&errbuf)
+ for _, o := range failed {
+ // Dump the function in which this opcode check was supposed to
+ // pass but failed.
+ funcIdx := lineFuncMap[o.fileline]
+ if funcIdx != 0 && funcIdx != lastFunction {
+ funcLines := lines[functionMarkers[funcIdx]:functionMarkers[funcIdx+1]]
+ log.Println(strings.Join(funcLines, "\n"))
+ lastFunction = funcIdx // avoid printing same function twice
+ }
+
+ if o.negative {
+ fmt.Fprintf(&errbuf, "%s:%d: %s: wrong opcode found: %q\n", t.goFileName(), o.line, env, o.opcode.String())
+ } else {
+ fmt.Fprintf(&errbuf, "%s:%d: %s: opcode not found: %q\n", t.goFileName(), o.line, env, o.opcode.String())
+ }
+ }
+ err = errors.New(errbuf.String())
+ return
+}
+
// defaultRunOutputLimit returns the number of runoutput tests that
// can be executed in parallel.
func defaultRunOutputLimit() int {
diff --git a/test/sigchld.go b/test/sigchld.go
index 38437e552..3b4960640 100644
--- a/test/sigchld.go
+++ b/test/sigchld.go
@@ -1,5 +1,5 @@
// +build !plan9,!windows
-// cmpout
+// run
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
diff --git a/test/sinit_run.go b/test/sinit_run.go
index c9afd3b77..fdd19c492 100644
--- a/test/sinit_run.go
+++ b/test/sinit_run.go
@@ -1,4 +1,4 @@
-// +build !nacl
+// +build !nacl,!js
// run
// Copyright 2014 The Go Authors. All rights reserved.
diff --git a/test/sliceopt.go b/test/sliceopt.go
index eb24701f3..b8b947229 100644
--- a/test/sliceopt.go
+++ b/test/sliceopt.go
@@ -1,4 +1,4 @@
-// errorcheck -0 -d=append,slice,ssa/prove/debug=1
+// errorcheck -0 -d=append,slice
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
@@ -21,51 +21,12 @@ func a3(x *[]int, y int) {
*x = append(*x, y) // ERROR "append: len-only update$"
}
-// s1_if_false_then_anything
-func s1_if_false_then_anything(x **[]int, xs **string, i, j int) {
- z := (**x)[0:i]
- z = z[i : i+1]
- println(z) // if we get here, then we have proven that i==i+1 (this cannot happen, but the program is still being analyzed...)
-
- zs := (**xs)[0:i] // since i=i+1 is proven, i+1 is "in bounds", ha-ha
- zs = zs[i : i+1] // ERROR "Proved boolean IsSliceInBounds$"
- println(zs)
-}
-
func s1(x **[]int, xs **string, i, j int) {
var z []int
- z = (**x)[2:]
- z = (**x)[2:len(**x)] // ERROR "Proved boolean IsSliceInBounds$"
- z = (**x)[2:cap(**x)] // ERROR "Proved IsSliceInBounds$"
- z = (**x)[i:i] // -ERROR "Proved IsSliceInBounds"
- z = (**x)[1:i:i] // ERROR "Proved boolean IsSliceInBounds$"
- z = (**x)[i:j:0]
- z = (**x)[i:0:j] // ERROR "Disproved IsSliceInBounds$"
- z = (**x)[0:i:j] // ERROR "Proved boolean IsSliceInBounds$"
- z = (**x)[0:] // ERROR "slice: omit slice operation$"
- z = (**x)[2:8] // ERROR "Proved slicemask not needed$"
- println(z)
- z = (**x)[2:2]
- z = (**x)[0:i]
- z = (**x)[2:i:8] // ERROR "Disproved IsSliceInBounds$" "Proved IsSliceInBounds$"
- z = (**x)[i:2:i] // ERROR "Proved IsSliceInBounds$" "Proved boolean IsSliceInBounds$"
-
- z = z[0:i] // ERROR "Proved boolean IsSliceInBounds"
- z = z[0:i : i+1]
- z = z[i : i+1] // ERROR "Proved boolean IsSliceInBounds$"
-
+ z = (**x)[0:] // ERROR "slice: omit slice operation$"
println(z)
var zs string
- zs = (**xs)[2:]
- zs = (**xs)[2:len(**xs)] // ERROR "Proved IsSliceInBounds$" "Proved boolean IsSliceInBounds$"
- zs = (**xs)[i:i] // -ERROR "Proved boolean IsSliceInBounds"
- zs = (**xs)[0:] // ERROR "slice: omit slice operation$"
- zs = (**xs)[2:8]
- zs = (**xs)[2:2] // ERROR "Proved boolean IsSliceInBounds$"
- zs = (**xs)[0:i] // ERROR "Proved boolean IsSliceInBounds$"
-
- zs = zs[0:i] // See s1_if_false_then_anything above to explain the counterfactual bounds check result below
- zs = zs[i : i+1] // ERROR "Proved boolean IsSliceInBounds$"
+ zs = (**xs)[0:] // ERROR "slice: omit slice operation$"
println(zs)
}
diff --git a/test/strcopy.go b/test/strcopy.go
new file mode 100644
index 000000000..6d32baeec
--- /dev/null
+++ b/test/strcopy.go
@@ -0,0 +1,29 @@
+// run
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Test that string([]byte(string)) makes a copy and doesn't reduce to
+// nothing. (Issue 25834)
+
+package main
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+func main() {
+ var (
+ buf = make([]byte, 2<<10)
+ large = string(buf)
+ sub = large[10:12]
+ subcopy = string([]byte(sub))
+ subh = *(*reflect.StringHeader)(unsafe.Pointer(&sub))
+ subcopyh = *(*reflect.StringHeader)(unsafe.Pointer(&subcopy))
+ )
+ if subh.Data == subcopyh.Data {
+ panic("sub and subcopy have the same underlying array")
+ }
+}
diff --git a/test/syntax/typesw.go b/test/syntax/typesw.go
index 8d89860d1..f9120e885 100644
--- a/test/syntax/typesw.go
+++ b/test/syntax/typesw.go
@@ -7,7 +7,7 @@
package main
func main() {
- switch main() := interface{}(nil).(type) { // ERROR "invalid variable name"
+ switch main() := interface{}(nil).(type) { // ERROR "invalid variable name|used as value"
default:
}
}
diff --git a/test/uintptrescapes2.go b/test/uintptrescapes2.go
index 57c21edbc..c94bc148c 100644
--- a/test/uintptrescapes2.go
+++ b/test/uintptrescapes2.go
@@ -20,12 +20,24 @@ func F1(a uintptr) {} // ERROR "escaping uintptr"
//go:noinline
func F2(a ...uintptr) {} // ERROR "escaping ...uintptr" "a does not escape"
+//go:uintptrescapes
+//go:noinline
+func F3(uintptr) {} // ERROR "escaping uintptr"
+
+//go:uintptrescapes
+//go:noinline
+func F4(...uintptr) {} // ERROR "escaping ...uintptr"
+
func G() {
- var t int // ERROR "moved to heap"
- F1(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to F1: .?autotmp" "&t escapes to heap"
+ var t int // ERROR "moved to heap"
+ F1(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to F1: .?autotmp" "&t escapes to heap"
+ var t2 int // ERROR "moved to heap"
+ F3(uintptr(unsafe.Pointer(&t2))) // ERROR "live at call to F3: .?autotmp" "&t2 escapes to heap"
}
func H() {
- var v int // ERROR "moved to heap"
- F2(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to newobject: .?autotmp" "live at call to F2: .?autotmp" "escapes to heap"
+ var v int // ERROR "moved to heap"
+ F2(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to newobject: .?autotmp" "live at call to F2: .?autotmp" "escapes to heap"
+ var v2 int // ERROR "moved to heap"
+ F4(0, 1, uintptr(unsafe.Pointer(&v2)), 2) // ERROR "live at call to newobject: .?autotmp" "live at call to F4: .?autotmp" "escapes to heap"
}