Rollup merge of #119365 - nbdd0121:asm-goto, r=Amanieu
Add asm goto support to `asm!` Tracking issue: #119364 This PR implements asm-goto support, using the syntax described in "future possibilities" section of [RFC2873](https://rust-lang.github.io/rfcs/2873-inline-asm.html#asm-goto). Currently I have only implemented the `label` part, not the `fallthrough` part (i.e. fallthrough is implicit). This doesn't reduce the expressive though, since you can use label-break to get arbitrary control flow or simply set a value and rely on jump threading optimisation to get the desired control flow. I can add that later if deemed necessary. r? ``@Amanieu`` cc ``@ojeda``
This commit is contained in:
commit
d774fbea7c
76 changed files with 857 additions and 200 deletions
|
@ -383,6 +383,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
line_spans,
|
||||
}) => {
|
||||
use rustc_middle::{mir, thir};
|
||||
|
||||
let destination_block = this.cfg.start_new_block();
|
||||
let mut targets = if options.contains(InlineAsmOptions::NORETURN) {
|
||||
vec![]
|
||||
} else {
|
||||
vec![destination_block]
|
||||
};
|
||||
|
||||
let operands = operands
|
||||
.into_iter()
|
||||
.map(|op| match *op {
|
||||
|
@ -438,14 +446,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
thir::InlineAsmOperand::SymStatic { def_id } => {
|
||||
mir::InlineAsmOperand::SymStatic { def_id }
|
||||
}
|
||||
thir::InlineAsmOperand::Label { block } => {
|
||||
let target = this.cfg.start_new_block();
|
||||
let target_index = targets.len();
|
||||
targets.push(target);
|
||||
|
||||
let tmp = this.get_unit_temp();
|
||||
let target = unpack!(this.ast_block(tmp, target, block, source_info));
|
||||
this.cfg.terminate(
|
||||
target,
|
||||
source_info,
|
||||
TerminatorKind::Goto { target: destination_block },
|
||||
);
|
||||
|
||||
mir::InlineAsmOperand::Label { target_index }
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
if !options.contains(InlineAsmOptions::NORETURN) {
|
||||
if !expr.ty.is_never() {
|
||||
this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
|
||||
}
|
||||
|
||||
let destination_block = this.cfg.start_new_block();
|
||||
this.cfg.terminate(
|
||||
block,
|
||||
source_info,
|
||||
|
@ -454,11 +476,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
operands,
|
||||
options,
|
||||
line_spans,
|
||||
destination: if options.contains(InlineAsmOptions::NORETURN) {
|
||||
None
|
||||
} else {
|
||||
Some(destination_block)
|
||||
},
|
||||
targets,
|
||||
unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) {
|
||||
UnwindAction::Continue
|
||||
} else {
|
||||
|
|
|
@ -199,9 +199,10 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor<BasicBlocks<'tcx
|
|||
| TerminatorKind::Unreachable
|
||||
| TerminatorKind::Yield { .. } => ControlFlow::Break(NonRecursive),
|
||||
|
||||
// A diverging InlineAsm is treated as non-recursing
|
||||
TerminatorKind::InlineAsm { destination, .. } => {
|
||||
if destination.is_some() {
|
||||
// A InlineAsm without targets (diverging and contains no labels)
|
||||
// is treated as non-recursing.
|
||||
TerminatorKind::InlineAsm { ref targets, .. } => {
|
||||
if !targets.is_empty() {
|
||||
ControlFlow::Continue(())
|
||||
} else {
|
||||
ControlFlow::Break(NonRecursive)
|
||||
|
|
|
@ -656,6 +656,9 @@ impl<'tcx> Cx<'tcx> {
|
|||
hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
|
||||
InlineAsmOperand::SymStatic { def_id }
|
||||
}
|
||||
hir::InlineAsmOperand::Label { block } => {
|
||||
InlineAsmOperand::Label { block: self.mirror_block(block) }
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
options: asm.options,
|
||||
|
|
|
@ -889,6 +889,12 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
|
|||
print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
InlineAsmOperand::Label { block } => {
|
||||
print_indented!(self, "InlineAsmOperand::Block {", depth_lvl);
|
||||
print_indented!(self, "block:", depth_lvl + 1);
|
||||
self.print_block(*block, depth_lvl + 2);
|
||||
print_indented!(self, "}", depth_lvl + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue