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
|
@ -264,7 +264,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
mir::UnwindAction::Unreachable => None,
|
||||
};
|
||||
|
||||
if let Some(cleanup) = unwind_target {
|
||||
if operands.iter().any(|x| matches!(x, InlineAsmOperandRef::Label { .. })) {
|
||||
assert!(unwind_target.is_none());
|
||||
let ret_llbb = if let Some(target) = destination {
|
||||
fx.llbb(target)
|
||||
} else {
|
||||
|
@ -277,11 +278,29 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
options,
|
||||
line_spans,
|
||||
instance,
|
||||
Some((ret_llbb, cleanup, self.funclet(fx))),
|
||||
Some(ret_llbb),
|
||||
None,
|
||||
);
|
||||
MergingSucc::False
|
||||
} else if let Some(cleanup) = unwind_target {
|
||||
let ret_llbb = if let Some(target) = destination {
|
||||
fx.llbb(target)
|
||||
} else {
|
||||
fx.unreachable_block()
|
||||
};
|
||||
|
||||
bx.codegen_inline_asm(
|
||||
template,
|
||||
operands,
|
||||
options,
|
||||
line_spans,
|
||||
instance,
|
||||
Some(ret_llbb),
|
||||
Some((cleanup, self.funclet(fx))),
|
||||
);
|
||||
MergingSucc::False
|
||||
} else {
|
||||
bx.codegen_inline_asm(template, operands, options, line_spans, instance, None);
|
||||
bx.codegen_inline_asm(template, operands, options, line_spans, instance, None, None);
|
||||
|
||||
if let Some(target) = destination {
|
||||
self.funclet_br(fx, bx, target, mergeable_succ)
|
||||
|
@ -1100,7 +1119,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
operands: &[mir::InlineAsmOperand<'tcx>],
|
||||
options: ast::InlineAsmOptions,
|
||||
line_spans: &[Span],
|
||||
destination: Option<mir::BasicBlock>,
|
||||
targets: &[mir::BasicBlock],
|
||||
unwind: mir::UnwindAction,
|
||||
instance: Instance<'_>,
|
||||
mergeable_succ: bool,
|
||||
|
@ -1152,6 +1171,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
mir::InlineAsmOperand::SymStatic { def_id } => {
|
||||
InlineAsmOperandRef::SymStatic { def_id }
|
||||
}
|
||||
mir::InlineAsmOperand::Label { target_index } => {
|
||||
InlineAsmOperandRef::Label { label: self.llbb(targets[target_index]) }
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -1162,7 +1184,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
&operands,
|
||||
options,
|
||||
line_spans,
|
||||
destination,
|
||||
if options.contains(InlineAsmOptions::NORETURN) {
|
||||
None
|
||||
} else {
|
||||
targets.get(0).copied()
|
||||
},
|
||||
unwind,
|
||||
instance,
|
||||
mergeable_succ,
|
||||
|
@ -1318,7 +1344,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
ref operands,
|
||||
options,
|
||||
line_spans,
|
||||
destination,
|
||||
ref targets,
|
||||
unwind,
|
||||
} => self.codegen_asm_terminator(
|
||||
helper,
|
||||
|
@ -1328,7 +1354,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
operands,
|
||||
options,
|
||||
line_spans,
|
||||
destination,
|
||||
targets,
|
||||
unwind,
|
||||
self.instance,
|
||||
mergeable_succ(),
|
||||
|
|
|
@ -76,7 +76,8 @@ impl<'a, 'tcx: 'a> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> {
|
|||
hir::InlineAsmOperand::In { .. }
|
||||
| hir::InlineAsmOperand::Out { .. }
|
||||
| hir::InlineAsmOperand::InOut { .. }
|
||||
| hir::InlineAsmOperand::SplitInOut { .. } => {
|
||||
| hir::InlineAsmOperand::SplitInOut { .. }
|
||||
| hir::InlineAsmOperand::Label { .. } => {
|
||||
span_bug!(*op_sp, "invalid operand type for global_asm!")
|
||||
}
|
||||
})
|
||||
|
|
|
@ -33,6 +33,9 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> {
|
|||
SymStatic {
|
||||
def_id: DefId,
|
||||
},
|
||||
Label {
|
||||
label: B::BasicBlock,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -51,7 +54,8 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes {
|
|||
options: InlineAsmOptions,
|
||||
line_spans: &[Span],
|
||||
instance: Instance<'_>,
|
||||
dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>,
|
||||
dest: Option<Self::BasicBlock>,
|
||||
catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue