aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/backend
diff options
context:
space:
mode:
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>2023-09-20 17:39:16 +0200
committerArthur Cohen <arthur.cohen@embecosm.com>2024-01-16 19:09:33 +0100
commitc0a7f3e67a428affcd508eb272034fceb7f2841f (patch)
tree9522bf61764260647b38a1894907179b4be9b249 /gcc/rust/backend
parent10699fb34a2969102afe3519caae62dddb8075fc (diff)
downloadgcc-c0a7f3e67a428affcd508eb272034fceb7f2841f.zip
gcc-c0a7f3e67a428affcd508eb272034fceb7f2841f.tar.gz
gcc-c0a7f3e67a428affcd508eb272034fceb7f2841f.tar.bz2
gccrs: Add macro buffer global variable export
Export a new symbol containing the proc macros. gcc/rust/ChangeLog: * backend/rust-compile-base.h: Make static function address_expression public. * backend/rust-compile.cc (CompileCrate::add_proc_macro_symbols): Add new global variable in export function. (build_bang_proc_macro): Add a function to build the bang proc macro structure type. (build_proc_macro): Add a function to build the proc macro structure type. (build_proc_macro_payload): Add a function to build the proc macro union used in proc macro structures. (init_derive_proc_macro): Add a function to initialize custom derive proc macros. (init_attribute_proc_macro): Add a function to initialize attribute proc macros. (init_bang_proc_macro): Add a function to initialize bang proc macros. (init_proc_macro): Add a function to initialize proc macro structures. (initialize_proc_macro_array): Add a function to initialize the proc macro buffer array. (CompileCrate::add_proc_macro_symbols): Add call to the new functions to correctly initialize proc macros as well as their entrypoint. Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Diffstat (limited to 'gcc/rust/backend')
-rw-r--r--gcc/rust/backend/rust-compile-base.h4
-rw-r--r--gcc/rust/backend/rust-compile.cc252
2 files changed, 206 insertions, 50 deletions
diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h
index 41907ec..6529123 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -29,6 +29,8 @@ class HIRCompileBase
public:
virtual ~HIRCompileBase () {}
+ static tree address_expression (tree expr, location_t locus);
+
protected:
HIRCompileBase (Context *ctx) : ctx (ctx) {}
@@ -139,8 +141,6 @@ protected:
static void setup_abi_options (tree fndecl, ABI abi);
- static tree address_expression (tree expr, location_t locus);
-
static tree indirect_expression (tree expr, location_t locus);
static bool mark_addressable (tree, location_t);
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index cc5382b..3aee807 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -17,6 +17,7 @@
// <http://www.gnu.org/licenses/>.
#include "rust-compile.h"
+#include "libproc_macro_internal/proc_macro.h"
#include "rust-compile-item.h"
#include "rust-compile-implitem.h"
#include "rust-hir-type-bounds.h"
@@ -28,6 +29,8 @@
namespace Rust {
namespace Compile {
+const std::string GCCRS_PROC_MACRO_SYMBOL_PREFIX = "__gccrs_proc_macro_";
+
CompileCrate::CompileCrate (HIR::Crate &crate, Context *ctx)
: crate (crate), ctx (ctx)
{}
@@ -52,6 +55,8 @@ CompileCrate::go ()
add_proc_macro_symbols ();
}
+// This namespace brings multiple function to build and initialize multiple
+// structures that needs to get exposed in the final shared object binary.
namespace {
tree
@@ -71,7 +76,7 @@ build_attribute_array (std::vector<std::string> attributes)
// TokenStream (fndecl*) (TokenStream);
// }
tree
-build_derive_proc_macro (std::vector<std::string> attributes)
+build_derive_proc_macro ()
{
tree char_ptr = build_pointer_type (char_type_node);
tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
@@ -79,20 +84,13 @@ build_derive_proc_macro (std::vector<std::string> attributes)
= 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);
-
+ tree attribute_ptr = build_pointer_type (const_ptr_type_node);
Backend::typed_identifier attributes_field
- = Backend::typed_identifier ("attributes", const_attribute_type,
+ = Backend::typed_identifier ("attributes", attribute_ptr,
BUILTINS_LOCATION);
Backend::typed_identifier size_field
@@ -117,11 +115,7 @@ build_bang_proc_macro ()
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);
+ tree handle_ptr = ptr_type_node;
Backend::typed_identifier fndecl_field
= Backend::typed_identifier ("fndecl", handle_ptr, BUILTINS_LOCATION);
@@ -143,15 +137,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_derive_proc_macro ();
+
Backend::typed_identifier bang_field
= Backend::typed_identifier ("bang", bang, BUILTINS_LOCATION);
Backend::typed_identifier attribute_field
@@ -159,9 +151,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<Backend::typed_identifier> 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 +196,147 @@ build_entrypoint (tree proc_macro_buffer)
return build_reference_type_for_mode (proc_macro_buffer, E_VOIDmode, false);
}
+tree
+init_derive_proc_macro (Context *ctx, CustomDeriveInfo infos)
+{
+ tree derive_proc_macro_type = build_derive_proc_macro ();
+ tree trait_name = build_string_literal (infos.trait_name.c_str ());
+
+ tree attribute_ptr;
+ if (infos.attributes.size () == 0)
+ {
+ attribute_ptr = HIRCompileBase::address_expression (null_pointer_node,
+ BUILTINS_LOCATION);
+ }
+ else
+ {
+ tree attribute_array_type = build_attribute_array (infos.attributes);
+
+ std::vector<tree> attr_ctors;
+ std::vector<unsigned long> indices;
+
+ size_t index = 0;
+ for (auto &attr : infos.attributes)
+ {
+ attr_ctors.push_back (build_string_literal (attr.c_str ()));
+ indices.push_back (index);
+ index++;
+ }
+
+ tree attributes
+ = Backend::array_constructor_expression (attribute_array_type, indices,
+ attr_ctors, BUILTINS_LOCATION);
+
+ std::string attribute_var_name
+ = GCCRS_PROC_MACRO_SYMBOL_PREFIX + infos.trait_name;
+ Bvariable *attributes_var
+ = Backend::global_variable (attribute_var_name.c_str (),
+ attribute_var_name.c_str (),
+ attribute_array_type, false /* internal */,
+ true /* hidden */, false /* no gc */,
+ BUILTINS_LOCATION);
+ Backend::global_variable_set_init (attributes_var, attributes);
+ ctx->push_var (attributes_var);
+
+ attribute_ptr
+ = HIRCompileBase::address_expression (attributes_var->get_decl (),
+ BUILTINS_LOCATION);
+ }
+
+ tree attr_size = build_int_cst (unsigned_type_node, infos.attributes.size ());
+
+ tree handle
+ = HIRCompileBase::address_expression (infos.fndecl, BUILTINS_LOCATION);
+
+ return Backend::constructor_expression (derive_proc_macro_type, false,
+ {trait_name, attribute_ptr, 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 = HIRCompileBase::address_expression (macro, BUILTINS_LOCATION);
+
+ return Backend::constructor_expression (attribute_proc_macro_type, false,
+ {macro_name, handle},
+ -1 /* Structure: No index */,
+ BUILTINS_LOCATION);
+}
+
+tree
+init_bang_proc_macro (tree macro)
+{
+ // Attribute and bang proc macros have the same structure, they can be
+ // initialized with the same code.
+ return init_attribute_proc_macro (macro);
+}
+
+tree
+init_proc_macro (tree payload, tree proc_macro_type,
+ ProcMacro::ProcmacroTag tag)
+{
+ auto discriminant = static_cast<int> (tag);
+
+ tree macro_tag = build_int_cst (short_unsigned_type_node, discriminant);
+
+ 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<unsigned long> indexes;
+ std::vector<tree> ctors;
+ size_t index = 0;
+ for (auto &macro : ctx->get_derive_proc_macros ())
+ {
+ tree proc_macro = init_derive_proc_macro (ctx, macro);
+ ctors.push_back (
+ init_proc_macro (proc_macro, proc_macro_type,
+ ProcMacro::ProcmacroTag::CUSTOM_DERIVE));
+ indexes.push_back (index);
+ index++;
+ }
+ for (auto &macro : ctx->get_attribute_proc_macros ())
+ {
+ 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 &macro : ctx->get_bang_proc_macros ())
+ {
+ 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,36 +346,39 @@ 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);
+
+ std::string decl_symbol_name = generate_proc_macro_decls_symbol (
+ 0 /* FIXME: Change to stable crate id */);
+
Bvariable *macro_decls
- = Backend::global_variable ("__gccrs_proc_macro_decl_",
- "__gccrs_proc_macro_decls_", entrypoint_type,
- false, false, false, BUILTINS_LOCATION);
+ = Backend::global_variable (decl_symbol_name.c_str (),
+ decl_symbol_name.c_str (), entrypoint_type,
+ false /* internal */, false /* not hidden */,
+ false /* no gc */, BUILTINS_LOCATION);
+
+ std::string buffer_name
+ = GCCRS_PROC_MACRO_SYMBOL_PREFIX + "proc_macro_buffer";
+
+ Bvariable *proc_macro_buffer
+ = Backend::global_variable (buffer_name.c_str (), buffer_name.c_str (),
+ proc_macro_buffer_type, false /* internal */,
+ true /* hidden */, false /* no gc */,
+ BUILTINS_LOCATION);
+ 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);
+
+ Backend::global_variable_set_init (
+ macro_decls,
+ HIRCompileBase::address_expression (proc_macro_buffer->get_decl (),
+ 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