Skip to content

Commit a07265e

Browse files
committed
Deduplicate UnwindAction handling
1 parent 84a39f9 commit a07265e

File tree

2 files changed

+133
-236
lines changed

2 files changed

+133
-236
lines changed

Diff for: src/abi/mod.rs

+126-196
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
2020
use rustc_session::Session;
2121
use rustc_span::source_map::Spanned;
2222
use rustc_target::callconv::{Conv, FnAbi, PassMode};
23-
use smallvec::SmallVec;
23+
use smallvec::{SmallVec, smallvec};
2424

2525
use self::pass_mode::*;
2626
pub(crate) use self::returning::codegen_return;
@@ -518,12 +518,6 @@ pub(crate) fn codegen_terminator_call<'tcx>(
518518
let args = args;
519519
assert_eq!(fn_abi.args.len(), args.len());
520520

521-
#[derive(Copy, Clone)]
522-
enum CallTarget {
523-
Direct(FuncRef),
524-
Indirect(SigRef, Value),
525-
}
526-
527521
let (func_ref, first_arg_override) = match instance {
528522
// Trait object call
529523
Some(Instance { def: InstanceKind::Virtual(_, idx), .. }) => {
@@ -590,81 +584,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
590584
with_no_trimmed_paths!(fx.add_comment(nop_inst, format!("abi: {:?}", fn_abi)));
591585
}
592586

593-
let sig_ref = match func_ref {
594-
CallTarget::Direct(func_ref) => fx.bcx.func.dfg.ext_funcs[func_ref].signature,
595-
CallTarget::Indirect(sig_ref, _func_ptr) => sig_ref,
596-
};
597-
598-
match unwind {
599-
// FIXME abort on unreachable and terminate unwinds
600-
UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate(_) => {
601-
let call_inst = match func_ref {
602-
CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args),
603-
CallTarget::Indirect(sig, func_ptr) => {
604-
fx.bcx.ins().call_indirect(sig, func_ptr, &call_args)
605-
}
606-
};
607-
608-
fx.bcx
609-
.func
610-
.dfg
611-
.inst_results(call_inst)
612-
.iter()
613-
.copied()
614-
.collect::<SmallVec<[Value; 2]>>()
615-
}
616-
UnwindAction::Cleanup(cleanup) => {
617-
let returns_types = fx.bcx.func.dfg.signatures[sig_ref]
618-
.returns
619-
.iter()
620-
.map(|return_param| return_param.value_type)
621-
.collect::<Vec<_>>();
622-
623-
let fallthrough_block = fx.bcx.create_block();
624-
let fallthrough_block_call_args = returns_types
625-
.iter()
626-
.enumerate()
627-
.map(|(i, _)| BlockArg::TryCallRet(i.try_into().unwrap()))
628-
.collect::<Vec<_>>();
629-
let fallthrough_block_call =
630-
fx.bcx.func.dfg.block_call(fallthrough_block, &fallthrough_block_call_args);
631-
let pre_cleanup_block = fx.bcx.create_block();
632-
let pre_cleanup_block_call =
633-
fx.bcx.func.dfg.block_call(pre_cleanup_block, &[BlockArg::TryCallExn(0)]);
634-
let exception_table =
635-
fx.bcx.func.dfg.exception_tables.push(ExceptionTableData::new(
636-
sig_ref,
637-
fallthrough_block_call,
638-
[(Some(ExceptionTag::with_number(0).unwrap()), pre_cleanup_block_call)],
639-
));
640-
641-
match func_ref {
642-
CallTarget::Direct(func_ref) => {
643-
fx.bcx.ins().try_call(func_ref, &call_args, exception_table);
644-
}
645-
CallTarget::Indirect(_sig, func_ptr) => {
646-
fx.bcx.ins().try_call_indirect(func_ptr, &call_args, exception_table);
647-
}
648-
}
649-
650-
fx.bcx.seal_block(pre_cleanup_block);
651-
fx.bcx.switch_to_block(pre_cleanup_block);
652-
fx.bcx.set_cold_block(pre_cleanup_block);
653-
let exception_ptr = fx.bcx.append_block_param(pre_cleanup_block, fx.pointer_type);
654-
fx.bcx.def_var(fx.exception_slot, exception_ptr);
655-
let cleanup_block = fx.get_block(cleanup);
656-
fx.bcx.ins().jump(cleanup_block, &[]);
657-
658-
fx.bcx.seal_block(fallthrough_block);
659-
fx.bcx.switch_to_block(fallthrough_block);
660-
let returns = returns_types
661-
.into_iter()
662-
.map(|ty| fx.bcx.append_block_param(fallthrough_block, ty))
663-
.collect();
664-
fx.bcx.ins().nop();
665-
returns
666-
}
667-
}
587+
codegen_call_with_unwind_action(fx, func_ref, unwind, &call_args, None)
668588
});
669589

