Skip to content

Commit 1673331

Browse files
committed
Change InlineAsm to allow multiple targets instead
1 parent 929ea36 commit 1673331

File tree

22 files changed

+112
-91
lines changed

22 files changed

+112
-91
lines changed

compiler/rustc_borrowck/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
724724
operands,
725725
options: _,
726726
line_spans: _,
727-
destination: _,
727+
targets: _,
728728
unwind: _,
729729
} => {
730730
for op in operands {

compiler/rustc_borrowck/src/polonius/loan_invalidations.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> {
163163
operands,
164164
options: _,
165165
line_spans: _,
166-
destination: _,
166+
targets: _,
167167
unwind: _,
168168
} => {
169169
for op in operands {

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1669,8 +1669,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
16691669
self.assert_iscleanup(body, block_data, real_target, is_cleanup);
16701670
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
16711671
}
1672-
TerminatorKind::InlineAsm { destination, unwind, .. } => {
1673-
if let Some(target) = destination {
1672+
TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
1673+
for &target in targets {
16741674
self.assert_iscleanup(body, block_data, target, is_cleanup);
16751675
}
16761676
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);

compiler/rustc_codegen_cranelift/src/base.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
445445
template,
446446
operands,
447447
options,
448-
destination,
448+
targets,
449449
line_spans: _,
450450
unwind: _,
451451
} => {
@@ -456,13 +456,25 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
456456
);
457457
}
458458

459+
let have_labels = if options.contains(InlineAsmOptions::NORETURN) {
460+
!targets.is_empty()
461+
} else {
462+
targets.len() > 1
463+
};
464+
if have_labels {
465+
fx.tcx.dcx().span_fatal(
466+
source_info.span,
467+
"cranelift doesn't support labels in inline assembly.",
468+
);
469+
}
470+
459471
crate::inline_asm::codegen_inline_asm_terminator(
460472
fx,
461473
source_info.span,
462474
template,
463475
operands,
464476
*options,
465-
*destination,
477+
targets.get(0).copied(),
466478
);
467479
}
468480
TerminatorKind::UnwindTerminate(reason) => {

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1276,7 +1276,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
12761276
ref operands,
12771277
options,
12781278
line_spans,
1279-
destination,
1279+
ref targets,
12801280
unwind,
12811281
} => self.codegen_asm_terminator(
12821282
helper,
@@ -1286,7 +1286,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
12861286
operands,
12871287
options,
12881288
line_spans,
1289-
destination,
1289+
targets.get(0).copied(),
12901290
unwind,
12911291
self.instance,
12921292
mergeable_succ(),

compiler/rustc_const_eval/messages.ftl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,6 @@ const_eval_non_const_fn_call =
214214
const_eval_non_const_impl =
215215
impl defined here, but it is not `const`
216216
217-
const_eval_noreturn_asm_returned =
218-
returned from noreturn inline assembly
219-
220217
const_eval_not_enough_caller_args =
221218
calling a function with fewer arguments than it requires
222219

compiler/rustc_const_eval/src/interpret/machine.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,11 +373,17 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
373373
kind: Option<MemoryKind<Self::MemoryKind>>,
374374
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>;
375375

376+
/// Evaluate the inline assembly.
377+
///
378+
/// This should take care of jumping to the next block (one of `targets`) when asm goto
379+
/// is triggered, `targets[0]` when the assembly falls through, or diverge in case of
380+
/// `InlineAsmOptions::NORETURN` being set.
376381
fn eval_inline_asm(
377382
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
378383
_template: &'tcx [InlineAsmTemplatePiece],
379384
_operands: &[mir::InlineAsmOperand<'tcx>],
380385
_options: InlineAsmOptions,
386+
_targets: &[mir::BasicBlock],
381387
) -> InterpResult<'tcx> {
382388
throw_unsup_format!("inline assembly is not supported")
383389
}

compiler/rustc_const_eval/src/interpret/terminator.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::borrow::Cow;
22

3-
use rustc_ast::ast::InlineAsmOptions;
43
use rustc_middle::{
54
mir,
65
ty::{
@@ -224,15 +223,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
224223
terminator.kind
225224
),
226225

227-
InlineAsm { template, ref operands, options, destination, .. } => {
228-
M::eval_inline_asm(self, template, operands, options)?;
229-
if options.contains(InlineAsmOptions::NORETURN) {
230-
throw_ub_custom!(fluent::const_eval_noreturn_asm_returned);
231-
}
232-
self.go_to_block(
233-
destination
234-
.expect("InlineAsm terminators without noreturn must have a destination"),
235-
)
226+
InlineAsm { template, ref operands, options, ref targets, .. } => {
227+
M::eval_inline_asm(self, template, operands, options, targets)?;
236228
}
237229
}
238230

compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -481,9 +481,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
481481
self.check_edge(location, *real_target, EdgeKind::Normal);
482482
self.check_unwind_edge(location, *unwind);
483483
}
484-
TerminatorKind::InlineAsm { destination, unwind, .. } => {
485-
if let Some(destination) = destination {
486-
self.check_edge(location, *destination, EdgeKind::Normal);
484+
TerminatorKind::InlineAsm { targets, unwind, .. } => {
485+
for &target in targets {
486+
self.check_edge(location, target, EdgeKind::Normal);
487487
}
488488
self.check_unwind_edge(location, *unwind);
489489
}

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,13 +1651,13 @@ mod size_asserts {
16511651
use super::*;
16521652
use rustc_data_structures::static_assert_size;
16531653
// tidy-alphabetical-start
1654-
static_assert_size!(BasicBlockData<'_>, 136);
1654+
static_assert_size!(BasicBlockData<'_>, 144);
16551655
static_assert_size!(LocalDecl<'_>, 40);
16561656
static_assert_size!(SourceScopeData<'_>, 72);
16571657
static_assert_size!(Statement<'_>, 32);
16581658
static_assert_size!(StatementKind<'_>, 16);
1659-
static_assert_size!(Terminator<'_>, 104);
1660-
static_assert_size!(TerminatorKind<'_>, 88);
1659+
static_assert_size!(Terminator<'_>, 112);
1660+
static_assert_size!(TerminatorKind<'_>, 96);
16611661
static_assert_size!(VarDebugInfo<'_>, 88);
16621662
// tidy-alphabetical-end
16631663
}

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::path::{Path, PathBuf};
66

77
use super::graphviz::write_mir_fn_graphviz;
88
use super::spanview::write_mir_fn_spanview;
9-
use rustc_ast::InlineAsmTemplatePiece;
9+
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
1010
use rustc_middle::mir::interpret::{
1111
alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer,
1212
Provenance,
@@ -895,16 +895,19 @@ impl<'tcx> TerminatorKind<'tcx> {
895895
vec!["real".into(), "unwind".into()]
896896
}
897897
FalseUnwind { unwind: _, .. } => vec!["real".into()],
898-
InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
899-
vec!["return".into(), "unwind".into()]
900-
}
901-
InlineAsm { destination: Some(_), unwind: _, .. } => {
902-
vec!["return".into()]
903-
}
904-
InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => {
905-
vec!["unwind".into()]
898+
InlineAsm { options, ref targets, unwind, .. } => {
899+
let mut vec = Vec::with_capacity(targets.len() + 1);
900+
if !options.contains(InlineAsmOptions::NORETURN) {
901+
vec.push("return".into());
902+
}
903+
vec.resize(targets.len(), "label".into());
904+
905+
if let UnwindAction::Cleanup(_) = unwind {
906+
vec.push("unwind".into());
907+
}
908+
909+
vec
906910
}
907-
InlineAsm { destination: None, unwind: _, .. } => vec![],
908911
}
909912
}
910913
}

compiler/rustc_middle/src/mir/syntax.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -790,9 +790,10 @@ pub enum TerminatorKind<'tcx> {
790790
/// used to map assembler errors back to the line in the source code.
791791
line_spans: &'tcx [Span],
792792

793-
/// Destination block after the inline assembly returns, unless it is
794-
/// diverging (InlineAsmOptions::NORETURN).
795-
destination: Option<BasicBlock>,
793+
/// Valid targets for the inline assembly.
794+
/// The first element is the fallthrough destination, unless
795+
/// InlineAsmOptions::NORETURN is set.
796+
targets: Vec<BasicBlock>,
796797

797798
/// Action to be taken if the inline assembly unwinds. This is present
798799
/// if and only if InlineAsmOptions::MAY_UNWIND is set.

compiler/rustc_middle/src/mir/terminator.rs

Lines changed: 33 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,7 @@ impl<'tcx> TerminatorKind<'tcx> {
358358
| Yield { resume: ref t, drop: Some(u), .. }
359359
| Drop { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
360360
| Assert { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
361-
| FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) }
362-
| InlineAsm { destination: Some(ref t), unwind: UnwindAction::Cleanup(u), .. } => {
361+
| FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } => {
363362
slice::from_ref(t).into_iter().copied().chain(Some(u))
364363
}
365364
Goto { target: ref t }
@@ -368,20 +367,19 @@ impl<'tcx> TerminatorKind<'tcx> {
368367
| Yield { resume: ref t, drop: None, .. }
369368
| Drop { target: ref t, unwind: _, .. }
370369
| Assert { target: ref t, unwind: _, .. }
371-
| FalseUnwind { real_target: ref t, unwind: _ }
372-
| InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref t), .. }
373-
| InlineAsm { destination: Some(ref t), unwind: _, .. } => {
370+
| FalseUnwind { real_target: ref t, unwind: _ } => {
374371
slice::from_ref(t).into_iter().copied().chain(None)
375372
}
376373
UnwindResume
377374
| UnwindTerminate(_)
378375
| CoroutineDrop
379376
| Return
380377
| Unreachable
381-
| Call { target: None, unwind: _, .. }
382-
| InlineAsm { destination: None, unwind: _, .. } => {
383-
(&[]).into_iter().copied().chain(None)
378+
| Call { target: None, unwind: _, .. } => (&[]).into_iter().copied().chain(None),
379+
InlineAsm { ref targets, unwind: UnwindAction::Cleanup(u), .. } => {
380+
targets.iter().copied().chain(Some(u))
384381
}
382+
InlineAsm { ref targets, unwind: _, .. } => targets.iter().copied().chain(None),
385383
SwitchInt { ref targets, .. } => targets.targets.iter().copied().chain(None),
386384
FalseEdge { ref real_target, imaginary_target } => {
387385
slice::from_ref(real_target).into_iter().copied().chain(Some(imaginary_target))
@@ -396,30 +394,28 @@ impl<'tcx> TerminatorKind<'tcx> {
396394
| Yield { resume: ref mut t, drop: Some(ref mut u), .. }
397395
| Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
398396
| Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
399-
| FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) }
400-
| InlineAsm {
401-
destination: Some(ref mut t),
402-
unwind: UnwindAction::Cleanup(ref mut u),
403-
..
404-
} => slice::from_mut(t).into_iter().chain(Some(u)),
397+
| FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) } => {
398+
slice::from_mut(t).into_iter().chain(Some(u))
399+
}
405400
Goto { target: ref mut t }
406401
| Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
407402
| Call { target: Some(ref mut t), unwind: _, .. }
408403
| Yield { resume: ref mut t, drop: None, .. }
409404
| Drop { target: ref mut t, unwind: _, .. }
410405
| Assert { target: ref mut t, unwind: _, .. }
411-
| FalseUnwind { real_target: ref mut t, unwind: _ }
412-
| InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
413-
| InlineAsm { destination: Some(ref mut t), unwind: _, .. } => {
406+
| FalseUnwind { real_target: ref mut t, unwind: _ } => {
414407
slice::from_mut(t).into_iter().chain(None)
415408
}
416409
UnwindResume
417410
| UnwindTerminate(_)
418411
| CoroutineDrop
419412
| Return
420413
| Unreachable
421-
| Call { target: None, unwind: _, .. }
422-
| InlineAsm { destination: None, unwind: _, .. } => (&mut []).into_iter().chain(None),
414+
| Call { target: None, unwind: _, .. } => (&mut []).into_iter().chain(None),
415+
InlineAsm { ref mut targets, unwind: UnwindAction::Cleanup(ref mut u), .. } => {
416+
targets.iter_mut().chain(Some(u))
417+
}
418+
InlineAsm { ref mut targets, unwind: _, .. } => targets.iter_mut().chain(None),
423419
SwitchInt { ref mut targets, .. } => targets.targets.iter_mut().chain(None),
424420
FalseEdge { ref mut real_target, ref mut imaginary_target } => {
425421
slice::from_mut(real_target).into_iter().chain(Some(imaginary_target))
@@ -490,7 +486,7 @@ pub enum TerminatorEdges<'mir, 'tcx> {
490486
Double(BasicBlock, BasicBlock),
491487
/// Special action for `Yield`, `Call` and `InlineAsm` terminators.
492488
AssignOnReturn {
493-
return_: Option<BasicBlock>,
489+
return_: &'mir [BasicBlock],
494490
/// The cleanup block, if it exists.
495491
cleanup: Option<BasicBlock>,
496492
place: CallReturnPlaces<'mir, 'tcx>,
@@ -554,31 +550,37 @@ impl<'tcx> TerminatorKind<'tcx> {
554550
TerminatorEdges::Double(real_target, imaginary_target)
555551
}
556552

557-
Yield { resume: target, drop, resume_arg, value: _ } => {
553+
Yield { resume: ref target, drop, resume_arg, value: _ } => {
558554
TerminatorEdges::AssignOnReturn {
559-
return_: Some(target),
555+
return_: slice::from_ref(target),
560556
cleanup: drop,
561557
place: CallReturnPlaces::Yield(resume_arg),
562558
}
563559
}
564560

565-
Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => {
566-
TerminatorEdges::AssignOnReturn {
567-
return_: target,
568-
cleanup: unwind.cleanup_block(),
569-
place: CallReturnPlaces::Call(destination),
570-
}
571-
}
561+
Call {
562+
unwind,
563+
destination,
564+
ref target,
565+
func: _,
566+
args: _,
567+
fn_span: _,
568+
call_source: _,
569+
} => TerminatorEdges::AssignOnReturn {
570+
return_: target.as_ref().map(slice::from_ref).unwrap_or_default(),
571+
cleanup: unwind.cleanup_block(),
572+
place: CallReturnPlaces::Call(destination),
573+
},
572574

573575
InlineAsm {
574576
template: _,
575577
ref operands,
576578
options: _,
577579
line_spans: _,
578-
destination,
580+
ref targets,
579581
unwind,
580582
} => TerminatorEdges::AssignOnReturn {
581-
return_: destination,
583+
return_: targets,
582584
cleanup: unwind.cleanup_block(),
583585
place: CallReturnPlaces::InlineAsm(operands),
584586
},

compiler/rustc_middle/src/mir/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ macro_rules! make_mir_visitor {
563563
operands,
564564
options: _,
565565
line_spans: _,
566-
destination: _,
566+
targets: _,
567567
unwind: _,
568568
} => {
569569
for op in operands {

compiler/rustc_mir_build/src/build/expr/into.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -468,10 +468,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
468468
operands,
469469
options,
470470
line_spans,
471-
destination: if options.contains(InlineAsmOptions::NORETURN) {
472-
None
471+
targets: if options.contains(InlineAsmOptions::NORETURN) {
472+
Vec::new()
473473
} else {
474-
Some(destination_block)
474+
vec![destination_block]
475475
},
476476
unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) {
477477
UnwindAction::Continue

compiler/rustc_mir_build/src/lints.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,10 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor<BasicBlocks<'tcx
198198
| TerminatorKind::Unreachable
199199
| TerminatorKind::Yield { .. } => ControlFlow::Break(NonRecursive),
200200

201-
// A diverging InlineAsm is treated as non-recursing
202-
TerminatorKind::InlineAsm { destination, .. } => {
203-
if destination.is_some() {
201+
// A InlineAsm without targets (diverging and contains no labels)
202+
// is treated as non-recursing.
203+
TerminatorKind::InlineAsm { ref targets, .. } => {
204+
if !targets.is_empty() {
204205
ControlFlow::Continue(())
205206
} else {
206207
ControlFlow::Break(NonRecursive)

0 commit comments

Comments
 (0)