diff options
author | Philip Herron <philip.herron@embecosm.com> | 2022-02-13 14:27:01 +0000 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2022-02-13 14:27:01 +0000 |
commit | 112f2841ee3adac146d1c04703fa36068adfdefc (patch) | |
tree | 118e4dc6e60678194b65ccd9d097c465ed46a18d /gcc | |
parent | b71cc52613219f353b054eb5520cd3886f354c10 (diff) | |
download | gcc-112f2841ee3adac146d1c04703fa36068adfdefc.zip gcc-112f2841ee3adac146d1c04703fa36068adfdefc.tar.gz gcc-112f2841ee3adac146d1c04703fa36068adfdefc.tar.bz2 |
Support inline never and always options
This maps over to DECL_UNINLINEABLE and to use the GCC attribute
always_inline.
Fixes #921
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/backend/rust-compile-base.cc | 68 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-base.h | 5 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-item.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/inline_1.rs | 15 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/inline_2.rs | 6 |
5 files changed, 82 insertions, 14 deletions
diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index 9f936d2..33e4c26 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -30,12 +30,14 @@ namespace Compile { void HIRCompileBase::setup_attributes_on_fndecl ( - tree fndecl, bool is_main_entry_point, bool has_visibility, + tree fndecl, bool is_main_entry_point, HIR::Visibility &visibility, const HIR::FunctionQualifiers &qualifiers, const AST::AttrVec &attrs) { // if its the main fn or pub visibility mark its as DECL_PUBLIC // please see https://github.com/Rust-GCC/gccrs/pull/137 - if (is_main_entry_point || has_visibility) + bool is_pub + = visibility.get_vis_type () != HIR::Visibility::PublicVisType::NONE; + if (is_main_entry_point || is_pub) { TREE_PUBLIC (fndecl) = 1; } @@ -52,20 +54,60 @@ HIRCompileBase::setup_attributes_on_fndecl ( bool is_inline = attr.get_path ().as_string ().compare ("inline") == 0; if (is_inline) { - DECL_DECLARED_INLINE_P (fndecl) = 1; - - // do we want to force inline regardless of optimisation level? - // https://gcc.gnu.org/onlinedocs/gcc/Inline.html - // - // /* Add attribute "always_inline": */ - // DECL_ATTRIBUTES (fndecl) - // = tree_cons (get_identifier ("always_inline"), NULL, - // DECL_ATTRIBUTES (fndecl)); + handle_inline_attribute_on_fndecl (fndecl, attr); } } } void +HIRCompileBase::handle_inline_attribute_on_fndecl (tree fndecl, + const AST::Attribute &attr) +{ + // simple #[inline] + if (!attr.has_attr_input ()) + { + DECL_DECLARED_INLINE_P (fndecl) = 1; + return; + } + + const AST::AttrInput &input = attr.get_attr_input (); + bool is_token_tree + = input.get_attr_input_type () == AST::AttrInput::AttrInputType::TOKEN_TREE; + rust_assert (is_token_tree); + const auto &option = static_cast<const AST::DelimTokenTree &> (input); + AST::AttrInputMetaItemContainer *meta_item = option.parse_to_meta_item (); + if (meta_item->get_items ().size () != 1) + { + rust_error_at (attr.get_locus (), "invalid number of arguments"); + return; + } + + const std::string inline_option + = meta_item->get_items ().at (0)->as_string (); + + // we only care about NEVER and ALWAYS else its an error + bool is_always = inline_option.compare ("always") == 0; + bool is_never = inline_option.compare ("never") == 0; + + // #[inline(never)] + if (is_never) + { + DECL_UNINLINABLE (fndecl) = 1; + } + // #[inline(always)] + else if (is_always) + { + DECL_DECLARED_INLINE_P (fndecl) = 1; + DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("always_inline"), + NULL, DECL_ATTRIBUTES (fndecl)); + } + else + { + rust_error_at (attr.get_locus (), "unknown inline option"); + } +} + +void HIRCompileBase::setup_abi_options (tree fndecl, ABI abi) { switch (abi) @@ -278,8 +320,8 @@ HIRCompileBase::compile_function ( unsigned int flags = 0; tree fndecl = ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name, flags, locus); - setup_attributes_on_fndecl (fndecl, is_main_fn, !visibility.is_error (), - qualifiers, outer_attrs); + setup_attributes_on_fndecl (fndecl, is_main_fn, visibility, qualifiers, + outer_attrs); setup_abi_options (fndecl, fntype->get_abi ()); // insert into the context diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h index 54116da..5d27f7b 100644 --- a/gcc/rust/backend/rust-compile-base.h +++ b/gcc/rust/backend/rust-compile-base.h @@ -71,9 +71,12 @@ protected: tree expression, Location locus); static void setup_attributes_on_fndecl ( - tree fndecl, bool is_main_entry_point, bool has_visibility, + tree fndecl, bool is_main_entry_point, HIR::Visibility &visibility, const HIR::FunctionQualifiers &qualifiers, const AST::AttrVec &attrs); + static void handle_inline_attribute_on_fndecl (tree fndecl, + const AST::Attribute &attr); + static void setup_abi_options (tree fndecl, ABI abi); static tree address_expression (tree, Location); diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index d1cb762..ffde1ca 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -632,6 +632,8 @@ public: return Visibility (IN_PATH, std::move (in_path)); } + PublicVisType get_vis_type () const { return public_vis_type; } + std::string as_string () const; protected: diff --git a/gcc/testsuite/rust/compile/inline_1.rs b/gcc/testsuite/rust/compile/inline_1.rs new file mode 100644 index 0000000..df2486f --- /dev/null +++ b/gcc/testsuite/rust/compile/inline_1.rs @@ -0,0 +1,15 @@ +#[inline] +fn test_a() {} + +// { dg-final { scan-tree-dump-times {always_inline} 1 gimple } } +#[inline(always)] +fn test_b() {} + +#[inline(never)] +fn test_c() {} + +fn main() { + test_a(); + test_b(); + test_c(); +} diff --git a/gcc/testsuite/rust/compile/inline_2.rs b/gcc/testsuite/rust/compile/inline_2.rs new file mode 100644 index 0000000..3665fda --- /dev/null +++ b/gcc/testsuite/rust/compile/inline_2.rs @@ -0,0 +1,6 @@ +// { dg-additional-options "-w" } +#[inline(A)] // { dg-error "unknown inline option" } +fn test_a() {} + +#[inline(A, B)] // { dg-error "invalid number of arguments" } +fn test_b() {} |