@@ -434,6 +434,89 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
434
434
helper. do_call ( self , & mut bx, fn_abi, llfn, & args, None , cleanup) ;
435
435
}
436
436
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
+
437
520
fn codegen_call_terminator (
438
521
& mut self ,
439
522
helper : TerminatorCodegenHelper < ' tcx > ,
@@ -520,72 +603,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
520
603
bug ! ( "`miri_start_panic` should never end up in compiled code" ) ;
521
604
}
522
605
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
+ ) {
589
615
return ;
590
616
}
591
617
0 commit comments