1
Fork 0

LLVM codgen support for unwinding inline assembly

This commit is contained in:
cynecx 2021-09-04 19:25:09 +02:00
parent 491dd1f387
commit 91021de1f6
7 changed files with 109 additions and 18 deletions

View file

@ -276,9 +276,9 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
| TerminatorKind::SwitchInt { .. }
| TerminatorKind::Yield { .. }
| TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. }
| TerminatorKind::InlineAsm { .. } => { /* nothing to do */ }
| TerminatorKind::FalseUnwind { .. } => { /* nothing to do */ }
TerminatorKind::Call { cleanup: unwind, .. }
| TerminatorKind::InlineAsm { cleanup: unwind, .. }
| TerminatorKind::Assert { cleanup: unwind, .. }
| TerminatorKind::DropAndReplace { unwind, .. }
| TerminatorKind::Drop { unwind, .. } => {

View file

@ -10,6 +10,7 @@ use crate::traits::*;
use crate::MemFlags;
use rustc_ast as ast;
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_hir::lang_items::LangItem;
use rustc_index::vec::Idx;
use rustc_middle::mir::AssertKind;
@ -174,6 +175,45 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
}
}
}
/// Generates inline assembly with optional `destination` and `cleanup`.
fn do_inlineasm<Bx: BuilderMethods<'a, 'tcx>>(
&self,
fx: &mut FunctionCx<'a, 'tcx, Bx>,
bx: &mut Bx,
template: &[InlineAsmTemplatePiece],
operands: &[InlineAsmOperandRef<'tcx, Bx>],
options: InlineAsmOptions,
line_spans: &[Span],
destination: Option<mir::BasicBlock>,
cleanup: Option<mir::BasicBlock>,
instance: Instance<'_>,
) {
if let Some(cleanup) = cleanup {
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, self.llblock(fx, cleanup), self.funclet(fx))),
);
} else {
bx.codegen_inline_asm(template, &operands, options, line_spans, instance, None);
if let Some(target) = destination {
self.funclet_br(fx, bx, target);
} else {
bx.unreachable();
}
}
}
}
/// Codegen implementations for some terminator variants.
@ -877,6 +917,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
options: ast::InlineAsmOptions,
line_spans: &[Span],
destination: Option<mir::BasicBlock>,
cleanup: Option<mir::BasicBlock>,
instance: Instance<'_>,
) {
let span = terminator.source_info.span;
@ -931,13 +972,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
})
.collect();
bx.codegen_inline_asm(template, &operands, options, line_spans, instance);
if let Some(target) = destination {
helper.funclet_br(self, &mut bx, target);
} else {
bx.unreachable();
}
helper.do_inlineasm(
self,
&mut bx,
template,
&operands,
options,
line_spans,
destination,
cleanup,
instance,
);
}
}
@ -1041,7 +1086,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
options,
line_spans,
destination,
cleanup: _, // TODO
cleanup,
} => {
self.codegen_asm_terminator(
helper,
@ -1052,6 +1097,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
options,
line_spans,
destination,
cleanup,
self.instance,
);
}

View file

@ -59,6 +59,7 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes {
options: InlineAsmOptions,
line_spans: &[Span],
instance: Instance<'_>,
dest_catch_funclet: Option<(Self::BasicBlock, Self::BasicBlock, Option<&Self::Funclet>)>,
);
}