Initial commit: Go 1.23 release state
This commit is contained in:
73
test/abi/bad_internal_offsets.go
Normal file
73
test/abi/bad_internal_offsets.go
Normal 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
|
||||
}
|
||||
272
test/abi/bad_select_crash.go
Normal file
272
test/abi/bad_select_crash.go
Normal 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
|
||||
}
|
||||
27
test/abi/convF_criteria.go
Normal file
27
test/abi/convF_criteria.go
Normal 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)
|
||||
}
|
||||
2
test/abi/convF_criteria.out
Normal file
2
test/abi/convF_criteria.out
Normal file
@@ -0,0 +1,2 @@
|
||||
{[] -1.25}
|
||||
{[] -7.97 []}
|
||||
25
test/abi/convT64_criteria.go
Normal file
25
test/abi/convT64_criteria.go
Normal 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)
|
||||
}
|
||||
1
test/abi/convT64_criteria.out
Normal file
1
test/abi/convT64_criteria.out
Normal file
@@ -0,0 +1 @@
|
||||
{[] 27 9887 {0}}
|
||||
48
test/abi/defer_aggregate.go
Normal file
48
test/abi/defer_aggregate.go
Normal 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)
|
||||
}
|
||||
36
test/abi/defer_recover_results.go
Normal file
36
test/abi/defer_recover_results.go
Normal 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")
|
||||
}
|
||||
}
|
||||
61
test/abi/double_nested_addressed_struct.go
Normal file
61
test/abi/double_nested_addressed_struct.go
Normal 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)
|
||||
}
|
||||
}
|
||||
53
test/abi/double_nested_struct.go
Normal file
53
test/abi/double_nested_struct.go
Normal 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
38
test/abi/f_ret_z_not.go
Normal 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
1
test/abi/f_ret_z_not.out
Normal file
@@ -0,0 +1 @@
|
||||
7
|
||||
32
test/abi/fibish.go
Normal file
32
test/abi/fibish.go
Normal 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
1
test/abi/fibish.out
Normal file
@@ -0,0 +1 @@
|
||||
f(40)=39088169,126491972
|
||||
33
test/abi/fibish_closure.go
Normal file
33
test/abi/fibish_closure.go
Normal 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)
|
||||
}
|
||||
1
test/abi/fibish_closure.out
Normal file
1
test/abi/fibish_closure.out
Normal file
@@ -0,0 +1 @@
|
||||
f(40)=39088169,126491972
|
||||
39
test/abi/fuzz_trailing_zero_field.go
Normal file
39
test/abi/fuzz_trailing_zero_field.go
Normal 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
97
test/abi/idata.go
Normal 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
1
test/abi/idata.out
Normal file
@@ -0,0 +1 @@
|
||||
s=3.14286
|
||||
35
test/abi/leaf.go
Normal file
35
test/abi/leaf.go
Normal 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
42
test/abi/leaf2.go
Normal 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)
|
||||
}
|
||||
}
|
||||
32
test/abi/many_int_input.go
Normal file
32
test/abi/many_int_input.go
Normal 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)
|
||||
}
|
||||
1
test/abi/many_int_input.out
Normal file
1
test/abi/many_int_input.out
Normal 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
|
||||
44
test/abi/many_intstar_input.go
Normal file
44
test/abi/many_intstar_input.go
Normal 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)
|
||||
}
|
||||
3
test/abi/many_intstar_input.out
Normal file
3
test/abi/many_intstar_input.out
Normal 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
34
test/abi/map.go
Normal 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()
|
||||
}
|
||||
35
test/abi/method_wrapper.go
Normal file
35
test/abi/method_wrapper.go
Normal 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")
|
||||
}
|
||||
}
|
||||
39
test/abi/more_intstar_input.go
Normal file
39
test/abi/more_intstar_input.go
Normal 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)
|
||||
}
|
||||
2
test/abi/more_intstar_input.out
Normal file
2
test/abi/more_intstar_input.out
Normal file
@@ -0,0 +1,2 @@
|
||||
Got this far!
|
||||
Sink = 7
|
||||
90
test/abi/named_results.go
Normal file
90
test/abi/named_results.go
Normal 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)
|
||||
|
||||
}
|
||||
13
test/abi/named_results.out
Normal file
13
test/abi/named_results.out
Normal 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!
|
||||
93
test/abi/named_return_stuff.go
Normal file
93
test/abi/named_return_stuff.go
Normal 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)
|
||||
|
||||
}
|
||||
13
test/abi/named_return_stuff.out
Normal file
13
test/abi/named_return_stuff.out
Normal 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
36
test/abi/open_defer_1.go
Normal 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
48
test/abi/part_live.go
Normal 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
53
test/abi/part_live_2.go
Normal 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
39
test/abi/reg_not_ssa.go
Normal 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
20
test/abi/result_live.go
Normal 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
|
||||
46
test/abi/result_regalloc.go
Normal file
46
test/abi/result_regalloc.go
Normal 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
37
test/abi/return_stuff.go
Normal 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)
|
||||
}
|
||||
3
test/abi/return_stuff.out
Normal file
3
test/abi/return_stuff.out
Normal file
@@ -0,0 +1,3 @@
|
||||
x = 21
|
||||
len(y) = 12
|
||||
y = Hello World!
|
||||
36
test/abi/s_sif_sif.go
Normal file
36
test/abi/s_sif_sif.go
Normal 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
47
test/abi/spills3.go
Normal 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
43
test/abi/spills4.go
Normal 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)
|
||||
}
|
||||
}
|
||||
29
test/abi/store_reg_args.go
Normal file
29
test/abi/store_reg_args.go
Normal 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")
|
||||
}
|
||||
}
|
||||
39
test/abi/struct_3_string_input.go
Normal file
39
test/abi/struct_3_string_input.go
Normal 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)
|
||||
}
|
||||
}
|
||||
0
test/abi/struct_3_string_input.out
Normal file
0
test/abi/struct_3_string_input.out
Normal file
29
test/abi/struct_lower_1.go
Normal file
29
test/abi/struct_lower_1.go
Normal 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}}))
|
||||
}
|
||||
1
test/abi/struct_lower_1.out
Normal file
1
test/abi/struct_lower_1.out
Normal file
@@ -0,0 +1 @@
|
||||
{{1 2 3}}
|
||||
47
test/abi/too_big_to_ssa.go
Normal file
47
test/abi/too_big_to_ssa.go
Normal 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)
|
||||
}
|
||||
}
|
||||
2
test/abi/too_big_to_ssa.out
Normal file
2
test/abi/too_big_to_ssa.out
Normal file
@@ -0,0 +1,2 @@
|
||||
Hello there, World
|
||||
Ahoy there, Matey
|
||||
81
test/abi/uglyfib.go
Normal file
81
test/abi/uglyfib.go
Normal 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
1
test/abi/uglyfib.out
Normal file
@@ -0,0 +1 @@
|
||||
Fib(40)=102334155
|
||||
36
test/abi/wrapdefer_largetmp.go
Normal file
36
test/abi/wrapdefer_largetmp.go
Normal 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() }
|
||||
1
test/abi/wrapdefer_largetmp.out
Normal file
1
test/abi/wrapdefer_largetmp.out
Normal file
@@ -0,0 +1 @@
|
||||
2
|
||||
36
test/abi/zombie_struct_select.go
Normal file
36
test/abi/zombie_struct_select.go
Normal 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})
|
||||
}
|
||||
Reference in New Issue
Block a user