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