From: Arthur Cohen <[email protected]>

This currently traps with ud2 on x86 instead of int3, as there is no equivalent 
to the
llvm.debugtrap OP in GCC.

gcc/rust/ChangeLog:

        * backend/rust-compile-intrinsic.cc: Register the handler.
        * backend/rust-intrinsic-handlers.cc (breakpoint): Define it.
        * backend/rust-intrinsic-handlers.h (breakpoint): Declare it.
        * typecheck/rust-hir-type-check-intrinsic.cc: Add tychk entry for 
breakpoint.
        * util/rust-intrinsic-values.h: Add new value for breakpoint.

gcc/testsuite/ChangeLog:

        * rust/compile/breakpoint.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   | 20 +++++++++++++++++++
 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/breakpoint.rs      | 15 ++++++++++++++
 6 files changed, 43 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/breakpoint.rs

diff --git a/gcc/rust/backend/rust-compile-intrinsic.cc 
b/gcc/rust/backend/rust-compile-intrinsic.cc
index 131ad42dd45..5cdee95aad8 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 = {
    handlers::fop_fast (ArithmeticOrLogicalOperator::MODULUS)},
   {IValue::FLOAT_TO_INT_UNCHECKED, handlers::float_to_int_unchecked},
   {IValue::EXACT_DIV, handlers::exact_div_handler},
+  {IValue::BREAKPOINT, handlers::breakpoint},
   {IValue::ASSERT_ZERO_VALID, handlers::type_assert (TyAssert::ZeroValid)},
   {IValue::ASSERT_INHABITED, handlers::type_assert (TyAssert::Inhabited)},
   {IValue::ASSERT_UNINIT_VALID, handlers::type_assert (TyAssert::UninitValid)},
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.cc 
b/gcc/rust/backend/rust-intrinsic-handlers.cc
index 58f3f345ea3..034d28044c6 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.cc
+++ b/gcc/rust/backend/rust-intrinsic-handlers.cc
@@ -1896,6 +1896,26 @@ float_to_int_unchecked (IntrinsicCtx &ctx)
   ctx.add_statement (return_statement);
 }
 
+void
+breakpoint (IntrinsicCtx &ctx)
+{
+  // For now, we don't have access to an equivalent of LLVM's debugtrap inst. 
We
+  // work around the problem by emitting a regular trap and we hope that the
+  // user's debugger can catch it :) Ideally, this would emit an `int3` on x86
+  // rather than a `ud2`
+
+  auto trap = BuiltinsContext::get ().lookup_simple_builtin ("__builtin_trap");
+  rust_assert (trap);
+
+  tree trap_call = build_call_expr_loc (ctx.loc, *trap, 0);
+
+  ctx.add_statement (trap_call);
+
+  TREE_READONLY (ctx.fn) = 0;
+  TREE_USED (ctx.fn) = 1;
+  TREE_SIDE_EFFECTS (ctx.fn) = 1;
+}
+
 } // namespace handlers
 } // namespace Compile
 } // namespace Rust
diff --git a/gcc/rust/backend/rust-intrinsic-handlers.h 
b/gcc/rust/backend/rust-intrinsic-handlers.h
index d0aad88ee6a..68fdec129d2 100644
--- a/gcc/rust/backend/rust-intrinsic-handlers.h
+++ b/gcc/rust/backend/rust-intrinsic-handlers.h
@@ -208,6 +208,8 @@ Intrinsic::CompileFn fop_fast (ArithmeticOrLogicalOperator 
op);
  */
 Intrinsic::CompileFn type_assert (TyAssert assert);
 
+void breakpoint (IntrinsicCtx &ctx);
+
 } // namespace handlers
 
 } // namespace Compile
diff --git a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc 
b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
index 728b5fdd090..9914a292849 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-intrinsic.cc
@@ -312,6 +312,9 @@ const std::unordered_map<std::string, IntrinsicRules>
     {IValue::WRITE_BYTES,
      {1, {IRT::MutPtrFirstGeneric, IRT::U8, IRT::Usize}, IRT::Unit}},
 
+    // fn breakpoint()
+    {IValue::BREAKPOINT, {0, {}, IRT::Unit}},
+
     // pub fn assert_zero_valid<T>();
     {IValue::ASSERT_ZERO_VALID, {1, {}, IRT::Unit}},
     // fn assert_inhabited<T>();
diff --git a/gcc/rust/util/rust-intrinsic-values.h 
b/gcc/rust/util/rust-intrinsic-values.h
index e154f60b5e4..e748616eba5 100644
--- a/gcc/rust/util/rust-intrinsic-values.h
+++ b/gcc/rust/util/rust-intrinsic-values.h
@@ -175,6 +175,8 @@ public:
   static constexpr auto &ARITH_OFFSET = "arith_offset";
   static constexpr auto &WRITE_BYTES = "write_bytes";
 
+  static constexpr auto &BREAKPOINT = "breakpoint";
+
   static constexpr auto &ASSERT_ZERO_VALID = "assert_zero_valid";
   static constexpr auto &ASSERT_INHABITED = "assert_inhabited";
   static constexpr auto &ASSERT_UNINIT_VALID = "assert_uninit_valid";
diff --git a/gcc/testsuite/rust/compile/breakpoint.rs 
b/gcc/testsuite/rust/compile/breakpoint.rs
new file mode 100644
index 00000000000..d3286e1d938
--- /dev/null
+++ b/gcc/testsuite/rust/compile/breakpoint.rs
@@ -0,0 +1,15 @@
+#![feature(no_core)]
+#![feature(intrinsics)]
+#![no_core]
+
+extern "rust-intrinsic" {
+    fn breakpoint();
+}
+
+fn foo() {
+    unsafe { breakpoint() };
+}
+
+fn main() {
+    foo();
+}
-- 
2.55.0

Reply via email to