Skip to content

Commit 7c84e45

Browse files
committed
move panic intrinsic codegen to helper function
1 parent bfe593e commit 7c84e45

File tree

1 file changed

+92
-66
lines changed

1 file changed

+92
-66
lines changed

src/librustc_codegen_ssa/mir/block.rs

Lines changed: 92 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,89 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
434434
helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup);
435435
}
436436

437+
/// Returns `true` if this is indeed a panic intrinsic and codegen is done.
438+
fn codegen_panic_intrinsic(
439+
&mut self,
440+
helper: &TerminatorCodegenHelper<'tcx>,
441+
bx: &mut Bx,
442+
intrinsic: Option<&str>,
443+
instance: Option<Instance<'tcx>>,
444+
span: Span,
445+
destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
446+
cleanup: Option<mir::BasicBlock>,
447+
) -> bool {
448+
// Emit a panic or a no-op for `panic_if_uninhabited`.
449+
// These are intrinsics that compile to panics so that we can get a message
450+
// which mentions the offending type, even from a const context.
451+
#[derive(Debug, PartialEq)]
452+
enum PanicIntrinsic {
453+
IfUninhabited,
454+
IfZeroInvalid,
455+
IfAnyInvalid,
456+
};
457+
let panic_intrinsic = intrinsic.and_then(|i| match i {
458+
// FIXME: Move to symbols instead of strings.
459+
"panic_if_uninhabited" => Some(PanicIntrinsic::IfUninhabited),
460+
"panic_if_zero_invalid" => Some(PanicIntrinsic::IfZeroInvalid),
461+
"panic_if_any_invalid" => Some(PanicIntrinsic::IfAnyInvalid),
462+
_ => None,
463+
});
464+
if let Some(intrinsic) = panic_intrinsic {
465+
use PanicIntrinsic::*;
466+
let ty = instance.unwrap().substs.type_at(0);
467+
let layout = bx.layout_of(ty);
468+
let do_panic = match intrinsic {
469+
IfUninhabited => layout.abi.is_uninhabited(),
470+
// We unwrap as the error type is `!`.
471+
IfZeroInvalid => !layout.might_permit_raw_init(bx, /*zero:*/ true).unwrap(),
472+
// We unwrap as the error type is `!`.
473+
IfAnyInvalid => !layout.might_permit_raw_init(bx, /*zero:*/ false).unwrap(),
474+
};
475+
if do_panic {
476+
let msg_str = if layout.abi.is_uninhabited() {
477+
// Use this error even for the other intrinsics as it is more precise.
478+
format!("attempted to instantiate uninhabited type `{}`", ty)
479+
} else if intrinsic == IfZeroInvalid {
480+
format!("attempted to zero-initialize type `{}`, which is invalid", ty)
481+
} else {
482+
format!("attempted to leave type `{}` uninitialized, which is invalid", ty)
483+
};
484+
let msg = bx.const_str(Symbol::intern(&msg_str));
485+
let location = self.get_caller_location(bx, span).immediate();
486+
487+
// Obtain the panic entry point.
488+
// FIXME: dedup this with `codegen_assert_terminator` above.
489+
let def_id =
490+
common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
491+
let instance = ty::Instance::mono(bx.tcx(), def_id);
492+
let fn_abi = FnAbi::of_instance(bx, instance, &[]);
493+
let llfn = bx.get_fn_addr(instance);
494+
495+
if let Some((_, target)) = destination.as_ref() {
496+
helper.maybe_sideeffect(self.mir, bx, &[*target]);
497+
}
498+
// Codegen the actual panic invoke/call.
499+
helper.do_call(
500+
self,
501+
bx,
502+
fn_abi,
503+
llfn,
504+
&[msg.0, msg.1, location],
505+
destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
506+
cleanup,
507+
);
508+
} else {
509+
// a NOP
510+
let target = destination.as_ref().unwrap().1;
511+
helper.maybe_sideeffect(self.mir, bx, &[target]);
512+
helper.funclet_br(self, bx, target)
513+
}
514+
true
515+
} else {
516+
false
517+
}
518+
}
519+
437520
fn codegen_call_terminator(
438521
&mut self,
439522
helper: TerminatorCodegenHelper<'tcx>,
@@ -520,72 +603,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
520603
bug!("`miri_start_panic` should never end up in compiled code");
521604
}
522605

