From: Arthur Cohen <[email protected]>

gcc/rust/ChangeLog:

        * util/rust-intrinsic-values.h: Declare the new intrinsic.
        * backend/rust-intrinsic-handlers.cc (exact_div_handler): Implement the 
new handler.
        * backend/rust-intrinsic-handlers.h (exact_div_handler): Declare it.
        * backend/rust-compile-intrinsic.cc: Use the new handler.
        * typecheck/rust-hir-type-check-intrinsic.cc: Give type information for 
exact_div.

gcc/testsuite/ChangeLog:

        * rust/compile/exact_div.rs: New test.

Tested on x86_64-pc-linux-gnu.

---
 gcc/rust/backend/rust-compile-intrinsic.cc    |  1 +
 gcc/rust/backend/rust-intrinsic-handlers.cc   | 17 ++++++++++++++
 gcc/rust/backend/rust-intrinsic-handlers.h    |  2 ++
 .../rust-hir-type-check-intrinsic.cc          |  3 +++
 gcc/rust/util/rust-intrinsic-values.h         |  2 ++
 gcc/testsuite/rust/compile/exact_div.rs       | 22 +++++++++++++++++++
 6 files changed, 47 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/exact_div.rs

diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc 
b/gcc/rust/backend/rust-compile-intrinsic.cc
index 89fb3d90250..312d0f77894 100644
--- a/gcc/rust/backend/rust-compile-intrinsic.cc
+++ b/gcc/rust/backend/rust-compile-intrinsic.cc
@@ -91,6 +91,7 @@ static const std::map<std::string, Intrinsic::CompileFn> 
intrinsics = {
   {IValue::FREM_FAST,
    handlers::fop_fast (ArithmeticOrLogicalOperator::MODULUS)},
   {IValue::FLOAT_TO_INT_UNCHECKED, handlers::float_to_int_unchecked},
+  {IValue::EXACT_DIV, handlers::exact_div_handler},
 };
 
 Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.cc 
b/gcc/rust/backend/rust-intrinsic-handlers.cc
index 30521bca579..d9b56b7e341 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.cc
+++ b/gcc/rust/backend/rust-intrinsic-handlers.cc
@@ -1734,6 +1734,23 @@ assert_zero_valid_handler (IntrinsicCtx &ctx)
   ctx.add_statement (return_statement);
 }
 
+void
+exact_div_handler (IntrinsicCtx &ctx)
+{
+  auto lhs_param = ctx.param_vars.at (0);
+  auto rhs_param = ctx.param_vars.at (1);
+
+  auto lhs = Backend::var_expression (lhs_param, ctx.loc);
+  auto rhs = Backend::var_expression (rhs_param, ctx.loc);
+
+  auto div_expr
+    = build2_loc (ctx.loc, EXACT_DIV_EXPR, TREE_TYPE (lhs), lhs, rhs);
+
+  auto return_stmt = Backend::return_statement (ctx.fn, div_expr, ctx.loc);
+
+  ctx.add_statement (return_stmt);
+}
+
 void
 float_to_int_unchecked (IntrinsicCtx &ctx)
 {
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.h 
b/gcc/rust/backend/rust-intrinsic-handlers.h
index 9aa5e2aa339..8bccd65b071 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.h
+++ b/gcc/rust/backend/rust-intrinsic-handlers.h
@@ -175,6 +175,8 @@ void write_bytes_handler (IntrinsicCtx &ctx);
 void arith_offset_handler (IntrinsicCtx &ctx);
 void assert_zero_valid_handler (IntrinsicCtx &ctx);
 
+void exact_div_handler (IntrinsicCtx &ctx);
+
 Intrinsic::CompileFn op_with_overflow (tree_code op);
 
 Intrinsic::CompileFn wrapping_op (tree_code op);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc 
b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
index 1498a09c4da..ae1bc3e1dcf 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
@@ -332,6 +332,9 @@ const std::unordered_map<std::string, IntrinsicRules>
     {IValue::FLOAT_TO_INT_UNCHECKED,
      {2, {IRT::FirstGeneric}, IRT::SecondGeneric}},
 
+    // fn exact_div<T>(lhs: T, rhs: T) -> T
+    {IValue::EXACT_DIV,
+     {1, {IRT::FirstGeneric, IRT::FirstGeneric}, IRT::FirstGeneric}},
 };
 
 IntrinsicCheckResult
diff --git a/gcc/rust/util/rust-intrinsic-values.h 
b/gcc/rust/util/rust-intrinsic-values.h
index 0da1f0c3ac3..42af67988a5 100644
--- a/gcc/rust/util/rust-intrinsic-values.h
+++ b/gcc/rust/util/rust-intrinsic-values.h
@@ -183,6 +183,8 @@ public:
   static constexpr auto &FREM_FAST = "frem_fast";
 
   static constexpr auto &FLOAT_TO_INT_UNCHECKED = "float_to_int_unchecked";
+
+  static constexpr auto &EXACT_DIV = "exact_div";
 };
 } // namespace Values
 } // namespace Rust
diff --git a/gcc/testsuite/rust/compile/exact_div.rs 
b/gcc/testsuite/rust/compile/exact_div.rs
new file mode 100644
index 00000000000..9e777a38431
--- /dev/null
+++ b/gcc/testsuite/rust/compile/exact_div.rs
@@ -0,0 +1,22 @@
+// { dg-additional-options "-fdump-tree-gimple" }
+
+#![feature(no_core)]
+#![feature(intrinsics)]
+#![feature(lang_items)]
+#![no_core]
+
+// Scan for the exact division gimple operator
+// { dg-final { scan-tree-dump-times "x /.ex. y" 1 gimple } }
+
+#[lang = "sized"]
+trait Sized {}
+
+extern "rust-intrinsic" {
+    fn exact_div<T>(x: T, y: T) -> T;
+}
+
+fn main() {
+    let b = 15;
+
+    let _ = unsafe { exact_div(b, 5) };
+}
-- 
2.55.0

Reply via email to