Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 73f8309

Browse filesBrowse files
committed
Support use of asm goto with outputs and options(noreturn)
When labels are present, the `noreturn` option really means that asm block won't fallthrough -- if labels are present, then outputs can still be meaningfully used.
1 parent b8df869 commit 73f8309
Copy full SHA for 73f8309

File tree

Expand file treeCollapse file tree

5 files changed

+45
-5
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+45
-5
lines changed

‎compiler/rustc_builtin_macros/src/asm.rs

Copy file name to clipboardExpand all lines: compiler/rustc_builtin_macros/src/asm.rs
+4-1Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,10 @@ pub fn parse_asm_args<'a>(
300300
if args.options.contains(ast::InlineAsmOptions::PURE) && !have_real_output {
301301
dcx.emit_err(errors::AsmPureNoOutput { spans: args.options_spans.clone() });
302302
}
303-
if args.options.contains(ast::InlineAsmOptions::NORETURN) && !outputs_sp.is_empty() {
303+
if args.options.contains(ast::InlineAsmOptions::NORETURN)
304+
&& !outputs_sp.is_empty()
305+
&& labels_sp.is_empty()
306+
{
304307
let err = dcx.create_err(errors::AsmNoReturn { outputs_sp });
305308
// Bail out now since this is likely to confuse MIR
306309
return Err(err);

‎compiler/rustc_codegen_llvm/src/asm.rs

Copy file name to clipboardExpand all lines: compiler/rustc_codegen_llvm/src/asm.rs
+8-1Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,14 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
343343
attributes::apply_to_callsite(result, llvm::AttributePlace::Function, &{ attrs });
344344

345345
// Write results to outputs. We need to do this for all possible control flow.
346-
for block in Some(dest).into_iter().chain(labels.iter().copied().map(Some)) {
346+
//
347+
// Note that `dest` maybe populated with unreachable_block when asm goto with outputs
348+
// is used (because we need to codegen callbr which always needs a destination), so
349+
// here we use the NORETURN option to determine if `dest` should be used.
350+
for block in (if options.contains(InlineAsmOptions::NORETURN) { None } else { Some(dest) })
351+
.into_iter()
352+
.chain(labels.iter().copied().map(Some))
353+
{
347354
if let Some(block) = block {
348355
self.switch_to_block(block);
349356
}

‎tests/codegen/asm/goto.rs

Copy file name to clipboardExpand all lines: tests/codegen/asm/goto.rs
+11-1Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,21 @@ pub unsafe fn asm_goto_with_outputs_use_in_label() -> u64 {
4343
// CHECK-LABEL: @asm_goto_noreturn
4444
#[no_mangle]
4545
pub unsafe fn asm_goto_noreturn() -> u64 {
46-
let out: u64;
4746
// CHECK: callbr void asm sideeffect alignstack inteldialect "
4847
// CHECK-NEXT: to label %unreachable [label %[[JUMPBB:[a-b0-9]+]]]
4948
asm!("jmp {}", label { return 1; }, options(noreturn));
5049
// CHECK: [[JUMPBB]]:
5150
// CHECK-NEXT: ret i64 1
51+
}
52+
53+
// CHECK-LABEL: @asm_goto_noreturn_with_outputs
54+
#[no_mangle]
55+
pub unsafe fn asm_goto_noreturn_with_outputs() -> u64 {
56+
let out: u64;
57+
// CHECK: [[RES:%[0-9]+]] = callbr i64 asm sideeffect alignstack inteldialect "
58+
// CHECK-NEXT: to label %[[FALLTHROUGHBB:[a-b0-9]+]] [label %[[JUMPBB:[a-b0-9]+]]]
59+
asm!("mov {}, 1", "jmp {}", out(reg) out, label { return out; });
60+
// CHECK: [[JUMPBB]]:
61+
// CHECK-NEXT: ret i64 [[RES]]
5262
out
5363
}

‎tests/ui/asm/x86_64/goto.rs

Copy file name to clipboardExpand all lines: tests/ui/asm/x86_64/goto.rs
+20Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,25 @@ fn goto_out_jump() {
6565
}
6666
}
6767

68+
fn goto_out_jump_noreturn() {
69+
unsafe {
70+
let mut value = false;
71+
let mut out: usize;
72+
asm!(
73+
"lea {}, [{} + 1]",
74+
"jmp {}",
75+
out(reg) out,
76+
in(reg) 0x12345678usize,
77+
label {
78+
value = true;
79+
assert_eq!(out, 0x12345679);
80+
},
81+
options(noreturn)
82+
);
83+
assert!(value);
84+
}
85+
}
86+
6887
// asm goto with outputs cause miscompilation in LLVM when multiple outputs are present.
6988
// The code sample below is adapted from https://github.com/llvm/llvm-project/issues/74483
7089
// and does not work with `-C opt-level=0`
@@ -131,6 +150,7 @@ fn main() {
131150
goto_jump();
132151
goto_out_fallthrough();
133152
goto_out_jump();
153+
goto_out_jump_noreturn();
134154
// goto_multi_out();
135155
goto_noreturn();
136156
goto_noreturn_diverge();

‎tests/ui/asm/x86_64/goto.stderr

Copy file name to clipboardExpand all lines: tests/ui/asm/x86_64/goto.stderr
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
warning: unreachable statement
2-
--> $DIR/goto.rs:124:9
2+
--> $DIR/goto.rs:143:9
33
|
44
LL | / asm!(
55
LL | | "jmp {}",
@@ -13,7 +13,7 @@ LL | unreachable!();
1313
| ^^^^^^^^^^^^^^ unreachable statement
1414
|
1515
note: the lint level is defined here
16-
--> $DIR/goto.rs:114:8
16+
--> $DIR/goto.rs:133:8
1717
|
1818
LL | #[warn(unreachable_code)]
1919
| ^^^^^^^^^^^^^^^^

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.