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