https://gcc.gnu.org/g:4b9b1bfe119945c7855e51c047d36615a77fa995

commit r17-1890-g4b9b1bfe119945c7855e51c047d36615a77fa995
Author: Enes Cevik <[email protected]>
Date:   Mon May 25 19:00:08 2026 +0300

    gccrs: attr: Add attributes rustc_allocator and rustc_allocator_nounwind
    
    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]>

Diff:
---
 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(-)

diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index 1318b876e650..54b531173e94 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 551a02e4d82b..d93cc3ba3dfe 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 46b96f23aced..ba1bf6be1153 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 02d915f1acbd..9c14df39b1cd 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 7042f8bd10ed..08115d4653c5 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 000000000000..282109580642
--- /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 000000000000..215204391d71
--- /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 000000000000..9eb70452bef9
--- /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() {}
+

Reply via email to