1 // This file is part of GCC.
3 // GCC is free software; you can redistribute it and/or modify it under
4 // the terms of the GNU General Public License as published by the Free
5 // Software Foundation; either version 3, or (at your option) any later
8 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
9 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 // You should have received a copy of the GNU General Public License
14 // along with GCC; see the file COPYING3. If not see
15 // <http://www.gnu.org/licenses/>.
17 #include "rust-diagnostics.h"
18 #include "rust-proc-macro.h"
20 #include "rust-token-converter.h"
27 const std::string PROC_MACRO_DECL_PREFIX
= "__gccrs_proc_macro_decls_";
29 static ProcMacro::TokenStream
30 tokenstream_from_string (std::string
&data
, bool &lex_error
)
32 // FIXME: Insert location pointing to call site in tokens
35 std::vector
<const_TokenPtr
> tokens
;
37 for (ptr
= lex
.build_token ();
38 ptr
!= nullptr && ptr
->get_id () != END_OF_FILE
;
39 ptr
= lex
.build_token ())
41 tokens
.emplace_back (ptr
);
47 return ProcMacro::TokenStream::make_tokenstream ();
51 return convert (tokens
);
55 std::is_same
<decltype (tokenstream_from_string
) *,
56 ProcMacro::from_str_function_t
>::value
,
57 "Registration callback signature not synced, check proc macro internals.");
59 template <typename Symbol
, typename Callback
>
61 register_callback (void *handle
, Symbol
, std::string symbol_name
,
64 void *addr
= dlsym (handle
, symbol_name
.c_str ());
67 rust_error_at (Location (),
68 "Callback registration symbol (%s) missing from "
69 "proc macro, wrong version?",
70 symbol_name
.c_str ());
74 auto storage
= reinterpret_cast<Symbol
*> (addr
);
80 #define REGISTER_CALLBACK(HANDLE, SYMBOL, CALLBACK) \
81 register_callback (HANDLE, SYMBOL, #SYMBOL, CALLBACK)
83 const ProcMacro::ProcmacroArray
*
84 load_macros_array (std::string path
)
87 void *handle
= dlopen (path
.c_str (), RTLD_LAZY
| RTLD_LOCAL
);
88 // We're leaking the handle since we can't ever unload it
91 rust_debug ("Error whilst opening procedural macro: %s", dlerror ());
95 if (!REGISTER_CALLBACK (handle
, __gccrs_proc_macro_from_str_fn
,
96 tokenstream_from_string
))
99 // FIXME: Add CrateStableId handling, right now all versions may be loaded,
100 // even incompatible ones.
101 return *reinterpret_cast<const ProcMacro::ProcmacroArray
**> (
102 dlsym (handle
, PROC_MACRO_DECL_PREFIX
.c_str ()));
104 rust_sorry_at (UNDEF_LOCATION
,
105 "Procedural macros are not yet supported on windows host");
110 #undef REGISTER_CALLBACK
112 const std::vector
<ProcMacro::Procmacro
>
113 load_macros (std::string path
)
115 const ProcMacro::ProcmacroArray
*array
= load_macros_array (path
);
116 // Did not load the proc macro
117 if (array
== nullptr)
120 rust_debug ("Found %lu procedural macros", array
->length
);
122 return std::vector
<ProcMacro::Procmacro
> (array
->macros
,
123 array
->macros
+ array
->length
);