From: Enes Cevik <[email protected]>

This patch implements the 'min_align_of' compiler intrinsic. It
resolves the minimum alignment of a given compile-time sized type
and returns it as a size_type_node integer constant expression.

gcc/rust/ChangeLog:

        * backend/rust-compile-intrinsic.cc (generic_intrinsics): Add
        min_align_of to map.
        * backend/rust-intrinsic-handlers.cc (min_align_of_handler):
        New function.
        * backend/rust-intrinsic-handlers.h (min_align_of_handler):
        New declaration.

gcc/testsuite/ChangeLog:

        * rust/execute/min_align_of.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/6dae3d0f957eb21b9ed9d0a2472dcd851a156b38

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/4582

 gcc/rust/backend/rust-compile-intrinsic.cc  |  1 +
 gcc/rust/backend/rust-intrinsic-handlers.cc | 39 +++++++++++++++++++++
 gcc/rust/backend/rust-intrinsic-handlers.h  |  1 +
 gcc/testsuite/rust/execute/min_align_of.rs  | 29 +++++++++++++++
 4 files changed, 70 insertions(+)
 create mode 100644 gcc/testsuite/rust/execute/min_align_of.rs

diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc 
b/gcc/rust/backend/rust-compile-intrinsic.cc
index 1456f88df..ab6423092 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -30,6 +30,7 @@ using IValue = Values::Intrinsics;
 static const std::map<std::string, handlers::HandlerBuilder> generic_intrinsics
   = {{IValue::OFFSET, handlers::offset},
      {IValue::SIZE_OF, handlers::sizeof_handler},
+     {IValue::MIN_ALIGN_OF, handlers::min_align_of_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 dab2ca861..55bc06385 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.cc
+++ b/gcc/rust/backend/rust-intrinsic-handlers.cc
@@ -1612,6 +1612,45 @@ sizeof_handler (Context *ctx, TyTy::FnType *fntype)
   return fndecl;
 }
 
+/**
+ * pub fn min_align_of<T>() -> usize;
+ */
+tree
+min_align_of_handler (Context *ctx, TyTy::FnType *fntype)
+{
+  // min_align_of has _zero_ parameters its parameter is the generic one
+  rust_assert (fntype->get_params ().size () == 0);
+
+  tree lookup = NULL_TREE;
+  if (check_for_cached_intrinsic (ctx, fntype, &lookup))
+    return lookup;
+
+  auto fndecl = compile_intrinsic_function (ctx, fntype);
+
+  // get the template parameter type tree fn min_align_of<T>();
+  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 min_align_of FN BODY BEGIN
+  tree 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 min_align_of FN BODY END
+
+  finalize_intrinsic_block (ctx, fndecl);
+
+  return fndecl;
+}
+
 tree
 offset (Context *ctx, TyTy::FnType *fntype)
 {
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.h 
b/gcc/rust/backend/rust-intrinsic-handlers.h
index f4c36b3fe..8a5605366 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.h
+++ b/gcc/rust/backend/rust-intrinsic-handlers.h
@@ -57,6 +57,7 @@ tree rotate_right (Context *ctx, TyTy::FnType *fntype);
 const HandlerBuilder wrapping_op (tree_code op);
 tree offset (Context *ctx, TyTy::FnType *fntype);
 tree sizeof_handler (Context *ctx, TyTy::FnType *fntype);
+tree min_align_of_handler (Context *ctx, TyTy::FnType *fntype);
 tree transmute (Context *ctx, TyTy::FnType *fntype);
 tree rotate (Context *ctx, TyTy::FnType *fntype, tree_code op);
 tree uninit (Context *ctx, TyTy::FnType *fntype);
diff --git a/gcc/testsuite/rust/execute/min_align_of.rs 
b/gcc/testsuite/rust/execute/min_align_of.rs
new file mode 100644
index 000000000..a1aa2272d
--- /dev/null
+++ b/gcc/testsuite/rust/execute/min_align_of.rs
@@ -0,0 +1,29 @@
+// { dg-require-effective-target lp64 }
+#![no_core]
+#![feature(no_core, intrinsics, lang_items)]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+extern "rust-intrinsic" {
+    pub fn min_align_of<T>() -> usize;
+}
+
+fn main() -> i32 {
+    let align_u16 = get_u16_align() as i32;
+    let align_u32 = get_i32_align() as i32;
+
+    if align_u16 != 2 || align_u32 != 4 {
+        1
+    } else {
+        0
+    }
+}
+
+pub fn get_u16_align() -> usize {
+    unsafe { min_align_of::<u16>() }
+}
+
+pub fn get_i32_align() -> usize {
+    unsafe { min_align_of::<i32>() }
+}

base-commit: ea3adb2cf4d302991ce671588cbe770931d64e34
-- 
2.54.0

Reply via email to