From 04c9af6d0f2d38504a5add30c44a348a91af4b57 Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Tue, 11 Jul 2023 14:41:33 +0200 Subject: proc_macro: Add from string implementation Add a callback registration function into the proc macro library so the compiler can register it's own lexing/parsing functions on load. gcc/rust/ChangeLog: * expand/rust-proc-macro.cc (tokenstream_from_string): Add a function that creates a tokenstream from a given string. (load_macros_array): Add call to registration function. ChangeLog: * libgrust/libproc_macro/proc_macro.cc (proc_macro_register_from_str): Add registration function. * libgrust/libproc_macro/proc_macro.h (proc_macro_register_from_str): Add registration function prototype. * libgrust/libproc_macro/tokenstream.cc (TokenStream::make_tokenstream): Add a new constructor from a string that uses the registered callback. (TokenStream__from_string): Add call to new constructor. * libgrust/libproc_macro/tokenstream.h: Add registration declaration. * libgrust/libproc_macro/registration.h: New file. Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/expand/rust-proc-macro.cc | 62 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'gcc') diff --git a/gcc/rust/expand/rust-proc-macro.cc b/gcc/rust/expand/rust-proc-macro.cc index b68486e..6ba87b6 100644 --- a/gcc/rust/expand/rust-proc-macro.cc +++ b/gcc/rust/expand/rust-proc-macro.cc @@ -16,6 +16,8 @@ #include "rust-diagnostics.h" #include "rust-proc-macro.h" +#include "rust-lex.h" +#include "rust-token-converter.h" #ifndef _WIN32 #include #endif @@ -24,6 +26,60 @@ namespace Rust { const std::string PROC_MACRO_DECL_PREFIX = "__gccrs_proc_macro_decls_"; +ProcMacro::TokenStream +tokenstream_from_string (std::string &data, bool &lex_error) +{ + // FIXME: Insert location pointing to call site in tokens + Lexer lex (data); + + std::vector tokens; + TokenPtr ptr; + for (ptr = lex.build_token (); + ptr != nullptr && ptr->get_id () != END_OF_FILE; + ptr = lex.build_token ()) + { + tokens.emplace_back (ptr); + } + + if (ptr == nullptr) + { + lex_error = true; + return ProcMacro::TokenStream::make_tokenstream (); + } + + lex_error = false; + return convert (tokens); +} + +static_assert ( + std::is_same::value, + "Registration callback signature not synced, check proc macro internals."); + +template +bool +register_callback (void *handle, Symbol, std::string symbol_name, + Callback callback) +{ + void *addr = dlsym (handle, symbol_name.c_str ()); + if (addr == nullptr) + { + rust_error_at (Location (), + "Callback registration symbol (%s) missing from " + "proc macro, wrong version?", + symbol_name.c_str ()); + return false; + } + + auto storage = reinterpret_cast (addr); + *storage = callback; + + return true; +} + +#define REGISTER_CALLBACK(HANDLE, SYMBOL, CALLBACK) \ + register_callback (HANDLE, SYMBOL, #SYMBOL, CALLBACK) + const ProcMacro::ProcmacroArray * load_macros_array (std::string path) { @@ -36,6 +92,10 @@ load_macros_array (std::string path) return nullptr; } + if (!REGISTER_CALLBACK (handle, __gccrs_pm_callback_from_str_fn, + tokenstream_from_string)) + return nullptr; + // FIXME: Add CrateStableId handling, right now all versions may be loaded, // even incompatible ones. return *reinterpret_cast ( @@ -47,6 +107,8 @@ load_macros_array (std::string path) #endif } +#undef REGISTER_CALLBACK + const std::vector load_macros (std::string path) { -- cgit v1.1