@@ -500,6 +500,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
500
500
&mut self,
501
501
helper: TerminatorCodegenHelper<'tcx>,
502
502
bx: &mut Bx,
503
+ source_info: &mir::SourceInfo,
503
504
location: mir::Place<'tcx>,
504
505
target: mir::BasicBlock,
505
506
unwind: mir::UnwindAction,
@@ -523,90 +524,106 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
523
524
args1 = [place.val.llval];
524
525
&args1[..]
525
526
};
526
- let (drop_fn, fn_abi, drop_instance) =
527
- match ty.kind() {
528
- // FIXME(eddyb) perhaps move some of this logic into
529
- // `Instance::resolve_drop_in_place`?
530
- ty::Dynamic(_, _, ty::Dyn) => {
531
- // IN THIS ARM, WE HAVE:
532
- // ty = *mut (dyn Trait)
533
- // which is: exists<T> ( *mut T, Vtable<T: Trait> )
534
- // args[0] args[1]
535
- //
536
- // args = ( Data, Vtable )
537
- // |
538
- // v
539
- // /-------\
540
- // | ... |
541
- // \-------/
542
- //
543
- let virtual_drop = Instance {
544
- def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
545
- args: drop_fn.args,
546
- };
547
- debug!("ty = {:?}", ty);
548
- debug!("drop_fn = {:?}", drop_fn);
549
- debug!("args = {:?}", args);
550
- let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
551
- let vtable = args[1];
552
- // Truncate vtable off of args list
553
- args = &args[..1];
554
- (
555
- meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
556
- .get_fn(bx, vtable, ty, fn_abi),
557
- fn_abi,
558
- virtual_drop,
559
- )
560
- }
561
- ty::Dynamic(_, _, ty::DynStar) => {
562
- // IN THIS ARM, WE HAVE:
563
- // ty = *mut (dyn* Trait)
564
- // which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
565
- //
566
- // args = [ * ]
567
- // |
568
- // v
569
- // ( Data, Vtable )
570
- // |
571
- // v
572
- // /-------\
573
- // | ... |
574
- // \-------/
575
- //
576
- //
577
- // WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
578
- //
579
- // data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
580
- // vtable = (*args[0]).1 // loads the vtable out
581
- // (data, vtable) // an equivalent Rust `*mut dyn Trait`
582
- //
583
- // SO THEN WE CAN USE THE ABOVE CODE.
584
- let virtual_drop = Instance {
585
- def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
586
- args: drop_fn.args,
587
- };
588
- debug!("ty = {:?}", ty);
589
- debug!("drop_fn = {:?}", drop_fn);
590
- debug!("args = {:?}", args);
591
- let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
592
- let meta_ptr = place.project_field(bx, 1);
593
- let meta = bx.load_operand(meta_ptr);
594
- // Truncate vtable off of args list
595
- args = &args[..1];
596
- debug!("args' = {:?}", args);
597
- (
598
- meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
599
- .get_fn(bx, meta.immediate(), ty, fn_abi),
600
- fn_abi,
601
- virtual_drop,
602
- )
603
- }
604
- _ => (
605
- bx.get_fn_addr(drop_fn),
606
- bx.fn_abi_of_instance(drop_fn, ty::List::empty()),
607
- drop_fn,
608
- ),
609
- };
527
+ let (maybe_null, drop_fn, fn_abi, drop_instance) = match ty.kind() {
528
+ // FIXME(eddyb) perhaps move some of this logic into
529
+ // `Instance::resolve_drop_in_place`?
530
+ ty::Dynamic(_, _, ty::Dyn) => {
531
+ // IN THIS ARM, WE HAVE:
532
+ // ty = *mut (dyn Trait)
533
+ // which is: exists<T> ( *mut T, Vtable<T: Trait> )
534
+ // args[0] args[1]
535
+ //
536
+ // args = ( Data, Vtable )
537
+ // |
538
+ // v
539
+ // /-------\
540
+ // | ... |
541
+ // \-------/
542
+ //
543
+ let virtual_drop = Instance {
544
+ def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
545
+ args: drop_fn.args,
546
+ };
547
+ debug!("ty = {:?}", ty);
548
+ debug!("drop_fn = {:?}", drop_fn);
549
+ debug!("args = {:?}", args);
550
+ let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
551
+ let vtable = args[1];
552
+ // Truncate vtable off of args list
553
+ args = &args[..1];
554
+ (
555
+ true,
556
+ meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
557
+ .get_optional_fn(bx, vtable, ty, fn_abi),
558
+ fn_abi,
559
+ virtual_drop,
560
+ )
561
+ }
562
+ ty::Dynamic(_, _, ty::DynStar) => {
563
+ // IN THIS ARM, WE HAVE:
564
+ // ty = *mut (dyn* Trait)
565
+ // which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
566
+ //
567
+ // args = [ * ]
568
+ // |
569
+ // v
570
+ // ( Data, Vtable )
571
+ // |
572
+ // v
573
+ // /-------\
574
+ // | ... |
575
+ // \-------/
576
+ //
577
+ //
578
+ // WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
579
+ //
580
+ // data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
581
+ // vtable = (*args[0]).1 // loads the vtable out
582
+ // (data, vtable) // an equivalent Rust `*mut dyn Trait`
583
+ //
584
+ // SO THEN WE CAN USE THE ABOVE CODE.
585
+ let virtual_drop = Instance {
586
+ def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
587
+ args: drop_fn.args,
588
+ };
589
+ debug!("ty = {:?}", ty);
590
+ debug!("drop_fn = {:?}", drop_fn);
591
+ debug!("args = {:?}", args);
592
+ let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
593
+ let meta_ptr = place.project_field(bx, 1);
594
+ let meta = bx.load_operand(meta_ptr);
595
+ // Truncate vtable off of args list
596
+ args = &args[..1];
597
+ debug!("args' = {:?}", args);
598
+ (
599
+ true,
600
+ meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
601
+ .get_optional_fn(bx, meta.immediate(), ty, fn_abi),
602
+ fn_abi,
603
+ virtual_drop,
604
+ )
605
+ }
606
+ _ => (
607
+ false,
608
+ bx.get_fn_addr(drop_fn),
609
+ bx.fn_abi_of_instance(drop_fn, ty::List::empty()),
610
+ drop_fn,
611
+ ),
612
+ };
613
+
614
+ // We generate a null check for the drop_fn. This saves a bunch of relocations being
615
+ // generated for no-op drops.
616
+ if maybe_null {
617
+ let is_not_null = bx.append_sibling_block("is_not_null");
618
+ let llty = bx.fn_ptr_backend_type(fn_abi);
619
+ let null = bx.const_null(llty);
620
+ let non_null =
621
+ bx.icmp(base::bin_op_to_icmp_predicate(mir::BinOp::Ne, false), drop_fn, null);
622
+ bx.cond_br(non_null, is_not_null, helper.llbb_with_cleanup(self, target));
623
+ bx.switch_to_block(is_not_null);
624
+ self.set_debug_loc(bx, *source_info);
625
+ }
626
+
610
627
helper.do_call(
611
628
self,
612
629
bx,
@@ -617,7 +634,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
617
634
unwind,
618
635
&[],
619
636
Some(drop_instance),
620
- mergeable_succ,
637
+ !maybe_null && mergeable_succ,
621
638
)
622
639
}
623
640
@@ -1346,9 +1363,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1346
1363
MergingSucc::False
1347
1364
}
1348
1365
1349
- mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => {
1350
- self.codegen_drop_terminator(helper, bx, place, target, unwind, mergeable_succ())
1351
- }
1366
+ mir::TerminatorKind::Drop { place, target, unwind, replace: _ } => self
1367
+ .codegen_drop_terminator(
1368
+ helper,
1369
+ bx,
1370
+ &terminator.source_info,
1371
+ place,
1372
+ target,
1373
+ unwind,
1374
+ mergeable_succ(),
1375
+ ),
1352
1376
1353
1377
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, unwind } => self
1354
1378
.codegen_assert_terminator(
0 commit comments