[gcc r17-2256] gccrs: intrinsic: Add min_align_of_val

Arthur Cohen via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:b7a9ebe63ddb3112b63ea9ad6629d08a7d8dc47a

commit r17-2256-gb7a9ebe63ddb3112b63ea9ad6629d08a7d8dc47a
Author: Enes Cevik <[email protected]>
Date:   Tue Jun 30 10:14:36 2026 +0300

    gccrs: intrinsic: Add min_align_of_val
    
    This patch adds the min_align_of_val intrinsic to the compiler. This
    intrinsic evaluates the align of a value at runtime, including
    Dynamically Sized Types (DSTs).
    
    gcc/rust/ChangeLog:
    
            * backend/rust-compile-intrinsic.cc (generic_intrinsics): Add
            min_align_of_val_handler to the map.
            * backend/rust-intrinsic-handlers.cc (min_align_of_val_handler):
            New function.
            * backend/rust-intrinsic-handlers.h (min_align_of_val_handler):
            New declaration.
            * typecheck/rust-hir-type-check-intrinsic.cc
            (IntrinsicChecker::intrinsic_rules): Add min_align_of_val
            signature rule to the map.
            * util/rust-intrinsic-values.h (class Intrinsics): Add
            MIN_ALIGN_OF_VAL constexpr.
    
    gcc/testsuite/ChangeLog:
    
            * rust/execute/min-align-of-val.rs: New test.
    
    Signed-off-by: Enes Cevik <[email protected]>

Diff:
---
 gcc/rust/backend/rust-compile-intrinsic.cc         |   1 +
 gcc/rust/backend/rust-intrinsic-handlers.cc        | 100 +++++++++++++++++++++
 gcc/rust/backend/rust-intrinsic-handlers.h         |   2 +
 .../typecheck/rust-hir-type-check-intrinsic.cc     |   2 +
 gcc/rust/util/rust-intrinsic-values.h              |   1 +
 gcc/testsuite/rust/execute/min-align-of-val.rs     |  64 +++++++++++++
 6 files changed, 170 insertions(+)

diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc b/gcc/rust/backend/rust-compile-intrinsic.cc
index 05187c35ca4b..205bf4113962 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -34,6 +34,7 @@ static const std::map<std::string, handlers::HandlerBuilder> generic_intrinsics
      {IValue::SIZE_OF, handlers::sizeof_handler},
      {IValue::SIZE_OF_VAL, handlers::size_of_val_handler},
      {IValue::MIN_ALIGN_OF, handlers::min_align_of_handler},
+     {IValue::MIN_ALIGN_OF_VAL, handlers::min_align_of_val_handler},
      {IValue::TRANSMUTE, handlers::transmute},
      {IValue::ROTATE_LEFT, handlers::rotate_left},
      {IValue::ROTATE_RIGHT, handlers::rotate_right},
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.cc b/gcc/rust/backend/rust-intrinsic-handlers.cc
index d08b1e2e2d61..b119593b8a92 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.cc
+++ b/gcc/rust/backend/rust-intrinsic-handlers.cc
@@ -1750,6 +1750,106 @@ min_align_of_handler (Context *ctx, TyTy::FnType *fntype, location_t)
   return fndecl;
 }
 
