Skip to content

Commit

Permalink
Do not merge this WIP
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
P-E-P committed Oct 2, 2023
1 parent e6e8be3 commit ac94723
Showing 1 changed file with 137 additions and 28 deletions.
165 changes: 137 additions & 28 deletions gcc/rust/backend/rust-compile.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,17 @@
// <http://www.gnu.org/licenses/>.

#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"
#include "rust-compile-type.h"
#include "rust-substitution-mapper.h"
#include "rust-type-util.h"
#include "rust-session-manager.h"
#include "tree.h"

namespace Rust {
namespace Compile {
Expand Down Expand Up @@ -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
Expand All @@ -143,25 +147,43 @@ 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
= 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});
// 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);

Expand All @@ -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<int> (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<unsigned long> indexes;
std::vector<tree> ctors;
size_t index = 0;
for (auto &macro : ctx->get_derive_proc_macros ())
{
rust_debug ("Found one derive macro");
index++;
}
for (auto &macro : 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 &macro : 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
Expand All @@ -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);
Expand All @@ -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 &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
Expand Down

0 comments on commit ac94723

Please sign in to comment.