about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_trans/collector.rs51
-rw-r--r--src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs41
2 files changed, 89 insertions, 3 deletions
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index 3675bf4b8ce..7a04e45895c 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -202,9 +202,9 @@ use rustc::mir::repr as mir;
 use rustc::mir::visit as mir_visit;
 use rustc::mir::visit::Visitor as MirVisitor;
 
+use syntax::abi::Abi;
 use syntax::codemap::DUMMY_SP;
 use syntax::errors;
-
 use base::custom_coerce_unsize_info;
 use context::SharedCrateContext;
 use common::{fulfill_obligation, normalize_and_test_predicates, type_is_sized};
@@ -602,6 +602,49 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             can_have_local_instance(tcx, def_id)
         }
     }
+
+    // This takes care of the "drop_in_place" intrinsic for which we otherwise
+    // we would not register drop-glues.
+    fn visit_terminator_kind(&mut self,
+                             block: mir::BasicBlock,
+                             kind: &mir::TerminatorKind<'tcx>) {
+        let tcx = self.scx.tcx();
+        match *kind {
+            mir::TerminatorKind::Call {
+                func: mir::Operand::Constant(ref constant),
+                ref args,
+                ..
+            } => {
+                match constant.ty.sty {
+                    ty::TyFnDef(def_id, _, bare_fn_ty)
+                        if is_drop_in_place_intrinsic(tcx, def_id, bare_fn_ty) => {
+                        let operand_ty = self.mir.operand_ty(tcx, &args[0]);
+                        if let ty::TyRawPtr(mt) = operand_ty.sty {
+                            let operand_ty = monomorphize::apply_param_substs(tcx,
+                                                                              self.param_substs,
+                                                                              &mt.ty);
+                            self.output.push(TransItem::DropGlue(DropGlueKind::Ty(operand_ty)));
+                        } else {
+                            bug!("Has the drop_in_place() intrinsic's signature changed?")
+                        }
+                    }
+                    _ => { /* Nothing to do. */ }
+                }
+            }
+            _ => { /* Nothing to do. */ }
+        }
+
+        self.super_terminator_kind(block, kind);
+
+        fn is_drop_in_place_intrinsic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                                def_id: DefId,
+                                                bare_fn_ty: &ty::BareFnTy<'tcx>)
+                                                -> bool {
+            (bare_fn_ty.abi == Abi::RustIntrinsic ||
+             bare_fn_ty.abi == Abi::PlatformIntrinsic) &&
+            tcx.item_name(def_id).as_str() == "drop_in_place"
+        }
+    }
 }
 
 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>,
         ty::TyRef(..)   |
         ty::TyFnDef(..) |
         ty::TyFnPtr(_)  |
-        ty::TySlice(_)  |
         ty::TyTrait(_)  => {
             /* nothing to do */
         }
@@ -725,6 +767,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
             }
         }
         ty::TyBox(inner_type)      |
+        ty::TySlice(inner_type)    |
         ty::TyArray(inner_type, _) => {
             let inner_type = glue::get_drop_glue_type(scx.tcx(), inner_type);
             if glue::type_needs_drop(scx.tcx(), inner_type) {
@@ -746,6 +789,8 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
             bug!("encountered unexpected type");
         }
     }
+
+
 }
 
 fn do_static_dispatch<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
@@ -1187,7 +1232,7 @@ pub enum TransItemState {
 }
 
 pub fn collecting_debug_information(scx: &SharedCrateContext) -> bool {
-    return cfg!(debug_assertions) &&
+    return scx.sess().opts.cg.debug_assertions == Some(true) &&
            scx.sess().opts.debugging_opts.print_trans_items.is_some();
 }
 
diff --git a/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
new file mode 100644
index 00000000000..db940b68047
--- /dev/null
+++ b/src/test/codegen-units/item-collection/drop_in_place_intrinsic.rs
@@ -0,0 +1,41 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-tidy-linelength
+// compile-flags:-Zprint-trans-items=eager
+
+//~ TRANS_ITEM drop-glue drop_in_place_intrinsic::StructWithDtor[0]
+//~ TRANS_ITEM drop-glue-contents drop_in_place_intrinsic::StructWithDtor[0]
+struct StructWithDtor(u32);
+
+impl Drop for StructWithDtor {
+    //~ TRANS_ITEM fn drop_in_place_intrinsic::{{impl}}[0]::drop[0]
+    fn drop(&mut self) {}
+}
+
+//~ TRANS_ITEM fn drop_in_place_intrinsic::main[0]
+fn main() {
+
+    //~ TRANS_ITEM drop-glue [drop_in_place_intrinsic::StructWithDtor[0]; 2]
+    let x = [StructWithDtor(0), StructWithDtor(1)];
+
+    drop_slice_in_place(&x);
+}
+
+//~ TRANS_ITEM fn drop_in_place_intrinsic::drop_slice_in_place[0]
+fn drop_slice_in_place(x: &[StructWithDtor]) {
+    unsafe {
+        // This is the interesting thing in this test case: Normally we would
+        // not have drop-glue for the unsized [StructWithDtor]. This has to be
+        // generated though when the drop_in_place() intrinsic is used.
+        //~ TRANS_ITEM drop-glue [drop_in_place_intrinsic::StructWithDtor[0]]
+        ::std::ptr::drop_in_place(x as *const _ as *mut [StructWithDtor]);
+    }
+}