blob: b500de9f18a872aa0e2535e942ad0333571ffac3 [file] [log] [blame]
Than McIntosh89f38322020-11-24 18:10:11 -05001// Copyright 2020 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
David Chasec41b9992021-01-08 10:15:36 -05005package test
Than McIntosh89f38322020-11-24 18:10:11 -05006
7import (
8 "bufio"
David Chasec41b9992021-01-08 10:15:36 -05009 "cmd/compile/internal/abi"
Than McIntosh89f38322020-11-24 18:10:11 -050010 "cmd/compile/internal/base"
Russ Cox6c34d2f2020-12-23 00:57:10 -050011 "cmd/compile/internal/ssagen"
Russ Coxb9693d72020-12-23 00:41:49 -050012 "cmd/compile/internal/typecheck"
Than McIntosh89f38322020-11-24 18:10:11 -050013 "cmd/compile/internal/types"
14 "cmd/internal/obj"
15 "cmd/internal/obj/x86"
16 "cmd/internal/src"
Than McIntoshd19eece2021-04-29 11:47:18 -040017 "fmt"
Than McIntosh89f38322020-11-24 18:10:11 -050018 "os"
19 "testing"
20)
21
22// AMD64 registers available:
23// - integer: RAX, RBX, RCX, RDI, RSI, R8, R9, r10, R11
24// - floating point: X0 - X14
David Chasea9036392023-10-03 12:14:53 -040025var configAMD64 = abi.NewABIConfig(9, 15, 0, 1)
Than McIntosh89f38322020-11-24 18:10:11 -050026
27func TestMain(m *testing.M) {
Russ Cox6c34d2f2020-12-23 00:57:10 -050028 ssagen.Arch.LinkArch = &x86.Linkamd64
29 ssagen.Arch.REGSP = x86.REGSP
30 ssagen.Arch.MAXWIDTH = 1 << 50
31 types.MaxWidth = ssagen.Arch.MAXWIDTH
32 base.Ctxt = obj.Linknew(ssagen.Arch.LinkArch)
Than McIntosh89f38322020-11-24 18:10:11 -050033 base.Ctxt.DiagFunc = base.Errorf
34 base.Ctxt.DiagFlush = base.FlushErrors
35 base.Ctxt.Bso = bufio.NewWriter(os.Stdout)
Matthew Dempsky35d83532022-05-12 15:50:11 -070036 types.LocalPkg = types.NewPkg("p", "local")
37 types.LocalPkg.Prefix = "p"
Russ Cox6c34d2f2020-12-23 00:57:10 -050038 types.PtrSize = ssagen.Arch.LinkArch.PtrSize
39 types.RegSize = ssagen.Arch.LinkArch.RegSize
Matthew Dempsky3a4474c2020-12-31 23:39:15 -080040 typecheck.InitUniverse()
Than McIntosh89f38322020-11-24 18:10:11 -050041 os.Exit(m.Run())
42}
43
44func TestABIUtilsBasic1(t *testing.T) {
45
46 // func(x int32) int32
47 i32 := types.Types[types.TINT32]
48 ft := mkFuncType(nil, []*types.Type{i32}, []*types.Type{i32})
49
50 // expected results
51 exp := makeExpectedDump(`
David Chase5a76c3d2021-01-21 12:02:39 -050052 IN 0: R{ I0 } spilloffset: 0 typ: int32
53 OUT 0: R{ I0 } spilloffset: -1 typ: int32
54 offsetToSpillArea: 0 spillAreaSize: 8
Than McIntosh89f38322020-11-24 18:10:11 -050055`)
56
57 abitest(t, ft, exp)
58}
59
60func TestABIUtilsBasic2(t *testing.T) {
Than McIntosh2887ef42021-01-26 08:24:00 -050061 // func(p1 int8, p2 int16, p3 int32, p4 int64,
62 // p5 float32, p6 float32, p7 float64, p8 float64,
63 // p9 int8, p10 int16, p11 int32, p12 int64,
64 // p13 float32, p14 float32, p15 float64, p16 float64,
65 // p17 complex128, p18 complex128, p19 complex12, p20 complex128,
66 // p21 complex64, p22 int8, p23 in16, p24 int32, p25 int64,
67 // p26 int8, p27 in16, p28 int32, p29 int64)
68 // (r1 int32, r2 float64, r3 float64) {
Than McIntosh89f38322020-11-24 18:10:11 -050069 i8 := types.Types[types.TINT8]
70 i16 := types.Types[types.TINT16]
71 i32 := types.Types[types.TINT32]
72 i64 := types.Types[types.TINT64]
73 f32 := types.Types[types.TFLOAT32]
74 f64 := types.Types[types.TFLOAT64]
75 c64 := types.Types[types.TCOMPLEX64]
76 c128 := types.Types[types.TCOMPLEX128]
77 ft := mkFuncType(nil,
78 []*types.Type{
79 i8, i16, i32, i64,
80 f32, f32, f64, f64,
81 i8, i16, i32, i64,
82 f32, f32, f64, f64,
83 c128, c128, c128, c128, c64,
84 i8, i16, i32, i64,
85 i8, i16, i32, i64},
86 []*types.Type{i32, f64, f64})
87 exp := makeExpectedDump(`
David Chase5a76c3d2021-01-21 12:02:39 -050088 IN 0: R{ I0 } spilloffset: 0 typ: int8
89 IN 1: R{ I1 } spilloffset: 2 typ: int16
90 IN 2: R{ I2 } spilloffset: 4 typ: int32
91 IN 3: R{ I3 } spilloffset: 8 typ: int64
92 IN 4: R{ F0 } spilloffset: 16 typ: float32
93 IN 5: R{ F1 } spilloffset: 20 typ: float32
94 IN 6: R{ F2 } spilloffset: 24 typ: float64
95 IN 7: R{ F3 } spilloffset: 32 typ: float64
96 IN 8: R{ I4 } spilloffset: 40 typ: int8
97 IN 9: R{ I5 } spilloffset: 42 typ: int16
98 IN 10: R{ I6 } spilloffset: 44 typ: int32
99 IN 11: R{ I7 } spilloffset: 48 typ: int64
100 IN 12: R{ F4 } spilloffset: 56 typ: float32
101 IN 13: R{ F5 } spilloffset: 60 typ: float32
102 IN 14: R{ F6 } spilloffset: 64 typ: float64
103 IN 15: R{ F7 } spilloffset: 72 typ: float64
104 IN 16: R{ F8 F9 } spilloffset: 80 typ: complex128
105 IN 17: R{ F10 F11 } spilloffset: 96 typ: complex128
106 IN 18: R{ F12 F13 } spilloffset: 112 typ: complex128
107 IN 19: R{ } offset: 0 typ: complex128
108 IN 20: R{ } offset: 16 typ: complex64
109 IN 21: R{ I8 } spilloffset: 128 typ: int8
110 IN 22: R{ } offset: 24 typ: int16
111 IN 23: R{ } offset: 28 typ: int32
112 IN 24: R{ } offset: 32 typ: int64
113 IN 25: R{ } offset: 40 typ: int8
114 IN 26: R{ } offset: 42 typ: int16
115 IN 27: R{ } offset: 44 typ: int32
116 IN 28: R{ } offset: 48 typ: int64
117 OUT 0: R{ I0 } spilloffset: -1 typ: int32
118 OUT 1: R{ F0 } spilloffset: -1 typ: float64
119 OUT 2: R{ F1 } spilloffset: -1 typ: float64
120 offsetToSpillArea: 56 spillAreaSize: 136
Than McIntosh89f38322020-11-24 18:10:11 -0500121`)
122
123 abitest(t, ft, exp)
124}
125
126func TestABIUtilsArrays(t *testing.T) {
Than McIntosh2887ef42021-01-26 08:24:00 -0500127 // func(p1 [1]int32, p2 [0]int32, p3 [1][1]int32, p4 [2]int32)
128 // (r1 [2]int32, r2 [1]int32, r3 [0]int32, r4 [1][1]int32) {
Than McIntosh89f38322020-11-24 18:10:11 -0500129 i32 := types.Types[types.TINT32]
130 ae := types.NewArray(i32, 0)
131 a1 := types.NewArray(i32, 1)
132 a2 := types.NewArray(i32, 2)
133 aa1 := types.NewArray(a1, 1)
134 ft := mkFuncType(nil, []*types.Type{a1, ae, aa1, a2},
135 []*types.Type{a2, a1, ae, aa1})
136
137 exp := makeExpectedDump(`
David Chase5a76c3d2021-01-21 12:02:39 -0500138 IN 0: R{ I0 } spilloffset: 0 typ: [1]int32
139 IN 1: R{ } offset: 0 typ: [0]int32
140 IN 2: R{ I1 } spilloffset: 4 typ: [1][1]int32
141 IN 3: R{ } offset: 0 typ: [2]int32
142 OUT 0: R{ } offset: 8 typ: [2]int32
143 OUT 1: R{ I0 } spilloffset: -1 typ: [1]int32
144 OUT 2: R{ } offset: 16 typ: [0]int32
145 OUT 3: R{ I1 } spilloffset: -1 typ: [1][1]int32
146 offsetToSpillArea: 16 spillAreaSize: 8
Than McIntosh89f38322020-11-24 18:10:11 -0500147`)
148
149 abitest(t, ft, exp)
150}
151
152func TestABIUtilsStruct1(t *testing.T) {
Than McIntosh2887ef42021-01-26 08:24:00 -0500153 // type s struct { f1 int8; f2 int8; f3 struct {}; f4 int8; f5 int16) }
154 // func(p1 int6, p2 s, p3 int64)
155 // (r1 s, r2 int8, r3 int32) {
Than McIntosh89f38322020-11-24 18:10:11 -0500156 i8 := types.Types[types.TINT8]
157 i16 := types.Types[types.TINT16]
158 i32 := types.Types[types.TINT32]
159 i64 := types.Types[types.TINT64]
Matthew Dempskyc0e2a9d2023-09-11 21:13:10 -0700160 s := mkstruct(i8, i8, mkstruct(), i8, i16)
Than McIntosh89f38322020-11-24 18:10:11 -0500161 ft := mkFuncType(nil, []*types.Type{i8, s, i64},
162 []*types.Type{s, i8, i32})
163
164 exp := makeExpectedDump(`
David Chase5a76c3d2021-01-21 12:02:39 -0500165 IN 0: R{ I0 } spilloffset: 0 typ: int8
166 IN 1: R{ I1 I2 I3 I4 } spilloffset: 2 typ: struct { int8; int8; struct {}; int8; int16 }
167 IN 2: R{ I5 } spilloffset: 8 typ: int64
168 OUT 0: R{ I0 I1 I2 I3 } spilloffset: -1 typ: struct { int8; int8; struct {}; int8; int16 }
169 OUT 1: R{ I4 } spilloffset: -1 typ: int8
170 OUT 2: R{ I5 } spilloffset: -1 typ: int32
171 offsetToSpillArea: 0 spillAreaSize: 16
Than McIntosh89f38322020-11-24 18:10:11 -0500172`)
173
174 abitest(t, ft, exp)
175}
176
177func TestABIUtilsStruct2(t *testing.T) {
Than McIntosh2887ef42021-01-26 08:24:00 -0500178 // type s struct { f1 int64; f2 struct { } }
179 // type fs struct { f1 float64; f2 s; f3 struct { } }
180 // func(p1 s, p2 s, p3 fs)
181 // (r1 fs, r2 fs)
Than McIntosh89f38322020-11-24 18:10:11 -0500182 f64 := types.Types[types.TFLOAT64]
183 i64 := types.Types[types.TINT64]
Matthew Dempskyc0e2a9d2023-09-11 21:13:10 -0700184 s := mkstruct(i64, mkstruct())
185 fs := mkstruct(f64, s, mkstruct())
Than McIntosh89f38322020-11-24 18:10:11 -0500186 ft := mkFuncType(nil, []*types.Type{s, s, fs},
187 []*types.Type{fs, fs})
188
189 exp := makeExpectedDump(`
David Chase5a76c3d2021-01-21 12:02:39 -0500190 IN 0: R{ I0 } spilloffset: 0 typ: struct { int64; struct {} }
191 IN 1: R{ I1 } spilloffset: 16 typ: struct { int64; struct {} }
David Chase382851c2021-03-07 14:00:10 -0500192 IN 2: R{ F0 I2 } spilloffset: 32 typ: struct { float64; struct { int64; struct {} }; struct {} }
193 OUT 0: R{ F0 I0 } spilloffset: -1 typ: struct { float64; struct { int64; struct {} }; struct {} }
194 OUT 1: R{ F1 I1 } spilloffset: -1 typ: struct { float64; struct { int64; struct {} }; struct {} }
David Chase5a76c3d2021-01-21 12:02:39 -0500195 offsetToSpillArea: 0 spillAreaSize: 64
Than McIntosh89f38322020-11-24 18:10:11 -0500196`)
197
198 abitest(t, ft, exp)
199}
200
Than McIntosh2887ef42021-01-26 08:24:00 -0500201// TestABIUtilsEmptyFieldAtEndOfStruct is testing to make sure
202// the abi code is doing the right thing for struct types that have
203// a trailing zero-sized field (where the we need to add padding).
204func TestABIUtilsEmptyFieldAtEndOfStruct(t *testing.T) {
205 // type s struct { f1 [2]int64; f2 struct { } }
206 // type s2 struct { f1 [3]int16; f2 struct { } }
207 // type fs struct { f1 float64; f s; f3 struct { } }
208 // func(p1 s, p2 s, p3 fs) (r1 fs, r2 fs)
209 f64 := types.Types[types.TFLOAT64]
210 i64 := types.Types[types.TINT64]
211 i16 := types.Types[types.TINT16]
212 tb := types.Types[types.TBOOL]
213 ab2 := types.NewArray(tb, 2)
214 a2 := types.NewArray(i64, 2)
215 a3 := types.NewArray(i16, 3)
Matthew Dempskyc0e2a9d2023-09-11 21:13:10 -0700216 empty := mkstruct()
217 s := mkstruct(a2, empty)
218 s2 := mkstruct(a3, empty)
219 fs := mkstruct(f64, s, empty)
Than McIntosh2887ef42021-01-26 08:24:00 -0500220 ft := mkFuncType(nil, []*types.Type{s, ab2, s2, fs, fs},
221 []*types.Type{fs, ab2, fs})
222
223 exp := makeExpectedDump(`
224 IN 0: R{ } offset: 0 typ: struct { [2]int64; struct {} }
225 IN 1: R{ } offset: 24 typ: [2]bool
226 IN 2: R{ } offset: 26 typ: struct { [3]int16; struct {} }
227 IN 3: R{ } offset: 40 typ: struct { float64; struct { [2]int64; struct {} }; struct {} }
228 IN 4: R{ } offset: 80 typ: struct { float64; struct { [2]int64; struct {} }; struct {} }
229 OUT 0: R{ } offset: 120 typ: struct { float64; struct { [2]int64; struct {} }; struct {} }
230 OUT 1: R{ } offset: 160 typ: [2]bool
231 OUT 2: R{ } offset: 168 typ: struct { float64; struct { [2]int64; struct {} }; struct {} }
232 offsetToSpillArea: 208 spillAreaSize: 0
233`)
234
235 abitest(t, ft, exp)
236
Matthew Dempskyc0e2a9d2023-09-11 21:13:10 -0700237 // Test that NumParamRegs doesn't assign registers to trailing padding.
238 typ := mkstruct(i64, i64, mkstruct())
239 have := configAMD64.NumParamRegs(typ)
240 if have != 2 {
241 t.Errorf("NumParams(%v): have %v, want %v", typ, have, 2)
Than McIntosh2887ef42021-01-26 08:24:00 -0500242 }
243}
244
Than McIntosh89f38322020-11-24 18:10:11 -0500245func TestABIUtilsSliceString(t *testing.T) {
Than McIntosh2887ef42021-01-26 08:24:00 -0500246 // func(p1 []int32, p2 int8, p3 []int32, p4 int8, p5 string,
247 // p6 int64, p6 []intr32) (r1 string, r2 int64, r3 string, r4 []int32)
Than McIntosh89f38322020-11-24 18:10:11 -0500248 i32 := types.Types[types.TINT32]
249 sli32 := types.NewSlice(i32)
Matthew Dempskya9377182021-08-26 19:18:57 -0700250 str := types.Types[types.TSTRING]
Than McIntosh89f38322020-11-24 18:10:11 -0500251 i8 := types.Types[types.TINT8]
252 i64 := types.Types[types.TINT64]
253 ft := mkFuncType(nil, []*types.Type{sli32, i8, sli32, i8, str, i8, i64, sli32},
254 []*types.Type{str, i64, str, sli32})
255
256 exp := makeExpectedDump(`
David Chase5a76c3d2021-01-21 12:02:39 -0500257 IN 0: R{ I0 I1 I2 } spilloffset: 0 typ: []int32
258 IN 1: R{ I3 } spilloffset: 24 typ: int8
259 IN 2: R{ I4 I5 I6 } spilloffset: 32 typ: []int32
260 IN 3: R{ I7 } spilloffset: 56 typ: int8
261 IN 4: R{ } offset: 0 typ: string
262 IN 5: R{ I8 } spilloffset: 57 typ: int8
263 IN 6: R{ } offset: 16 typ: int64
264 IN 7: R{ } offset: 24 typ: []int32
265 OUT 0: R{ I0 I1 } spilloffset: -1 typ: string
266 OUT 1: R{ I2 } spilloffset: -1 typ: int64
267 OUT 2: R{ I3 I4 } spilloffset: -1 typ: string
268 OUT 3: R{ I5 I6 I7 } spilloffset: -1 typ: []int32
269 offsetToSpillArea: 48 spillAreaSize: 64
Than McIntosh89f38322020-11-24 18:10:11 -0500270`)
271
272 abitest(t, ft, exp)
273}
274
275func TestABIUtilsMethod(t *testing.T) {
Than McIntosh2887ef42021-01-26 08:24:00 -0500276 // type s1 struct { f1 int16; f2 int16; f3 int16 }
277 // func(p1 *s1, p2 [7]*s1, p3 float64, p4 int16, p5 int16, p6 int16)
278 // (r1 [7]*s1, r2 float64, r3 int64)
Than McIntosh89f38322020-11-24 18:10:11 -0500279 i16 := types.Types[types.TINT16]
280 i64 := types.Types[types.TINT64]
281 f64 := types.Types[types.TFLOAT64]
Matthew Dempskyc0e2a9d2023-09-11 21:13:10 -0700282 s1 := mkstruct(i16, i16, i16)
Than McIntosh89f38322020-11-24 18:10:11 -0500283 ps1 := types.NewPtr(s1)
284 a7 := types.NewArray(ps1, 7)
285 ft := mkFuncType(s1, []*types.Type{ps1, a7, f64, i16, i16, i16},
286 []*types.Type{a7, f64, i64})
287
288 exp := makeExpectedDump(`
David Chase5a76c3d2021-01-21 12:02:39 -0500289 IN 0: R{ I0 I1 I2 } spilloffset: 0 typ: struct { int16; int16; int16 }
290 IN 1: R{ I3 } spilloffset: 8 typ: *struct { int16; int16; int16 }
291 IN 2: R{ } offset: 0 typ: [7]*struct { int16; int16; int16 }
292 IN 3: R{ F0 } spilloffset: 16 typ: float64
293 IN 4: R{ I4 } spilloffset: 24 typ: int16
294 IN 5: R{ I5 } spilloffset: 26 typ: int16
295 IN 6: R{ I6 } spilloffset: 28 typ: int16
296 OUT 0: R{ } offset: 56 typ: [7]*struct { int16; int16; int16 }
297 OUT 1: R{ F0 } spilloffset: -1 typ: float64
298 OUT 2: R{ I0 } spilloffset: -1 typ: int64
299 offsetToSpillArea: 112 spillAreaSize: 32
Than McIntosh89f38322020-11-24 18:10:11 -0500300`)
301
302 abitest(t, ft, exp)
303}
304
305func TestABIUtilsInterfaces(t *testing.T) {
Than McIntosh2887ef42021-01-26 08:24:00 -0500306 // type s1 { f1 int16; f2 int16; f3 bool)
307 // type nei interface { ...() string }
308 // func(p1 s1, p2 interface{}, p3 interface{}, p4 nei,
309 // p5 *interface{}, p6 nei, p7 int64)
310 // (r1 interface{}, r2 nei, r3 bool)
Than McIntosh89f38322020-11-24 18:10:11 -0500311 ei := types.Types[types.TINTER] // interface{}
312 pei := types.NewPtr(ei) // *interface{}
313 fldt := mkFuncType(types.FakeRecvType(), []*types.Type{},
Matthew Dempsky42fe1322021-07-07 16:15:53 -0700314 []*types.Type{types.Types[types.TSTRING]})
315 field := types.NewField(src.NoXPos, typecheck.Lookup("F"), fldt)
Matthew Dempskyf0b15632022-12-01 17:42:02 -0800316 nei := types.NewInterface([]*types.Field{field})
Than McIntosh89f38322020-11-24 18:10:11 -0500317 i16 := types.Types[types.TINT16]
318 tb := types.Types[types.TBOOL]
Matthew Dempskyc0e2a9d2023-09-11 21:13:10 -0700319 s1 := mkstruct(i16, i16, tb)
Than McIntosh89f38322020-11-24 18:10:11 -0500320 ft := mkFuncType(nil, []*types.Type{s1, ei, ei, nei, pei, nei, i16},
321 []*types.Type{ei, nei, pei})
322
323 exp := makeExpectedDump(`
David Chase5a76c3d2021-01-21 12:02:39 -0500324 IN 0: R{ I0 I1 I2 } spilloffset: 0 typ: struct { int16; int16; bool }
325 IN 1: R{ I3 I4 } spilloffset: 8 typ: interface {}
326 IN 2: R{ I5 I6 } spilloffset: 24 typ: interface {}
Matthew Dempsky42fe1322021-07-07 16:15:53 -0700327 IN 3: R{ I7 I8 } spilloffset: 40 typ: interface { F() string }
David Chase5a76c3d2021-01-21 12:02:39 -0500328 IN 4: R{ } offset: 0 typ: *interface {}
Matthew Dempsky42fe1322021-07-07 16:15:53 -0700329 IN 5: R{ } offset: 8 typ: interface { F() string }
David Chase5a76c3d2021-01-21 12:02:39 -0500330 IN 6: R{ } offset: 24 typ: int16
331 OUT 0: R{ I0 I1 } spilloffset: -1 typ: interface {}
Matthew Dempsky42fe1322021-07-07 16:15:53 -0700332 OUT 1: R{ I2 I3 } spilloffset: -1 typ: interface { F() string }
David Chase5a76c3d2021-01-21 12:02:39 -0500333 OUT 2: R{ I4 } spilloffset: -1 typ: *interface {}
334 offsetToSpillArea: 32 spillAreaSize: 56
Than McIntosh89f38322020-11-24 18:10:11 -0500335`)
336
337 abitest(t, ft, exp)
338}
David Chase5a76c3d2021-01-21 12:02:39 -0500339
340func TestABINumParamRegs(t *testing.T) {
341 i8 := types.Types[types.TINT8]
342 i16 := types.Types[types.TINT16]
343 i32 := types.Types[types.TINT32]
344 i64 := types.Types[types.TINT64]
345 f32 := types.Types[types.TFLOAT32]
346 f64 := types.Types[types.TFLOAT64]
347 c64 := types.Types[types.TCOMPLEX64]
348 c128 := types.Types[types.TCOMPLEX128]
349
Matthew Dempskyc0e2a9d2023-09-11 21:13:10 -0700350 s := mkstruct(i8, i8, mkstruct(), i8, i16)
351 a := mkstruct(s, s, s)
David Chase5a76c3d2021-01-21 12:02:39 -0500352
353 nrtest(t, i8, 1)
354 nrtest(t, i16, 1)
355 nrtest(t, i32, 1)
356 nrtest(t, i64, 1)
357 nrtest(t, f32, 1)
358 nrtest(t, f64, 1)
359 nrtest(t, c64, 2)
360 nrtest(t, c128, 2)
361 nrtest(t, s, 4)
362 nrtest(t, a, 12)
Cherry Zhang70c37ee2021-02-16 17:55:27 -0500363}
Than McIntoshd19eece2021-04-29 11:47:18 -0400364
365func TestABIUtilsComputePadding(t *testing.T) {
366 // type s1 { f1 int8; f2 int16; f3 struct{}; f4 int32; f5 int64 }
367 i8 := types.Types[types.TINT8]
368 i16 := types.Types[types.TINT16]
369 i32 := types.Types[types.TINT32]
370 i64 := types.Types[types.TINT64]
Matthew Dempskyc0e2a9d2023-09-11 21:13:10 -0700371 emptys := mkstruct()
372 s1 := mkstruct(i8, i16, emptys, i32, i64)
Than McIntoshd19eece2021-04-29 11:47:18 -0400373 // func (p1 int32, p2 s1, p3 emptys, p4 [1]int32)
374 a1 := types.NewArray(i32, 1)
Matthew Dempskyc0e2a9d2023-09-11 21:13:10 -0700375 ft := mkFuncType(nil, []*types.Type{i32, s1, emptys, a1}, nil)
Than McIntoshd19eece2021-04-29 11:47:18 -0400376
377 // Run abitest() just to document what we're expected to see.
378 exp := makeExpectedDump(`
379 IN 0: R{ I0 } spilloffset: 0 typ: int32
380 IN 1: R{ I1 I2 I3 I4 } spilloffset: 8 typ: struct { int8; int16; struct {}; int32; int64 }
381 IN 2: R{ } offset: 0 typ: struct {}
382 IN 3: R{ I5 } spilloffset: 24 typ: [1]int32
383 offsetToSpillArea: 0 spillAreaSize: 32
384`)
385 abitest(t, ft, exp)
386
387 // Analyze with full set of registers, then call ComputePadding
388 // on the second param, verifying the results.
389 regRes := configAMD64.ABIAnalyze(ft, false)
390 padding := make([]uint64, 32)
391 parm := regRes.InParams()[1]
392 padding = parm.ComputePadding(padding)
393 want := "[1 1 1 0]"
394 got := fmt.Sprintf("%+v", padding)
395 if got != want {
396 t.Errorf("padding mismatch: wanted %q got %q\n", got, want)
397 }
398}