about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-12-03 21:55:27 +0100
committerGitHub <noreply@github.com>2024-12-03 21:55:27 +0100
commite66e6324798768b045c77c099caa8073d5dce983 (patch)
tree3fcffdc422d9cd69e79d20a63444246a25eab965
parent6e87eb58ede97cce4bd1e392694f88a2a2936e84 (diff)
parentcea0582dbdd231c46884ca917de3e32b75b6287a (diff)
downloadrust-e66e6324798768b045c77c099caa8073d5dce983.tar.gz
rust-e66e6324798768b045c77c099caa8073d5dce983.zip
Rollup merge of #133726 - joshtriplett:breakpoint, r=oli-obk
Add `core::arch::breakpoint` and test

Approved in [ACP 491](https://github.com/rust-lang/libs-team/issues/491).
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0622.md9
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs1
-rw-r--r--library/core/src/arch.rs27
-rw-r--r--library/core/src/intrinsics/mod.rs12
-rw-r--r--src/tools/miri/tests/fail/breakpoint.rs4
-rw-r--r--src/tools/miri/tests/fail/breakpoint.stderr4
-rw-r--r--tests/assembly/breakpoint.rs14
-rw-r--r--tests/ui/error-codes/E0622.rs4
-rw-r--r--tests/ui/error-codes/E0622.stderr4
9 files changed, 66 insertions, 13 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0622.md b/compiler/rustc_error_codes/src/error_codes/E0622.md
index 5d71ee9949d..4cb605b636d 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0622.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0622.md
@@ -7,10 +7,11 @@ Erroneous code example:
 #![allow(internal_features)]
 
 extern "rust-intrinsic" {
-    pub static breakpoint: fn(); // error: intrinsic must be a function
+    pub static atomic_singlethreadfence_seqcst: fn();
+    // error: intrinsic must be a function
 }
 
-fn main() { unsafe { breakpoint(); } }
+fn main() { unsafe { atomic_singlethreadfence_seqcst(); } }
 ```
 
 An intrinsic is a function available for use in a given programming language
@@ -22,8 +23,8 @@ error, just declare a function. Example:
 #![allow(internal_features)]
 
 extern "rust-intrinsic" {
-    pub fn breakpoint(); // ok!
+    pub fn atomic_singlethreadfence_seqcst(); // ok!
 }
 
-fn main() { unsafe { breakpoint(); } }
+fn main() { unsafe { atomic_singlethreadfence_seqcst(); } }
 ```
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 7434bbf180b..2e6b511412b 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -87,6 +87,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
         | sym::assert_inhabited
         | sym::assert_zero_valid
         | sym::assert_mem_uninitialized_valid
+        | sym::breakpoint
         | sym::size_of
         | sym::min_align_of
         | sym::needs_drop
diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs
index 57f456c98b3..95d88c7f679 100644
--- a/library/core/src/arch.rs
+++ b/library/core/src/arch.rs
@@ -42,3 +42,30 @@ pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?)
 pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) {
     /* compiler built-in */
 }