670590
if let Some(dest) = target {
@@ -821,44 +741,13 @@ pub(crate) fn codegen_drop<'tcx>(
821741

822742
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
823743
let sig = fx.bcx.import_signature(sig);
824-
match unwind {
825-
// FIXME abort on unreachable and terminate unwinds
826-
UnwindAction::Continue
827-
| UnwindAction::Unreachable
828-
| UnwindAction::Terminate(_) => {
829-
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
830-
fx.bcx.ins().jump(ret_block, &[]);
831-
}
832-
UnwindAction::Cleanup(cleanup) => {
833-
let ret_block_call = fx.bcx.func.dfg.block_call(ret_block, &[]);
834-
let pre_cleanup_block = fx.bcx.create_block();
835-
let pre_cleanup_block_call = fx
836-
.bcx
837-
.func
838-
.dfg
839-
.block_call(pre_cleanup_block, &[BlockArg::TryCallExn(0)]);
840-
let exception_table =
841-
fx.bcx.func.dfg.exception_tables.push(ExceptionTableData::new(
842-
sig,
843-
ret_block_call,
844-
[(
845-
Some(ExceptionTag::with_number(0).unwrap()),
846-
pre_cleanup_block_call,
847-
)],
848-
));
849-
850-
fx.bcx.ins().try_call_indirect(drop_fn, &[ptr], exception_table);
851-
852-
fx.bcx.seal_block(pre_cleanup_block);
853-
fx.bcx.switch_to_block(pre_cleanup_block);
854-
fx.bcx.set_cold_block(pre_cleanup_block);
855-
let exception_ptr =
856-
fx.bcx.append_block_param(pre_cleanup_block, fx.pointer_type);
857-
fx.bcx.def_var(fx.exception_slot, exception_ptr);
858-
let cleanup_block = fx.get_block(cleanup);
859-
fx.bcx.ins().jump(cleanup_block, &[]);
860-
}
861-
}
744+
codegen_call_with_unwind_action(
745+
fx,
746+
CallTarget::Indirect(sig, drop_fn),
747+
unwind,
748+
&[ptr],
749+
Some(ret_block),
750+
);
862751
}
863752
ty::Dynamic(_, _, ty::DynStar) => {
864753
// IN THIS ARM, WE HAVE:
@@ -901,44 +790,13 @@ pub(crate) fn codegen_drop<'tcx>(
901790

902791
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
903792
let sig = fx.bcx.import_signature(sig);
904-
match unwind {
905-
// FIXME abort on unreachable and terminate unwinds
906-
UnwindAction::Continue
907-
| UnwindAction::Unreachable
908-
| UnwindAction::Terminate(_) => {
909-
fx.bcx.ins().call_indirect(sig, drop_fn, &[data]);
910-
fx.bcx.ins().jump(ret_block, &[]);
911-
}
912-
UnwindAction::Cleanup(cleanup) => {
913-
let ret_block_call = fx.bcx.func.dfg.block_call(ret_block, &[]);
914-
let pre_cleanup_block = fx.bcx.create_block();
915-
let pre_cleanup_block_call = fx
916-
.bcx
917-
.func
918-
.dfg
919-
.block_call(pre_cleanup_block, &[BlockArg::TryCallExn(0)]);
920-
let exception_table =
921-
fx.bcx.func.dfg.exception_tables.push(ExceptionTableData::new(
922-
sig,
923-
ret_block_call,
924-
[(
925-
Some(ExceptionTag::with_number(0).unwrap()),
926-
pre_cleanup_block_call,
927-
)],
928-
));
929-
930-
fx.bcx.ins().try_call_indirect(drop_fn, &[data], exception_table);
931-
932-
fx.bcx.seal_block(pre_cleanup_block);
933-
fx.bcx.switch_to_block(pre_cleanup_block);
934-
fx.bcx.set_cold_block(pre_cleanup_block);
935-
let exception_ptr =
936-
fx.bcx.append_block_param(pre_cleanup_block, fx.pointer_type);
937-
fx.bcx.def_var(fx.exception_slot, exception_ptr);
938-
let cleanup_block = fx.get_block(cleanup);
939-
fx.bcx.ins().jump(cleanup_block, &[]);
940-
}
941-
}
793+
codegen_call_with_unwind_action(
794+
fx,
795+
CallTarget::Indirect(sig, drop_fn),
796+
unwind,
797+
&[data],
798+
Some(ret_block),
799+
);
942800
}
943801
_ => {
944802
assert!(!matches!(drop_instance.def, InstanceKind::Virtual(_, _)));
@@ -963,45 +821,117 @@ pub(crate) fn codegen_drop<'tcx>(
963821
}
964822

