From: Enes Cevik <[email protected]>
This patch introduces the `rustc_allocator` and `rustc_allocator_nounwind`
attributes.
These attributes instruct the GCC backend to apply `malloc` and `nothrow`.
gcc/rust/ChangeLog:
* backend/rust-compile-base.cc (HIRCompileBase::setup_fndecl): Dispatch
the new
attributes.
(HIRCompileBase::handle_rustc_allocator_on_fndecl): New function.
(HIRCompileBase::handle_rustc_allocator_nounwind_on_fndecl): New
function.
* backend/rust-compile-base.h (handle_rustc_allocator_on_fndecl): New
declaration.
(handle_rustc_allocator_nounwind_on_fndecl): Likewise.
* util/rust-attribute-values.h (Attributes): Add RUSTC_ALLOCATOR and
RUSTC_ALLOCATOR_NOUNWIND constexprs.
* util/rust-attributes.cc (__definitions): Register rustc_allocator and
rustc_allocator_nounwind in the BuiltinAttributes list.
* checks/errors/rust-builtin-attribute-checker.cc (rustc_allocator):
New function.
(rustc_allocator_nounwind): New function.
(attribute_checking_handlers): Add rustc_allocator and
rustc_allocator_nounwind
functions.
gcc/testsuite/ChangeLog:
* rust/compile/attr-allocator1.rs: New test.
* rust/compile/attr-allocator2.rs: New test.
* rust/compile/attr-allocator3.rs: New test.
Signed-off-by: Enes Cevik <[email protected]>
---
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/7a4484b9258617de89901b0eaad22644f9bbff03
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/4556
gcc/rust/backend/rust-compile-base.cc | 60 +++++++++++++++++++
gcc/rust/backend/rust-compile-base.h | 7 +++
.../errors/rust-builtin-attribute-checker.cc | 26 ++++++++
gcc/rust/util/rust-attribute-values.h | 3 +
gcc/rust/util/rust-attributes.cc | 4 +-
gcc/testsuite/rust/compile/attr-allocator1.rs | 12 ++++
gcc/testsuite/rust/compile/attr-allocator2.rs | 10 ++++
gcc/testsuite/rust/compile/attr-allocator3.rs | 6 ++
8 files changed, 127 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/rust/compile/attr-allocator1.rs
create mode 100644 gcc/testsuite/rust/compile/attr-allocator2.rs
create mode 100644 gcc/testsuite/rust/compile/attr-allocator3.rs
diff --git a/gcc/rust/backend/rust-compile-base.cc
b/gcc/rust/backend/rust-compile-base.cc
index 1318b876e..54b531173 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -96,6 +96,9 @@ HIRCompileBase::setup_fndecl (tree fndecl, bool
is_main_entry_point,
= attr_str == Values::Attributes::PROC_MACRO_ATTRIBUTE;
bool is_proc_macro_derive
= attr_str == Values::Attributes::PROC_MACRO_DERIVE;
+ bool is_allocator = attr_str == Values::Attributes::RUSTC_ALLOCATOR;
+ bool is_allocator_nounwind
+ = attr_str == Values::Attributes::RUSTC_ALLOCATOR_NOUNWIND;
if (is_inline)
{
@@ -137,6 +140,14 @@ HIRCompileBase::setup_fndecl (tree fndecl, bool
is_main_entry_point,
{
handle_derive_proc_macro_attribute_on_fndecl (fndecl, attr);
}
+ else if (is_allocator)
+ {
+ handle_rustc_allocator_on_fndecl (fndecl, attr);
+ }
+ else if (is_allocator_nounwind)
+ {
+ handle_rustc_allocator_nounwind_on_fndecl (fndecl, attr);
+ }
}
}
@@ -298,6 +309,55 @@
HIRCompileBase::handle_rustc_std_internal_symbol_attribute_on_fndecl (
NULL_TREE, DECL_ATTRIBUTES (fndecl));
}
+void
+HIRCompileBase::handle_rustc_allocator_on_fndecl (tree fndecl,
+ const AST::Attribute &attr)
+{
+ tree return_type = TREE_TYPE (TREE_TYPE (fndecl));
+ if (!POINTER_TYPE_P (return_type))
+ {
+ rust_error_at (attr.get_locus (),
+ "%<rustc_allocator%> attribute must be applied to a "
+ "function returning a pointer");
+ return;
+ }
+
+ //
https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs#L49
+ // `#[rustc_allocator]`: a hint to LLVM that the pointer returned from this
+ // function is never null.
+ //
+ //
https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/compiler/rustc_typeck/src/collect.rs#L2482
+ // This attribute sets CodegenFnAttrFlags::ALLOCATOR.
+ //
+ //
https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/compiler/rustc_codegen_llvm/src/attributes.rs#L302
+ // This flag activates LLVM::NoAlias attribute.
+ //
+ // In GCC, setting DECL_IS_MALLOC on a FUNCTION_DECL means this function
+ // should be treated as if it were a malloc, meaning it returns a pointer
that
+ // is not an alias.
+ DECL_IS_MALLOC (fndecl) = 1;
+ DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("malloc"), NULL_TREE,
+ DECL_ATTRIBUTES (fndecl));
+}
+
+void
+HIRCompileBase::handle_rustc_allocator_nounwind_on_fndecl (
+ tree fndecl, const AST::Attribute &attr)
+{
+ //
https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs#L55
+ // `#[rustc_allocator_nounwind]`: an indicator that an imported FFI
+ // function will never unwind.
+ //
+ //
https://github.com/rust-lang/rust/blob/e1884a8e3c3e813aada8254edfa120e85bf5ffca/compiler/rustc_typeck/src/collect.rs#L2484
+ // This attribute sets CodegenFnAttrFlags::NOUNWIND.
+ //
+ // In GCC, setting TREE_NOTHROW on a FUNCTION_DECL means a call to the
+ // function cannot throw an exception, which exactly matches this behavior.
+ TREE_NOTHROW (fndecl) = 1;
+ DECL_ATTRIBUTES (fndecl) = tree_cons (get_identifier ("nothrow"), NULL_TREE,
+ DECL_ATTRIBUTES (fndecl));
+}
+
void
HIRCompileBase::handle_deprecated_attribute_on_fndecl (
tree fndecl, const AST::Attribute &attr)
diff --git a/gcc/rust/backend/rust-compile-base.h
b/gcc/rust/backend/rust-compile-base.h
index 551a02e4d..d93cc3ba3 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -155,6 +155,13 @@ protected:
static void handle_rustc_std_internal_symbol_attribute_on_fndecl (
tree fndecl, const AST::Attribute &attr);
+ static void handle_rustc_allocator_on_fndecl (tree fndecl,
+ const AST::Attribute &attr);
+
+ static void
+ handle_rustc_allocator_nounwind_on_fndecl (tree fndecl,
+ const AST::Attribute &attr);
+
static void setup_abi_options (tree fndecl, ABI abi);
static tree indirect_expression (tree expr, location_t locus);
diff --git a/gcc/rust/checks/errors/rust-builtin-attribute-checker.cc
b/gcc/rust/checks/errors/rust-builtin-attribute-checker.cc
index 46b96f23a..ba1bf6be1 100644
--- a/gcc/rust/checks/errors/rust-builtin-attribute-checker.cc
+++ b/gcc/rust/checks/errors/rust-builtin-attribute-checker.cc
@@ -370,6 +370,30 @@ rustc_std_internal_symbol (const AST::Attribute &attribute)
}
}
+void
+rustc_allocator (const AST::Attribute &attribute)
+{
+ if (attribute.has_attr_input ())
+ {
+ rust_error_at (attribute.get_locus (),
+ "malformed %<rustc_allocator%> attribute input");
+ rust_inform (attribute.get_locus (),
+ "must be of the form: %<#[rustc_allocator]%>");
+ }
+}
+
+void
+rustc_allocator_nounwind (const AST::Attribute &attribute)
+{
+ if (attribute.has_attr_input ())
+ {
+ rust_error_at (attribute.get_locus (),
+ "malformed %<rustc_allocator_nounwind%> attribute input");
+ rust_inform (attribute.get_locus (),
+ "must be of the form: %<#[rustc_allocator_nounwind]%>");
+ }
+}
+
} // namespace handlers
const std::unordered_map<std::string, std::function<void (AST::Attribute &)>>
@@ -389,6 +413,8 @@ const std::unordered_map<std::string, std::function<void
(AST::Attribute &)>>
{Attrs::PROC_MACRO_ATTRIBUTE, handlers::proc_macro},
{Attrs::TARGET_FEATURE, handlers::target_feature},
{Attrs::RUSTC_STD_INTERNAL_SYMBOL, handlers::rustc_std_internal_symbol},
+ {Attrs::RUSTC_ALLOCATOR, handlers::rustc_allocator},
+ {Attrs::RUSTC_ALLOCATOR_NOUNWIND, handlers::rustc_allocator_nounwind},
};
tl::optional<std::function<void (AST::Attribute &)>>
diff --git a/gcc/rust/util/rust-attribute-values.h
b/gcc/rust/util/rust-attribute-values.h
index 02d915f1a..9c14df39b 100644
--- a/gcc/rust/util/rust-attribute-values.h
+++ b/gcc/rust/util/rust-attribute-values.h
@@ -107,6 +107,9 @@ public:
static constexpr auto &RUSTC_ARGS_REQUIRED_CONST
= "rustc_args_required_const";
+
+ static constexpr auto &RUSTC_ALLOCATOR = "rustc_allocator";
+ static constexpr auto &RUSTC_ALLOCATOR_NOUNWIND = "rustc_allocator_nounwind";
};
} // namespace Values
} // namespace Rust
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index 7042f8bd1..08115d465 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -94,7 +94,9 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::FUNDAMENTAL, TYPE_CHECK},
{Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
{Attrs::RUSTFMT, EXTERNAL},
- {Attrs::TEST, CODE_GENERATION}};
+ {Attrs::TEST, CODE_GENERATION},
+ {Attrs::RUSTC_ALLOCATOR, CODE_GENERATION},
+ {Attrs::RUSTC_ALLOCATOR_NOUNWIND, CODE_GENERATION}};
static const std::set<std::string> __outer_attributes
= {Attrs::INLINE,
diff --git a/gcc/testsuite/rust/compile/attr-allocator1.rs
b/gcc/testsuite/rust/compile/attr-allocator1.rs
new file mode 100644
index 000000000..282109580
--- /dev/null
+++ b/gcc/testsuite/rust/compile/attr-allocator1.rs
@@ -0,0 +1,12 @@
+// { dg-additional-options "-fdump-tree-gimple" }
+#![feature(no_core, rustc_attrs)]
+#![no_core]
+
+#[rustc_allocator]
+#[rustc_allocator_nounwind]
+fn _foo() -> *mut u8 {
+ 0 as *mut u8
+}
+
+// { dg-final { scan-tree-dump "malloc" "gimple" } }
+// { dg-final { scan-tree-dump "nothrow" "gimple" } }
diff --git a/gcc/testsuite/rust/compile/attr-allocator2.rs
b/gcc/testsuite/rust/compile/attr-allocator2.rs
new file mode 100644
index 000000000..215204391
--- /dev/null
+++ b/gcc/testsuite/rust/compile/attr-allocator2.rs
@@ -0,0 +1,10 @@
+#![feature(no_core, rustc_attrs)]
+#![no_core]
+
+#[rustc_allocator(invalid)] // { dg-error "malformed .rustc_allocator.
attribute input" }
+pub fn _foo() -> *mut u8 {
+ 0 as *mut u8
+}
+
+#[rustc_allocator_nounwind(invalid)] // { dg-error "malformed
.rustc_allocator_nounwind. attribute input" }
+pub fn _bar() {}
diff --git a/gcc/testsuite/rust/compile/attr-allocator3.rs
b/gcc/testsuite/rust/compile/attr-allocator3.rs
new file mode 100644
index 000000000..9eb70452b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/attr-allocator3.rs
@@ -0,0 +1,6 @@
+#![feature(no_core, rustc_attrs)]
+#![no_core]
+
+#[rustc_allocator] // { dg-error ".rustc_allocator. attribute must be applied
to a function returning a pointer" }
+pub fn _foo() {}
+
--
2.54.0