cxxbridge_macro/syntax/
mangle.rs

1// Mangled symbol arrangements:
2//
3//   (a) One-off internal symbol.
4//          pattern:  {CXXBRIDGE} $ {NAME}
5//          examples:
6//             - cxxbridge1$exception
7//          defining characteristics:
8//             - 2 segments
9//             - starts with cxxbridge
10//
11//   (b) Behavior on a builtin binding without generic parameter.
12//          pattern:  {CXXBRIDGE} $ {TYPE} $ {NAME}
13//          examples:
14//             - cxxbridge1$string$len
15//          defining characteristics:
16//             - 3 segments
17//             - starts with cxxbridge
18//
19//   (c) Behavior on a builtin binding with generic parameter.
20//          pattern:  {CXXBRIDGE} $ {TYPE} $ {PARAM...} $ {NAME}
21//          examples:
22//             - cxxbridge1$box$org$rust$Struct$alloc
23//             - cxxbridge1$unique_ptr$std$vector$u8$drop
24//          defining characteristics:
25//             - 4+ segments
26//             - starts with cxxbridge
27//
28//   (d) User-defined extern function.
29//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {NAME}
30//          examples:
31//             - cxxbridge1$new_client
32//             - org$rust$cxxbridge1$new_client
33//          defining characteristics:
34//             - cxxbridge is second from end
35//          FIXME: conflict with (a) if they collide with one of our one-off symbol names in the global namespace
36//
37//   (e) User-defined extern member function.
38//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE} $ {NAME}
39//          examples:
40//             - org$cxxbridge1$Struct$get
41//          defining characteristics:
42//             - cxxbridge is third from end
43//          FIXME: conflict with (b) if e.g. user binds a type in global namespace that collides with our builtin type names
44//
45//   (f) Operator overload.
46//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE} $ operator $ {NAME}
47//          examples:
48//             - org$rust$cxxbridge1$Struct$operator$eq
49//          defining characteristics:
50//             - second segment from end is `operator` (not possible in type or namespace names)
51//
52//   (g) Closure trampoline.
53//          pattern:  {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE?} $ {NAME} $ {ARGUMENT} $ {DIRECTION}
54//          examples:
55//             - org$rust$cxxbridge1$Struct$invoke$f$0
56//          defining characteristics:
57//             - last symbol is `0` (C half) or `1` (Rust half) which are not legal identifiers on their own
58//
59//
60// Mangled preprocessor variable arrangements:
61//
62//   (A) One-off internal variable.
63//          pattern:  {CXXBRIDGE} _ {NAME}
64//          examples:
65//             - CXXBRIDGE1_PANIC
66//             - CXXBRIDGE1_RUST_STRING
67//          defining characteristics:
68//             - NAME does not begin with STRUCT or ENUM
69//
70//   (B) Guard around user-defined type.
71//          pattern:  {CXXBRIDGE} _ {STRUCT or ENUM} _ {NAMESPACE...} $ {TYPE}
72//          examples:
73//             - CXXBRIDGE1_STRUCT_org$rust$Struct
74//             - CXXBRIDGE1_ENUM_Enabled
75
76use crate::syntax::symbol::{self, Symbol};
77use crate::syntax::{ExternFn, Pair, Types};
78
79const CXXBRIDGE: &str = "cxxbridge1";
80
81macro_rules! join {
82    ($($segment:expr),+ $(,)?) => {
83        symbol::join(&[$(&$segment),+])
84    };
85}
86
87pub(crate) fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
88    match &efn.receiver {
89        Some(receiver) => {
90            let receiver_ident = types.resolve(&receiver.ty);
91            join!(
92                efn.name.namespace,
93                CXXBRIDGE,
94                receiver_ident.name.cxx,
95                efn.name.rust,
96            )
97        }
98        None => join!(efn.name.namespace, CXXBRIDGE, efn.name.rust),
99    }
100}
101
102pub(crate) fn operator(receiver: &Pair, operator: &'static str) -> Symbol {
103    join!(
104        receiver.namespace,
105        CXXBRIDGE,
106        receiver.cxx,
107        "operator",
108        operator,
109    )
110}
111
112// The C half of a function pointer trampoline.
113pub(crate) fn c_trampoline(efn: &ExternFn, var: &Pair, types: &Types) -> Symbol {
114    join!(extern_fn(efn, types), var.rust, 0)
115}
116
117// The Rust half of a function pointer trampoline.
118pub(crate) fn r_trampoline(efn: &ExternFn, var: &Pair, types: &Types) -> Symbol {
119    join!(extern_fn(efn, types), var.rust, 1)
120}