1 #ifndef RENODE_IMPORTS_H_
2 #define RENODE_IMPORTS_H_
3 
4 #ifdef __cplusplus
5 #define EXTERN_C extern "C"
6 #else
7 #define EXTERN_C
8 #endif
9 
10 /* If this header is used as a part of tlib, we will call this hook after every callback */
11 #ifdef TARGET_LONG_BITS
12 EXTERN_C void tlib_try_interrupt_translation_block(void);
13 #else
14 #define tlib_try_interrupt_translation_block()
15 #endif
16 
17 #include "map.h"
18 
19 #define VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N
20 #define VA_NARGS(ARGS...) VA_NARGS_IMPL(_, ##ARGS, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
21 
22 #define CONCAT_0()
23 #define CONCAT_1(A) A
24 #define CONCAT_2(A, B) A##B
25 #define CONCAT_3(A, B, C) A##B##C
26 #define CONCAT_4(A, B, C, D) A##B##C##D
27 #define CONCAT_5(A, B, C, D, E) A##B##C##D##E
28 #define CONCAT_6(A, B, C, D, E, F) A##B##C##D##E##F
29 #define CONCAT_EXP_2(A, B) CONCAT_2(A, B)
30 #define CONCAT_EXP_5(A, B, C, D, E) CONCAT_5(A, B, C, D, E)
31 
32 #define CONCAT_IMPL2(N, XS...) CONCAT_##N(XS)
33 #define CONCAT_IMPL(N, XS...) CONCAT_IMPL2(N, XS)
34 #define CONCAT(XS...) CONCAT_IMPL(VA_NARGS(XS), XS)
35 
36 #define IF_THEN_ELSE(COND, THEN, ELSE) CONCAT_2(IF_THEN_ELSE_, COND)(THEN, ELSE)
37 #define IF_THEN_ELSE_0(THEN, ELSE) ELSE
38 #define IF_THEN_ELSE_1(THEN, ELSE) THEN
39 
40 // We need these typedefs in order for the type name mapping based on token pasting to work
41 typedef void *voidptr;
42 typedef char *charptr;
43 
44 #define CSHARP_TYPE_uint8_t Byte
45 #define CSHARP_TYPE_uint16_t UInt16
46 #define CSHARP_TYPE_uint32_t UInt32
47 #define CSHARP_TYPE_uint64_t UInt64
48 #define CSHARP_TYPE_int8_t SByte
49 #define CSHARP_TYPE_int16_t Int16
50 #define CSHARP_TYPE_int32_t Int32
51 #define CSHARP_TYPE_int64_t Int64
52 #define CSHARP_TYPE_charptr String
53 #define CSHARP_TYPE_voidptr IntPtr /* a pointer is a pointer */
54 #define CSHARP_TYPE_void           /* for return types */
55 #define CSHARP_TYPE_               /* for zero-arg functions */
56 #define CSHARP_TYPE(TYPE) CSHARP_TYPE_##TYPE
57 
58 #define CSHARP_PREFIX_uint8_t Func
59 #define CSHARP_PREFIX_uint16_t Func
60 #define CSHARP_PREFIX_uint32_t Func
61 #define CSHARP_PREFIX_uint64_t Func
62 #define CSHARP_PREFIX_int8_t Func
63 #define CSHARP_PREFIX_int16_t Func
64 #define CSHARP_PREFIX_int32_t Func
65 #define CSHARP_PREFIX_int64_t Func
66 #define CSHARP_PREFIX_charptr Func
67 #define CSHARP_PREFIX_voidptr Func
68 #define CSHARP_PREFIX_void Action
69 #define CSHARP_PREFIX(TYPE) CSHARP_PREFIX_##TYPE
70 
71 #define PARAMS_0() void
72 #define PARAMS_1(T0) T0 a0
73 #define PARAMS_2(T0, T1) PARAMS_1(T0), T1 a1
74 #define PARAMS_3(T0, T1, T2) PARAMS_2(T0, T1), T2 a2
75 #define PARAMS_4(T0, T1, T2, T3) PARAMS_3(T0, T1, T2), T3 a3
76 #define PARAMS_5(T0, T1, T2, T3, T4) PARAMS_4(T0, T1, T2, T3), T4 a4
77 #define PARAMS_6(T0, T1, T2, T3, T4, T5) PARAMS_5(T0, T1, T2, T3, T4), T5 a5
78 #define PARAMS_IMPL(N, TYPES...) CONCAT_EXP_2(PARAMS_, N)(TYPES)
79 #define PARAMS(TYPES...) PARAMS_IMPL(VA_NARGS(TYPES), TYPES)
80 
81 #define PARAM_NAMES_0()
82 #define PARAM_NAMES_1(T0) a0
83 #define PARAM_NAMES_2(T0, T1) PARAM_NAMES_1(T0), a1
84 #define PARAM_NAMES_3(T0, T1, T2) PARAM_NAMES_2(T0, T1), a2
85 #define PARAM_NAMES_4(T0, T1, T2, T3) PARAM_NAMES_3(T0, T1, T2), a3
86 #define PARAM_NAMES_5(T0, T1, T2, T3, T4) PARAM_NAMES_4(T0, T1, T2, T3), a4
87 #define PARAM_NAMES_6(T0, T1, T2, T3, T4, T5) PARAM_NAMES_5(T0, T1, T2, T3, T4), a5
88 #define PARAM_NAMES_IMPL(N, TYPES...) CONCAT_EXP_2(PARAM_NAMES_, N)(TYPES)
89 #define PARAM_NAMES(TYPES...) PARAM_NAMES_IMPL(VA_NARGS(TYPES), TYPES)
90 
91 #define RETURN_KEYWORD_Action
92 #define RETURN_KEYWORD_Func return
93 #define HAS_RETURN_Action 0
94 #define HAS_RETURN_Func 1
95 #define RETURN_KEYWORD(TYPE) CONCAT_EXP_2(RETURN_KEYWORD_, CSHARP_PREFIX(TYPE))
96 #define HAS_RETURN(TYPE) CONCAT_EXP_2(HAS_RETURN_, CSHARP_PREFIX(TYPE))
97 
98 // Usage example: EXTERNAL_AS(int32_t, CSharpName, c_name, uint32_t, voidptr)
99 //
100 // Warning: for historical reasons, the return type goes FIRST in the generated
101 // renode_external_attach function name, which is reversed from the C# approach
102 // seen in delegate type parameters (as in Func<Arg1, Arg2, Ret>)
103 #define EXTERNAL_AS(RETURN_TYPE, IMPORTED_NAME, LOCAL_NAME, PARAMETER_TYPES...)                   \
104     static RETURN_TYPE (*LOCAL_NAME##_callback$)(PARAMS(PARAMETER_TYPES));                        \
105                                                                                                   \
106     RETURN_TYPE LOCAL_NAME(PARAMS(PARAMETER_TYPES))                                               \
107     {                                                                                             \
108         /* If this function returns a value, generate code of the form                            \
109          * uint32_t retval = (*callback)(); return retval;, possibly with something in between.   \
110          * Otherwise, just call it. */                                                            \
111         IF_THEN_ELSE(HAS_RETURN(RETURN_TYPE), RETURN_TYPE retval =,)                              \
112         LOCAL_NAME##_callback$(PARAM_NAMES(PARAMETER_TYPES));                                     \
113         tlib_try_interrupt_translation_block();                                                   \
114         IF_THEN_ELSE(HAS_RETURN(RETURN_TYPE), return retval;,)                                    \
115     }                                                                                             \
116                                                                                                   \
117     EXTERN_C void CONCAT_EXP_5(renode_external_attach__, CSHARP_PREFIX(RETURN_TYPE),              \
118                                 CSHARP_TYPE(RETURN_TYPE),                                         \
119                                 CONCAT(MAP_LIST(CSHARP_TYPE, PARAMETER_TYPES)),                   \
120                                 __##IMPORTED_NAME(RETURN_TYPE (*param)(PARAMS(PARAMETER_TYPES)))) \
121     {                                                                                             \
122         LOCAL_NAME##_callback$ = param;                                                           \
123     }
124 
125 #define EXTERNAL(RETURN_TYPE, NAME, PARAMETER_TYPES...) \
126     EXTERNAL_AS(RETURN_TYPE, $##NAME, NAME, PARAMETER_TYPES)
127 
128 #endif
129