public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-8099] gccrs: Add utility function to build proc macro types
@ 2024-01-16 18:18 Arthur Cohen
  0 siblings, 0 replies; only message in thread
From: Arthur Cohen @ 2024-01-16 18:18 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:150403984d818895e40629ea7c5369f32f96fc1c

commit r14-8099-g150403984d818895e40629ea7c5369f32f96fc1c
Author: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
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 <pierre-emmanuel.patry@embecosm.com>

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<std::string> 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<std::string> 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 &macro : ctx->get_derive_proc_macros ())
+    {
+      rust_debug ("Found one derive macro");
+    }
+  for (auto &macro : ctx->get_attribute_proc_macros ())
+    {
+      rust_debug ("Found one attribute macro");
+    }
+  for (auto &macro : 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;
 };

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-01-16 18:18 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-16 18:18 [gcc r14-8099] gccrs: Add utility function to build proc macro types Arthur Cohen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).