]> git.lizzy.rs Git - rust.git/blob - tests/auxiliary/rust_test_helpers.c
Rollup merge of #107695 - Swatinem:futcallx3, r=compiler-errors
[rust.git] / tests / auxiliary / rust_test_helpers.c
1 // Helper functions used only in tests
2
3 #include <stdint.h>
4 #include <stdlib.h>
5 #include <assert.h>
6 #include <stdarg.h>
7
8 // These functions are used in the unit tests for C ABI calls.
9
10 uint32_t
11 rust_dbg_extern_identity_u32(uint32_t u) {
12     return u;
13 }
14
15 uint64_t
16 rust_dbg_extern_identity_u64(uint64_t u) {
17     return u;
18 }
19
20 double
21 rust_dbg_extern_identity_double(double u) {
22     return u;
23 }
24
25 char
26 rust_dbg_extern_identity_u8(char u) {
27     return u;
28 }
29
30 typedef void *(*dbg_callback)(void*);
31
32 void *
33 rust_dbg_call(dbg_callback cb, void *data) {
34     return cb(data);
35 }
36
37 void rust_dbg_do_nothing() { }
38
39 struct TwoU8s {
40     uint8_t one;
41     uint8_t two;
42 };
43
44 struct TwoU8s
45 rust_dbg_extern_return_TwoU8s() {
46     struct TwoU8s s;
47     s.one = 10;
48     s.two = 20;
49     return s;
50 }
51
52 struct TwoU8s
53 rust_dbg_extern_identity_TwoU8s(struct TwoU8s u) {
54     return u;
55 }
56
57 struct TwoU16s {
58     uint16_t one;
59     uint16_t two;
60 };
61
62 struct TwoU16s
63 rust_dbg_extern_return_TwoU16s() {
64     struct TwoU16s s;
65     s.one = 10;
66     s.two = 20;
67     return s;
68 }
69
70 struct TwoU16s
71 rust_dbg_extern_identity_TwoU16s(struct TwoU16s u) {
72     return u;
73 }
74
75 struct TwoU32s {
76     uint32_t one;
77     uint32_t two;
78 };
79
80 struct TwoU32s
81 rust_dbg_extern_return_TwoU32s() {
82     struct TwoU32s s;
83     s.one = 10;
84     s.two = 20;
85     return s;
86 }
87
88 struct TwoU32s
89 rust_dbg_extern_identity_TwoU32s(struct TwoU32s u) {
90     return u;
91 }
92
93 struct TwoU64s {
94     uint64_t one;
95     uint64_t two;
96 };
97
98 struct TwoU64s
99 rust_dbg_extern_return_TwoU64s() {
100     struct TwoU64s s;
101     s.one = 10;
102     s.two = 20;
103     return s;
104 }
105
106 struct TwoU64s
107 rust_dbg_extern_identity_TwoU64s(struct TwoU64s u) {
108     return u;
109 }
110
111 struct TwoDoubles {
112     double one;
113     double two;
114 };
115
116 struct TwoDoubles
117 rust_dbg_extern_identity_TwoDoubles(struct TwoDoubles u) {
118     return u;
119 }
120
121 struct ManyInts {
122     int8_t arg1;
123     int16_t arg2;
124     int32_t arg3;
125     int16_t arg4;
126     int8_t arg5;
127     struct TwoU8s arg6;
128 };
129
130 // MSVC doesn't allow empty structs or unions
131 #ifndef _MSC_VER
132 struct Empty {
133 };
134
135 void
136 rust_dbg_extern_empty_struct(struct ManyInts v1, struct Empty e, struct ManyInts v2) {
137     assert(v1.arg1 == v2.arg1 + 1);
138     assert(v1.arg2 == v2.arg2 + 1);
139     assert(v1.arg3 == v2.arg3 + 1);
140     assert(v1.arg4 == v2.arg4 + 1);
141     assert(v1.arg5 == v2.arg5 + 1);
142     assert(v1.arg6.one == v2.arg6.one + 1);
143     assert(v1.arg6.two == v2.arg6.two + 1);
144 }
145 #endif
146
147 intptr_t
148 rust_get_test_int() {
149   return 1;
150 }
151
152 char *
153 rust_get_null_ptr() {
154     return 0;
155 }
156
157 // Debug helpers strictly to verify ABI conformance.
158
159 struct quad {
160     uint64_t a;
161     uint64_t b;
162     uint64_t c;
163     uint64_t d;
164 };
165
166 struct floats {
167     double a;
168     uint8_t b;
169     double c;
170 };
171
172 struct char_char_double {
173     uint8_t a;
174     uint8_t b;
175     double c;
176 };
177
178 struct char_char_float {
179     uint8_t a;
180     uint8_t b;
181     float c;
182 };
183
184 struct quad
185 rust_dbg_abi_1(struct quad q) {
186     struct quad qq = { q.c + 1,
187                        q.d - 1,
188                        q.a + 1,
189                        q.b - 1 };
190     return qq;
191 }
192
193 struct floats
194 rust_dbg_abi_2(struct floats f) {
195     struct floats ff = { f.c + 1.0,
196                          0xff,
197                          f.a - 1.0 };
198     return ff;
199 }
200
201 struct char_char_double
202 rust_dbg_abi_3(struct char_char_double a) {
203     struct char_char_double ccd = { a.a + 1,
204                                     a.b - 1,
205                                     a.c + 1.0 };
206     return ccd;
207 }
208
209 struct char_char_float
210 rust_dbg_abi_4(struct char_char_float a) {
211     struct char_char_float ccd = { a.a + 1,
212                                    a.b - 1,
213                                    a.c + 1.0 };
214     return ccd;
215 }
216
217
218 int
219 rust_dbg_static_mut = 3;
220
221 void
222 rust_dbg_static_mut_check_four() {
223     assert(rust_dbg_static_mut == 4);
224 }
225
226 struct S {
227     uint64_t x;
228     uint64_t y;
229     uint64_t z;
230 };
231
232 uint64_t get_x(struct S s) {
233     return s.x;
234 }
235
236 uint64_t get_y(struct S s) {
237     return s.y;
238 }
239
240 uint64_t get_z(struct S s) {
241     return s.z;
242 }
243
244 uint64_t get_c_many_params(void *a, void *b, void *c, void *d, struct quad f) {
245     return f.c;
246 }
247
248 struct quad_floats {
249     float a;
250     float b;
251     float c;
252     float d;
253 };
254
255 float get_c_exhaust_sysv64_ints(
256     void *a,
257     void *b,
258     void *c,
259     void *d,
260     void *e,
261     void *f,
262     // `f` used the last integer register, so `g` goes on the stack.
263     // It also used to bring the "count of available integer registers" down to
264     // `-1` which broke the next SSE-only aggregate argument (`h`) - see #62350.
265     void *g,
266     struct quad_floats h
267 ) {
268     return h.c;
269 }
270
271 // Calculates the average of `(x + y) / n` where x: i64, y: f64. There must be exactly n pairs
272 // passed as variadic arguments. There are two versions of this function: the
273 // variadic one, and the one that takes a `va_list`.
274 double rust_valist_interesting_average(uint64_t n, va_list pairs) {
275     double sum = 0.0;
276     int i;
277     for(i = 0; i < n; i += 1) {
278         sum += (double)va_arg(pairs, int64_t);
279         sum += va_arg(pairs, double);
280     }
281     return sum / n;
282 }
283
284 double rust_interesting_average(uint64_t n, ...) {
285     double sum;
286     va_list pairs;
287     va_start(pairs, n);
288     sum = rust_valist_interesting_average(n, pairs);
289     va_end(pairs);
290     return sum;
291 }
292
293 int32_t rust_int8_to_int32(int8_t x) {
294     return (int32_t)x;
295 }
296
297 typedef union LARGE_INTEGER {
298   struct {
299     uint32_t LowPart;
300     uint32_t HighPart;
301   };
302   struct {
303     uint32_t LowPart;
304     uint32_t HighPart;
305   } u;
306   uint64_t QuadPart;
307 } LARGE_INTEGER;
308
309 LARGE_INTEGER increment_all_parts(LARGE_INTEGER li) {
310     li.LowPart += 1;
311     li.HighPart += 1;
312     li.u.LowPart += 1;
313     li.u.HighPart += 1;
314     li.QuadPart += 1;
315     return li;
316 }
317
318 #if __SIZEOF_INT128__ == 16
319
320 unsigned __int128 identity(unsigned __int128 a) {
321     return a;
322 }
323
324 __int128 square(__int128 a) {
325     return a * a;
326 }
327
328 __int128 sub(__int128 a, __int128 b) {
329     return a - b;
330 }
331
332 #endif
333
334 #define OPTION_TAG_NONE (0)
335 #define OPTION_TAG_SOME (1)
336
337 struct U8TaggedEnumOptionU64 {
338     uint8_t tag;
339     union {
340         uint64_t some;
341     };
342 };
343
344 struct U8TaggedEnumOptionU64
345 rust_dbg_new_some_u64(uint64_t some) {
346     struct U8TaggedEnumOptionU64 r = {
347         .tag = OPTION_TAG_SOME,
348         .some = some,
349     };
350     return r;
351 }
352
353 struct U8TaggedEnumOptionU64
354 rust_dbg_new_none_u64(void) {
355     struct U8TaggedEnumOptionU64 r = {
356         .tag = OPTION_TAG_NONE,
357     };
358     return r;
359 }
360
361 int32_t
362 rust_dbg_unpack_option_u64(struct U8TaggedEnumOptionU64 o, uint64_t *into) {
363     assert(into);
364     switch (o.tag) {
365     case OPTION_TAG_SOME:
366         *into = o.some;
367         return 1;
368     case OPTION_TAG_NONE:
369         return 0;
370     default:
371         assert(0 && "unexpected tag");
372         return 0;
373     }
374 }
375
376 struct U8TaggedEnumOptionU64U64 {
377     uint8_t tag;
378     union {
379         struct {
380             uint64_t a;
381             uint64_t b;
382         } some;
383     };
384 };
385
386 struct U8TaggedEnumOptionU64U64
387 rust_dbg_new_some_u64u64(uint64_t a, uint64_t b) {
388     struct U8TaggedEnumOptionU64U64 r = {
389         .tag = OPTION_TAG_SOME,
390         .some = { .a = a, .b = b },
391     };
392     return r;
393 }
394
395 struct U8TaggedEnumOptionU64U64
396 rust_dbg_new_none_u64u64(void) {
397     struct U8TaggedEnumOptionU64U64 r = {
398         .tag = OPTION_TAG_NONE,
399     };
400     return r;
401 }
402
403 int32_t
404 rust_dbg_unpack_option_u64u64(struct U8TaggedEnumOptionU64U64 o, uint64_t *a, uint64_t *b) {
405     assert(a);
406     assert(b);
407     switch (o.tag) {
408     case OPTION_TAG_SOME:
409         *a = o.some.a;
410         *b = o.some.b;
411         return 1;
412     case OPTION_TAG_NONE:
413         return 0;
414     default:
415         assert(0 && "unexpected tag");
416         return 0;
417     }
418 }
419
420 uint16_t issue_97463_leak_uninit_data(uint32_t a, uint32_t b, uint32_t c) {
421     struct bloc { uint16_t a; uint16_t b; uint16_t c; };
422     struct bloc *data = malloc(sizeof(struct bloc));
423
424     data->a = a & 0xFFFF;
425     data->b = b & 0xFFFF;
426     data->c = c & 0xFFFF;
427
428     return data->b; /* leak data */
429 }