From ac947238cc9dc87e227d70575c5467551633e5ce Mon Sep 17 00:00:00 2001 From: Pierre-Emmanuel Patry Date: Wed, 27 Sep 2023 16:44:48 +0200 Subject: [PATCH] Do not merge this WIP gcc/rust/ChangeLog: * backend/rust-compile.cc (build_bang_proc_macro): (build_proc_macro): (build_proc_macro_payload): (init_derive_proc_macro): (init_attribute_proc_macro): (init_bang_proc_macro): (init_proc_macro): (initialize_proc_macro_array): (CompileCrate::add_proc_macro_symbols): Signed-off-by: Pierre-Emmanuel Patry --- gcc/rust/backend/rust-compile.cc | 165 +++++++++++++++++++++++++------ 1 file changed, 137 insertions(+), 28 deletions(-) diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index df3e1c5a02e..3f1ea2e2747 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -17,6 +17,9 @@ // . #include "rust-compile.h" +#include "libproc_macro_internal/proc_macro.h" +#include "rust-backend.h" +#include "rust-compile-context.h" #include "rust-compile-item.h" #include "rust-compile-implitem.h" #include "rust-hir-type-bounds.h" @@ -24,6 +27,7 @@ #include "rust-substitution-mapper.h" #include "rust-type-util.h" #include "rust-session-manager.h" +#include "tree.h" namespace Rust { namespace Compile { @@ -125,7 +129,7 @@ build_bang_proc_macro () Backend::typed_identifier fndecl_field = Backend::typed_identifier ("fndecl", handle_ptr, BUILTINS_LOCATION); - return Backend::struct_type ({name_field, fndecl_field}); + return Backend::struct_type ({name_field /*, fndecl_field */}); } // Bang proc macros and attribute proc macros almost have the same members @@ -143,15 +147,13 @@ 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) +build_proc_macro_payload () { + tree bang = build_bang_proc_macro (); + tree attribute = build_attribute_proc_macro (); + tree derive = build_attribute_proc_macro (); + Backend::typed_identifier bang_field = Backend::typed_identifier ("bang", bang, BUILTINS_LOCATION); Backend::typed_identifier attribute_field @@ -159,9 +161,29 @@ build_proc_macro (tree bang, tree attribute, tree derive) 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}); + // We rely on the tag to represent the index of any union member. This means + // we should keep those fields in the same order as the tag representation for + // it to be kept in sync. + // Hence why the following code exist: to keep in sync the field vector and + // the tag enumeration. + std::vector fields; + fields.insert (fields.begin () + ProcMacro::CUSTOM_DERIVE, derive_field); + fields.insert (fields.begin () + ProcMacro::ATTR, attribute_field); + fields.insert (fields.begin () + ProcMacro::BANG, bang_field); + + return Backend::union_type (fields); +} +// Build the tagged union proc macro type +// +// struct { +// unsigned short tag; +// union { BangProcMacro , DeriveProcMacro, AttributeProcMacro} payload; +// } +tree +build_proc_macro () +{ + auto union_field = build_proc_macro_payload (); Backend::typed_identifier payload_field = Backend::typed_identifier ("payload", union_field, BUILTINS_LOCATION); @@ -184,6 +206,105 @@ build_entrypoint (tree proc_macro_buffer) return build_reference_type_for_mode (proc_macro_buffer, E_VOIDmode, false); } +tree +init_derive_proc_macro (CustomDeriveInfo infos) +{ + tree derive_proc_macro_type = build_derive_proc_macro (infos.attributes); + tree trait_name = build_string_literal (infos.trait_name.c_str ()); + tree attributes; // FIXME + tree attr_size; // FIXME + tree handle = infos.fndecl; + + return Backend::constructor_expression ( + derive_proc_macro_type, false, {trait_name, attributes, attr_size, handle}, + -1 /* Structure: no index */, BUILTINS_LOCATION); +} + +tree +init_attribute_proc_macro (tree macro) +{ + tree attribute_proc_macro_type = build_attribute_proc_macro (); + tree macro_name + = build_string_literal (IDENTIFIER_POINTER (DECL_NAME (macro))); + tree handle = macro; + + return Backend::constructor_expression (attribute_proc_macro_type, false, + {macro_name /*, handle */}, + -1 /* Structure: No index */, + BUILTINS_LOCATION); +} + +// Attribute and bang proc macros have the same structure, they can be +// initialized with the same code. +tree +init_bang_proc_macro (tree macro) +{ + return init_attribute_proc_macro (macro); +} + +tree +init_proc_macro (tree payload, tree proc_macro_type, + ProcMacro::ProcmacroTag tag) +{ + auto discriminant = static_cast (tag); + mpz_t ival; + // HACK: There surely is a better function ? No ? + mpz_init_set_str (ival, std::string{discriminant}.c_str (), 10); + tree macro_tag + = Backend::integer_constant_expression (short_unsigned_type_node, ival); + + // FIXME: SHould we create a payload ?? Like this ? Should we directly put + // payload into the expression struct? + tree payload_union + = Backend::constructor_expression (build_proc_macro_payload (), false, + {payload}, + discriminant /* Union: member index */, + BUILTINS_LOCATION); + + return Backend::constructor_expression (proc_macro_type, + false /* invariant */, + {macro_tag, payload_union}, + -1 /* Structure: No index */, + BUILTINS_LOCATION); +} + +tree +initialize_proc_macro_array (Context *ctx, tree proc_macro_buffer_type, + tree proc_macro_type) +{ + std::vector indexes; + std::vector ctors; + size_t index = 0; + for (auto ¯o : ctx->get_derive_proc_macros ()) + { + rust_debug ("Found one derive macro"); + index++; + } + for (auto ¯o : ctx->get_attribute_proc_macros ()) + { + rust_debug ("Found one attribute macro"); + tree proc_macro = init_attribute_proc_macro (macro); + + ctors.push_back (init_proc_macro (proc_macro, proc_macro_type, + ProcMacro::ProcmacroTag::ATTR)); + indexes.push_back (index); + index++; + } + for (auto ¯o : ctx->get_bang_proc_macros ()) + { + rust_debug ("Found one bang macro"); + tree proc_macro = init_bang_proc_macro (macro); + + ctors.push_back (init_proc_macro (proc_macro, proc_macro_type, + ProcMacro::ProcmacroTag::BANG)); + indexes.push_back (index); + index++; + } + + return Backend::array_constructor_expression (proc_macro_buffer_type, indexes, + ctors, BUILTINS_LOCATION); +} + } // namespace void @@ -193,11 +314,7 @@ CompileCrate::add_proc_macro_symbols () + 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_type = build_proc_macro (); tree proc_macro_buffer_type = build_proc_macro_buffer (proc_macro_type, total_macros); tree entrypoint_type = build_entrypoint (proc_macro_buffer_type); @@ -214,21 +331,13 @@ CompileCrate::add_proc_macro_symbols () // tree init = value == error_mark_node ? error_mark_node : DECL_INITIAL // (value); Backend::global_variable_set_init (macro_decls, error_mark_node); + + Backend::global_variable_set_init ( + proc_macro_buffer, + initialize_proc_macro_array (ctx, proc_macro_buffer_type, proc_macro_type)); + ctx->push_var (proc_macro_buffer); 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