Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 1 | // 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 Chase | c41b999 | 2021-01-08 10:15:36 -0500 | [diff] [blame] | 5 | package test |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 6 | |
| 7 | import ( |
| 8 | "bufio" |
David Chase | c41b999 | 2021-01-08 10:15:36 -0500 | [diff] [blame] | 9 | "cmd/compile/internal/abi" |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 10 | "cmd/compile/internal/base" |
Russ Cox | 6c34d2f | 2020-12-23 00:57:10 -0500 | [diff] [blame] | 11 | "cmd/compile/internal/ssagen" |
Russ Cox | b9693d7 | 2020-12-23 00:41:49 -0500 | [diff] [blame] | 12 | "cmd/compile/internal/typecheck" |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 13 | "cmd/compile/internal/types" |
| 14 | "cmd/internal/obj" |
| 15 | "cmd/internal/obj/x86" |
| 16 | "cmd/internal/src" |
Than McIntosh | d19eece | 2021-04-29 11:47:18 -0400 | [diff] [blame] | 17 | "fmt" |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 18 | "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 Chase | a903639 | 2023-10-03 12:14:53 -0400 | [diff] [blame] | 25 | var configAMD64 = abi.NewABIConfig(9, 15, 0, 1) |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 26 | |
| 27 | func TestMain(m *testing.M) { |
Russ Cox | 6c34d2f | 2020-12-23 00:57:10 -0500 | [diff] [blame] | 28 | 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 33 | base.Ctxt.DiagFunc = base.Errorf |
| 34 | base.Ctxt.DiagFlush = base.FlushErrors |
| 35 | base.Ctxt.Bso = bufio.NewWriter(os.Stdout) |
Matthew Dempsky | 35d8353 | 2022-05-12 15:50:11 -0700 | [diff] [blame] | 36 | types.LocalPkg = types.NewPkg("p", "local") |
| 37 | types.LocalPkg.Prefix = "p" |
Russ Cox | 6c34d2f | 2020-12-23 00:57:10 -0500 | [diff] [blame] | 38 | types.PtrSize = ssagen.Arch.LinkArch.PtrSize |
| 39 | types.RegSize = ssagen.Arch.LinkArch.RegSize |
Matthew Dempsky | 3a4474c | 2020-12-31 23:39:15 -0800 | [diff] [blame] | 40 | typecheck.InitUniverse() |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 41 | os.Exit(m.Run()) |
| 42 | } |
| 43 | |
| 44 | func 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 Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 52 | IN 0: R{ I0 } spilloffset: 0 typ: int32 |
| 53 | OUT 0: R{ I0 } spilloffset: -1 typ: int32 |
| 54 | offsetToSpillArea: 0 spillAreaSize: 8 |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 55 | `) |
| 56 | |
| 57 | abitest(t, ft, exp) |
| 58 | } |
| 59 | |
| 60 | func TestABIUtilsBasic2(t *testing.T) { |
Than McIntosh | 2887ef4 | 2021-01-26 08:24:00 -0500 | [diff] [blame] | 61 | // 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 69 | 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 Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 88 | 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 121 | `) |
| 122 | |
| 123 | abitest(t, ft, exp) |
| 124 | } |
| 125 | |
| 126 | func TestABIUtilsArrays(t *testing.T) { |
Than McIntosh | 2887ef4 | 2021-01-26 08:24:00 -0500 | [diff] [blame] | 127 | // 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 129 | 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 Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 138 | 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 147 | `) |
| 148 | |
| 149 | abitest(t, ft, exp) |
| 150 | } |
| 151 | |
| 152 | func TestABIUtilsStruct1(t *testing.T) { |
Than McIntosh | 2887ef4 | 2021-01-26 08:24:00 -0500 | [diff] [blame] | 153 | // 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 156 | i8 := types.Types[types.TINT8] |
| 157 | i16 := types.Types[types.TINT16] |
| 158 | i32 := types.Types[types.TINT32] |
| 159 | i64 := types.Types[types.TINT64] |
Matthew Dempsky | c0e2a9d | 2023-09-11 21:13:10 -0700 | [diff] [blame] | 160 | s := mkstruct(i8, i8, mkstruct(), i8, i16) |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 161 | ft := mkFuncType(nil, []*types.Type{i8, s, i64}, |
| 162 | []*types.Type{s, i8, i32}) |
| 163 | |
| 164 | exp := makeExpectedDump(` |
David Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 165 | 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 172 | `) |
| 173 | |
| 174 | abitest(t, ft, exp) |
| 175 | } |
| 176 | |
| 177 | func TestABIUtilsStruct2(t *testing.T) { |
Than McIntosh | 2887ef4 | 2021-01-26 08:24:00 -0500 | [diff] [blame] | 178 | // 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 182 | f64 := types.Types[types.TFLOAT64] |
| 183 | i64 := types.Types[types.TINT64] |
Matthew Dempsky | c0e2a9d | 2023-09-11 21:13:10 -0700 | [diff] [blame] | 184 | s := mkstruct(i64, mkstruct()) |
| 185 | fs := mkstruct(f64, s, mkstruct()) |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 186 | ft := mkFuncType(nil, []*types.Type{s, s, fs}, |
| 187 | []*types.Type{fs, fs}) |
| 188 | |
| 189 | exp := makeExpectedDump(` |
David Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 190 | IN 0: R{ I0 } spilloffset: 0 typ: struct { int64; struct {} } |
| 191 | IN 1: R{ I1 } spilloffset: 16 typ: struct { int64; struct {} } |
David Chase | 382851c | 2021-03-07 14:00:10 -0500 | [diff] [blame] | 192 | 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 Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 195 | offsetToSpillArea: 0 spillAreaSize: 64 |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 196 | `) |
| 197 | |
| 198 | abitest(t, ft, exp) |
| 199 | } |
| 200 | |
Than McIntosh | 2887ef4 | 2021-01-26 08:24:00 -0500 | [diff] [blame] | 201 | // 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). |
| 204 | func 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 Dempsky | c0e2a9d | 2023-09-11 21:13:10 -0700 | [diff] [blame] | 216 | empty := mkstruct() |
| 217 | s := mkstruct(a2, empty) |
| 218 | s2 := mkstruct(a3, empty) |
| 219 | fs := mkstruct(f64, s, empty) |
Than McIntosh | 2887ef4 | 2021-01-26 08:24:00 -0500 | [diff] [blame] | 220 | 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 Dempsky | c0e2a9d | 2023-09-11 21:13:10 -0700 | [diff] [blame] | 237 | // 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 McIntosh | 2887ef4 | 2021-01-26 08:24:00 -0500 | [diff] [blame] | 242 | } |
| 243 | } |
| 244 | |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 245 | func TestABIUtilsSliceString(t *testing.T) { |
Than McIntosh | 2887ef4 | 2021-01-26 08:24:00 -0500 | [diff] [blame] | 246 | // 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 248 | i32 := types.Types[types.TINT32] |
| 249 | sli32 := types.NewSlice(i32) |
Matthew Dempsky | a937718 | 2021-08-26 19:18:57 -0700 | [diff] [blame] | 250 | str := types.Types[types.TSTRING] |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 251 | 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 Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 257 | 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 270 | `) |
| 271 | |
| 272 | abitest(t, ft, exp) |
| 273 | } |
| 274 | |
| 275 | func TestABIUtilsMethod(t *testing.T) { |
Than McIntosh | 2887ef4 | 2021-01-26 08:24:00 -0500 | [diff] [blame] | 276 | // 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 279 | i16 := types.Types[types.TINT16] |
| 280 | i64 := types.Types[types.TINT64] |
| 281 | f64 := types.Types[types.TFLOAT64] |
Matthew Dempsky | c0e2a9d | 2023-09-11 21:13:10 -0700 | [diff] [blame] | 282 | s1 := mkstruct(i16, i16, i16) |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 283 | 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 Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 289 | 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 300 | `) |
| 301 | |
| 302 | abitest(t, ft, exp) |
| 303 | } |
| 304 | |
| 305 | func TestABIUtilsInterfaces(t *testing.T) { |
Than McIntosh | 2887ef4 | 2021-01-26 08:24:00 -0500 | [diff] [blame] | 306 | // 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 McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 311 | ei := types.Types[types.TINTER] // interface{} |
| 312 | pei := types.NewPtr(ei) // *interface{} |
| 313 | fldt := mkFuncType(types.FakeRecvType(), []*types.Type{}, |
Matthew Dempsky | 42fe132 | 2021-07-07 16:15:53 -0700 | [diff] [blame] | 314 | []*types.Type{types.Types[types.TSTRING]}) |
| 315 | field := types.NewField(src.NoXPos, typecheck.Lookup("F"), fldt) |
Matthew Dempsky | f0b1563 | 2022-12-01 17:42:02 -0800 | [diff] [blame] | 316 | nei := types.NewInterface([]*types.Field{field}) |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 317 | i16 := types.Types[types.TINT16] |
| 318 | tb := types.Types[types.TBOOL] |
Matthew Dempsky | c0e2a9d | 2023-09-11 21:13:10 -0700 | [diff] [blame] | 319 | s1 := mkstruct(i16, i16, tb) |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 320 | ft := mkFuncType(nil, []*types.Type{s1, ei, ei, nei, pei, nei, i16}, |
| 321 | []*types.Type{ei, nei, pei}) |
| 322 | |
| 323 | exp := makeExpectedDump(` |
David Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 324 | 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 Dempsky | 42fe132 | 2021-07-07 16:15:53 -0700 | [diff] [blame] | 327 | IN 3: R{ I7 I8 } spilloffset: 40 typ: interface { F() string } |
David Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 328 | IN 4: R{ } offset: 0 typ: *interface {} |
Matthew Dempsky | 42fe132 | 2021-07-07 16:15:53 -0700 | [diff] [blame] | 329 | IN 5: R{ } offset: 8 typ: interface { F() string } |
David Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 330 | IN 6: R{ } offset: 24 typ: int16 |
| 331 | OUT 0: R{ I0 I1 } spilloffset: -1 typ: interface {} |
Matthew Dempsky | 42fe132 | 2021-07-07 16:15:53 -0700 | [diff] [blame] | 332 | OUT 1: R{ I2 I3 } spilloffset: -1 typ: interface { F() string } |
David Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 333 | OUT 2: R{ I4 } spilloffset: -1 typ: *interface {} |
| 334 | offsetToSpillArea: 32 spillAreaSize: 56 |
Than McIntosh | 89f3832 | 2020-11-24 18:10:11 -0500 | [diff] [blame] | 335 | `) |
| 336 | |
| 337 | abitest(t, ft, exp) |
| 338 | } |
David Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 339 | |
| 340 | func 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 Dempsky | c0e2a9d | 2023-09-11 21:13:10 -0700 | [diff] [blame] | 350 | s := mkstruct(i8, i8, mkstruct(), i8, i16) |
| 351 | a := mkstruct(s, s, s) |
David Chase | 5a76c3d | 2021-01-21 12:02:39 -0500 | [diff] [blame] | 352 | |
| 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 Zhang | 70c37ee | 2021-02-16 17:55:27 -0500 | [diff] [blame] | 363 | } |
Than McIntosh | d19eece | 2021-04-29 11:47:18 -0400 | [diff] [blame] | 364 | |
| 365 | func 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 Dempsky | c0e2a9d | 2023-09-11 21:13:10 -0700 | [diff] [blame] | 371 | emptys := mkstruct() |
| 372 | s1 := mkstruct(i8, i16, emptys, i32, i64) |
Than McIntosh | d19eece | 2021-04-29 11:47:18 -0400 | [diff] [blame] | 373 | // func (p1 int32, p2 s1, p3 emptys, p4 [1]int32) |
| 374 | a1 := types.NewArray(i32, 1) |
Matthew Dempsky | c0e2a9d | 2023-09-11 21:13:10 -0700 | [diff] [blame] | 375 | ft := mkFuncType(nil, []*types.Type{i32, s1, emptys, a1}, nil) |
Than McIntosh | d19eece | 2021-04-29 11:47:18 -0400 | [diff] [blame] | 376 | |
| 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 | } |