+
+/// Compiles to a target-specific software breakpoint instruction or equivalent.
+///
+/// This will typically abort the program. It may result in a core dump, and/or the system logging
+/// debug information. Additional target-specific capabilities may be possible depending on
+/// debuggers or other tooling; in particular, a debugger may be able to resume execution.
+///
+/// If possible, this will produce an instruction sequence that allows a debugger to resume *after*
+/// the breakpoint, rather than resuming *at* the breakpoint; however, the exact behavior is
+/// target-specific and debugger-specific, and not guaranteed.
+///
+/// If the target platform does not have any kind of debug breakpoint instruction, this may compile
+/// to a trapping instruction (e.g. an undefined instruction) instead, or to some other form of
+/// target-specific abort that may or may not support convenient resumption.
+///
+/// The precise behavior and the precise instruction generated are not guaranteed, except that in
+/// normal execution with no debug tooling involved this will not continue executing.
+///
+/// - On x86 targets, this produces an `int3` instruction.
+/// - On aarch64 targets, this produces a `brk #0xf000` instruction.
+// When stabilizing this, update the comment on `core::intrinsics::breakpoint`.
+#[unstable(feature = "breakpoint", issue = "133724")]
+#[inline(always)]
+#[cfg(not(bootstrap))]
+pub fn breakpoint() {
+    core::intrinsics::breakpoint();
+}
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 46873fdc047..4c8fd922f19 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -1381,6 +1381,18 @@ pub unsafe fn prefetch_write_instruction<T>(_data: *const T, _locality: i32) {
 #[rustc_intrinsic]
 #[rustc_intrinsic_must_be_overridden]
 #[rustc_nounwind]
+#[cfg(not(bootstrap))]
+pub fn breakpoint() {
+    unreachable!()
+}
+
+/// Executes a breakpoint trap, for inspection by a debugger.
+///
+/// This intrinsic does not have a stable counterpart.
+#[rustc_intrinsic]
+#[rustc_intrinsic_must_be_overridden]
+#[rustc_nounwind]
+#[cfg(bootstrap)]
 pub unsafe fn breakpoint() {
     unreachable!()
 }
diff --git a/src/tools/miri/tests/fail/breakpoint.rs b/src/tools/miri/tests/fail/breakpoint.rs
index 2dd87ea6083..42943d58191 100644
--- a/src/tools/miri/tests/fail/breakpoint.rs
+++ b/src/tools/miri/tests/fail/breakpoint.rs
@@ -1,7 +1,5 @@
 #![feature(core_intrinsics)]
 
 fn main() {
-    unsafe {
-        core::intrinsics::breakpoint() //~ ERROR: trace/breakpoint trap
-    };
+    core::intrinsics::breakpoint(); //~ ERROR: trace/breakpoint trap
 }
diff --git a/src/tools/miri/tests/fail/breakpoint.stderr b/src/tools/miri/tests/fail/breakpoint.stderr
index ca98e81f1f4..f203cb0c15f 100644
--- a/src/tools/miri/tests/fail/breakpoint.stderr
+++ b/src/tools/miri/tests/fail/breakpoint.stderr
@@ -1,8 +1,8 @@
 error: abnormal termination: trace/breakpoint trap
   --> tests/fail/breakpoint.rs:LL:CC
    |
-LL |         core::intrinsics::breakpoint()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap
+LL |     core::intrinsics::breakpoint();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap
    |
    = note: BACKTRACE:
    = note: inside `main` at tests/fail/breakpoint.rs:LL:CC
diff --git a/tests/assembly/breakpoint.rs b/tests/assembly/breakpoint.rs
new file mode 100644
index 00000000000..e0cc2d1eebb
--- /dev/null
+++ b/tests/assembly/breakpoint.rs
@@ -0,0 +1,14 @@
+//@ revisions: aarch64 x86_64
+//@ assembly-output: emit-asm
+//@[aarch64] only-aarch64
+//@[x86_64] only-x86_64
+
+#![feature(breakpoint)]
+#![crate_type = "lib"]
+
+// CHECK-LABEL: use_bp
+// aarch64: brk #0xf000
+// x86_64: int3
+pub fn use_bp() {
+    core::arch::breakpoint();
+}
diff --git a/tests/ui/error-codes/E0622.rs b/tests/ui/error-codes/E0622.rs
index ae7378a707e..08c6d171296 100644
--- a/tests/ui/error-codes/E0622.rs
+++ b/tests/ui/error-codes/E0622.rs
@@ -1,6 +1,6 @@
 #![feature(intrinsics)]
 extern "rust-intrinsic" {
-    pub static breakpoint : unsafe extern "rust-intrinsic" fn();
+    pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn();
     //~^ ERROR intrinsic must be a function [E0622]
 }
-fn main() { unsafe { breakpoint(); } }
+fn main() { unsafe { atomic_singlethreadfence_seqcst(); } }
diff --git a/tests/ui/error-codes/E0622.stderr b/tests/ui/error-codes/E0622.stderr
index c59776b211f..739ec984fc6 100644
--- a/tests/ui/error-codes/E0622.stderr
+++ b/tests/ui/error-codes/E0622.stderr
@@ -1,8 +1,8 @@
 error[E0622]: intrinsic must be a function
   --> $DIR/E0622.rs:3:5
    |
-LL |     pub static breakpoint : unsafe extern "rust-intrinsic" fn();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function
+LL |     pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function
 
 error: aborting due to 1 previous error