965823
let func_ref = fx.get_function_ref(drop_instance);
966-
let sig_ref = fx.bcx.func.dfg.ext_funcs[func_ref].signature;
967-
match unwind {
968-
// FIXME abort on unreachable and terminate unwinds
969-
UnwindAction::Continue
970-
| UnwindAction::Unreachable
971-
| UnwindAction::Terminate(_) => {
972-
fx.bcx.ins().call(func_ref, &call_args);
973-
fx.bcx.ins().jump(ret_block, &[]);
974-
}
975-
UnwindAction::Cleanup(cleanup) => {
976-
let ret_block_call = fx.bcx.func.dfg.block_call(ret_block, &[]);
977-
let pre_cleanup_block = fx.bcx.create_block();
978-
let pre_cleanup_block_call = fx
979-
.bcx
980-
.func
981-
.dfg
982-
.block_call(pre_cleanup_block, &[BlockArg::TryCallExn(0)]);
983-
let exception_table =
984-
fx.bcx.func.dfg.exception_tables.push(ExceptionTableData::new(
985-
sig_ref,
986-
ret_block_call,
987-
[(
988-
Some(ExceptionTag::with_number(0).unwrap()),
989-
pre_cleanup_block_call,
990-
)],
991-
));
992-
993-
fx.bcx.ins().try_call(func_ref, &call_args, exception_table);
994-
995-
fx.bcx.seal_block(pre_cleanup_block);
996-
fx.bcx.switch_to_block(pre_cleanup_block);
997-
fx.bcx.set_cold_block(pre_cleanup_block);
998-
let exception_ptr =
999-
fx.bcx.append_block_param(pre_cleanup_block, fx.pointer_type);
1000-
fx.bcx.def_var(fx.exception_slot, exception_ptr);
1001-
let cleanup_block = fx.get_block(cleanup);
1002-
fx.bcx.ins().jump(cleanup_block, &[]);
1003-
}
824+
codegen_call_with_unwind_action(
825+
fx,
826+
CallTarget::Direct(func_ref),
827+
unwind,
828+
&call_args,
829+
Some(ret_block),
830+
);
831+
}
832+
}
833+
}
834+
}
835+
836+
#[derive(Copy, Clone)]
837+
pub(crate) enum CallTarget {
838+
Direct(FuncRef),
839+
Indirect(SigRef, Value),
840+
}
841+
842+
pub(crate) fn codegen_call_with_unwind_action(
843+
fx: &mut FunctionCx<'_, '_, '_>,
844+
func_ref: CallTarget,
845+
unwind: UnwindAction,
846+
call_args: &[Value],
847+
target_block: Option<Block>,
848+
) -> SmallVec<[Value; 2]> {
849+
let sig_ref = match func_ref {
850+
CallTarget::Direct(func_ref) => fx.bcx.func.dfg.ext_funcs[func_ref].signature,
851+
CallTarget::Indirect(sig_ref, _func_ptr) => sig_ref,
852+
};
853+
854+
if target_block.is_some() {
855+
assert!(fx.bcx.func.dfg.signatures[sig_ref].returns.is_empty());
856+
}
857+
858+
match unwind {
859+
// FIXME abort on unreachable and terminate unwinds
860+
UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate(_) => {
861+
let call_inst = match func_ref {
862+
CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args),
863+
CallTarget::Indirect(sig, func_ptr) => {
864+
fx.bcx.ins().call_indirect(sig, func_ptr, &call_args)
1004865
}
866+
};
867+
868+
if let Some(target_block) = target_block {
869+
fx.bcx.ins().jump(target_block, &[]);
870+
smallvec![]
871+
} else {
872+
fx.bcx
873+
.func
874+
.dfg
875+
.inst_results(call_inst)
876+
.iter()
877+
.copied()
878+
.collect::<SmallVec<[Value; 2]>>()
879+
}
880+
}
881+
UnwindAction::Cleanup(cleanup) => {
882+
let returns_types = fx.bcx.func.dfg.signatures[sig_ref]
883+
.returns
884+
.iter()
885+
.map(|return_param| return_param.value_type)
886+
.collect::<Vec<_>>();
887+
888+
let fallthrough_block = fx.bcx.create_block();
889+
let fallthrough_block_call_args = returns_types
890+
.iter()
891+
.enumerate()
892+
.map(|(i, _)| BlockArg::TryCallRet(i.try_into().unwrap()))
893+
.collect::<Vec<_>>();
894+
let fallthrough_block_call = fx.bcx.func.dfg.block_call(
895+
target_block.unwrap_or(fallthrough_block),
896+
&fallthrough_block_call_args,
897+
);
898+
let pre_cleanup_block = fx.bcx.create_block();
899+
let pre_cleanup_block_call =
900+
fx.bcx.func.dfg.block_call(pre_cleanup_block, &[BlockArg::TryCallExn(0)]);
901+
let exception_table = fx.bcx.func.dfg.exception_tables.push(ExceptionTableData::new(
902+
sig_ref,
903+
fallthrough_block_call,
904+
[(Some(ExceptionTag::with_number(0).unwrap()), pre_cleanup_block_call)],
905+
));
906+
907+
match func_ref {
908+
CallTarget::Direct(func_ref) => {
909+
fx.bcx.ins().try_call(func_ref, &call_args, exception_table);
910+
}
911+
CallTarget::Indirect(_sig, func_ptr) => {
912+
fx.bcx.ins().try_call_indirect(func_ptr, &call_args, exception_table);
913+
}
914+
}
915+
916+
fx.bcx.seal_block(pre_cleanup_block);
917+
fx.bcx.switch_to_block(pre_cleanup_block);
918+
fx.bcx.set_cold_block(pre_cleanup_block);
919+
let exception_ptr = fx.bcx.append_block_param(pre_cleanup_block, fx.pointer_type);
920+
fx.bcx.def_var(fx.exception_slot, exception_ptr);
921+
let cleanup_block = fx.get_block(cleanup);
922+
fx.bcx.ins().jump(cleanup_block, &[]);
923+
924+
if target_block.is_none() {
925+
fx.bcx.seal_block(fallthrough_block);
926+
fx.bcx.switch_to_block(fallthrough_block);
927+
let returns = returns_types
928+
.into_iter()
929+
.map(|ty| fx.bcx.append_block_param(fallthrough_block, ty))
930+
.collect();
931+
fx.bcx.ins().nop();
932+
returns
933+
} else {
934+
smallvec![]
1005935
}
1006936
}
1007937
}

0 commit comments

Comments
 (0)