Initial commit: Go 1.23 release state

This commit is contained in:
Vorapol Rinsatitnon
2024-09-21 23:49:08 +10:00
commit 17cd57a668
13231 changed files with 3114330 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
// compile
//go:build !wasm
// Copyright 2021 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 genChecker0
var FailCount int
//go:noinline
func NoteFailure(fidx int, pkg string, pref string, parmNo int, _ uint64) {
FailCount += 1
if FailCount > 10 {
panic("bad")
}
}
//go:noinline
func NoteFailureElem(fidx int, pkg string, pref string, parmNo int, elem int, _ uint64) {
FailCount += 1
if FailCount > 10 {
panic("bad")
}
}
type StructF0S0 struct {
F0 int16
F1 string
F2 StructF0S1
}
type StructF0S1 struct {
_ uint16
}
// 0 returns 3 params
//go:registerparams
//go:noinline
func Test0(p0 uint32, p1 StructF0S0, p2 int32) {
// consume some stack space, so as to trigger morestack
var pad [256]uint64
pad[FailCount]++
if p0 == 0 {
return
}
p1f0c := int16(-3096)
if p1.F0 != p1f0c {
NoteFailureElem(0, "genChecker0", "parm", 1, 0, pad[0])
return
}
p1f1c := "f6ꂅ8ˋ<"
if p1.F1 != p1f1c {
NoteFailureElem(0, "genChecker0", "parm", 1, 1, pad[0])
return
}
p1f2c := StructF0S1{}
if p1.F2 != p1f2c {
NoteFailureElem(0, "genChecker0", "parm", 1, 2, pad[0])
return
}
p2f0c := int32(496713155)
if p2 != p2f0c {
NoteFailureElem(0, "genChecker0", "parm", 2, 0, pad[0])
return
}
// recursive call
Test0(p0-1, p1, p2)
return
// 0 addr-taken params, 0 addr-taken returns
}

View File

@@ -0,0 +1,272 @@
// build -goexperiment regabi,regabiargs
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"os"
"reflect"
)
func main() {
// Only print if there is a problem
Caller2()
if FailCount != 0 {
fmt.Fprintf(os.Stderr, "FAILURES: %d\n", FailCount)
os.Exit(2)
}
}
var ParamFailCount int
var ReturnFailCount int
var FailCount int
var Mode string
type UtilsType int
//go:noinline
func NoteFailure(cm int, pidx int, fidx int, pkg string, pref string, parmNo int, isret bool, _ uint64) {
if isret {
if ParamFailCount != 0 {
return
}
ReturnFailCount++
} else {
ParamFailCount++
}
fmt.Fprintf(os.Stderr, "Error: fail %s |%d|%d|%d| =%s.Test%d= %s %d\n", Mode, cm, pidx, fidx, pkg, fidx, pref, parmNo)
if ParamFailCount+FailCount+ReturnFailCount > 9999 {
os.Exit(1)
}
}
//go:noinline
func NoteFailureElem(cm int, pidx int, fidx int, pkg string, pref string, parmNo int, elem int, isret bool, _ uint64) {
if isret {
if ParamFailCount != 0 {
return
}
ReturnFailCount++
} else {
ParamFailCount++
}
fmt.Fprintf(os.Stderr, "Error: fail %s |%d|%d|%d| =%s.Test%d= %s %d elem %d\n", Mode, cm, pidx, fidx, pkg, fidx, pref, parmNo, elem)
if ParamFailCount+FailCount+ReturnFailCount > 9999 {
os.Exit(1)
}
}
func BeginFcn() {
ParamFailCount = 0
ReturnFailCount = 0
}
func EndFcn() {
FailCount += ParamFailCount
FailCount += ReturnFailCount
}
func Caller2() {
BeginFcn()
c0 := StructF2S0{F0: ArrayF2S1E1{New_3(float64(-0.4418990509835844))}}
c1 := ArrayF2S2E1{StructF2S1{ /* _: "񊶿(z̽|" */ F1: "􂊇񊶿"}}
c2 := int16(4162)
c3 := float32(-7.667096e+37)
c4 := int64(3202175648847048679)
var p0 ArrayF2S0E0
p0 = ArrayF2S0E0{}
var p1 uint8
p1 = uint8(57)
var p2 uint16
p2 = uint16(10920)
var p3 float64
p3 = float64(-1.597256501942112)
Mode = ""
// 5 returns 4 params
r0, r1, r2, r3, r4 := Test2(p0, p1, p2, p3)
if !EqualStructF2S0(r0, c0) {
NoteFailure(9, 42, 2, "genChecker42", "return", 0, true, uint64(0))
}
if r1 != c1 {
NoteFailure(9, 42, 2, "genChecker42", "return", 1, true, uint64(0))
}
if r2 != c2 {
NoteFailure(9, 42, 2, "genChecker42", "return", 2, true, uint64(0))
}
if r3 != c3 {
NoteFailure(9, 42, 2, "genChecker42", "return", 3, true, uint64(0))
}
if r4 != c4 {
NoteFailure(9, 42, 2, "genChecker42", "return", 4, true, uint64(0))
}
// same call via reflection
Mode = "reflect"
rc := reflect.ValueOf(Test2)
rvslice := rc.Call([]reflect.Value{reflect.ValueOf(p0), reflect.ValueOf(p1), reflect.ValueOf(p2), reflect.ValueOf(p3)})
rr0i := rvslice[0].Interface()
rr0v := rr0i.(StructF2S0)
if !EqualStructF2S0(rr0v, c0) {
NoteFailure(9, 42, 2, "genChecker42", "return", 0, true, uint64(0))
}
rr1i := rvslice[1].Interface()
rr1v := rr1i.(ArrayF2S2E1)
if rr1v != c1 {
NoteFailure(9, 42, 2, "genChecker42", "return", 1, true, uint64(0))
}
rr2i := rvslice[2].Interface()
rr2v := rr2i.(int16)
if rr2v != c2 {
NoteFailure(9, 42, 2, "genChecker42", "return", 2, true, uint64(0))
}
rr3i := rvslice[3].Interface()
rr3v := rr3i.(float32)
if rr3v != c3 {
NoteFailure(9, 42, 2, "genChecker42", "return", 3, true, uint64(0))
}
rr4i := rvslice[4].Interface()
rr4v := rr4i.(int64)
if rr4v != c4 {
NoteFailure(9, 42, 2, "genChecker42", "return", 4, true, uint64(0))
}
EndFcn()
}
type StructF0S0 struct {
}
type ArrayF0S0E2 [2]int16
type ArrayF0S1E1 [1]StructF0S0
type StructF1S0 struct {
F0 StructF1S1
_ ArrayF1S0E4
}
type StructF1S1 struct {
}
type StructF1S2 struct {
F0 uint32
F1 uint8
F2 string
F3 string
F4 ArrayF1S1E1
}
type StructF1S3 struct {
F0 float64
}
type StructF1S4 struct {
_ int32
F1 float32
}
type StructF1S5 struct {
F0 uint16
}
type StructF1S6 struct {
F0 uint8
F1 uint32
}
type ArrayF1S0E4 [4]float64
type ArrayF1S1E1 [1]StructF1S3
type ArrayF1S2E2 [2]StructF1S4
type ArrayF1S3E2 [2]StructF1S5
type ArrayF1S4E4 [4]ArrayF1S5E3
type ArrayF1S5E3 [3]string
type ArrayF1S6E1 [1]float64
type StructF2S0 struct {
F0 ArrayF2S1E1
}
// equal func for StructF2S0
//go:noinline
func EqualStructF2S0(left StructF2S0, right StructF2S0) bool {
return EqualArrayF2S1E1(left.F0, right.F0)
}
type StructF2S1 struct {
_ string
F1 string
}
type ArrayF2S0E0 [0]int8
type ArrayF2S1E1 [1]*float64
// equal func for ArrayF2S1E1
//go:noinline
func EqualArrayF2S1E1(left ArrayF2S1E1, right ArrayF2S1E1) bool {
return *left[0] == *right[0]
}
type ArrayF2S2E1 [1]StructF2S1
// 5 returns 4 params
//go:registerparams
//go:noinline
func Test2(p0 ArrayF2S0E0, p1 uint8, _ uint16, p3 float64) (r0 StructF2S0, r1 ArrayF2S2E1, r2 int16, r3 float32, r4 int64) {
// consume some stack space, so as to trigger morestack
var pad [16]uint64
pad[FailCount&0x1]++
rc0 := StructF2S0{F0: ArrayF2S1E1{New_3(float64(-0.4418990509835844))}}
rc1 := ArrayF2S2E1{StructF2S1{ /* _: "񊶿(z̽|" */ F1: "􂊇񊶿"}}
rc2 := int16(4162)
rc3 := float32(-7.667096e+37)
rc4 := int64(3202175648847048679)
p1f0c := uint8(57)
if p1 != p1f0c {
NoteFailureElem(9, 42, 2, "genChecker42", "parm", 1, 0, false, pad[0])
return
}
_ = uint16(10920)
p3f0c := float64(-1.597256501942112)
if p3 != p3f0c {
NoteFailureElem(9, 42, 2, "genChecker42", "parm", 3, 0, false, pad[0])
return
}
defer func(p0 ArrayF2S0E0, p1 uint8) {
// check parm passed
// check parm passed
if p1 != p1f0c {
NoteFailureElem(9, 42, 2, "genChecker42", "parm", 1, 0, false, pad[0])
return
}
// check parm captured
if p3 != p3f0c {
NoteFailureElem(9, 42, 2, "genChecker42", "parm", 3, 0, false, pad[0])
return
}
}(p0, p1)
return rc0, rc1, rc2, rc3, rc4
// 0 addr-taken params, 0 addr-taken returns
}
//go:noinline
func New_3(i float64) *float64 {
x := new(float64)
*x = i
return x
}

View File

@@ -0,0 +1,27 @@
// run
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "fmt"
type myStruct struct {
F0 [0]struct{}
F1 float32
}
type myStruct2 struct {
F0 [0]struct{}
F1 float32
F2 [0]struct{}
}
func main() {
x := myStruct{F1: -1.25}
fmt.Println(x)
x2 := myStruct2{F1: -7.97}
fmt.Println(x2)
}

View File

@@ -0,0 +1,2 @@
{[] -1.25}
{[] -7.97 []}

View File

@@ -0,0 +1,25 @@
// run
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
)
type MyStruct struct {
F0 [0]float64
F1 byte
F2 int16
_ struct {
F0 uint32
}
}
func main() {
p0 := MyStruct{F0: [0]float64{}, F1: byte(27), F2: int16(9887)}
fmt.Println(p0)
}

View File

@@ -0,0 +1 @@
{[] 27 9887 {0}}

View File

@@ -0,0 +1,48 @@
// run
// Copyright 2021 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 p0exp = "foo"
const p1exp = 10101
const p2exp = 3030303
const p3exp = 505050505
const p4exp = 70707070707
//go:noinline
//go:registerparams
func callee(p0 string, p1 uint64, p2 uint64, p3 uint64, p4 uint64) {
if p0 != p0exp {
panic("bad p0")
}
if p1 != p1exp {
panic("bad p1")
}
if p2 != p2exp {
panic("bad p2")
}
if p3 != p3exp {
panic("bad p3")
}
if p4 != p4exp {
panic("bad p4")
}
defer func(p0 string, p2 uint64) {
if p0 != p0exp {
panic("defer bad p0")
}
if p1 != p1exp {
panic("defer bad p1")
}
if p2 != p2exp {
panic("defer bad p2")
}
}(p0, p2)
}
func main() {
callee(p0exp, p1exp, p2exp, p3exp, p4exp)
}

View File

@@ -0,0 +1,36 @@
// run
// Copyright 2021 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 when a function recovers from a panic, it
// returns the correct results to the caller (in particular,
// setting the result registers correctly).
package main
type S struct {
x uint8
y uint16
z uint32
w float64
}
var a0, b0, c0, d0 = 10, "hello", S{1, 2, 3, 4}, [2]int{111, 222}
//go:noinline
//go:registerparams
func F() (a int, b string, _ int, c S, d [2]int) {
a, b, c, d = a0, b0, c0, d0
defer func() { recover() }()
panic("XXX")
return
}
func main() {
a1, b1, zero, c1, d1 := F()
if a1 != a0 || b1 != b0 || c1 != c0 || d1 != d0 || zero != 0 { // unnamed result gets zero value
panic("FAIL")
}
}

View File

@@ -0,0 +1,61 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import (
"fmt"
)
var sink *string
type stringPair struct {
a, b string
}
type stringPairPair struct {
x, y stringPair
}
// The goal of this test is to be sure that the call arg/result expander works correctly
// for a corner case of passing a 2-nested struct that fits in registers to/from calls.
// AND, the struct has its address taken.
//go:registerparams
//go:noinline
func H(spp stringPairPair) string {
F(&spp)
return spp.x.a + " " + spp.x.b + " " + spp.y.a + " " + spp.y.b
}
//go:registerparams
//go:noinline
func G(d, c, b, a string) stringPairPair {
return stringPairPair{stringPair{a, b}, stringPair{c, d}}
}
//go:registerparams
//go:noinline
func F(spp *stringPairPair) {
spp.x.a, spp.x.b, spp.y.a, spp.y.b = spp.y.b, spp.y.a, spp.x.b, spp.x.a
}
func main() {
spp := G("this", "is", "a", "test")
s := H(spp)
gotVsWant(s, "this is a test")
}
func gotVsWant(got, want string) {
if got != want {
fmt.Printf("FAIL, got %s, wanted %s\n", got, want)
}
}

View File

@@ -0,0 +1,53 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import (
"fmt"
)
var sink *string
type stringPair struct {
a, b string
}
type stringPairPair struct {
x, y stringPair
}
// The goal of this test is to be sure that the call arg/result expander works correctly
// for a corner case of passing a 2-nested struct that fits in registers to/from calls.
//go:registerparams
//go:noinline
func H(spp stringPairPair) string {
return spp.x.a + " " + spp.x.b + " " + spp.y.a + " " + spp.y.b
}
//go:registerparams
//go:noinline
func G(a, b, c, d string) stringPairPair {
return stringPairPair{stringPair{a, b}, stringPair{c, d}}
}
func main() {
spp := G("this", "is", "a", "test")
s := H(spp)
gotVsWant(s, "this is a test")
}
func gotVsWant(got, want string) {
if got != want {
fmt.Printf("FAIL, got %s, wanted %s\n", got, want)
}
}

38
test/abi/f_ret_z_not.go Normal file
View File

@@ -0,0 +1,38 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import "fmt"
type Z struct {
}
type NZ struct {
x, y int
}
//go:noinline
func f(x, y int) (Z, NZ, Z) {
var z Z
return z, NZ{x, y}, z
}
//go:noinline
func g() (Z, NZ, Z) {
a, b, c := f(3, 4)
return c, b, a
}
func main() {
_, b, _ := g()
fmt.Println(b.x + b.y)
}

1
test/abi/f_ret_z_not.out Normal file
View File

@@ -0,0 +1 @@
7

32
test/abi/fibish.go Normal file
View File

@@ -0,0 +1,32 @@
// run
//go:build !wasm
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "fmt"
// Test that register results are correctly returned (and passed)
//go:registerparams
//go:noinline
func f(x int) (int, int) {
if x < 3 {
return 0, x
}
a, b := f(x - 2)
c, d := f(x - 1)
return a + d, b + c
}
func main() {
x := 40
a, b := f(x)
fmt.Printf("f(%d)=%d,%d\n", x, a, b)
}

1
test/abi/fibish.out Normal file
View File

@@ -0,0 +1 @@
f(40)=39088169,126491972

View File

@@ -0,0 +1,33 @@
// run
//go:build !wasm
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "fmt"
// Test that register results are correctly returned (and passed)
type MagicLastTypeNameForTestingRegisterABI func(int, MagicLastTypeNameForTestingRegisterABI) (int, int)
//go:noinline
func f(x int, unused MagicLastTypeNameForTestingRegisterABI) (int, int) {
if x < 3 {
return 0, x
}
a, b := f(x-2, unused)
c, d := f(x-1, unused)
return a + d, b + c
}
func main() {
x := 40
a, b := f(x, f)
fmt.Printf("f(%d)=%d,%d\n", x, a, b)
}

View File

@@ -0,0 +1 @@
f(40)=39088169,126491972

View File

@@ -0,0 +1,39 @@
// run
// Copyright 2021 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 p0exp = S1{
F1: complex(float64(2.3640607624715027), float64(-0.2717825524109192)),
F2: S2{F1: 9},
F3: 103050709,
}
type S1 struct {
F1 complex128
F2 S2
F3 uint64
}
type S2 struct {
F1 uint64
F2 empty
}
type empty struct {
}
//go:noinline
//go:registerparams
func callee(p0 S1) {
if p0 != p0exp {
panic("bad p0")
}
}
func main() {
callee(p0exp)
}

97
test/abi/idata.go Normal file
View File

@@ -0,0 +1,97 @@
// run
// Copyright 2021 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.
// Excerpted from go/constant/value.go to capture a bug from there.
package main
import (
"fmt"
"math"
"math/big"
)
type (
unknownVal struct{}
intVal struct{ val *big.Int } // Int values not representable as an int64
ratVal struct{ val *big.Rat } // Float values representable as a fraction
floatVal struct{ val *big.Float } // Float values not representable as a fraction
complexVal struct{ re, im Value }
)
const prec = 512
func (unknownVal) String() string { return "unknown" }
func (x intVal) String() string { return x.val.String() }
func (x ratVal) String() string { return rtof(x).String() }
func (x floatVal) String() string {
f := x.val
// Use exact fmt formatting if in float64 range (common case):
// proceed if f doesn't underflow to 0 or overflow to inf.
if x, _ := f.Float64(); f.Sign() == 0 == (x == 0) && !math.IsInf(x, 0) {
return fmt.Sprintf("%.6g", x)
}
return "OOPS"
}
func (x complexVal) String() string { return fmt.Sprintf("(%s + %si)", x.re, x.im) }
func newFloat() *big.Float { return new(big.Float).SetPrec(prec) }
//go:noinline
//go:registerparams
func itor(x intVal) ratVal { return ratVal{nil} }
//go:noinline
//go:registerparams
func itof(x intVal) floatVal { return floatVal{nil} }
func rtof(x ratVal) floatVal { return floatVal{newFloat().SetRat(x.val)} }
type Value interface {
String() string
}
//go:noinline
//go:registerparams
func ToFloat(x Value) Value {
switch x := x.(type) {
case intVal:
if smallInt(x.val) {
return itor(x)
}
return itof(x)
case ratVal, floatVal:
return x
case complexVal:
if Sign(x.im) == 0 {
return ToFloat(x.re)
}
}
return unknownVal{}
}
//go:noinline
//go:registerparams
func smallInt(x *big.Int) bool {
return false
}
//go:noinline
//go:registerparams
func Sign(x Value) int {
return 0
}
func main() {
v := ratVal{big.NewRat(22,7)}
s := ToFloat(v).String()
fmt.Printf("s=%s\n", s)
}

1
test/abi/idata.out Normal file
View File

@@ -0,0 +1 @@
s=3.14286

35
test/abi/leaf.go Normal file
View File

@@ -0,0 +1,35 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import "fmt"
type i5f5 struct {
a, b int16
c, d, e int32
r, s, t, u, v float32
}
//go:registerparams
//go:noinline
func F(x i5f5) i5f5 {
return x
}
func main() {
x := i5f5{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
y := x
z := F(x)
if y != z {
fmt.Printf("y=%v, z=%v\n", y, z)
}
}

42
test/abi/leaf2.go Normal file
View File

@@ -0,0 +1,42 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import "fmt"
type i4 struct {
a, b, c, d int
}
//go:registerparams
//go:noinline
func F(x i4) i4 {
ab := x.a + x.b
bc := x.b + x.c
cd := x.c + x.d
ad := x.a + x.d
ba := x.a - x.b
cb := x.b - x.c
dc := x.c - x.d
da := x.a - x.d
return i4{ab*bc + da, cd*ad + cb, ba*cb + ad, dc*da + bc}
}
func main() {
x := i4{1, 2, 3, 4}
y := x
z := F(x)
if (i4{12, 34, 6, 8}) != z {
fmt.Printf("y=%v, z=%v\n", y, z)
}
}

View File

@@ -0,0 +1,32 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import (
"fmt"
)
//go:registerparams
//go:noinline
func F(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z int64) {
G(z, y, x, w, v, u, t, s, r, q, p, o, n, m, l, k, j, i, h, g, f, e, d, c, b, a)
}
//go:registerparams
//go:noinline
func G(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z int64) {
fmt.Println(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z)
}
func main() {
F(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26)
}

View File

@@ -0,0 +1 @@
26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1

View File

@@ -0,0 +1,44 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import (
"fmt"
)
var sink int = 3
//go:registerparams
//go:noinline
func F(a, b, c, d, e, f *int) {
G(f, e, d, c, b, a)
sink += *a // *a == 6 after swapping in G
}
//go:registerparams
//go:noinline
func G(a, b, c, d, e, f *int) {
var scratch [1000 * 100]int
scratch[*a] = *f // scratch[6] = 1
fmt.Println(*a, *b, *c, *d, *e, *f) // Forces it to spill b
sink = scratch[*b+1] // scratch[5+1] == 1
*f, *a = *a, *f
*e, *b = *b, *e
*d, *c = *c, *d
}
func main() {
a, b, c, d, e, f := 1, 2, 3, 4, 5, 6
F(&a, &b, &c, &d, &e, &f)
fmt.Println(a, b, c, d, e, f)
fmt.Println(sink)
}

View File

@@ -0,0 +1,3 @@
6 5 4 3 2 1
6 5 4 3 2 1
7

34
test/abi/map.go Normal file
View File

@@ -0,0 +1,34 @@
// run
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "runtime"
type T [10]int
var m map[*T]int
//go:noinline
func F() {
m = map[*T]int{
K(): V(), // the key temp should be live across call to V
}
}
//go:noinline
func V() int { runtime.GC(); runtime.GC(); runtime.GC(); return 123 }
//go:noinline
func K() *T {
p := new(T)
runtime.SetFinalizer(p, func(*T) { println("FAIL") })
return p
}
func main() {
F()
}

View File

@@ -0,0 +1,35 @@
// run
// Copyright 2021 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 S int
type T struct {
a int
S
}
//go:noinline
func (s *S) M(a int, x [2]int, b float64, y [2]float64) (S, int, [2]int, float64, [2]float64) {
return *s, a, x, b, y
}
var s S = 42
var t = &T{S: s}
var fn = (*T).M // force a method wrapper
func main() {
a := 123
x := [2]int{456, 789}
b := 1.2
y := [2]float64{3.4, 5.6}
s1, a1, x1, b1, y1 := fn(t, a, x, b, y)
if a1 != a || x1 != x || b1 != b || y1 != y || s1 != s {
panic("FAIL")
}
}

View File

@@ -0,0 +1,39 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
var sink int
//go:registerparams
//go:noinline
func F(a, b, c, d, e, f, g, h, i, j, k, l, m *int) {
G(m, l, k, j, i, h, g, f, e, d, c, b, a)
// did the pointers get properly updated?
sink = *a + *m
}
//go:registerparams
//go:noinline
func G(a, b, c, d, e, f, g, h, i, j, k, l, m *int) {
// Do not reference the parameters
var scratch [1000 * 100]int
I := *c - *e - *l // zero.
scratch[I] = *d
println("Got this far!")
sink += scratch[0]
}
func main() {
a, b, c, d, e, f, g, h, i, j, k, l, m := 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
F(&a, &b, &c, &d, &e, &f, &g, &h, &i, &j, &k, &l, &m)
println("Sink =", sink-7)
}

View File

@@ -0,0 +1,2 @@
Got this far!
Sink = 7

90
test/abi/named_results.go Normal file
View File

@@ -0,0 +1,90 @@
// run
//go:build !wasm
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
)
var sink *string
var y int
//go:registerparams
//go:noinline
func F(a, b, c *int) (x int) {
x = *a
G(&x)
x += *b
G(&x)
x += *c
G(&x)
return
}
//go:registerparams
//go:noinline
func G(x *int) {
y += *x
fmt.Println("y = ", y)
}
//go:registerparams
//go:noinline
func X() {
*sink += " !!!!!!!!!!!!!!!"
}
//go:registerparams
//go:noinline
func H(s, t string) (result string) { // result leaks to heap
result = "Aloha! " + s + " " + t
sink = &result
r := ""
if len(s) <= len(t) {
r = "OKAY! "
X()
}
return r + result
}
//go:registerparams
//go:noinline
func K(s, t string) (result string) { // result spills
result = "Aloha! " + s + " " + t
r := ""
if len(s) <= len(t) {
r = "OKAY! "
X()
}
return r + result
}
func main() {
a, b, c := 1, 4, 16
x := F(&a, &b, &c)
fmt.Printf("x = %d\n", x)
y := H("Hello", "World!")
fmt.Println("len(y) =", len(y))
fmt.Println("y =", y)
z := H("Hello", "Pal!")
fmt.Println("len(z) =", len(z))
fmt.Println("z =", z)
fmt.Println()
y = K("Hello", "World!")
fmt.Println("len(y) =", len(y))
fmt.Println("y =", y)
z = K("Hello", "Pal!")
fmt.Println("len(z) =", len(z))
fmt.Println("z =", z)
}

View File

@@ -0,0 +1,13 @@
y = 1
y = 6
y = 27
x = 21
len(y) = 41
y = OKAY! Aloha! Hello World! !!!!!!!!!!!!!!!
len(z) = 17
z = Aloha! Hello Pal!
len(y) = 25
y = OKAY! Aloha! Hello World!
len(z) = 17
z = Aloha! Hello Pal!

View File

@@ -0,0 +1,93 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import (
"fmt"
)
var sink *string
var y int
//go:registerparams
//go:noinline
func F(a, b, c *int) (x int) {
x = *a
G(&x)
x += *b
G(&x)
x += *c
G(&x)
return
}
//go:registerparams
//go:noinline
func G(x *int) {
y += *x
fmt.Println("y = ", y)
}
//go:registerparams
//go:noinline
func X() {
*sink += " !!!!!!!!!!!!!!!"
}
//go:registerparams
//go:noinline
func H(s, t string) (result string) { // result leaks to heap
result = "Aloha! " + s + " " + t
sink = &result
r := ""
if len(s) <= len(t) {
r = "OKAY! "
X()
}
return r + result
}
//go:registerparams
//go:noinline
func K(s, t string) (result string) { // result spills
result = "Aloha! " + s + " " + t
r := ""
if len(s) <= len(t) {
r = "OKAY! "
X()
}
return r + result
}
func main() {
a, b, c := 1, 4, 16
x := F(&a, &b, &c)
fmt.Printf("x = %d\n", x)
y := H("Hello", "World!")
fmt.Println("len(y) =", len(y))
fmt.Println("y =", y)
z := H("Hello", "Pal!")
fmt.Println("len(z) =", len(z))
fmt.Println("z =", z)
fmt.Println()
y = K("Hello", "World!")
fmt.Println("len(y) =", len(y))
fmt.Println("y =", y)
z = K("Hello", "Pal!")
fmt.Println("len(z) =", len(z))
fmt.Println("z =", z)
}

View File

@@ -0,0 +1,13 @@
y = 1
y = 6
y = 27
x = 21
len(y) = 41
y = OKAY! Aloha! Hello World! !!!!!!!!!!!!!!!
len(z) = 17
z = Aloha! Hello Pal!
len(y) = 25
y = OKAY! Aloha! Hello World!
len(z) = 17
z = Aloha! Hello Pal!

36
test/abi/open_defer_1.go Normal file
View File

@@ -0,0 +1,36 @@
// run
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// For #45062, miscompilation of open defer of method invocation
package main
func main() {
var x, y, z int = -1, -2, -3
F(x, y, z)
}
//go:noinline
func F(x, y, z int) {
defer i.M(x, y, z)
defer func() { recover() }()
panic("XXX")
}
type T int
func (t *T) M(x, y, z int) {
if x == -1 && y == -2 && z == -3 {
return
}
println("FAIL: Expected -1, -2, -3, but x, y, z =", x, y, z)
}
var t T = 42
type I interface{ M(x, y, z int) }
var i I = &t

48
test/abi/part_live.go Normal file
View File

@@ -0,0 +1,48 @@
// run
// Copyright 2021 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 test for partial liveness / partial spilling / compiler-induced GC failure
package main
import "runtime"
import "unsafe"
//go:registerparams
func F(s []int) {
for i, x := range s {
G(i, x)
}
GC()
G(len(s), cap(s))
GC()
}
//go:noinline
//go:registerparams
func G(int, int) {}
//go:registerparams
func GC() { runtime.GC(); runtime.GC() }
func main() {
s := make([]int, 3)
escape(s)
p := int(uintptr(unsafe.Pointer(&s[2])) + 42) // likely point to unallocated memory
poison([3]int{p, p, p})
F(s)
}
//go:noinline
//go:registerparams
func poison([3]int) {}
//go:noinline
//go:registerparams
func escape(s []int) {
g = s
}
var g []int

53
test/abi/part_live_2.go Normal file
View File

@@ -0,0 +1,53 @@
// run
// Copyright 2021 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 test for partial liveness / partial spilling / compiler-induced GC failure
package main
import "runtime"
import "unsafe"
//go:registerparams
func F(s []int) {
for i, x := range s {
G(i, x)
}
GC()
H(&s[0]) // It's possible that this will make the spill redundant, but there's a bug in spill slot allocation.
G(len(s), cap(s))
GC()
}
//go:noinline
//go:registerparams
func G(int, int) {}
//go:noinline
//go:registerparams
func H(*int) {}
//go:registerparams
func GC() { runtime.GC(); runtime.GC() }
func main() {
s := make([]int, 3)
escape(s)
p := int(uintptr(unsafe.Pointer(&s[2])) + 42) // likely point to unallocated memory
poison([3]int{p, p, p})
F(s)
}
//go:noinline
//go:registerparams
func poison([3]int) {}
//go:noinline
//go:registerparams
func escape(s []int) {
g = s
}
var g []int

39
test/abi/reg_not_ssa.go Normal file
View File

@@ -0,0 +1,39 @@
// run
//go:build !wasm
// Copyright 2023 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
// small enough for registers, too large for SSA
type T struct {
a, b, c, d, e int
}
//go:noinline
func F() {
a, b := g(), g()
h(b, b)
h(a, g())
if a.a == 1 {
a = g()
}
h(a, a)
}
//go:noinline
func g() T {
return T{1, 2, 3, 4, 5}
}
//go:noinline
func h(s, t T) {
if s != t {
println("NEQ")
}
}
func main() { F() }

20
test/abi/result_live.go Normal file
View File

@@ -0,0 +1,20 @@
// errorcheck -0 -live
// Copyright 2021 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 struct { a, b, c, d string } // pass in registers, not SSA-able
//go:registerparams
func F() (r T) {
r.a = g(1) // ERROR "live at call to g: r"
r.b = g(2) // ERROR "live at call to g: r"
r.c = g(3) // ERROR "live at call to g: r"
r.d = g(4) // ERROR "live at call to g: r"
return
}
func g(int) string

View File

@@ -0,0 +1,46 @@
// run
// Copyright 2021 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.
// Bug: in (*bb).d, the value to be returned was not allocated to
// a register that satisfies its register mask.
package main
type bb struct {
r float64
x []float64
}
//go:noinline
func B(r float64, x []float64) I {
return bb{r, x}
}
func (b bb) d() (int, int) {
if b.r == 0 {
return 0, len(b.x)
}
return len(b.x), len(b.x)
}
type I interface { d() (int, int) }
func D(r I) (int, int) { return r.d() }
//go:noinline
func F() (int, int) {
r := float64(1)
x := []float64{0, 1, 2}
b := B(r, x)
return D(b)
}
func main() {
x, y := F()
if x != 3 || y != 3 {
panic("FAIL")
}
}

37
test/abi/return_stuff.go Normal file
View File

@@ -0,0 +1,37 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import (
"fmt"
)
//go:registerparams
//go:noinline
func F(a, b, c *int) int {
return *a + *b + *c
}
//go:registerparams
//go:noinline
func H(s, t string) string {
return s + " " + t
}
func main() {
a, b, c := 1, 4, 16
x := F(&a, &b, &c)
fmt.Printf("x = %d\n", x)
y := H("Hello", "World!")
fmt.Println("len(y) =", len(y))
fmt.Println("y =", y)
}

View File

@@ -0,0 +1,3 @@
x = 21
len(y) = 12
y = Hello World!

36
test/abi/s_sif_sif.go Normal file
View File

@@ -0,0 +1,36 @@
// run
//go:build !wasm
// Copyright 2021 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
// Test ensures that abi information producer and consumer agree about the
// order of registers for inputs. T's registers should be I0, F0, I1, F1.
import "fmt"
type P struct {
a int8
x float64
}
type T struct {
d, e P
}
//go:registerparams
//go:noinline
func G(t T) float64 {
return float64(t.d.a+t.e.a) + t.d.x + t.e.x
}
func main() {
x := G(T{P{10, 20}, P{30, 40}})
if x != 100.0 {
fmt.Printf("FAIL, Expected 100, got %f\n", x)
}
}

47
test/abi/spills3.go Normal file
View File

@@ -0,0 +1,47 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import "fmt"
type i4 struct {
a, b, c, d int
}
//go:noinline
func spills(px *i4) {
}
//go:registerparams
//go:noinline
func F(x i4) i4 {
ab := x.a + x.b
bc := x.b + x.c
cd := x.c + x.d
ad := x.a + x.d
ba := x.a - x.b
cb := x.b - x.c
dc := x.c - x.d
da := x.a - x.d
i := i4{ab*bc + da, cd*ad + cb, ba*cb + ad, dc*da + bc}
spills(&i)
return i
}
func main() {
x := i4{1, 2, 3, 4}
y := x
z := F(x)
if z != (i4{12, 34, 6, 8}) {
fmt.Printf("y=%v, z=%v\n", y, z)
}
}

43
test/abi/spills4.go Normal file
View File

