main 3a10209

abi_test.c RawHistoryFolder

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2025 The Ebitengine Authors
3
4#include <assert.h>
5#include <inttypes.h>
6#include <stdbool.h>
7#include <stdint.h>
8#include <stdio.h>
9#include <string.h>
10
11uint32_t stack_uint8_t(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f, uint32_t g, uint32_t h, uint8_t i, uint8_t j, uint32_t k ) {
12    assert(i == 1);
13    assert(j == 2);
14    assert(k == 1024);
15    return a | b | c | d | e | f | g | h | (uint32_t)i | (uint32_t)j | k;
16}
17
18uint32_t reg_uint8_t(uint8_t a, uint8_t b, uint32_t c) {
19    assert(a == 1);
20    assert(b == 2);
21    assert(c == 1024);
22    return a | b | c;
23}
24
25uint32_t stack_string(uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t e, uint32_t f, uint32_t g, uint32_t h, const char * i) {
26    assert(i != 0);
27    assert(strcmp(i, "test") == 0);
28    return a | b | c | d | e | f | g | h;
29}
30
31void stack_8i32_3strings(char* result, size_t size, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8, const char* s1, const char* s2, const char* s3) {
32    snprintf(result, size, "%d:%d:%d:%d:%d:%d:%d:%d:%s:%s:%s", a1, a2, a3, a4, a5, a6, a7, a8, s1, s2, s3);
33}
34
35// HFA (Homogeneous Float Aggregate) struct with 2 floats
36typedef struct {
37    float x;
38    float y;
39} Float2;
40
41// HFA struct with 4 floats
42typedef struct {
43    float x;
44    float y;
45    float z;
46    float w;
47} Float4;
48
49// Non-HFA struct (mixed types)
50typedef struct {
51    int32_t a;
52    float b;
53} MixedStruct;
54
55// Small struct that fits in one register
56typedef struct {
57    int32_t x;
58    int32_t y;
59} IntPair;
60
61// Test: 8 int registers exhausted, then HFA struct on stack
62void stack_8int_hfa2_stack(char *buf, size_t bufsize, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8, Float2 f) {
63    snprintf(buf, bufsize, "%d:%d:%d:%d:%d:%d:%d:%d:%.1f:%.1f",
64             a1, a2, a3, a4, a5, a6, a7, a8, f.x, f.y);
65}
66
67// Test: 8 int registers exhausted, then multiple structs on stack
68void stack_8int_2structs_stack(char *buf, size_t bufsize, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8, IntPair p1, IntPair p2) {
69    snprintf(buf, bufsize, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
70             a1, a2, a3, a4, a5, a6, a7, a8, p1.x, p1.y, p2.x, p2.y);
71}
72
73// Test: 8 float registers exhausted, then HFA on stack
74void stack_8float_hfa2_stack(char *buf, size_t bufsize, float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, Float2 f) {
75    snprintf(buf, bufsize, "%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f",
76             f1, f2, f3, f4, f5, f6, f7, f8, f.x, f.y);
77}
78
79// Test: mixed - int regs exhausted, float struct can still use float regs
80void stack_8int_hfa2_floatregs(char *buf, size_t bufsize, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8, Float2 f) {
81    snprintf(buf, bufsize, "%d:%d:%d:%d:%d:%d:%d:%d:%.1f:%.1f",
82             a1, a2, a3, a4, a5, a6, a7, a8, f.x, f.y);
83}
84
85// Test: primitives and struct interleaved on stack
86void stack_8int_int_struct_int(char *buf, size_t bufsize, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8, int32_t a9, IntPair p, int32_t a10) {
87    snprintf(buf, bufsize, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
88             a1, a2, a3, a4, a5, a6, a7, a8, a9, p.x, p.y, a10);
89}
90
91// Test: HFA4 struct on stack (4 floats)
92void stack_8int_hfa4_stack(char *buf, size_t bufsize, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8, Float4 f) {
93    snprintf(buf, bufsize, "%d:%d:%d:%d:%d:%d:%d:%d:%.1f:%.1f:%.1f:%.1f",
94             a1, a2, a3, a4, a5, a6, a7, a8, f.x, f.y, f.z, f.w);
95}
96
97// Test: mixed type struct on stack
98void stack_8int_mixed_struct(char *buf, size_t bufsize, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8, MixedStruct m) {
99    snprintf(buf, bufsize, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%.1f",
100             a1, a2, a3, a4, a5, a6, a7, a8, m.a, m.b);
101}
102
103void stack_10_int32(char *buf, size_t bufsize, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8, int32_t a9, int32_t a10) {
104    snprintf(buf, bufsize, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
105             a1, a2, a3, a4, a5, a6, a7, a8, a9, a10);
106}
107
108void stack_11_int32(char *buf, size_t bufsize, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8, int32_t a9, int32_t a10, int32_t a11) {
109    snprintf(buf, bufsize, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
110             a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11);
111}
112
113void stack_10_float32(char *buf, size_t bufsize, float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float f10) {
114    snprintf(buf, bufsize, "%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f:%.1f",
115             f1, f2, f3, f4, f5, f6, f7, f8, f9, f10);
116}
117
118void stack_mixed_stack_4args(char *buf, size_t bufsize, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8, const char *s1, bool b1, int32_t a9, const char *s2) {
119    snprintf(buf, bufsize, "%d:%d:%d:%d:%d:%d:%d:%d:%s:%d:%d:%s",
120             a1, a2, a3, a4, a5, a6, a7, a8, s1, b1, a9, s2);
121}
122
123void stack_20_int32(char *buf, size_t bufsize, int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5, int32_t a6, int32_t a7, int32_t a8, int32_t a9, int32_t a10, int32_t a11, int32_t a12, int32_t a13, int32_t a14, int32_t a15, int32_t a16, int32_t a17, int32_t a18, int32_t a19, int32_t a20) {
124    snprintf(buf, bufsize, "%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d",
125             a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
126}
127
128void stack_25_int64_exceeds(char *buf, size_t bufsize, int64_t a1, int64_t a2, int64_t a3, int64_t a4, int64_t a5, int64_t a6, int64_t a7, int64_t a8, int64_t a9, int64_t a10, int64_t a11, int64_t a12, int64_t a13, int64_t a14, int64_t a15, int64_t a16, int64_t a17, int64_t a18, int64_t a19, int64_t a20, int64_t a21, int64_t a22, int64_t a23, int64_t a24, int64_t a25) {
129    snprintf(buf, bufsize, "%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64 ":%" PRId64,
130             a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, a21, a22, a23, a24, a25);
131}
132
133uintptr_t stack_20_uintptr(
134    uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5,
135    uintptr_t a6, uintptr_t a7, uintptr_t a8, uintptr_t a9, uintptr_t a10,
136    uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14, uintptr_t a15,
137    uintptr_t a16, uintptr_t a17, uintptr_t a18, uintptr_t a19, uintptr_t a20
138) {
139    return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 +
140           a11 + a12 + a13 + a14 + a15 + a16 + a17 + a18 + a19 + a20;
141}
142
143uintptr_t stack_32_uintptr(
144    uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8,
145    uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14, uintptr_t a15, uintptr_t a16,
146    uintptr_t a17, uintptr_t a18, uintptr_t a19, uintptr_t a20, uintptr_t a21, uintptr_t a22, uintptr_t a23, uintptr_t a24,
147    uintptr_t a25, uintptr_t a26, uintptr_t a27, uintptr_t a28, uintptr_t a29, uintptr_t a30, uintptr_t a31, uintptr_t a32
148) {
149    return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 +
150           a9 + a10 + a11 + a12 + a13 + a14 + a15 + a16 +
151           a17 + a18 + a19 + a20 + a21 + a22 + a23 + a24 +
152           a25 + a26 + a27 + a28 + a29 + a30 + a31 + a32;
153}
154
155double stack_32_mixed_int_float(
156    uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, uintptr_t a6, uintptr_t a7, uintptr_t a8,
157    uintptr_t a9, uintptr_t a10, uintptr_t a11, uintptr_t a12, uintptr_t a13, uintptr_t a14, uintptr_t a15, uintptr_t a16,
158    double f1, double f2, double f3, double f4, double f5, double f6, double f7, double f8,
159    double f9, double f10, double f11, double f12, double f13, double f14, double f15, double f16
160) {
161    return (double)a1 * 1 + (double)a2 * 2 + (double)a3 * 3 + (double)a4 * 4 +
162           (double)a5 * 5 + (double)a6 * 6 + (double)a7 * 7 + (double)a8 * 8 +
163           (double)a9 * 9 + (double)a10 * 10 + (double)a11 * 11 + (double)a12 * 12 +
164           (double)a13 * 13 + (double)a14 * 14 + (double)a15 * 15 + (double)a16 * 16 +
165           f1 * 17 + f2 * 18 + f3 * 19 + f4 * 20 +
166           f5 * 21 + f6 * 22 + f7 * 23 + f8 * 24 +
167           f9 * 25 + f10 * 26 + f11 * 27 + f12 * 28 +
168           f13 * 29 + f14 * 30 + f15 * 31 + f16 * 32;
169}
170
171int64_t arm_int64_unaligned_in_registers(uintptr_t a1, int64_t a2) {
172    return (int64_t)a1 * 123 + a2;
173}
174
175int64_t arm_int64_unaligned_on_stack(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, int64_t a6) {
176    return (int64_t)a1 * 1 + (int64_t)a2 * 2 + (int64_t)a3 * 3 + (int64_t)a4 * 4 +
177           (int64_t)a5 * 5 + a6;
178}
179
180int64_t arm_int64_unaligned_on_stack_after_floats(
181    uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, /* these args are going to integer registers */
182    float f1, float f2, float f3, float f4, /* these args are going to float registers */
183    float f5, float f6, float f7, float f8,
184    float f9, float f10, float f11, float f12,
185    float f13, float f14, float f15, float f16,
186    float f17, /* this is a first arg on stack */
187    int64_t a5 /* this arg must be padded */
188) {
189    return (int64_t)a1 * 1 + (int64_t)a2 * 2 + (int64_t)a3 * 3 + (int64_t)a4 * 4 + a5;
190}
191
192double arm_float64_unaligned_in_registers(uintptr_t a1, double a2) {
193    return (double)a1 * 123.5 + a2;
194}
195
196double arm_float64_unaligned_on_stack(uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5, double a6) {
197    return (double)a1 * 1 + (double)a2 * 2 + (double)a3 * 3 + (double)a4 * 4 +
198           (double)a5 * 5 + a6;
199}
200
201typedef int32_t (*AddFunc)(int32_t, int32_t);
202
203int32_t returned_add(int32_t a, int32_t b) {
204    return a + b;
205}
206
207AddFunc return_func_ptr(void) {
208    return returned_add;
209}
210
211AddFunc return_null_func_ptr(void) {
212    return NULL;
213}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close