Skip to content

Commit b044aaa

Browse files
committed
Change InlineAsm to allow multiple targets instead
1 parent 7152993 commit b044aaa

File tree

23 files changed

+125
-96
lines changed

23 files changed

+125
-96
lines changed

compiler/rustc_borrowck/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -723,7 +723,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
723723
operands,
724724
options: _,
725725
line_spans: _,
726-
destination: _,
726+
targets: _,
727727
unwind: _,
728728
} => {
729729
for op in operands {

compiler/rustc_borrowck/src/polonius/loan_invalidations.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for LoanInvalidationsGenerator<'cx, 'tcx> {
161161
operands,
162162
options: _,
163163
line_spans: _,
164-
destination: _,
164+
targets: _,
165165
unwind: _,
166166
} => {
167167
for op in operands {

compiler/rustc_borrowck/src/type_check/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1771,8 +1771,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
17711771
self.assert_iscleanup(body, block_data, real_target, is_cleanup);
17721772
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
17731773
}
1774-
TerminatorKind::InlineAsm { destination, unwind, .. } => {
1775-
if let Some(target) = destination {
1774+
TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
1775+
for &target in targets {
17761776
self.assert_iscleanup(body, block_data, target, is_cleanup);
17771777
}
17781778
self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);

compiler/rustc_codegen_cranelift/src/base.rs

+14-2
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

+2-2
Original file line numberDiff line numberDiff line change
@@ -1285,7 +1285,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
12851285
ref operands,
12861286
options,
12871287
line_spans,
1288-
destination,
1288+
ref targets,
12891289
unwind,
12901290
} => self.codegen_asm_terminator(
12911291
helper,
@@ -1295,7 +1295,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
12951295
operands,
12961296
options,
12971297
line_spans,
1298-
destination,
1298+
targets.get(0).copied(),
12991299
unwind,
13001300
self.instance,
13011301
mergeable_succ(),

compiler/rustc_const_eval/messages.ftl

-3
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,6 @@ const_eval_non_const_fn_call =
232232
const_eval_non_const_impl =
233233
impl defined here, but it is not `const`
234234
235-
const_eval_noreturn_asm_returned =
236-
returned from noreturn inline assembly
237-
238235
const_eval_not_enough_caller_args =
239236
calling a function with fewer arguments than it requires
240237

compiler/rustc_const_eval/src/interpret/machine.rs

+6
Original file line numberDiff line numberDiff line change
@@ -374,11 +374,17 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
374374
kind: Option<MemoryKind<Self::MemoryKind>>,
375375
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra, Self::Bytes>>>;
376376

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

compiler/rustc_const_eval/src/interpret/terminator.rs

+2-10
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

+3-3
Original file line numberDiff line numberDiff line change
@@ -471,9 +471,9 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
471471
self.check_edge(location, *real_target, EdgeKind::Normal);
472472
self.check_unwind_edge(location, *unwind);
473473
}
474-
TerminatorKind::InlineAsm { destination, unwind, .. } => {
475-
if let Some(destination) = destination {
476-
self.check_edge(location, *destination, EdgeKind::Normal);
474+
TerminatorKind::InlineAsm { targets, unwind, .. } => {
475+
for &target in targets {
476+
self.check_edge(location, target, EdgeKind::Normal);
477477
}
478478
self.check_unwind_edge(location, *unwind);
479479
}

compiler/rustc_middle/src/mir/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1718,13 +1718,13 @@ mod size_asserts {
17181718
use super::*;
17191719
use rustc_data_structures::static_assert_size;
17201720
// tidy-alphabetical-start
1721-
static_assert_size!(BasicBlockData<'_>, 136);
1721+
static_assert_size!(BasicBlockData<'_>, 144);
17221722
static_assert_size!(LocalDecl<'_>, 40);
17231723
static_assert_size!(SourceScopeData<'_>, 72);
17241724
static_assert_size!(Statement<'_>, 32);
17251725
static_assert_size!(StatementKind<'_>, 16);
1726-
static_assert_size!(Terminator<'_>, 104);
1727-
static_assert_size!(TerminatorKind<'_>, 88);
1726+
static_assert_size!(Terminator<'_>, 112);
1727+
static_assert_size!(TerminatorKind<'_>, 96);
17281728
static_assert_size!(VarDebugInfo<'_>, 88);
17291729
// tidy-alphabetical-end
17301730
}

compiler/rustc_middle/src/mir/pretty.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::path::{Path, PathBuf};
77
use crate::mir::interpret::ConstAllocation;
88

99
use super::graphviz::write_mir_fn_graphviz;
10-
use rustc_ast::InlineAsmTemplatePiece;
10+
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
1111
use rustc_middle::mir::interpret::{
1212
alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer,
1313
Provenance,
@@ -868,16 +868,19 @@ impl<'tcx> TerminatorKind<'tcx> {
868868
vec!["real".into(), "unwind".into()]
869869
}
870870
FalseUnwind { unwind: _, .. } => vec!["real".into()],
871-
InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
872-
vec!["return".into(), "unwind".into()]
873-
}
874-
InlineAsm { destination: Some(_), unwind: _, .. } => {
875-
vec!["return".into()]
876-
}
877-
InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => {
878-
vec!["unwind".into()]
871+
InlineAsm { options, ref targets, unwind, .. } => {
872+
let mut vec = Vec::with_capacity(targets.len() + 1);
873+
if !options.contains(InlineAsmOptions::NORETURN) {
874+
vec.push("return".into());
875+
}
876+
vec.resize(targets.len(), "label".into());
877+
878+
if let UnwindAction::Cleanup(_) = unwind {
879+
vec.push("unwind".into());
880+
}
881+
882+
vec
879883
}
880-
InlineAsm { destination: None, unwind: _, .. } => vec![],
881884
}
882885
}
883886
}

compiler/rustc_middle/src/mir/syntax.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -793,9 +793,10 @@ pub enum TerminatorKind<'tcx> {
793793
/// used to map assembler errors back to the line in the source code.
794794
line_spans: &'tcx [Span],
795795

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

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

compiler/rustc_middle/src/mir/terminator.rs

+33-31
Original file line numberDiff line numberDiff line change
@@ -374,8 +374,7 @@ impl<'tcx> TerminatorKind<'tcx> {
374374
| Yield { resume: ref t, drop: Some(u), .. }
375375
| Drop { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
376376
| Assert { target: ref t, unwind: UnwindAction::Cleanup(u), .. }
377-
| FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) }
378-
| InlineAsm { destination: Some(ref t), unwind: UnwindAction::Cleanup(u), .. } => {
377+
| FalseUnwind { real_target: ref t, unwind: UnwindAction::Cleanup(u) } => {
379378
slice::from_ref(t).into_iter().copied().chain(Some(u))
380379
}
381380
Goto { target: ref t }
@@ -384,20 +383,19 @@ impl<'tcx> TerminatorKind<'tcx> {
384383
| Yield { resume: ref t, drop: None, .. }
385384
| Drop { target: ref t, unwind: _, .. }
386385
| Assert { target: ref t, unwind: _, .. }
387-
| FalseUnwind { real_target: ref t, unwind: _ }
388-
| InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref t), .. }
389-
| InlineAsm { destination: Some(ref t), unwind: _, .. } => {
386+
| FalseUnwind { real_target: ref t, unwind: _ } => {
390387
slice::from_ref(t).into_iter().copied().chain(None)
391388
}
392389
UnwindResume
393390
| UnwindTerminate(_)
394391
| CoroutineDrop
395392
| Return
396393
| Unreachable
397-
| Call { target: None, unwind: _, .. }
398-
| InlineAsm { destination: None, unwind: _, .. } => {
399-
(&[]).into_iter().copied().chain(None)
394+
| Call { target: None, unwind: _, .. } => (&[]).into_iter().copied().chain(None),
395+
InlineAsm { ref targets, unwind: UnwindAction::Cleanup(u), .. } => {
396+
targets.iter().copied().chain(Some(u))
400397
}
398+
InlineAsm { ref targets, unwind: _, .. } => targets.iter().copied().chain(None),
401399
SwitchInt { ref targets, .. } => targets.targets.iter().copied().chain(None),
402400
FalseEdge { ref real_target, imaginary_target } => {
403401
slice::from_ref(real_target).into_iter().copied().chain(Some(imaginary_target))
@@ -413,30 +411,28 @@ impl<'tcx> TerminatorKind<'tcx> {
413411
| Yield { resume: ref mut t, drop: Some(ref mut u), .. }
414412
| Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
415413
| Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
416-
| FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) }
417-
| InlineAsm {
418-
destination: Some(ref mut t),
419-
unwind: UnwindAction::Cleanup(ref mut u),
420-
..
421-
} => slice::from_mut(t).into_iter().chain(Some(u)),
414+
| FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) } => {
415+
slice::from_mut(t).into_iter().chain(Some(u))
416+
}
422417
Goto { target: ref mut t }
423418
| Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
424419
| Call { target: Some(ref mut t), unwind: _, .. }
425420
| Yield { resume: ref mut t, drop: None, .. }
426421
| Drop { target: ref mut t, unwind: _, .. }
427422
| Assert { target: ref mut t, unwind: _, .. }
428-
| FalseUnwind { real_target: ref mut t, unwind: _ }
429-
| InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
430-
| InlineAsm { destination: Some(ref mut t), unwind: _, .. } => {
423+
| FalseUnwind { real_target: ref mut t, unwind: _ } => {
431424
slice::from_mut(t).into_iter().chain(None)
432425
}
433426
UnwindResume
434427
| UnwindTerminate(_)
435428
| CoroutineDrop
436429
| Return
437430
| Unreachable
438-
| Call { target: None, unwind: _, .. }
439-
| InlineAsm { destination: None, unwind: _, .. } => (&mut []).into_iter().chain(None),
431+
| Call { target: None, unwind: _, .. } => (&mut []).into_iter().chain(None),
432+
InlineAsm { ref mut targets, unwind: UnwindAction::Cleanup(ref mut u), .. } => {
433+
targets.iter_mut().chain(Some(u))
434+
}
435+
InlineAsm { ref mut targets, unwind: _, .. } => targets.iter_mut().chain(None),
440436
SwitchInt { ref mut targets, .. } => targets.targets.iter_mut().chain(None),
441437
FalseEdge { ref mut real_target, ref mut imaginary_target } => {
442438
slice::from_mut(real_target).into_iter().chain(Some(imaginary_target))
@@ -511,7 +507,7 @@ pub enum TerminatorEdges<'mir, 'tcx> {
511507
Double(BasicBlock, BasicBlock),
512508
/// Special action for `Yield`, `Call` and `InlineAsm` terminators.
513509
AssignOnReturn {
514-
return_: Option<BasicBlock>,
510+
return_: &'mir [BasicBlock],
515511
/// The cleanup block, if it exists.
516512
cleanup: Option<BasicBlock>,
517513
place: CallReturnPlaces<'mir, 'tcx>,
@@ -575,31 +571,37 @@ impl<'tcx> TerminatorKind<'tcx> {
575571
TerminatorEdges::Double(real_target, imaginary_target)
576572
}
577573

578-
Yield { resume: target, drop, resume_arg, value: _ } => {
574+
Yield { resume: ref target, drop, resume_arg, value: _ } => {
579575
TerminatorEdges::AssignOnReturn {
580-
return_: Some(target),
576+
return_: slice::from_ref(target),
581577
cleanup: drop,
582578
place: CallReturnPlaces::Yield(resume_arg),
583579
}
584580
}
585581

586-
Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => {
587-
TerminatorEdges::AssignOnReturn {
588-
return_: target,
589-
cleanup: unwind.cleanup_block(),
590-
place: CallReturnPlaces::Call(destination),
591-
}
592-
}
582+
Call {
583+
unwind,
584+
destination,
585+
ref target,
586+
func: _,
587+
args: _,
588+
fn_span: _,
589+
call_source: _,
590+
} => TerminatorEdges::AssignOnReturn {
591+
return_: target.as_ref().map(slice::from_ref).unwrap_or_default(),
592+
cleanup: unwind.cleanup_block(),
593+
place: CallReturnPlaces::Call(destination),
594+
},
593595

594596
InlineAsm {
595597
template: _,
596598
ref operands,
597599
options: _,
598600
line_spans: _,
599-
destination,
601+
ref targets,
600602
unwind,
601603
} => TerminatorEdges::AssignOnReturn {
602-
return_: destination,
604+
return_: targets,
603605
cleanup: unwind.cleanup_block(),
604606
place: CallReturnPlaces::InlineAsm(operands),
605607
},

compiler/rustc_middle/src/mir/visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ macro_rules! make_mir_visitor {
565565
operands,
566566
options: _,
567567
line_spans: _,
568-
destination: _,
568+
targets: _,
569569
unwind: _,
570570
} => {
571571
for op in operands {

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -474,10 +474,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
474474
operands,
475475
options,
476476
line_spans,
477-
destination: if options.contains(InlineAsmOptions::NORETURN) {
478-
None
477+
targets: if options.contains(InlineAsmOptions::NORETURN) {
478+
Vec::new()
479479
} else {
480-
Some(destination_block)
480+
vec![destination_block]
481481
},
482482
unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) {
483483
UnwindAction::Continue

compiler/rustc_mir_build/src/lints.rs

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

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

0 commit comments

Comments
 (0)