@@ -493,13 +493,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
493
493
let discr_ty = adt. repr . discr_type ( ) . to_ty ( self . tcx ( ) ) ;
494
494
let discr = Lvalue :: Local ( self . new_temp ( discr_ty) ) ;
495
495
let discr_rv = Rvalue :: Discriminant ( self . lvalue . clone ( ) ) ;
496
- let switch_block = self . elaborator . patch ( ) . new_block ( BasicBlockData {
497
- statements : vec ! [
498
- Statement {
499
- source_info: self . source_info,
500
- kind: StatementKind :: Assign ( discr. clone( ) , discr_rv) ,
501
- }
502
- ] ,
496
+ let switch_block = BasicBlockData {
497
+ statements : vec ! [ self . assign( & discr, discr_rv) ] ,
503
498
terminator : Some ( Terminator {
504
499
source_info : self . source_info ,
505
500
kind : TerminatorKind :: SwitchInt {
@@ -510,7 +505,8 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
510
505
}
511
506
} ) ,
512
507
is_cleanup : unwind. is_cleanup ( ) ,
513
- } ) ;
508
+ } ;
509
+ let switch_block = self . elaborator . patch ( ) . new_block ( switch_block) ;
514
510
self . drop_flag_test_block ( switch_block, succ, unwind)
515
511
}
516
512
@@ -531,14 +527,11 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
531
527
let ref_lvalue = self . new_temp ( ref_ty) ;
532
528
let unit_temp = Lvalue :: Local ( self . new_temp ( tcx. mk_nil ( ) ) ) ;
533
529
534
- self . elaborator . patch ( ) . new_block ( BasicBlockData {
535
- statements : vec ! [ Statement {
536
- source_info: self . source_info,
537
- kind: StatementKind :: Assign (
538
- Lvalue :: Local ( ref_lvalue) ,
539
- Rvalue :: Ref ( tcx. types. re_erased, BorrowKind :: Mut , self . lvalue. clone( ) )
540
- )
541
- } ] ,
530
+ let result = BasicBlockData {
531
+ statements : vec ! [ self . assign(
532
+ & Lvalue :: Local ( ref_lvalue) ,
533
+ Rvalue :: Ref ( tcx. types. re_erased, BorrowKind :: Mut , self . lvalue. clone( ) )
534
+ ) ] ,
542
535
terminator : Some ( Terminator {
543
536
kind : TerminatorKind :: Call {
544
537
func : Operand :: function_handle ( tcx, drop_fn. def_id , substs,
@@ -550,24 +543,33 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
550
543
source_info : self . source_info
551
544
} ) ,
552
545
is_cleanup : unwind. is_cleanup ( ) ,
553
- } )
546
+ } ;
547
+ self . elaborator . patch ( ) . new_block ( result)
554
548
}
555
549
556
550
/// create a loop that drops an array:
551
+ ///
552
+
557
553
///
558
554
/// loop-block:
559
- /// can_go = index == len
555
+ /// can_go = cur == length_or_end
560
556
/// if can_go then succ else drop-block
561
557
/// drop-block:
562
- /// ptr = &mut LV[index]
563
- /// index = index + 1
558
+ /// if ptr_based {
559
+ /// ptr = cur
560
+ /// cur = cur.offset(1)
561
+ /// } else {
562
+ /// ptr = &mut LV[cur]
563
+ /// cur = cur + 1
564
+ /// }
564
565
/// drop(ptr)
565
566
fn drop_loop ( & mut self ,
566
567
succ : BasicBlock ,
567
- index : & Lvalue < ' tcx > ,
568
- length : & Lvalue < ' tcx > ,
568
+ cur : & Lvalue < ' tcx > ,
569
+ length_or_end : & Lvalue < ' tcx > ,
569
570
ety : Ty < ' tcx > ,
570
- unwind : Unwind )
571
+ unwind : Unwind ,
572
+ ptr_based : bool )
571
573
-> BasicBlock
572
574
{
573
575
let use_ = |lv : & Lvalue < ' tcx > | Operand :: Consume ( lv. clone ( ) ) ;
@@ -581,38 +583,44 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
581
583
let can_go = & Lvalue :: Local ( self . new_temp ( tcx. types . bool ) ) ;
582
584
583
585
let one = self . constant_usize ( 1 ) ;
584
- let drop_block = self . elaborator . patch ( ) . new_block ( BasicBlockData {
586
+ let ( ptr_next, cur_next) = if ptr_based {
587
+ ( Rvalue :: Use ( use_ ( cur) ) ,
588
+ Rvalue :: BinaryOp ( BinOp :: Offset , use_ ( cur) , one) )
589
+ } else {
590
+ ( Rvalue :: Ref (
591
+ tcx. types . re_erased ,
592
+ BorrowKind :: Mut ,
593
+ self . lvalue . clone ( ) . index ( use_ ( cur) ) ) ,
594
+ Rvalue :: BinaryOp ( BinOp :: Add , use_ ( cur) , one) )
595
+ } ;
596
+
597
+ let drop_block = BasicBlockData {
585
598
statements : vec ! [
586
- Statement { source_info: self . source_info, kind: StatementKind :: Assign (
587
- ptr. clone( ) , Rvalue :: Ref (
588
- tcx. types. re_erased, BorrowKind :: Mut ,
589
- self . lvalue. clone( ) . index( use_( index) )
590
- ) ,
591
- ) } ,
592
- Statement { source_info: self . source_info, kind: StatementKind :: Assign (
593
- index. clone( ) , Rvalue :: BinaryOp ( BinOp :: Add , use_( index) , one)
594
- ) } ,
599
+ self . assign( ptr, ptr_next) ,
600
+ self . assign( cur, cur_next)
595
601
] ,
596
602
is_cleanup : unwind. is_cleanup ( ) ,
597
603
terminator : Some ( Terminator {
598
604
source_info : self . source_info ,
599
605
// this gets overwritten by drop elaboration.
600
606
kind : TerminatorKind :: Unreachable ,
601
607
} )
602
- } ) ;
608
+ } ;
609
+ let drop_block = self . elaborator . patch ( ) . new_block ( drop_block) ;
603
610
604
- let loop_block = self . elaborator . patch ( ) . new_block ( BasicBlockData {
611
+ let loop_block = BasicBlockData {
605
612
statements : vec ! [
606
- Statement { source_info : self . source_info , kind : StatementKind :: Assign (
607
- can_go . clone ( ) , Rvalue :: BinaryOp ( BinOp :: Eq , use_ ( index ) , use_( length ) )
608
- ) } ,
613
+ self . assign ( can_go , Rvalue :: BinaryOp ( BinOp :: Eq ,
614
+ use_( cur ) ,
615
+ use_ ( length_or_end ) ) )
609
616
] ,
610
617
is_cleanup : unwind. is_cleanup ( ) ,
611
618
terminator : Some ( Terminator {
612
619
source_info : self . source_info ,
613
620
kind : TerminatorKind :: if_ ( tcx, use_ ( can_go) , succ, drop_block)
614
621
} )
615
- } ) ;
622
+ } ;
623
+ let loop_block = self . elaborator . patch ( ) . new_block ( loop_block) ;
616
624
617
625
self . elaborator . patch ( ) . patch_terminator ( drop_block, TerminatorKind :: Drop {
618
626
location : ptr. clone ( ) . deref ( ) ,
@@ -625,29 +633,97 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
625
633
626
634
fn open_drop_for_array ( & mut self , ety : Ty < ' tcx > ) -> BasicBlock {
627
635
debug ! ( "open_drop_for_array({:?})" , ety) ;
628
- // FIXME: using an index instead of a pointer to avoid
629
- // special-casing ZSTs.
636
+
637
+ // if size_of::<ety>() == 0 {
638
+ // index_based_loop
639
+ // } else {
640
+ // ptr_based_loop
641
+ // }
642
+
643
+ let tcx = self . tcx ( ) ;
644
+
645
+ let use_ = |lv : & Lvalue < ' tcx > | Operand :: Consume ( lv. clone ( ) ) ;
646
+ let size = & Lvalue :: Local ( self . new_temp ( tcx. types . usize ) ) ;
647
+ let size_is_zero = & Lvalue :: Local ( self . new_temp ( tcx. types . bool ) ) ;
648
+ let base_block = BasicBlockData {
649
+ statements : vec ! [
650
+ self . assign( size, Rvalue :: NullaryOp ( NullOp :: SizeOf , ety) ) ,
651
+ self . assign( size_is_zero, Rvalue :: BinaryOp ( BinOp :: Eq ,
652
+ use_( size) ,
653
+ self . constant_usize( 0 ) ) )
654
+ ] ,
655
+ is_cleanup : self . unwind . is_cleanup ( ) ,
656
+ terminator : Some ( Terminator {
657
+ source_info : self . source_info ,
658
+ kind : TerminatorKind :: if_ (
659
+ tcx,
660
+ use_ ( size_is_zero) ,
661
+ self . drop_loop_pair ( ety, false ) ,
662
+ self . drop_loop_pair ( ety, true )
663
+ )
664
+ } )
665
+ } ;
666
+ self . elaborator . patch ( ) . new_block ( base_block)
667
+ }
668
+
669
+ // create a pair of drop-loops of `lvalue`, which drops its contents
670
+ // even in the case of 1 panic. If `ptr_based`, create a pointer loop,
671
+ // otherwise create an index loop.
672
+ fn drop_loop_pair ( & mut self , ety : Ty < ' tcx > , ptr_based : bool ) -> BasicBlock {
673
+ debug ! ( "drop_loop_pair({:?}, {:?})" , ety, ptr_based) ;
630
674
let tcx = self . tcx ( ) ;
631
- let index = & Lvalue :: Local ( self . new_temp ( tcx. types . usize ) ) ;
632
- let length = & Lvalue :: Local ( self . new_temp ( tcx. types . usize ) ) ;
675
+ let iter_ty = if ptr_based {
676
+ tcx. mk_ptr ( ty:: TypeAndMut { ty : ety, mutbl : hir:: Mutability :: MutMutable } )
677
+ } else {
678
+ tcx. types . usize
679
+ } ;
680
+
681
+ let cur = Lvalue :: Local ( self . new_temp ( iter_ty) ) ;
682
+ let length = Lvalue :: Local ( self . new_temp ( tcx. types . usize ) ) ;
683
+ let length_or_end = if ptr_based {
684
+ Lvalue :: Local ( self . new_temp ( iter_ty) )
685
+ } else {
686
+ length. clone ( )
687
+ } ;
633
688
634
689
let unwind = self . unwind . map ( |unwind| {
635
- self . drop_loop ( unwind, index, length, ety, Unwind :: InCleanup )
690
+ self . drop_loop ( unwind,
691
+ & cur,
692
+ & length_or_end,
693
+ ety,
694
+ Unwind :: InCleanup ,
695
+ ptr_based)
636
696
} ) ;
637
697
638
698
let succ = self . succ ; // FIXME(#6393)
639
- let loop_block = self . drop_loop ( succ, index, length, ety, unwind) ;
699
+ let loop_block = self . drop_loop (
700
+ succ,
701
+ & cur,
702
+ & length_or_end,
703
+ ety,
704
+ unwind,
705
+ ptr_based) ;
640
706
641
707
let zero = self . constant_usize ( 0 ) ;
708
+ let mut drop_block_stmts = vec ! [ ] ;
709
+ drop_block_stmts. push ( self . assign ( & length, Rvalue :: Len ( self . lvalue . clone ( ) ) ) ) ;
710
+ if ptr_based {
711
+ // cur = &LV[0];
712
+ // end = &LV[len];
713
+ drop_block_stmts. push ( self . assign ( & cur, Rvalue :: Ref (
714
+ tcx. types . re_erased , BorrowKind :: Mut ,
715
+ self . lvalue . clone ( ) . index ( zero. clone ( ) )
716
+ ) ) ) ;
717
+ drop_block_stmts. push ( self . assign ( & length_or_end, Rvalue :: Ref (
718
+ tcx. types . re_erased , BorrowKind :: Mut ,
719
+ self . lvalue . clone ( ) . index ( Operand :: Consume ( length. clone ( ) ) )
720
+ ) ) ) ;
721
+ } else {
722
+ // index = 0 (length already pushed)
723
+ drop_block_stmts. push ( self . assign ( & cur, Rvalue :: Use ( zero) ) ) ;
724
+ }
642
725
let drop_block = self . elaborator . patch ( ) . new_block ( BasicBlockData {
643
- statements : vec ! [
644
- Statement { source_info: self . source_info, kind: StatementKind :: Assign (
645
- length. clone( ) , Rvalue :: Len ( self . lvalue. clone( ) )
646
- ) } ,
647
- Statement { source_info: self . source_info, kind: StatementKind :: Assign (
648
- index. clone( ) , Rvalue :: Use ( zero) ,
649
- ) } ,
650
- ] ,
726
+ statements : drop_block_stmts,
651
727
is_cleanup : unwind. is_cleanup ( ) ,
652
728
terminator : Some ( Terminator {
653
729
source_info : self . source_info ,
@@ -836,4 +912,11 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
836
912
literal : Literal :: Value { value : ConstVal :: Integral ( self . tcx ( ) . const_usize ( val) ) }
837
913
} )
838
914
}
915
+
916
+ fn assign ( & self , lhs : & Lvalue < ' tcx > , rhs : Rvalue < ' tcx > ) -> Statement < ' tcx > {
917
+ Statement {
918
+ source_info : self . source_info ,
919
+ kind : StatementKind :: Assign ( lhs. clone ( ) , rhs)
920
+ }
921
+ }
839
922
}
0 commit comments