1/* @title: Test Export */
2#pragma once
3#include <compiler/core.h>
4#include <linker/symbols.h>
5#include <stddef.h>
6#include <types/types.h>
7
8#ifdef TEST_ENABLED
9
10#define TEST_EXPORT_AS(sym_name, export_fn) \
11 extern typeof(export_fn) __test_sym_##sym_name cc_alias(export_fn) \
12 cc_used; \
13 static LINKER_SECTION_OBJECT(const struct test_export_entry, test_exports) \
14 __test_exp_##sym_name = { \
15 .name = #sym_name, \
16 .fn = any_fn_from(export_fn), \
17 }
18#define TEST_EXPORT(fn) TEST_EXPORT_AS(fn, fn)
19
20#define TEST_IMPORT(ret, fn, ...) \
21 ret __test_sym_##fn(__VA_ARGS__); \
22 static LINKER_SECTION_OBJECT(const struct test_signature_record, \
23 test_canonical_signatures) \
24 __test_sig_##fn = { \
25 .name = #fn, \
26 .ret_str = #ret, \
27 .args_str = #__VA_ARGS__, \
28 .file = __FILE__, \
29 .line = __LINE__, \
30 }
31
32#define TEST_IMPORT_UNSAFE(ret, sym_name, ...) \
33 typedef ret (*__test_unsafe_fn_t_##sym_name)(__VA_ARGS__); \
34 static any_fn_t __test_unsafe_fn_##sym_name; \
35 static LINKER_SECTION_OBJECT(const struct test_import_entry, test_imports) \
36 __test_imp_##sym_name = { \
37 .name = #sym_name, \
38 .target_fn = &__test_unsafe_fn_##sym_name, \
39 .import_file = __FILE__, \
40 .import_line = __LINE__, \
41 }; \
42 static LINKER_SECTION_OBJECT(const struct test_signature_record, \
43 test_unsafe_signatures) \
44 __test_unsig_##sym_name = { \
45 .name = #sym_name, \
46 .ret_str = #ret, \
47 .args_str = #__VA_ARGS__, \
48 .file = __FILE__, \
49 .line = __LINE__, \
50 }
51
52#define TEST_CALL(fn) __test_sym_##fn
53#define TEST_CALL_UNSAFE(sym_name) \
54 any_fn_to(__test_unsafe_fn_##sym_name, __test_unsafe_fn_t_##sym_name)
55
56#else
57
58#define TEST_EXPORT(fn)
59#define TEST_IMPORT(ret, fn, ...)
60#define TEST_IMPORT_UNSAFE(ret, sym_name, ...)
61#define TEST_CALL(fn) (void)
62#define TEST_CALL_UNSAFE(sym_name) (void)
63
64#endif /* TEST_ENABLED */
65
66struct test_export_entry {
67 const char *name;
68 any_fn_t fn;
69};
70
71struct test_import_entry {
72 const char *name;
73 any_fn_t *target_fn;
74 const char *import_file;
75 uint32_t import_line;
76};
77
78struct test_signature_record {
79 const char *name;
80 const char *ret_str;
81 const char *args_str;
82 const char *file;
83 uint32_t line;
84};
85
86LINKER_SECTION_EXTERN(struct test_import_entry, test_imports);
87LINKER_SECTION_EXTERN(struct test_export_entry, test_exports);
88LINKER_SECTION_EXTERN(struct test_signature_record, test_canonical_signatures);
89LINKER_SECTION_EXTERN(struct test_signature_record, test_unsafe_signatures);
90