Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 3956495

Browse files
authoredNov 21, 2024
Rollup merge of rust-lang#131544 - nbdd0121:asm_goto_safe_block, r=petrochenkov
Make asm label blocks safe context Tracking issue: rust-lang#119364 `asm!()` is forced to be wrapped inside unsafe. If there's no special treatment, the label blocks would also always be unsafe with no way of opting out. It was suggested that a simple fix is to make asm label blocks safe: rust-lang#119364 (comment). `@rustbot` labels: +A-inline-assembly +F-asm
2 parents fe5403f + 809dc73 commit 3956495

File tree

4 files changed

+78
-2
lines changed

4 files changed

+78
-2
lines changed
 

‎compiler/rustc_mir_build/src/check_unsafety.rs

+38-1
Original file line numberDiff line numberDiff line change
@@ -537,8 +537,45 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
537537
self.requires_unsafe(expr.span, DerefOfRawPointer);
538538
}
539539
}
540-
ExprKind::InlineAsm { .. } => {
540+
ExprKind::InlineAsm(box InlineAsmExpr {
541+
asm_macro: _,
542+
ref operands,
543+
template: _,
544+
options: _,
545+
line_spans: _,
546+
}) => {
541547
self.requires_unsafe(expr.span, UseOfInlineAssembly);
548+
549+
// For inline asm, do not use `walk_expr`, since we want to handle the label block
550+
// specially.
551+
for op in &**operands {
552+
use rustc_middle::thir::InlineAsmOperand::*;
553+
match op {
554+
In { expr, reg: _ }
555+
| Out { expr: Some(expr), reg: _, late: _ }
556+
| InOut { expr, reg: _, late: _ } => self.visit_expr(&self.thir()[*expr]),
557+
SplitInOut { in_expr, out_expr, reg: _, late: _ } => {
558+
self.visit_expr(&self.thir()[*in_expr]);
559+
if let Some(out_expr) = out_expr {
560+
self.visit_expr(&self.thir()[*out_expr]);
561+
}
562+
}
563+
Out { expr: None, reg: _, late: _ }
564+
| Const { value: _, span: _ }
565+
| SymFn { value: _, span: _ }
566+
| SymStatic { def_id: _ } => {}
567+
Label { block } => {
568+
// Label blocks are safe context.
569+
// `asm!()` is forced to be wrapped inside unsafe. If there's no special
570+
// treatment, the label blocks would also always be unsafe with no way
571+
// of opting out.
572+
self.in_safety_context(SafetyContext::Safe, |this| {
573+
visit::walk_block(this, &this.thir()[*block])
574+
});
575+
}
576+
}
577+
}
578+
return;
542579
}
543580
ExprKind::Adt(box AdtExpr {
544581
adt_def,

‎src/doc/unstable-book/src/language-features/asm-goto.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ unsafe {
2121
}
2222
```
2323

24-
The block must have unit type or diverge.
24+
The block must have unit type or diverge. The block starts a new safety context,
25+
so despite outer `unsafe`, you need extra unsafe to perform unsafe operations
26+
within `label <block>`.
2527

2628
When `label <block>` is used together with `noreturn` option, it means that the
2729
assembly will not fallthrough. It's allowed to jump to a label within the
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ only-x86_64
2+
//@ needs-asm-support
3+
4+
#![deny(unreachable_code)]
5+
#![feature(asm_goto)]
6+
7+
use std::arch::asm;
8+
9+
fn goto_fallthough() {
10+
unsafe {
11+
asm!(
12+
"/* {} */",
13+
label {
14+
core::hint::unreachable_unchecked();
15+
//~^ ERROR [E0133]
16+
}
17+
)
18+
}
19+
}
20+
21+
fn main() {
22+
goto_fallthough();
23+
}
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error[E0133]: call to unsafe function `unreachable_unchecked` is unsafe and requires unsafe function or block
2+
--> $DIR/goto-block-safe.rs:14:17
3+
|
4+
LL | unsafe {
5+
| ------ items do not inherit unsafety from separate enclosing items
6+
...
7+
LL | core::hint::unreachable_unchecked();
8+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
9+
|
10+
= note: consult the function's documentation for information on how to avoid undefined behavior
11+
12+
error: aborting due to 1 previous error
13+
14+
For more information about this error, try `rustc --explain E0133`.

0 commit comments

Comments
 (0)
Failed to load comments.