aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2022-02-13 14:27:01 +0000
committerPhilip Herron <philip.herron@embecosm.com>2022-02-13 14:27:01 +0000
commit112f2841ee3adac146d1c04703fa36068adfdefc (patch)
tree118e4dc6e60678194b65ccd9d097c465ed46a18d /gcc
parentb71cc52613219f353b054eb5520cd3886f354c10 (diff)
downloadgcc-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.cc68
-rw-r--r--gcc/rust/backend/rust-compile-base.h5
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h2
-rw-r--r--gcc/testsuite/rust/compile/inline_1.rs15
-rw-r--r--gcc/testsuite/rust/compile/inline_2.rs6
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() {}