Skip to content

Commit 64bc3c2

Browse files
trans: Make collector handle the drop_in_place() intrinsic.
1 parent f4dd4be commit 64bc3c2

File tree

2 files changed

+89
-3
lines changed

2 files changed

+89
-3
lines changed

src/librustc_trans/collector.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,9 +202,9 @@ use rustc::mir::repr as mir;
202202
use rustc::mir::visit as mir_visit;
203203
use rustc::mir::visit::Visitor as MirVisitor;
204204

205+
use syntax::abi::Abi;
205206
use syntax::codemap::DUMMY_SP;
206207
use syntax::errors;
207-
208208
use base::custom_coerce_unsize_info;
209209
use context::SharedCrateContext;
210210
use common::{fulfill_obligation, normalize_and_test_predicates, type_is_sized};
@@ -602,6 +602,49 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
602602
can_have_local_instance(tcx, def_id)
603603
}
604604
}
605+
606+
// This takes care of the "drop_in_place" intrinsic for which we otherwise
607+
// we would not register drop-glues.
608+
fn visit_terminator_kind(&mut self,
609+
block: mir::BasicBlock,
610+
kind: &mir::TerminatorKind<'tcx>) {
611+
let tcx = self.scx.tcx();
612+
match *kind {
613+
mir::TerminatorKind::Call {
614+
func: mir::Operand::Constant(ref constant),
615+
ref args,
616+
..
617+
} => {
618+
match constant.ty.sty {
619+
ty::TyFnDef(def_id, _, bare_fn_ty)
620+
if is_drop_in_place_intrinsic(tcx, def_id, bare_fn_ty) => {
621+
let operand_ty = self.mir.operand_ty(tcx, &args[0]);
622+
if let ty::TyRawPtr(mt) = operand_ty.sty {
623+
let operand_ty = monomorphize::apply_param_substs(tcx,
624+
self.param_substs,
625+
&mt.ty);
626+
self.output.push(TransItem::DropGlue(DropGlueKind::Ty(operand_ty)));
627+
} else {
628+
bug!("Has the drop_in_place() intrinsic's signature changed?")
629+
}
630+
}
631+
_ => { /* Nothing to do. */ }
632+
}
633+
}
634+
_ => { /* Nothing to do. */ }
635+
}
636+
637+
self.super_terminator_kind(block, kind);
638+
639+
fn is_drop_in_place_intrinsic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
640+
def_id: DefId,
641+
bare_fn_ty: &ty::BareFnTy<'tcx>)
642+
-> bool {
643+
(bare_fn_ty.abi == Abi::RustIntrinsic ||
644+
bare_fn_ty.abi == Abi::PlatformIntrinsic) &&
645+
tcx.item_name(def_id).as_str() == "drop_in_place"
646+
}
647+
}
605648
}
606649

607650
fn can_have_local_instance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -699,7 +742,6 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
699742
ty::TyRef(..) |
700743
ty::TyFnDef(..) |
701744
ty::TyFnPtr(_) |
702-
ty::TySlice(_) |
703745
ty::TyTrait(_) => {
704746
/* nothing to do */
705747
}
@@ -725,6 +767,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
725767
}
726768
}
727769
ty::TyBox(inner_type) |
770+
ty::TySlice(inner_type) |
728771
ty::TyArray(inner_type, _) => {
729772
let inner_type = glue::get_drop_glue_type(scx.tcx(), inner_type);
730773
if glue::type_needs_drop(scx.tcx(), inner_type) {
@@ -746,6 +789,8 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
746789
bug!("encountered unexpected type");
747790
}
748791
}
792+
793+
749794
}
750795

751796
fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
@@ -1187,7 +1232,7 @@ pub enum TransItemState {
11871232
}
11881233

11891234
pub fn collecting_debug_information(scx: &SharedCrateContext) -> bool {
1190-
return cfg!(debug_assertions) &&
1235+
return scx.sess().opts.cg.debug_assertions == Some(true) &&
11911236
scx.sess().opts.debugging_opts.print_trans_items.is_some();
11921237
}
11931238

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-tidy-linelength
12+
// compile-flags:-Zprint-trans-items=eager
13+
14+
//~ TRANS_ITEM drop-glue drop_in_place_intrinsic::StructWithDtor[0]
15+
//~ TRANS_ITEM drop-glue-contents drop_in_place_intrinsic::StructWithDtor[0]
16+
struct StructWithDtor(u32);
17+
18+
impl Drop for StructWithDtor {
19+
//~ TRANS_ITEM fn drop_in_place_intrinsic::{{impl}}[0]::drop[0]
20+
fn drop(&mut self) {}
21+
}
22+
23+
//~ TRANS_ITEM fn drop_in_place_intrinsic::main[0]
24+
fn main() {
25+
26+
//~ TRANS_ITEM drop-glue [drop_in_place_intrinsic::StructWithDtor[0]; 2]
27+
let x = [StructWithDtor(0), StructWithDtor(1)];
28+
29+
drop_slice_in_place(&x);
30+
}
31+
32+
//~ TRANS_ITEM fn drop_in_place_intrinsic::drop_slice_in_place[0]
33+
fn drop_slice_in_place(x: &[StructWithDtor]) {
34+
unsafe {
35+
// This is the interesting thing in this test case: Normally we would
36+
// not have drop-glue for the unsized [StructWithDtor]. This has to be
37+
// generated though when the drop_in_place() intrinsic is used.
38+
//~ TRANS_ITEM drop-glue [drop_in_place_intrinsic::StructWithDtor[0]]
39+
::std::ptr::drop_in_place(x as *const _ as *mut [StructWithDtor]);
40+
}
41+
}

0 commit comments

Comments
 (0)