1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2024 The Ebitengine Authors
3
4#include <stdint.h>
5#include <stdio.h>
6#include <stdlib.h>
7
8// Empty is empty
9struct Empty {};
10
11// NoStruct tests that an empty struct doesn't cause issues
12uint64_t NoStruct(struct Empty e) {
13 return 0xdeadbeef;
14}
15
16struct EmptyEmpty {
17 struct Empty x;
18};
19
20uint64_t EmptyEmpty(struct EmptyEmpty e) {
21 return 0xdeadbeef;
22}
23
24uint64_t EmptyEmptyWithReg(unsigned int x, struct EmptyEmpty e, unsigned int y) {
25 return (x << 16) | y;
26}
27
28// GreaterThan16Bytes is 24 bytes on 64 bit systems
29struct GreaterThan16Bytes {
30 int64_t *x, *y, *z;
31};
32
33// GreaterThan16Bytes is a basic test for structs bigger than 16 bytes
34uint64_t GreaterThan16Bytes(struct GreaterThan16Bytes g) {
35 return *g.x + *g.y + *g.z;
36}
37
38// AfterRegisters tests to make sure that structs placed on the stack work properly
39uint64_t AfterRegisters(intptr_t a, intptr_t b, intptr_t c, intptr_t d, intptr_t e, intptr_t f, intptr_t g, intptr_t h, struct GreaterThan16Bytes bytes) {
40 intptr_t registers = a + b + c + d + e + f + g + h;
41 int64_t stack = *bytes.x + *bytes.y + *bytes.z;
42 if (registers != stack) {
43 return 0xbadbad;
44 }
45 if (stack != 0xdeadbeef) {
46 return 0xcafebad;
47 }
48 return stack;
49}
50
51uint64_t BeforeRegisters(struct GreaterThan16Bytes bytes, int64_t a, int64_t b) {
52 return *bytes.x + *bytes.y + *bytes.z + a + b;
53}
54
55struct GreaterThan16BytesStruct {
56 struct {
57 int64_t *x, *y, *z;
58 } a ;
59};
60
61uint64_t GreaterThan16BytesStruct(struct GreaterThan16BytesStruct g) {
62 return *(g.a.x) + *(g.a.y) + *(g.a.z);
63}
64
65struct IntLessThan16Bytes {
66 int64_t x, y;
67};
68
69uint64_t IntLessThan16Bytes(struct IntLessThan16Bytes l) {
70 return l.x + l.y;
71}
72
73struct FloatLessThan16Bytes {
74 float x, y;
75};
76
77float FloatLessThan16Bytes(struct FloatLessThan16Bytes f) {
78 return f.x + f.y;
79}
80
81struct ThreeSmallFields {
82 float x, y, z;
83};
84
85float ThreeSmallFields(struct ThreeSmallFields f) {
86 return f.x + f.y + f.z;
87}
88
89struct FloatAndInt {
90 float x;
91 int y;
92};
93
94float FloatAndInt(struct FloatAndInt f) {
95 return f.x + f.y;
96}
97
98struct DoubleStruct {
99 double x;
100};
101
102double DoubleStruct(struct DoubleStruct d) {
103 return d.x;
104}
105
106struct TwoDoubleStruct {
107 double x, y;
108};
109
110double TwoDoubleStruct(struct TwoDoubleStruct d) {
111 return d.x + d.y;
112}
113
114struct TwoDoubleTwoStruct {
115 struct {
116 double x, y;
117 } s;
118};
119
120double TwoDoubleTwoStruct(struct TwoDoubleTwoStruct d) {
121 return d.s.x + d.s.y;
122}
123
124struct ThreeDoubleStruct {
125 double x, y, z;
126};
127
128double ThreeDoubleStruct(struct ThreeDoubleStruct d) {
129 return d.x + d.y + d.z;
130}
131
132struct LargeFloatStruct {
133 double a, b, c, d, e, f;
134};
135
136double LargeFloatStruct(struct LargeFloatStruct s) {
137 return s.a + s.b + s.c + s.d + s.e + s.f;
138}
139
140double LargeFloatStructWithRegs(double a, double b, double c, struct LargeFloatStruct s) {
141 return a + b + c + s.a + s.b + s.c + s.d + s.e + s.f;
142}
143
144struct Rect {
145 double x, y, w, h;
146};
147
148double Rectangle(struct Rect rect) {
149 return rect.x + rect.y + rect.w + rect.h;
150}
151
152double RectangleSubtract(struct Rect rect) {
153 return (rect.x + rect.y) - (rect.w + rect.h);
154}
155
156double RectangleWithRegs(double a, double b, double c, double d, double e, struct Rect rect) {
157 return a + b + c + d + e + rect.x + rect.y + rect.w + rect.h;
158}
159
160struct FloatArray {
161 double a[2];
162};
163
164double FloatArray(struct FloatArray f) {
165 return f.a[0] + f.a[1];
166}
167
168struct UnsignedChar4Bytes {
169 unsigned char a, b, c, d;
170};
171
172unsigned int UnsignedChar4Bytes(struct UnsignedChar4Bytes b) {
173 return (((int)b.a)<<24) | (((int)b.b)<<16) | (((int)b.c)<<8) | (((int)b.d)<<0);
174}
175
176struct UnsignedChar4BytesStruct {
177 struct {
178 unsigned char a;
179 } x;
180 struct {
181 unsigned char b;
182 } y;
183 struct {
184 unsigned char c;
185 } z;
186 struct {
187 unsigned char d;
188 } w;
189};
190
191unsigned int UnsignedChar4BytesStruct(struct UnsignedChar4BytesStruct b) {
192 return (((int)b.x.a)<<24) | (((int)b.y.b)<<16) | (((int)b.z.c)<<8) | (((int)b.w.d)<<0);
193}
194
195struct Short {
196 unsigned short a, b, c, d;
197};
198
199uint64_t Short(struct Short s) {
200 return (uint64_t)s.a << 48 | (uint64_t)s.b << 32 | (uint64_t)s.c << 16 | (uint64_t)s.d << 0;
201}
202
203struct Int {
204 unsigned int a, b;
205};
206
207uint64_t Int(struct Int i) {
208 return (uint64_t)i.a << 32 | (uint64_t)i.b << 0;
209}
210
211struct Long {
212 uint64_t a;
213};
214
215uint64_t Long(struct Long l) {
216 return l.a;
217}
218
219struct Char8Bytes {
220 signed char a, b, c, d, e, f, g, h;
221};
222
223int Char8Bytes(struct Char8Bytes b) {
224 return (int)b.a + (int)b.b + (int)b.c + (int)b.d + (int)b.e + (int)b.f + (int)b.g + (int)b.h;
225}
226
227struct Odd {
228 unsigned char a, b, c;
229};
230
231int Odd(struct Odd o) {
232 return (int)o.a + (int)o.b + (int)o.c;
233}
234
235struct Char2Short1 {
236 unsigned char a, b;
237 unsigned short c;
238};
239
240int Char2Short1s(struct Char2Short1 s) {
241 return (int)s.a + (int)s.b + (int)s.c;
242}
243
244struct SignedChar2Short1 {
245 signed char a, b;
246 signed short c;
247};
248
249int SignedChar2Short1(struct SignedChar2Short1 s) {
250 return s.a + s.b + s.c;
251}
252
253struct Array4UnsignedChars {
254 unsigned char a[4];
255};
256
257unsigned int Array4UnsignedChars(struct Array4UnsignedChars a) {
258 return (((int)a.a[0])<<24) | (((int)a.a[1])<<16) | (((int)a.a[2])<<8) | (((int)a.a[3])<<0);
259}
260
261struct Array3UnsignedChar {
262 unsigned char a[3];
263};
264
265unsigned int Array3UnsignedChars(struct Array3UnsignedChar a) {
266 return (((int)a.a[0])<<24) | (((int)a.a[1])<<16) | (((int)a.a[2])<<8) | 0xef;
267}
268
269struct Array2UnsignedShort {
270 unsigned short a[2];
271};
272
273unsigned int Array2UnsignedShorts(struct Array2UnsignedShort a) {
274 return (((int)a.a[0])<<16) | (((int)a.a[1])<<0);
275}
276
277struct Array4Chars {
278 signed char a[4];
279};
280
281int Array4Chars(struct Array4Chars a) {
282 return (int)a.a[0] + (int)a.a[1] + (int)a.a[2] + (int)a.a[3];
283}
284
285struct Array2Short {
286 short a[2];
287};
288
289int Array2Shorts(struct Array2Short a) {
290 return (int)a.a[0] + (int)a.a[1];
291}
292
293struct Array3Short {
294 short a[3];
295};
296
297int Array3Shorts(struct Array3Short a) {
298 return (int)a.a[0] + (int)a.a[1] + (int)a.a[2];
299}
300
301struct BoolStruct {
302 _Bool b;
303};
304
305_Bool BoolStruct(struct BoolStruct b) {
306 return b.b;
307}
308
309struct BoolFloat {
310 _Bool b;
311 float f;
312};
313
314float BoolFloat(struct BoolFloat s) {
315 if (s.b)
316 return s.f;
317 return -s.f;
318}
319
320struct Content {
321 struct { double x, y; } point;
322 struct { double width, height; } size;
323};
324
325uint64_t InitWithContentRect(int *win, struct Content c, int style, int backing, _Bool flag) {
326 if (win == 0)
327 return 0xBAD;
328 if (!flag)
329 return 0xF1A6; // FLAG
330 return (uint64_t)(c.point.x + c.point.y + c.size.width + c.size.height) / (style - backing);
331}
332
333struct GoInt4 {
334 intptr_t a, b, c, d;
335};
336
337intptr_t GoInt4(struct GoInt4 g) {
338 return g.a + g.b - g.c + g.d;
339}
340
341struct GoUint4 {
342 uintptr_t a, b, c, d;
343};
344
345uintptr_t GoUint4(struct GoUint4 g) {
346 return g.a + g.b + g.c + g.d;
347}
348
349uintptr_t TakeGoUintAndReturn(uintptr_t a) {
350 return a;
351}
352
353struct FloatAndBool {
354 float value;
355 _Bool has_value;
356};
357
358int FloatAndBool(struct FloatAndBool f) {
359 return f.has_value;
360}
361
362struct FourInt32s {
363 int32_t f0;
364 int32_t f1;
365 int32_t f2;
366 int32_t f3;
367};
368
369int32_t FourInt32s(struct FourInt32s s) {
370 return s.f0 + s.f1 + s.f2 + s.f3;
371}
372
373struct PointerWrapper {
374 void* ctx;
375};
376
377uintptr_t ExtractPointer(struct PointerWrapper wrapper) {
378 return (uintptr_t)wrapper.ctx;
379}
380
381struct TwoPointers {
382 void* ptr1;
383 void* ptr2;
384};
385
386uintptr_t AddPointers(struct TwoPointers wrapper) {
387 return (uintptr_t)wrapper.ptr1 + (uintptr_t)wrapper.ptr2;
388}
389
390// Identity functions for round-trip testing of struct arguments
391
392struct OneInt64 {
393 int64_t a;
394};
395
396struct OneInt64 IdentityOneInt64(struct OneInt64 s) {
397 return s;
398}
399
400struct IntLessThan16Bytes IdentityIntLessThan16Bytes(struct IntLessThan16Bytes s) {
401 return s;
402}
403
404struct TwoDoubleStruct IdentityTwoDoubleStruct(struct TwoDoubleStruct s) {
405 return s;
406}
407
408struct FourFloat32 {
409 float a, b, c, d;
410};
411
412struct FourFloat32 IdentityFourFloat32(struct FourFloat32 s) {
413 return s;
414}
415
416struct FloatAndInt IdentityFloatAndInt(struct FloatAndInt s) {
417 return s;
418}
419
420struct ThreeInt64 {
421 int64_t a, b, c;
422};
423
424struct ThreeInt64 IdentityThreeInt64(struct ThreeInt64 s) {
425 return s;
426}
427
428struct PtrInt64Ptr {
429 int64_t *a;
430 int64_t b;
431 int64_t *c;
432};
433
434struct PtrInt64Ptr IdentityPtrInt64Ptr(struct PtrInt64Ptr s) {
435 return s;
436}
437
438struct IntLessThan16Bytes IdentityTwoInt64AfterPrims(int64_t x, double y, struct IntLessThan16Bytes s) {
439 return s;
440}
441
442struct FloatLessThan16Bytes IdentityTwoFloat32AfterFloats(double x, double y, struct FloatLessThan16Bytes s) {
443 return s;
444}
445
446struct Mixed5Args {
447 int64_t *a;
448 int32_t b;
449 float c;
450 int32_t d;
451};
452
453struct Mixed5Args IdentityMixed5Args(struct Mixed5Args s) {
454 return s;
455}