1// build -goexperiment regabi,regabiargs
2
3// Copyright 2021 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7package main
8
9import (
10	"fmt"
11	"os"
12	"reflect"
13)
14
15func main() {
16	// Only print if there is a problem
17	Caller2()
18	if FailCount != 0 {
19		fmt.Fprintf(os.Stderr, "FAILURES: %d\n", FailCount)
20		os.Exit(2)
21	}
22}
23
24var ParamFailCount int
25
26var ReturnFailCount int
27
28var FailCount int
29
30var Mode string
31
32type UtilsType int
33
34//go:noinline
35func NoteFailure(cm int, pidx int, fidx int, pkg string, pref string, parmNo int, isret bool, _ uint64) {
36	if isret {
37		if ParamFailCount != 0 {
38			return
39		}
40		ReturnFailCount++
41	} else {
42		ParamFailCount++
43	}
44	fmt.Fprintf(os.Stderr, "Error: fail %s |%d|%d|%d| =%s.Test%d= %s %d\n", Mode, cm, pidx, fidx, pkg, fidx, pref, parmNo)
45
46	if ParamFailCount+FailCount+ReturnFailCount > 9999 {
47		os.Exit(1)
48	}
49}
50
51//go:noinline
52func NoteFailureElem(cm int, pidx int, fidx int, pkg string, pref string, parmNo int, elem int, isret bool, _ uint64) {
53
54	if isret {
55		if ParamFailCount != 0 {
56			return
57		}
58		ReturnFailCount++
59	} else {
60		ParamFailCount++
61	}
62	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)
63
64	if ParamFailCount+FailCount+ReturnFailCount > 9999 {
65		os.Exit(1)
66	}
67}
68
69func BeginFcn() {
70	ParamFailCount = 0
71	ReturnFailCount = 0
72}
73
74func EndFcn() {
75	FailCount += ParamFailCount
76	FailCount += ReturnFailCount
77}
78
79func Caller2() {
80	BeginFcn()
81	c0 := StructF2S0{F0: ArrayF2S1E1{New_3(float64(-0.4418990509835844))}}
82	c1 := ArrayF2S2E1{StructF2S1{ /* _: "��(z̽|" */ F1: "����"}}
83	c2 := int16(4162)
84	c3 := float32(-7.667096e+37)
85	c4 := int64(3202175648847048679)
86	var p0 ArrayF2S0E0
87	p0 = ArrayF2S0E0{}
88	var p1 uint8
89	p1 = uint8(57)
90	var p2 uint16
91	p2 = uint16(10920)
92	var p3 float64
93	p3 = float64(-1.597256501942112)
94	Mode = ""
95	// 5 returns 4 params
96	r0, r1, r2, r3, r4 := Test2(p0, p1, p2, p3)
97	if !EqualStructF2S0(r0, c0) {
98		NoteFailure(9, 42, 2, "genChecker42", "return", 0, true, uint64(0))
99	}
100	if r1 != c1 {
101		NoteFailure(9, 42, 2, "genChecker42", "return", 1, true, uint64(0))
102	}
103	if r2 != c2 {
104		NoteFailure(9, 42, 2, "genChecker42", "return", 2, true, uint64(0))
105	}
106	if r3 != c3 {
107		NoteFailure(9, 42, 2, "genChecker42", "return", 3, true, uint64(0))
108	}
109	if r4 != c4 {
110		NoteFailure(9, 42, 2, "genChecker42", "return", 4, true, uint64(0))
111	}
112	// same call via reflection
113	Mode = "reflect"
114	rc := reflect.ValueOf(Test2)
115	rvslice := rc.Call([]reflect.Value{reflect.ValueOf(p0), reflect.ValueOf(p1), reflect.ValueOf(p2), reflect.ValueOf(p3)})
116	rr0i := rvslice[0].Interface()
117	rr0v := rr0i.(StructF2S0)
118	if !EqualStructF2S0(rr0v, c0) {
119		NoteFailure(9, 42, 2, "genChecker42", "return", 0, true, uint64(0))
120	}
121	rr1i := rvslice[1].Interface()
122	rr1v := rr1i.(ArrayF2S2E1)
123	if rr1v != c1 {
124		NoteFailure(9, 42, 2, "genChecker42", "return", 1, true, uint64(0))
125	}
126	rr2i := rvslice[2].Interface()
127	rr2v := rr2i.(int16)
128	if rr2v != c2 {
129		NoteFailure(9, 42, 2, "genChecker42", "return", 2, true, uint64(0))
130	}
131	rr3i := rvslice[3].Interface()
132	rr3v := rr3i.(float32)
133	if rr3v != c3 {
134		NoteFailure(9, 42, 2, "genChecker42", "return", 3, true, uint64(0))
135	}
136	rr4i := rvslice[4].Interface()
137	rr4v := rr4i.(int64)
138	if rr4v != c4 {
139		NoteFailure(9, 42, 2, "genChecker42", "return", 4, true, uint64(0))
140	}
141	EndFcn()
142}
143
144type StructF0S0 struct {
145}
146
147type ArrayF0S0E2 [2]int16
148
149type ArrayF0S1E1 [1]StructF0S0
150
151type StructF1S0 struct {
152	F0 StructF1S1
153	_  ArrayF1S0E4
154}
155
156type StructF1S1 struct {
157}
158
159type StructF1S2 struct {
160	F0 uint32
161	F1 uint8
162	F2 string
163	F3 string
164	F4 ArrayF1S1E1
165}
166
167type StructF1S3 struct {
168	F0 float64
169}
170
171type StructF1S4 struct {
172	_  int32
173	F1 float32
174}
175
176type StructF1S5 struct {
177	F0 uint16
178}
179
180type StructF1S6 struct {
181	F0 uint8
182	F1 uint32
183}
184
185type ArrayF1S0E4 [4]float64
186
187type ArrayF1S1E1 [1]StructF1S3
188
189type ArrayF1S2E2 [2]StructF1S4
190
191type ArrayF1S3E2 [2]StructF1S5
192
193type ArrayF1S4E4 [4]ArrayF1S5E3
194
195type ArrayF1S5E3 [3]string
196
197type ArrayF1S6E1 [1]float64
198
199type StructF2S0 struct {
200	F0 ArrayF2S1E1
201}
202
203// equal func for StructF2S0
204//go:noinline
205func EqualStructF2S0(left StructF2S0, right StructF2S0) bool {
206	return EqualArrayF2S1E1(left.F0, right.F0)
207}
208
209type StructF2S1 struct {
210	_  string
211	F1 string
212}
213
214type ArrayF2S0E0 [0]int8
215
216type ArrayF2S1E1 [1]*float64
217
218// equal func for ArrayF2S1E1
219//go:noinline
220func EqualArrayF2S1E1(left ArrayF2S1E1, right ArrayF2S1E1) bool {
221	return *left[0] == *right[0]
222}
223
224type ArrayF2S2E1 [1]StructF2S1
225
226// 5 returns 4 params
227//go:registerparams
228//go:noinline
229func Test2(p0 ArrayF2S0E0, p1 uint8, _ uint16, p3 float64) (r0 StructF2S0, r1 ArrayF2S2E1, r2 int16, r3 float32, r4 int64) {
230	// consume some stack space, so as to trigger morestack
231	var pad [16]uint64
232	pad[FailCount&0x1]++
233	rc0 := StructF2S0{F0: ArrayF2S1E1{New_3(float64(-0.4418990509835844))}}
234	rc1 := ArrayF2S2E1{StructF2S1{ /* _: "��(z̽|" */ F1: "����"}}
235	rc2 := int16(4162)
236	rc3 := float32(-7.667096e+37)
237	rc4 := int64(3202175648847048679)
238	p1f0c := uint8(57)
239	if p1 != p1f0c {
240		NoteFailureElem(9, 42, 2, "genChecker42", "parm", 1, 0, false, pad[0])
241		return
242	}
243	_ = uint16(10920)
244	p3f0c := float64(-1.597256501942112)
245	if p3 != p3f0c {
246		NoteFailureElem(9, 42, 2, "genChecker42", "parm", 3, 0, false, pad[0])
247		return
248	}
249	defer func(p0 ArrayF2S0E0, p1 uint8) {
250		// check parm passed
251		// check parm passed
252		if p1 != p1f0c {
253			NoteFailureElem(9, 42, 2, "genChecker42", "parm", 1, 0, false, pad[0])
254			return
255		}
256		// check parm captured
257		if p3 != p3f0c {
258			NoteFailureElem(9, 42, 2, "genChecker42", "parm", 3, 0, false, pad[0])
259			return
260		}
261	}(p0, p1)
262
263	return rc0, rc1, rc2, rc3, rc4
264	// 0 addr-taken params, 0 addr-taken returns
265}
266
267//go:noinline
268func New_3(i float64) *float64 {
269	x := new(float64)
270	*x = i
271	return x
272}
273