From: Arthur Cohen <[email protected]>
We now support the full implementation of the #[used] attribute, which
can be used to conserve a static variable even if the compiler deems it
unused. This commit also implements #[used(linker)], which instructs the
linker to not garbage collect the static even if it seems unused.
This behavior is equivalent to the `used` and `retain` attributes in C.
gcc/rust/ChangeLog:
* backend/rust-compile-item.cc (handle_used_attr): New function.
(CompileItem::visit): Call it.
gcc/testsuite/ChangeLog:
* rust/compile/used-attr4.rs: New test.
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/accca202ed122cb1e1af1988c144f9a889ee9103
The commit has NOT been mentioned in any issue.
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4837
gcc/rust/backend/rust-compile-item.cc | 62 ++++++++++++++++++------
gcc/testsuite/rust/compile/used-attr4.rs | 16 ++++++
2 files changed, 64 insertions(+), 14 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/used-attr4.rs
diff --git a/gcc/rust/backend/rust-compile-item.cc
b/gcc/rust/backend/rust-compile-item.cc
index 1fad40104..4dbd6aeb6 100644
--- a/gcc/rust/backend/rust-compile-item.cc
+++ b/gcc/rust/backend/rust-compile-item.cc
@@ -17,16 +17,60 @@
// <http://www.gnu.org/licenses/>.
#include "rust-compile-item.h"
+#include "rust-attribute-values.h"
#include "rust-compile-implitem.h"
#include "rust-compile-extern.h"
#include "rust-rib.h"
#include "rust-substitution-mapper.h"
#include "rust-type-util.h"
#include "rust-finalized-name-resolution-context.h"
+#include "tree.h"
+#include "stringpool.h"
+#include "target.h"
namespace Rust {
namespace Compile {
+static void
+handle_used_attr (HIR::StaticItem &var, tree decl)
+{
+ auto used_compiler = false; /* equivalent to C's used attribute */
+ auto used_linker = false; /* equivalent to C's retain attribute */
+
+ // If the attribute has no argument, then it is equivalent to
`used(compiler)`
+ for (const auto &attr : var.get_outer_attrs ())
+ {
+ if (attr.as_string () == Values::Attributes::USED)
+ used_compiler = true;
+
+ // We've already checked that the attribute was used properly, so just
+ // fetch the information we need
+ if (attr.has_attr_input ())
+ {
+ auto input
+ = static_cast<const AST::DelimTokenTree &> (attr.get_attr_input ())
+ .parse_to_meta_item ();
+
+ for (const auto &item : input->get_items ())
+ if (item->as_string () == "linker")
+ used_linker = true;
+ }
+ }
+
+ if (used_compiler)
+ {
+ DECL_PRESERVE_P (decl) = 1;
+ DECL_READ_P (decl) = 1;
+ }
+
+ // Check that the linker supports the attribute, and then add it
+ if (SUPPORTS_SHF_GNU_RETAIN && used_linker)
+ {
+ DECL_ATTRIBUTES (decl)
+ = tree_cons (get_identifier ("retain"), NULL, DECL_ATTRIBUTES (decl));
+ }
+}
+
void
CompileItem::visit (HIR::StaticItem &var)
{
@@ -71,24 +115,14 @@ CompileItem::visit (HIR::StaticItem &var)
bool is_hidden = false;
bool in_unique_section = true;
- // NOTE: We currently compile global variables and always mark them as "used"
- // with TREE_USED(tree). I'm not sure this is correct - they should be marked
- // as used only if the `MarkLive` pass reaches them and flags them. However,
- // the `#[used]` built-in attribute can be used here to *force* a static
- // variable to be used by the compiler so that it isn't deleted.
- // We should probably be doing something along the lines of:
- //
- // - Removing the `TREE_USED (decl) = 1` line in `Backend::global_variable`
- // - Check if the static item has a `used` attribute
- // - If it does, check whether it's the default `used` version, or the
version
- // with an argument - `used(compiler)` or `used(linker)`
- // - If we have the attribute or the `compiler` version of the attribute,
then
- // we `TREE_USED` the decl.
-
Bvariable *static_global
= Backend::global_variable (name, asm_name, type, is_external, is_hidden,
in_unique_section, var.get_locus ());
+ // Static items are concerned by the #[used] attribute which needs to be
+ // handled here
+ handle_used_attr (var, static_global->get_decl ());
+
tree init = value == error_mark_node ? error_mark_node : DECL_INITIAL
(value);
Backend::global_variable_set_init (static_global, init);
diff --git a/gcc/testsuite/rust/compile/used-attr4.rs
b/gcc/testsuite/rust/compile/used-attr4.rs
new file mode 100644
index 000000000..18078a8ca
--- /dev/null
+++ b/gcc/testsuite/rust/compile/used-attr4.rs
@@ -0,0 +1,16 @@
+#![feature(no_core)]
+#![feature(used_with_arg)]
+#![no_core]
+
+#[used]
+static FOO0: i32 = 15;
+// { dg-final { scan-assembler "FOO0" } }
+
+#[used(compiler)]
+static FOO1: i32 = 15;
+// { dg-final { scan-assembler "FOO1" } }
+
+#[used(linker)]
+static FOO2: i32 = 15;
+// { dg-final { scan-assembler "FOO2" } }
+// { dg-final { scan-assembler ".section.*awR" { target gnu_retain } } }
--
2.55.0