523-
// Emit a panic or a no-op for `panic_if_uninhabited`.
524-
// These are intrinsics that compile to panics so that we can get a message
525-
// which mentions the offending type, even from a const context.
526-
#[derive(Debug, PartialEq)]
527-
enum PanicIntrinsic {
528-
IfUninhabited,
529-
IfZeroInvalid,
530-
IfAnyInvalid,
531-
};
532-
let panic_intrinsic = intrinsic.and_then(|i| match i {
533-
// FIXME: Move to symbols instead of strings.
534-
"panic_if_uninhabited" => Some(PanicIntrinsic::IfUninhabited),
535-
"panic_if_zero_invalid" => Some(PanicIntrinsic::IfZeroInvalid),
536-
"panic_if_any_invalid" => Some(PanicIntrinsic::IfAnyInvalid),
537-
_ => None,
538-
});
539-
if let Some(intrinsic) = panic_intrinsic {
540-
use PanicIntrinsic::*;
541-
let ty = instance.unwrap().substs.type_at(0);
542-
let layout = bx.layout_of(ty);
543-
let do_panic = match intrinsic {
544-
IfUninhabited => layout.abi.is_uninhabited(),
545-
// We unwrap as the error type is `!`.
546-
IfZeroInvalid => !layout.might_permit_raw_init(&bx, /*zero:*/ true).unwrap(),
547-
// We unwrap as the error type is `!`.
548-
IfAnyInvalid => !layout.might_permit_raw_init(&bx, /*zero:*/ false).unwrap(),
549-
};
550-
if do_panic {
551-
let msg_str = if layout.abi.is_uninhabited() {
552-
// Use this error even for the other intrinsics as it is more precise.
553-
format!("attempted to instantiate uninhabited type `{}`", ty)
554-
} else if intrinsic == IfZeroInvalid {
555-
format!("attempted to zero-initialize type `{}`, which is invalid", ty)
556-
} else {
557-
format!("attempted to leave type `{}` uninitialized, which is invalid", ty)
558-
};
559-
let msg = bx.const_str(Symbol::intern(&msg_str));
560-
let location = self.get_caller_location(&mut bx, span).immediate();
561-
562-
// Obtain the panic entry point.
563-
// FIXME: dedup this with `codegen_assert_terminator` above.
564-
let def_id =
565-
common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem);
566-
let instance = ty::Instance::mono(bx.tcx(), def_id);
567-
let fn_abi = FnAbi::of_instance(&bx, instance, &[]);
568-
let llfn = bx.get_fn_addr(instance);
569-
570-
if let Some((_, target)) = destination.as_ref() {
571-
helper.maybe_sideeffect(self.mir, &mut bx, &[*target]);
572-
}
573-
// Codegen the actual panic invoke/call.
574-
helper.do_call(
575-
self,
576-
&mut bx,
577-
fn_abi,
578-
llfn,
579-
&[msg.0, msg.1, location],
580-
destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
581-
cleanup,
582-
);
583-
} else {
584-
// a NOP
585-
let target = destination.as_ref().unwrap().1;
586-
helper.maybe_sideeffect(self.mir, &mut bx, &[target]);
587-
helper.funclet_br(self, &mut bx, target)
588-
}
606+
if self.codegen_panic_intrinsic(
607+
&helper,
608+
&mut bx,
609+
intrinsic,
610+
instance,
611+
span,
612+
destination,
613+
cleanup,
614+
) {
589615
return;
590616
}
591617

0 commit comments

Comments
 (0)