/// Returns `true` if this is indeed a panic intrinsic and codegen is done.
Returns `true` if this is indeed a panic intrinsic and codegen is done.
Returns ` true ` if this is indeed a panic intrinsic and codegen is done .
fn codegen_panic_intrinsic(
        &mut self,
        helper: &TerminatorCodegenHelper<'tcx>,
        bx: &mut Bx,
        intrinsic: Option<Symbol>,
        instance: Option<Instance<'tcx>>,
        source_info: mir::SourceInfo,
        destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>,
        cleanup: Option<mir::BasicBlock>,
    ) -> bool {
        // Emit a panic or a no-op for `assert_*` intrinsics.
        // These are intrinsics that compile to panics so that we can get a message
        // which mentions the offending type, even from a const context.
        #[derive(Debug, PartialEq)]
        enum AssertIntrinsic {
            Inhabited,
            ZeroValid,
            UninitValid,
        }
        let panic_intrinsic = intrinsic.and_then(|i| match i {
            sym::assert_inhabited => Some(AssertIntrinsic::Inhabited),
            sym::assert_zero_valid => Some(AssertIntrinsic::ZeroValid),
            sym::assert_uninit_valid => Some(AssertIntrinsic::UninitValid),
            _ => None,
        });
        if let Some(intrinsic) = panic_intrinsic {
            use AssertIntrinsic::*;
            let ty = instance.unwrap().substs.type_at(0);
            let layout = bx.layout_of(ty);
            let do_panic = match intrinsic {
                Inhabited => layout.abi.is_uninhabited(),
                ZeroValid => !layout.might_permit_raw_init(bx, /*zero:*/ true),
                UninitValid => !layout.might_permit_raw_init(bx, /*zero:*/ false),
            };
            if do_panic {
                let msg_str = with_no_visible_paths(|| {
                    with_no_trimmed_paths(|| {
                        if layout.abi.is_uninhabited() {
                            // Use this error even for the other intrinsics as it is more precise.
                            format!("attempted to instantiate uninhabited type `{}`", ty)
                        } else if intrinsic == ZeroValid {
                            format!("attempted to zero-initialize type `{}`, which is invalid", ty)
                        } else {
                            format!(
                                "attempted to leave type `{}` uninitialized, which is invalid",
                                ty
                            )
                        }
                    })
                });
                let msg = bx.const_str(Symbol::intern(&msg_str));
                let location = self.get_caller_location(bx, source_info).immediate();
                // Obtain the panic entry point.
                // FIXME: dedup this with `codegen_assert_terminator` above.
                let def_id =
                    common::langcall(bx.tcx(), Some(source_info.span), "", LangItem::Panic);
                let instance = ty::Instance::mono(bx.tcx(), def_id);
                let fn_abi = bx.fn_abi_of_instance(instance, ty::List::empty());
                let llfn = bx.get_fn_addr(instance);
                // Codegen the actual panic invoke/call.
                helper.do_call(
                    self,
                    bx,
                    fn_abi,
                    llfn,
                    &[msg.0, msg.1, location],
                    destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)),
                    cleanup,
                );
            } else {
                // a NOP
                let target = destination.as_ref().unwrap().1;
                helper.funclet_br(self, bx, target)
            }
            true
        } else {
            false
        }
    }
fn codegen_panic_intrinsic ( & mut self , helper : & TerminatorCodegenHelper < ' tcx > , bx : & mut Bx , intrinsic : Option < Symbol > , instance : Option < Instance < ' tcx > > , source_info : mir :: SourceInfo , destination : & Option < ( mir :: Place < ' tcx > , mir :: BasicBlock ) > , cleanup : Option < mir :: BasicBlock > , ) -> bool { // Emit a panic or a no-op for `assert_*` intrinsics. // These are intrinsics that compile to panics so that we can get a message // which mentions the offending type, even from a const context. # [ derive ( Debug PartialEq ) ] enum AssertIntrinsic { Inhabited , ZeroValid , UninitValid , } let panic_intrinsic = intrinsic . and_then ( | i | match i { sym :: assert_inhabited => Some ( AssertIntrinsic :: Inhabited ) , sym :: assert_zero_valid => Some ( AssertIntrinsic :: ZeroValid ) , sym :: assert_uninit_valid => Some ( AssertIntrinsic :: UninitValid ) , _ => None , } ) ; if let Some ( intrinsic ) = panic_intrinsic { use AssertIntrinsic :: * ; let ty = instance . unwrap ( ) . substs . type_at ( 0 ) ; let layout = bx . layout_of ( ty ) ; let do_panic = match intrinsic { Inhabited => layout . abi . is_uninhabited ( ) , ZeroValid => ! layout . might_permit_raw_init ( bx , /*zero:*/ true ) , UninitValid => ! layout . might_permit_raw_init ( bx , /*zero:*/ false ) , } ; if do_panic { let msg_str = with_no_visible_paths ( | | { with_no_trimmed_paths ( | | { if layout . abi . is_uninhabited ( ) { // Use this error even for the other intrinsics as it is more precise. format ! ( " " ty ) } else if intrinsic == ZeroValid { format ! ( " " ty ) } else { format ! ( " " ty ) } } ) } ) ; let msg = bx . const_str ( Symbol :: intern ( & msg_str ) ) ; let location = self . get_caller_location ( bx , source_info ) . immediate ( ) ; // Obtain the panic entry point. // FIXME: dedup this with `codegen_assert_terminator` above. let def_id = common :: langcall ( bx . tcx ( ) , Some ( source_info . span ) , " " , LangItem :: Panic ) ; let instance = ty :: Instance :: mono ( bx . tcx ( ) , def_id ) ; let fn_abi = bx . fn_abi_of_instance ( instance , ty :: List :: empty ( ) ) ; let llfn = bx . get_fn_addr ( instance ) ; // Codegen the actual panic invoke/call. helper . do_call ( self , bx , fn_abi , llfn , & [ msg . 0 , msg . 1 , location ] , destination . as_ref ( ) . map ( | ( _ , bb ) | ( ReturnDest :: Nothing , * bb ) ) , cleanup , ) ; } else { // a NOP let target = destination . as_ref ( ) . unwrap ( ) . 1 ; helper . funclet_br ( self , bx , target ) } true } else { false } }
Returns `true` if this is indeed a panic intrinsic and codegen is done.
Returns ` true ` if this is indeed a panic intrinsic and codegen is done .
&mut self
helper
&TerminatorCodegenHelper<'tcx>
bx
&mut Bx
intrinsic
Option<Symbol>
instance
Option<Instance<'tcx>>
source_info
mir::SourceInfo
destination
&Option<(mir::Place<'tcx>, mir::BasicBlock)>
cleanup
Option<mir::BasicBlock>