wasm exception handling
This commit is contained in:
parent
35cdb28c84
commit
82730b4521
5 changed files with 117 additions and 14 deletions
|
@ -357,6 +357,13 @@ pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
}
|
||||
}
|
||||
|
||||
// Returns `true` if this session's target will use native wasm
|
||||
// exceptions. This means that the VM does the unwinding for
|
||||
// us
|
||||
pub fn wants_wasm_eh(sess: &Session) -> bool {
|
||||
sess.target.is_like_wasm && sess.target.os != "emscripten"
|
||||
}
|
||||
|
||||
/// Returns `true` if this session's target will use SEH-based unwinding.
|
||||
///
|
||||
/// This is only true for MSVC targets, and even then the 64-bit MSVC target
|
||||
|
@ -366,6 +373,13 @@ pub fn wants_msvc_seh(sess: &Session) -> bool {
|
|||
sess.target.is_like_msvc
|
||||
}
|
||||
|
||||
/// Returns `true` if this session's target requires the new exception
|
||||
/// handling LLVM IR instructions (catchpad / cleanuppad / ... instead
|
||||
/// of landingpad)
|
||||
pub fn wants_new_eh_instructions(sess: &Session) -> bool {
|
||||
wants_wasm_eh(sess) || wants_msvc_seh(sess)
|
||||
}
|
||||
|
||||
pub fn memcpy_ty<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
dst: Bx::Value,
|
||||
|
|
|
@ -79,8 +79,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
lltarget = fx.landing_pad_for(target);
|
||||
}
|
||||
if is_cleanupret {
|
||||
// MSVC cross-funclet jump - need a trampoline
|
||||
debug_assert!(base::wants_msvc_seh(fx.cx.tcx().sess));
|
||||
// Cross-funclet jump - need a trampoline
|
||||
debug_assert!(base::wants_new_eh_instructions(fx.cx.tcx().sess));
|
||||
debug!("llbb_with_cleanup: creating cleanup trampoline for {:?}", target);
|
||||
let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target);
|
||||
let trampoline_llbb = Bx::append_block(fx.cx, fx.llfn, name);
|
||||
|
@ -177,9 +177,16 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||
mir::UnwindAction::Continue => None,
|
||||
mir::UnwindAction::Unreachable => None,
|
||||
mir::UnwindAction::Terminate => {
|
||||
if fx.mir[self.bb].is_cleanup && base::wants_msvc_seh(fx.cx.tcx().sess) {
|
||||
// SEH will abort automatically if an exception tries to
|
||||
if fx.mir[self.bb].is_cleanup && base::wants_new_eh_instructions(fx.cx.tcx().sess) {
|
||||
// MSVC SEH will abort automatically if an exception tries to
|
||||
// propagate out from cleanup.
|
||||
|
||||
// FIXME(@mirkootter): For wasm, we currently do not support terminate during
|
||||
// cleanup, because this requires a few more changes: The current code
|
||||
// caches the `terminate_block` for each function; funclet based code - however -
|
||||
// requires a different terminate_block for each funclet
|
||||
// Until this is implemented, we just do not unwind inside cleanup blocks
|
||||
|
||||
None
|
||||
} else {
|
||||
Some(fx.terminate_block())
|
||||
|
@ -1528,7 +1535,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// FIXME(eddyb) rename this to `eh_pad_for_uncached`.
|
||||
fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
|
||||
let llbb = self.llbb(bb);
|
||||
if base::wants_msvc_seh(self.cx.sess()) {
|
||||
if base::wants_new_eh_instructions(self.cx.sess()) {
|
||||
let cleanup_bb = Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb));
|
||||
let mut cleanup_bx = Bx::build(self.cx, cleanup_bb);
|
||||
let funclet = cleanup_bx.cleanup_pad(None, &[]);
|
||||
|
|
|
@ -169,7 +169,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
start_bx.set_personality_fn(cx.eh_personality());
|
||||
}
|
||||
|
||||
let cleanup_kinds = base::wants_msvc_seh(cx.tcx().sess).then(|| analyze::cleanup_kinds(&mir));
|
||||
let cleanup_kinds =
|
||||
base::wants_new_eh_instructions(cx.tcx().sess).then(|| analyze::cleanup_kinds(&mir));
|
||||
|
||||
let cached_llbbs: IndexVec<mir::BasicBlock, CachedLlbb<Bx::BasicBlock>> =
|
||||
mir.basic_blocks
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue