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-system.h"
18 #include "rust-diagnostics.h"
19 #include "rust-proc-macro.h"
20 #include "rust-session-manager.h"
22 #include "rust-token-converter.h"
23 #include "rust-attributes.h"
31 BangProcMacro::BangProcMacro (ProcMacro::Bang macro
)
33 node_id (Analysis::Mappings::get ()->get_next_node_id ()),
37 AttributeProcMacro::AttributeProcMacro (ProcMacro::Attribute macro
)
39 node_id (Analysis::Mappings::get ()->get_next_node_id ()),
43 CustomDeriveProcMacro::CustomDeriveProcMacro (ProcMacro::CustomDerive macro
)
44 : trait_name (macro
.trait_name
),
45 attributes (macro
.attributes
, macro
.attributes
+ macro
.attr_size
),
46 node_id (Analysis::Mappings::get ()->get_next_node_id ()),
53 literal_from_string (const std::string
&data
, bool &error
)
55 Lexer
lex (data
, nullptr);
56 const_TokenPtr output
= lex
.build_token ();
57 if (output
== nullptr || !output
->is_literal ())
60 // We should probably rework this
61 return ProcMacro::Literal::make_usize (0);
65 return convert_literal (output
);
68 ProcMacro::TokenStream
69 tokenstream_from_string (std::string
&data
, bool &lex_error
)
71 // FIXME: Insert location pointing to call site in tokens
72 Lexer
lex (data
, Session::get_instance ().linemap
);
74 std::vector
<const_TokenPtr
> tokens
;
76 for (ptr
= lex
.build_token ();
77 ptr
!= nullptr && ptr
->get_id () != END_OF_FILE
;
78 ptr
= lex
.build_token ())
80 tokens
.emplace_back (ptr
);
86 return ProcMacro::TokenStream::make_tokenstream ();
90 return convert (tokens
);
94 std::is_same
<decltype (tokenstream_from_string
) *,
95 ProcMacro::ts_from_str_fn_t
>::value
,
96 "Registration callback signature not synced, check proc macro internals.");
99 std::is_same
<decltype (literal_from_string
) *,
100 ProcMacro::lit_from_str_fn_t
>::value
,
101 "Registration callback signature not synced, check proc macro internals.");
105 template <typename Symbol
, typename Callback
>
107 register_callback (void *handle
, Symbol
, std::string symbol_name
,
110 void *addr
= dlsym (handle
, symbol_name
.c_str ());
113 rust_error_at (UNDEF_LOCATION
,
114 "Callback registration symbol (%s) missing from "
115 "proc macro, wrong version?",
116 symbol_name
.c_str ());
120 auto storage
= reinterpret_cast<Symbol
*> (addr
);
126 #define REGISTER_CALLBACK(HANDLE, SYMBOL, CALLBACK) \
127 register_callback (HANDLE, SYMBOL, #SYMBOL, CALLBACK)
129 const ProcMacro::ProcmacroArray
*
130 load_macros_array (std::string path
)
133 void *handle
= dlopen (path
.c_str (), RTLD_LAZY
| RTLD_LOCAL
);
134 // We're leaking the handle since we can't ever unload it
137 rust_debug ("Error whilst opening procedural macro: %s", dlerror ());
141 if (!REGISTER_CALLBACK (handle
, __gccrs_proc_macro_ts_from_str_
,
142 tokenstream_from_string
))
144 if (!REGISTER_CALLBACK (handle
, __gccrs_proc_macro_lit_from_str_
,
145 literal_from_string
))
147 if (!REGISTER_CALLBACK (handle
, __gccrs_proc_macro_is_available_
,
148 ProcMacro::BridgeState::Available
))
151 // FIXME: Add CrateStableId handling, right now all versions may be loaded,
152 // even incompatible ones.
153 auto symbol_name
= generate_proc_macro_decls_symbol (0 /* FIXME */);
155 return *reinterpret_cast<const ProcMacro::ProcmacroArray
**> (
156 dlsym (handle
, symbol_name
.c_str ()));
158 rust_sorry_at (UNDEF_LOCATION
,
159 "Procedural macros are not yet supported on windows host");
164 #undef REGISTER_CALLBACK
166 const std::vector
<ProcMacro::Procmacro
>
167 load_macros (std::string path
)
169 const ProcMacro::ProcmacroArray
*array
= load_macros_array (path
);
170 // Did not load the proc macro
171 if (array
== nullptr)
174 rust_debug ("Found %lu procedural macros", (unsigned long) array
->length
);
176 return std::vector
<ProcMacro::Procmacro
> (array
->macros
,
177 array
->macros
+ array
->length
);
181 generate_proc_macro_decls_symbol (std::uint32_t stable_crate_id
)
183 std::ostringstream stream
;
184 stream
<< "__gccrs_proc_macro_decls_" << std::setfill ('0') << std::hex
185 << std::setw (8) << stable_crate_id
<< "__";
187 return stream
.str ();