From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7905) id 4A11E3857706; Tue, 16 Jan 2024 18:18:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4A11E3857706 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1705429114; bh=hGM/Sn6CMCzs0b4pHw4y511HMgwqxEjwa7bWWNUbkBY=; h=From:To:Subject:Date:From; b=oNbxKRucH7+q0h4WN3p/XEFzUdTnlQLqDywWISGn5hphRjkOYHU+joWSIGcg4ALSH bSfqh/X2RQjvWxR0+ihmXdmeBEXTM6hv3WLv6Ik/z62Io+qDnAi1FHVw9feNF2dVa7 THa1QxfG0jv+5KLCPH6JdbJxoVq9Vf6x6GSAz+8c= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Arthur Cohen To: gcc-cvs@gcc.gnu.org Subject: [gcc r14-8099] gccrs: Add utility function to build proc macro types X-Act-Checkin: gcc X-Git-Author: Pierre-Emmanuel Patry X-Git-Refname: refs/heads/trunk X-Git-Oldrev: d1e2f3dfbb643e45b2f6ad10fda231533b306417 X-Git-Newrev: 150403984d818895e40629ea7c5369f32f96fc1c Message-Id: <20240116181834.4A11E3857706@sourceware.org> Date: Tue, 16 Jan 2024 18:18:34 +0000 (GMT) List-Id: https://gcc.gnu.org/g:150403984d818895e40629ea7c5369f32f96fc1c commit r14-8099-g150403984d818895e40629ea7c5369f32f96fc1c Author: Pierre-Emmanuel Patry Date: Fri Sep 15 11:08:13 2023 +0200 gccrs: Add utility function to build proc macro types Add some utility function to build proc macro entrypoint related types. Those functions will help generate all required metadata in order for proc macros to be expanded properly. gcc/rust/ChangeLog: * backend/rust-compile.cc (build_attribute_array): Add a function to build the attribute array type. (build_derive_proc_macro): Add a function to build the derive proc macro type. (build_bang_proc_macro): Add a function to build the bang proc macro type. (build_attribute_proc_macro): Add a function to build the attribute proc macro type. (build_proc_macro): Add a function to build the proc macro tagged union type. (build_proc_macro_buffer): Add a function to build the proc macro buffer type. (build_entrypoint): Add a function to build the proc macro entrypoint type. * backend/rust-compile.h: Add function prototype. Signed-off-by: Pierre-Emmanuel Patry Diff: --- gcc/rust/backend/rust-compile.cc | 178 +++++++++++++++++++++++++++++++++++++++ gcc/rust/backend/rust-compile.h | 2 + 2 files changed, 180 insertions(+) diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 43c3da07a2f..cc5382bf5f8 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -23,6 +23,7 @@ #include "rust-compile-type.h" #include "rust-substitution-mapper.h" #include "rust-type-util.h" +#include "rust-session-manager.h" namespace Rust { namespace Compile { @@ -45,6 +46,183 @@ CompileCrate::go () { for (auto &item : crate.get_items ()) CompileItem::compile (item.get (), ctx); + auto crate_type + = Rust::Session::get_instance ().options.target_data.get_crate_type (); + if (crate_type == TargetOptions::CrateType::PROC_MACRO) + add_proc_macro_symbols (); +} + +namespace { + +tree +build_attribute_array (std::vector attributes) +{ + tree attribute_ptr = build_pointer_type (char_type_node); + tree attribute_type = build_qualified_type (attribute_ptr, TYPE_QUAL_CONST); + return build_array_type_nelts (attribute_type, attributes.size ()); +} + +// We're constructing the following structure: +// +// struct { +// const char *trait_name; +// const char **attributes; +// std::uint64_t attr_size; +// TokenStream (fndecl*) (TokenStream); +// } +tree +build_derive_proc_macro (std::vector attributes) +{ + tree char_ptr = build_pointer_type (char_type_node); + tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST); + Backend::typed_identifier name_field + = Backend::typed_identifier ("trait_name", const_char_type, + BUILTINS_LOCATION); + + // HACK: cannot use TREE_TYPE(fndecl) to retrieve the type, instead we're + // using a void pointer. We should probably find another way to achieve this. + // We cannot construct the type by ourselves because the function uses + // external TokenStream parameters and return type. + tree handle_ptr = build_pointer_type (void_type_node); + Backend::typed_identifier fndecl_field + = Backend::typed_identifier ("fndecl", handle_ptr, BUILTINS_LOCATION); + + tree attribute_ptr = build_pointer_type (build_attribute_array (attributes)); + tree const_attribute_type + = build_qualified_type (attribute_ptr, TYPE_QUAL_CONST); + + Backend::typed_identifier attributes_field + = Backend::typed_identifier ("attributes", const_attribute_type, + BUILTINS_LOCATION); + + Backend::typed_identifier size_field + = Backend::typed_identifier ("attr_size", unsigned_type_node, + BUILTINS_LOCATION); + + return Backend::struct_type ( + {name_field, attributes_field, size_field, fndecl_field}); +} + +// We're constructing the following structure: +// +// struct { +// const char *name; +// TokenStream (fndecl*) (TokenStream); +// } +tree +build_bang_proc_macro () +{ + tree char_ptr = build_pointer_type (char_type_node); + tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST); + Backend::typed_identifier name_field + = Backend::typed_identifier ("name", const_char_type, BUILTINS_LOCATION); + + // HACK: cannot use TREE_TYPE(fndecl) to retrieve the type, instead we're + // using a void pointer. We should probably find another way to achieve this. + // We cannot construct the type by ourselves because the function uses + // external TokenStream parameters and return type. + tree handle_ptr = build_pointer_type (void_type_node); + Backend::typed_identifier fndecl_field + = Backend::typed_identifier ("fndecl", handle_ptr, BUILTINS_LOCATION); + + return Backend::struct_type ({name_field, fndecl_field}); +} + +// Bang proc macros and attribute proc macros almost have the same members +// the function pointer type is not the same. +// +// We're constructing the following structure: +// +// struct { +// const char *name; +// TokenStream (fndecl*) (TokenStream, TokenStream); +// } +tree +build_attribute_proc_macro () +{ + return build_bang_proc_macro (); +} + +// Build the tagged union proc macro type +// +// struct { +// unsigned short tag; +// union { BangProcMacro , DeriveProcMacro, AttributeProcMacro} payload; +// } +tree +build_proc_macro (tree bang, tree attribute, tree derive) +{ + Backend::typed_identifier bang_field + = Backend::typed_identifier ("bang", bang, BUILTINS_LOCATION); + Backend::typed_identifier attribute_field + = Backend::typed_identifier ("attribute", attribute, BUILTINS_LOCATION); + Backend::typed_identifier derive_field + = Backend::typed_identifier ("custom_derive", derive, BUILTINS_LOCATION); + + tree union_field + = Backend::union_type ({bang_field, attribute_field, derive_field}); + + Backend::typed_identifier payload_field + = Backend::typed_identifier ("payload", union_field, BUILTINS_LOCATION); + + Backend::typed_identifier tag_field + = Backend::typed_identifier ("tag", short_unsigned_type_node, + BUILTINS_LOCATION); + + return Backend::struct_type ({tag_field, payload_field}); +} + +tree +build_proc_macro_buffer (tree proc_macro_type, size_t total_macro) +{ + return build_array_type_nelts (proc_macro_type, total_macro); +} + +tree +build_entrypoint (tree proc_macro_buffer) +{ + return build_reference_type_for_mode (proc_macro_buffer, E_VOIDmode, false); +} + +} // namespace + +void +CompileCrate::add_proc_macro_symbols () +{ + auto total_macros = ctx->get_attribute_proc_macros ().size () + + ctx->get_bang_proc_macros ().size () + + ctx->get_derive_proc_macros ().size (); + + tree custom_derive_type = build_derive_proc_macro ({}); + tree bang_type = build_bang_proc_macro (); + tree attribute_type = build_attribute_proc_macro (); + tree proc_macro_type + = build_proc_macro (bang_type, attribute_type, custom_derive_type); + tree proc_macro_buffer_type + = build_proc_macro_buffer (proc_macro_type, total_macros); + tree entrypoint_type = build_entrypoint (proc_macro_buffer_type); + Bvariable *macro_decls + = Backend::global_variable ("__gccrs_proc_macro_decl_", + "__gccrs_proc_macro_decls_", entrypoint_type, + false, false, false, BUILTINS_LOCATION); + + // tree init = value == error_mark_node ? error_mark_node : DECL_INITIAL + // (value); + // Backend::global_variable_set_init (macro_decls, error_mark_node); + ctx->push_var (macro_decls); + + for (auto ¯o : ctx->get_derive_proc_macros ()) + { + rust_debug ("Found one derive macro"); + } + for (auto ¯o : ctx->get_attribute_proc_macros ()) + { + rust_debug ("Found one attribute macro"); + } + for (auto ¯o : ctx->get_bang_proc_macros ()) + { + rust_debug ("Found one bang macro"); + } } // Shared methods in compilation diff --git a/gcc/rust/backend/rust-compile.h b/gcc/rust/backend/rust-compile.h index 6156f1c86a1..d49b95be762 100644 --- a/gcc/rust/backend/rust-compile.h +++ b/gcc/rust/backend/rust-compile.h @@ -37,6 +37,8 @@ private: CompileCrate (HIR::Crate &crate, Context *ctx); void go (); + void add_proc_macro_symbols (); + HIR::Crate &crate; Context *ctx; };