]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Add utility function to build proc macro types
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Fri, 15 Sep 2023 09:08:13 +0000 (11:08 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 18:09:32 +0000 (19:09 +0100)
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>
gcc/rust/backend/rust-compile.cc
gcc/rust/backend/rust-compile.h

index 43c3da07a2f963f7ce0593782f9d9d86f6422a3e..cc5382bf5f80d07377295854bfef59765071e7a6 100644 (file)
@@ -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
index 6156f1c86a1274ea644e2a88529af83af5ac91bb..d49b95be7627efa8c32b25945edd9c47f5a90d24 100644 (file)
@@ -37,6 +37,8 @@ private:
   CompileCrate (HIR::Crate &crate, Context *ctx);
   void go ();
 
+  void add_proc_macro_symbols ();
+
   HIR::Crate &crate;
   Context *ctx;
 };