@@ -0,0 +1,43 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import "fmt"
type i5f5 struct {
a, b int16
c, d, e int32
r, s, t, u, v float32
}
//go:noinline
func spills(_ *float32) {
}
//go:registerparams
//go:noinline
func F(x i5f5) i5f5 {
y := x.v
spills(&y)
x.r = y
return x
}
func main() {
x := i5f5{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
y := x
z := F(x)
if (i5f5{1, 2, 3, 4, 5, 10, 7, 8, 9, 10}) != z {
fmt.Printf("y=%v, z=%v\n", y, z)
}
}

View File

@@ -0,0 +1,29 @@
// run
// Copyright 2021 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 the function Store an Arg and also use it in another place,
// be sure not to generate duplicated OpArgXXXReg values, which confuses
// the register allocator.
package main
//go:noinline
//go:registerparams
func F(x, y float32) {
if x < 0 {
panic("FAIL")
}
g = [4]float32{x, y, x, y}
}
var g [4]float32
func main() {
F(1, 2)
if g[0] != 1 || g[1] != 2 || g[2] != 1 || g[3] != 2 {
panic("FAIL")
}
}

View File

@@ -0,0 +1,39 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import (
"fmt"
)
var sink *string
type toobig struct {
a, b, c string
}
//go:registerparams
//go:noinline
func H(x toobig) string {
return x.a + " " + x.b + " " + x.c
}
func main() {
s := H(toobig{"Hello", "there,", "World"})
gotVsWant(s, "Hello there, World")
}
func gotVsWant(got, want string) {
if got != want {
fmt.Printf("FAIL, got %s, wanted %s\n", got, want)
}
}

View File

View File

@@ -0,0 +1,29 @@
// run
//go:build !wasm
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "fmt"
//go:registerparams
//go:noinline
func passStruct6(a Struct6) Struct6 {
return a
}
type Struct6 struct {
Struct1
}
type Struct1 struct {
A, B, C uint
}
func main() {
fmt.Println(passStruct6(Struct6{Struct1{1, 2, 3}}))
}

View File

@@ -0,0 +1 @@
{{1 2 3}}

View File

@@ -0,0 +1,47 @@
// run
//go:build !wasm
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
)
var sink *string
type toobig struct {
// 6 words will not SSA but will fit in registers
a, b, c string
}
//go:registerparams
//go:noinline
func H(x toobig) string {
return x.a + " " + x.b + " " + x.c
}
//go:registerparams
//go:noinline
func I(a, b, c string) toobig {
return toobig{a, b, c}
}
func main() {
s := H(toobig{"Hello", "there,", "World"})
gotVsWant(s, "Hello there, World")
fmt.Println(s)
t := H(I("Ahoy", "there,", "Matey"))
gotVsWant(t, "Ahoy there, Matey")
fmt.Println(t)
}
func gotVsWant(got, want string) {
if got != want {
fmt.Printf("FAIL, got %s, wanted %s\n", got, want)
}
}

View File

@@ -0,0 +1,2 @@
Hello there, World
Ahoy there, Matey

81
test/abi/uglyfib.go Normal file
View File

@@ -0,0 +1,81 @@
// run
//go:build !wasm
// Copyright 2021 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.
// wasm is excluded because the compiler chatter about register abi pragma ends up
// on stdout, and causes the expected output to not match.
package main
import "fmt"
// This test is designed to provoke a stack growth
// in a way that very likely leaves junk in the
// parameter save area if they aren't saved or spilled
// there, as appropriate.
//go:registerparams
//go:noinline
func f(x int, xm1, xm2, p *int) {
var y = [2]int{x - 4, 0}
if x < 2 {
*p += x
return
}
x -= 3
g(*xm1, xm2, &x, p) // xm1 is no longer live.
h(*xm2, &x, &y[0], p) // xm2 is no longer live, but was spilled.
}
//go:registerparams
//go:noinline
func g(x int, xm1, xm2, p *int) {
var y = [3]int{x - 4, 0, 0}
if x < 2 {
*p += x
return
}
x -= 3
k(*xm2, &x, &y[0], p)
h(*xm1, xm2, &x, p)
}
//go:registerparams
//go:noinline
func h(x int, xm1, xm2, p *int) {
var y = [4]int{x - 4, 0, 0, 0}
if x < 2 {
*p += x
return
}
x -= 3
k(*xm1, xm2, &x, p)
f(*xm2, &x, &y[0], p)
}
//go:registerparams
//go:noinline
func k(x int, xm1, xm2, p *int) {
var y = [5]int{x - 4, 0, 0, 0, 0}
if x < 2 {
*p += x
return
}
x -= 3
f(*xm2, &x, &y[0], p)
g(*xm1, xm2, &x, p)
}
func main() {
x := 40
var y int
xm1 := x - 1
xm2 := x - 2
f(x, &xm1, &xm2, &y)
fmt.Printf("Fib(%d)=%d\n", x, y)
}

1
test/abi/uglyfib.out Normal file
View File

@@ -0,0 +1 @@
Fib(40)=102334155

View File

@@ -0,0 +1,36 @@
// run
//go:build !wasm
// Copyright 2021 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() {
b := g()
defer g2(b)
n := g()[20]
println(n)
}
type T [45]int
var x = 0
//go:noinline
func g() T {
x++
return T{20: x}
}
//go:noinline
func g2(t T) {
if t[20] != 1 {
println("FAIL", t[20])
}
}
func main() { F() }

View File

@@ -0,0 +1 @@
2

View File

@@ -0,0 +1,36 @@
// run
// Copyright 2021 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 patchlist struct {
head, tail uint32
}
type frag struct {
i uint32
out patchlist
}
//go:noinline
//go:registerparams
func patch(l patchlist, i uint32) {
}
//go:noinline
//go:registerparams
func badbad(f1, f2 frag) frag {
// concat of failure is failure
if f1.i == 0 || f2.i == 0 { // internal compiler error: 'badbad': incompatible OpArgIntReg [4]: v42 and v26
return frag{}
}
patch(f1.out, f2.i)
return frag{f1.i, f2.out}
}
func main() {
badbad(frag{i: 2}, frag{i: 3})
}