Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export proc macros in proc macro crates #2603

Merged
merged 15 commits into from
Oct 31, 2023
Merged
5 changes: 5 additions & 0 deletions gcc/rust/ast/rust-ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,11 @@ class DelimTokenTree : public TokenTree, public AttrInput
return token_trees;
}

const std::vector<std::unique_ptr<TokenTree>> &get_token_trees () const
{
return token_trees;
}

DelimType get_delim_type () const { return delim_type; }
};

Expand Down
123 changes: 116 additions & 7 deletions gcc/rust/backend/rust-compile-base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ HIRCompileBase::setup_fndecl (tree fndecl, bool is_main_entry_point,
= attr.get_path ().as_string () == Values::Attributes::NO_MANGLE;
bool is_deprecated
= attr.get_path ().as_string () == Values::Attributes::DEPRECATED;
bool is_proc_macro
= attr.get_path ().as_string () == Values::Attributes::PROC_MACRO;
bool is_proc_macro_attribute
= attr.get_path ().as_string ()
== Values::Attributes::PROC_MACRO_ATTRIBUTE;
bool is_proc_macro_derive = attr.get_path ().as_string ()
== Values::Attributes::PROC_MACRO_DERIVE;

if (is_inline)
{
Expand All @@ -108,7 +115,94 @@ HIRCompileBase::setup_fndecl (tree fndecl, bool is_main_entry_point,
{
handle_no_mangle_attribute_on_fndecl (fndecl, attr);
}
else if (is_proc_macro)
{
handle_bang_proc_macro_attribute_on_fndecl (fndecl, attr);
}
else if (is_proc_macro_attribute)
{
handle_attribute_proc_macro_attribute_on_fndecl (fndecl, attr);
}
else if (is_proc_macro_derive)
{
handle_derive_proc_macro_attribute_on_fndecl (fndecl, attr);
}
}
}

static void
handle_proc_macro_common (tree fndecl, const AST::Attribute &attr)
{
DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("gccrs_proc_macro"),
NULL, DECL_ATTRIBUTES (fndecl));
}

void
HIRCompileBase::handle_bang_proc_macro_attribute_on_fndecl (
tree fndecl, const AST::Attribute &attr)
{
handle_proc_macro_common (fndecl, attr);
ctx->collect_bang_proc_macro (fndecl);
}

void
HIRCompileBase::handle_attribute_proc_macro_attribute_on_fndecl (
tree fndecl, const AST::Attribute &attr)
{
handle_proc_macro_common (fndecl, attr);
ctx->collect_attribute_proc_macro (fndecl);
}

static std::vector<std::string>
get_attributes (const AST::Attribute &attr)
{
std::vector<std::string> result;

rust_assert (attr.get_attr_input ().get_attr_input_type ()
== Rust::AST::AttrInput::TOKEN_TREE);
const auto &tt
= static_cast<const AST::DelimTokenTree &> (attr.get_attr_input ());

// TODO: Should we rely on fixed index ? Should we search for the
// attribute tokentree instead ?
if (tt.get_token_trees ().size () > 3)
{
rust_assert (tt.get_token_trees ()[3]->as_string () == "attributes");

auto attributes = static_cast<const AST::DelimTokenTree *> (
tt.get_token_trees ()[4].get ());
auto &token_trees = attributes->get_token_trees ();
P-E-P marked this conversation as resolved.
Show resolved Hide resolved

for (auto i = token_trees.cbegin () + 1; // Skip opening parenthesis
i < token_trees.cend ();
i += 2) // Skip comma and closing parenthesis
{
result.push_back ((*i)->as_string ());
}
}
return result;
}

static std::string
get_trait_name (const AST::Attribute &attr)
{
rust_assert (attr.get_attr_input ().get_attr_input_type ()
== Rust::AST::AttrInput::TOKEN_TREE);
const auto &tt
= static_cast<const AST::DelimTokenTree &> (attr.get_attr_input ());
return tt.get_token_trees ()[1]->as_string ();
P-E-P marked this conversation as resolved.
Show resolved Hide resolved
}

void
HIRCompileBase::handle_derive_proc_macro_attribute_on_fndecl (
tree fndecl, const AST::Attribute &attr)
{
handle_proc_macro_common (fndecl, attr);

attr.get_attr_input ().parse_to_meta_item ();
CustomDeriveInfo macro
= {fndecl, get_trait_name (attr), get_attributes (attr)};
ctx->collect_derive_proc_macro (macro);
}

void
Expand Down Expand Up @@ -205,8 +299,8 @@ HIRCompileBase::handle_deprecated_attribute_on_fndecl (
auto key_value = converted_item->get_name_value_pair ();
if (key_value.first.as_string ().compare ("since") == 0)
{
// valid, but this is handled by Cargo and some third-party audit
// tools
// valid, but this is handled by Cargo and some third-party
// audit tools
continue;
}
else if (key_value.first.as_string ().compare ("note") == 0)
Expand Down Expand Up @@ -326,10 +420,10 @@ HIRCompileBase::setup_abi_options (tree fndecl, ABI abi)
case Rust::ABI::CDECL:
// `decl_attributes` function (not the macro) has the side-effect of
// actually switching the codegen backend to use the ABI we annotated.
// However, since `cdecl` is the default ABI GCC will be using, explicitly
// specifying that ABI will cause GCC to emit a warning saying the
// attribute is useless (which is confusing to the user as the attribute
// is added by us).
// However, since `cdecl` is the default ABI GCC will be using,
// explicitly specifying that ABI will cause GCC to emit a warning
// saying the attribute is useless (which is confusing to the user as
// the attribute is added by us).
DECL_ATTRIBUTES (fndecl)
= tree_cons (get_identifier ("cdecl"), NULL, DECL_ATTRIBUTES (fndecl));

Expand Down Expand Up @@ -544,6 +638,21 @@ HIRCompileBase::compile_function_body (tree fndecl,
}
}

static ABI
get_abi (const AST::AttrVec &outer_attrs,
const HIR::FunctionQualifiers &qualifiers)
{
bool is_proc_macro = std::any_of (outer_attrs.cbegin (), outer_attrs.cend (),
[] (const AST::Attribute &attr) {
auto path = attr.get_path ().as_string ();
return path == "proc_macro"
|| path == "proc_macro_derive"
|| path == "proc_macro_attribute";
});

return is_proc_macro ? ABI::CDECL : qualifiers.get_abi ();
}

tree
HIRCompileBase::compile_function (
const std::string &fn_name, HIR::SelfParam &self_param,
Expand All @@ -566,7 +675,7 @@ HIRCompileBase::compile_function (

setup_fndecl (fndecl, is_main_fn, fntype->has_substitutions_defined (),
visibility, qualifiers, outer_attrs);
setup_abi_options (fndecl, qualifiers.get_abi ());
setup_abi_options (fndecl, get_abi (outer_attrs, qualifiers));

// conditionally mangle the function name
bool should_mangle = should_mangle_item (fndecl);
Expand Down
23 changes: 17 additions & 6 deletions gcc/rust/backend/rust-compile-base.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ class HIRCompileBase
public:
virtual ~HIRCompileBase () {}

static tree address_expression (tree expr, location_t locus);

protected:
HIRCompileBase (Context *ctx) : ctx (ctx) {}

Expand Down Expand Up @@ -102,14 +104,25 @@ class HIRCompileBase

static tree unit_expression (Context *ctx, location_t locus);

static void setup_fndecl (tree fndecl, bool is_main_entry_point,
bool is_generic_fn, HIR::Visibility &visibility,
const HIR::FunctionQualifiers &qualifiers,
const AST::AttrVec &attrs);
void setup_fndecl (tree fndecl, bool is_main_entry_point, bool is_generic_fn,
HIR::Visibility &visibility,
const HIR::FunctionQualifiers &qualifiers,
const AST::AttrVec &attrs);

static void handle_inline_attribute_on_fndecl (tree fndecl,
const AST::Attribute &attr);

void handle_bang_proc_macro_attribute_on_fndecl (tree fndecl,
const AST::Attribute &attr);

void
handle_attribute_proc_macro_attribute_on_fndecl (tree fndecl,
const AST::Attribute &attr);

void
handle_derive_proc_macro_attribute_on_fndecl (tree fndecl,
const AST::Attribute &attr);

static void handle_cold_attribute_on_fndecl (tree fndecl,
const AST::Attribute &attr);

Expand All @@ -128,8 +141,6 @@ class HIRCompileBase

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);
Expand Down
33 changes: 33 additions & 0 deletions gcc/rust/backend/rust-compile-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ struct fncontext
TyTy::BaseType *retty;
};

struct CustomDeriveInfo
{
tree fndecl;
std::string trait_name;
std::vector<std::string> attributes;
};

class Context
{
public:
Expand Down Expand Up @@ -357,6 +364,28 @@ class Context

static hashval_t type_hasher (tree type);

void collect_attribute_proc_macro (tree fndecl)
{
attribute_macros.push_back (fndecl);
}

void collect_bang_proc_macro (tree fndecl) { bang_macros.push_back (fndecl); }

void collect_derive_proc_macro (CustomDeriveInfo macro)
{
custom_derive_macros.push_back (macro);
}

const std::vector<tree> &get_bang_proc_macros () const { return bang_macros; }
const std::vector<tree> &get_attribute_proc_macros () const
{
return attribute_macros;
}
const std::vector<CustomDeriveInfo> &get_derive_proc_macros () const
{
return custom_derive_macros;
}

private:
Resolver::Resolver *resolver;
Resolver::TypeCheckContext *tyctx;
Expand All @@ -381,6 +410,10 @@ class Context
std::map<HirId, tree> implicit_pattern_bindings;
std::map<hashval_t, tree> main_variants;

std::vector<CustomDeriveInfo> custom_derive_macros;
std::vector<tree> attribute_macros;
std::vector<tree> bang_macros;

// closure bindings
std::vector<HirId> closure_scope_bindings;
std::map<HirId, std::map<HirId, tree>> closure_bindings;
Expand Down
Loading