+/**
+ * pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
+ */
+tree
+min_align_of_val_handler (Context *ctx, TyTy::FnType *fntype, location_t)
+{
+  rust_assert (fntype->get_params ().size () == 1);
+
+  tree lookup = NULL_TREE;
+  if (check_for_cached_intrinsic (ctx, fntype, &lookup))
+    return lookup;
+
+  auto fndecl = compile_intrinsic_function (ctx, fntype);
+
+  auto locus = fntype->get_locus ();
+
+  std::vector<Bvariable *> param_vars;
+  compile_fn_params (ctx, fntype, fndecl, &param_vars);
+
+  auto &__param = param_vars.at (0);
+  rust_assert (param_vars.size () == 1);
+  if (!Backend::function_set_parameters (fndecl, param_vars))
+    return error_mark_node;
+
+  rust_assert (fntype->get_num_substitutions () == 1);
+  auto &param_mapping = fntype->get_substs ().at (0);
+  const auto param_tyty = param_mapping.get_param_ty ();
+  auto resolved_tyty = param_tyty->resolve ();
+  tree template_parameter_type
+    = TyTyResolveCompile::compile (ctx, resolved_tyty);
+
+  enter_intrinsic_block (ctx, fndecl);
+
+  // BUILTIN size_of FN BODY BEGIN
+
+  tree align_expr = NULL_TREE;
+  if (RS_DST_FLAG_P (template_parameter_type))
+    {
+      tree param = Backend::var_expression (__param, UNDEF_LOCATION);
+      tree param_ty = TREE_TYPE (param);
+      tree data_field = TYPE_FIELDS (param_ty);
+      tree meta_field = DECL_CHAIN (data_field);
+      tree meta_field_expr
+	= build3_loc (locus, COMPONENT_REF, TREE_TYPE (meta_field), param,
+		      meta_field, NULL_TREE);
+
+      if (resolved_tyty->get_kind () == TyTy::TypeKind::SLICE
+	  || resolved_tyty->get_kind () == TyTy::TypeKind::STR)
+	{
+	  tree elem_type = NULL_TREE;
+	  if (resolved_tyty->get_kind () == TyTy::TypeKind::SLICE)
+	    {
+	      auto slice_tyty = static_cast<TyTy::SliceType *> (resolved_tyty);
+	      elem_type
+		= TyTyResolveCompile::compile (ctx,
+					       slice_tyty->get_element_type ());
+	    }
+	  else
+	    elem_type = char_type_node;
+
+	  align_expr
+	    = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (elem_type));
+	}
+      else if (resolved_tyty->get_kind () == TyTy::TypeKind::DYNAMIC)
+	{
+	  tree vtable_ptr_ty = TREE_TYPE (meta_field_expr);
+	  tree vtable_ty = TREE_TYPE (vtable_ptr_ty);
+
+	  tree vtable_ref
+	    = build1_loc (locus, INDIRECT_REF, vtable_ty, meta_field_expr);
+
+	  tree vtable_field_0 = TYPE_FIELDS (vtable_ty);
+	  tree vtable_field_1 = DECL_CHAIN (vtable_field_0);
+	  tree vtable_field_align = DECL_CHAIN (vtable_field_1);
+	  rust_assert (vtable_field_align != NULL_TREE);
+
+	  align_expr
+	    = build3_loc (locus, COMPONENT_REF, TREE_TYPE (vtable_field_align),
+			  vtable_ref, vtable_field_align, NULL_TREE);
+	}
+      else
+	{
+	  rust_unreachable ();
+	}
+    }
+  else
+    align_expr = build_int_cst (size_type_node,
+				TYPE_ALIGN_UNIT (template_parameter_type));
+
+  auto return_statement
+    = Backend::return_statement (fndecl, align_expr, UNDEF_LOCATION);
+  ctx->add_statement (return_statement);
+
+  // BUILTIN size_of FN BODY END
+
+  finalize_intrinsic_block (ctx, fndecl);
+
+  return fndecl;
+}
+
 tree
 offset (Context *ctx, TyTy::FnType *fntype, location_t expr_locus)
 {
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.h b/gcc/rust/backend/rust-intrinsic-handlers.h
index 58f52650a451..8916c59f39c1 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.h
+++ b/gcc/rust/backend/rust-intrinsic-handlers.h
@@ -62,6 +62,8 @@ tree size_of_val_handler (Context *ctx, TyTy::FnType *fntype,
 			  location_t expr_locus);
 tree min_align_of_handler (Context *ctx, TyTy::FnType *fntype,
 			   location_t expr_locus);
+tree min_align_of_val_handler (Context *ctx, TyTy::FnType *fntype,
+			       location_t expr_locus);
 tree transmute (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
 tree rotate (Context *ctx, TyTy::FnType *fntype, tree_code op);
 tree uninit (Context *ctx, TyTy::FnType *fntype, location_t expr_locus);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
index bfb5baf3161a..df596c58a4e4 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
@@ -267,6 +267,8 @@ const std::unordered_map<std::string, IntrinsicRules>
     {IValue::ASSUME, {0, {IRT::Bool}, IRT::Unit}},
     // pub fn min_align_of<T>() -> usize;
     {IValue::MIN_ALIGN_OF, {1, {}, IRT::Usize}},
+    // pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
+    {IValue::MIN_ALIGN_OF_VAL, {1, {IRT::ConstPtrFirstGeneric}, IRT::Usize}},
     // pub fn needs_drop<T>() -> bool;
     {IValue::NEEDS_DROP, {1, {}, IRT::Bool}},
     // pub fn caller_location() -> &'static crate::panic::Location<'static>;
diff --git a/gcc/rust/util/rust-intrinsic-values.h b/gcc/rust/util/rust-intrinsic-values.h
index 35e76a87c349..d79326459116 100644
--- a/gcc/rust/util/rust-intrinsic-values.h
+++ b/gcc/rust/util/rust-intrinsic-values.h
@@ -138,6 +138,7 @@ public:
   static constexpr auto &ASSUME = "assume";
 
   static constexpr auto &MIN_ALIGN_OF = "min_align_of";
+  static constexpr auto &MIN_ALIGN_OF_VAL = "min_align_of_val";
   static constexpr auto &NEEDS_DROP = "needs_drop";
   static constexpr auto &CALLER_LOCATION = "caller_location";
   static constexpr auto &CTPOP = "ctpop";
diff --git a/gcc/testsuite/rust/execute/min-align-of-val.rs b/gcc/testsuite/rust/execute/min-align-of-val.rs
new file mode 100644
index 000000000000..eb01f5bcefe7
--- /dev/null
+++ b/gcc/testsuite/rust/execute/min-align-of-val.rs
@@ -0,0 +1,64 @@
+// { dg-require-effective-target lp64 }
+#![feature(no_core, intrinsics, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+extern "rust-intrinsic" {
+    pub fn min_align_of_val<T: ?Sized>(_: *const T) -> usize;
+}
+
+trait TraitA {
+    fn foo(&self) {}
+}
+
+struct StructA {
+    _a: i32,
+    _b: i16,
+}
+
+impl TraitA for StructA {}
+impl TraitA for u8 {}
+
+fn main() -> i32 {
+    let val_i32: i32 = 32;
+    let align_i32 = unsafe { min_align_of_val(&val_i32 as *const i32) };
+
+    let val_struct = StructA { _a: 1, _b: 2 };
+    let align_struct = unsafe { min_align_of_val(&val_struct as *const StructA) };
+
+    let arr: [i32; 3] = [10, 20, 30];
+    let val_slice: &[i32] = &arr;
+    let align_slice = unsafe { min_align_of_val(val_slice as *const [i32]) };
+
+    let val_str: &str = "gccrs";
+    let align_str = unsafe { min_align_of_val(val_str as *const str) };
+
+    let val_dyn_struct = &val_struct as &dyn TraitA;
+    let align_dyn_struct = unsafe { min_align_of_val(val_dyn_struct as *const dyn TraitA) };
+
+    let val_u8: u8 = 7;
+    let align_u8 = unsafe { min_align_of_val(&val_u8 as *const u8) };
+
+    let val_dyn_u8 = &val_u8 as &dyn TraitA;
+    let align_dyn_u8 = unsafe { min_align_of_val(val_dyn_u8 as *const dyn TraitA) };
+
+    if align_i32 != 4 {
+        1
+    } else if align_struct != 4 {
+        2
+    } else if align_slice != 4 {
+        3
+    } else if align_str != 1 {
+        4
+    } else if align_dyn_struct != 4 {
+        5
+    } else if align_u8 != 1 {
+        6
+    } else if align_dyn_u8 != 1 {
+        7
+    } else {
+        0
+    }
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.