Skip to content

Commit

Permalink
Add support for #[no_drop_flag] attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
James Miller authored and Aatch committed Jun 25, 2013
1 parent c6515ee commit 0cca08a
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/librustc/middle/trans/adt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
};
let packed = ty::lookup_packed(cx.tcx, def_id);
let dtor = ty::ty_dtor(cx.tcx, def_id).is_present();
let dtor = ty::ty_dtor(cx.tcx, def_id).has_drop_flag();
let ftys =
if dtor { ftys + [ty::mk_bool()] } else { ftys };
return Univariant(mk_struct(cx, ftys, packed), dtor)
Expand Down
57 changes: 49 additions & 8 deletions src/librustc/middle/trans/glue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -406,13 +406,8 @@ pub fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) {
build_return(bcx);
}

pub fn trans_struct_drop(bcx: block,
t: ty::t,
v0: ValueRef,
dtor_did: ast::def_id,
class_did: ast::def_id,
substs: &ty::substs)
-> block {
pub fn trans_struct_drop_flag(bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
class_did: ast::def_id, substs: &ty::substs) -> block {
let repr = adt::represent_type(bcx.ccx(), t);
let drop_flag = adt::trans_drop_flag_ptr(bcx, repr, v0);
do with_cond(bcx, IsNotNull(bcx, Load(bcx, drop_flag))) |cx| {
Expand Down Expand Up @@ -454,6 +449,49 @@ pub fn trans_struct_drop(bcx: block,
}
}

pub fn trans_struct_drop(mut bcx: block, t: ty::t, v0: ValueRef, dtor_did: ast::def_id,
class_did: ast::def_id, substs: &ty::substs) -> block {
let repr = adt::represent_type(bcx.ccx(), t);

// Find and call the actual destructor
let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did,
class_did, /*bad*/copy substs.tps);

// The second argument is the "self" argument for drop
let params = unsafe {
let ty = Type::from_ref(llvm::LLVMTypeOf(dtor_addr));
ty.element_type().func_params()
};

// Class dtors have no explicit args, so the params should
// just consist of the environment (self)
assert_eq!(params.len(), 1);

// Take a reference to the class (because it's using the Drop trait),
// do so now.
let llval = alloca(bcx, val_ty(v0));
Store(bcx, v0, llval);

let self_arg = PointerCast(bcx, llval, params[0]);
let args = ~[self_arg];

Call(bcx, dtor_addr, args);

// Drop the fields
let field_tys = ty::struct_fields(bcx.tcx(), class_did, substs);
for field_tys.iter().enumerate().advance |(i, fld)| {
let llfld_a = adt::trans_field_ptr(bcx, repr, v0, 0, i);
bcx = drop_ty(bcx, llfld_a, fld.mt.ty);
}

// Zero out the struct
unsafe {
let ty = Type::from_ref(llvm::LLVMTypeOf(v0));
memzero(bcx, v0, ty);
}

bcx
}

pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
// NB: v0 is an *alias* of type t here, not a direct value.
Expand All @@ -474,7 +512,10 @@ pub fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) {
ty::ty_struct(did, ref substs) => {
let tcx = bcx.tcx();
match ty::ty_dtor(tcx, did) {
ty::TraitDtor(dtor) => {
ty::TraitDtor(dtor, true) => {
trans_struct_drop_flag(bcx, t, v0, dtor, did, substs)
}
ty::TraitDtor(dtor, false) => {
trans_struct_drop(bcx, t, v0, dtor, did, substs)
}
ty::NoDtor => {
Expand Down
15 changes: 13 additions & 2 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3855,7 +3855,7 @@ pub fn item_path_str(cx: ctxt, id: ast::def_id) -> ~str {

pub enum DtorKind {
NoDtor,
TraitDtor(def_id)
TraitDtor(def_id, bool)
}

impl DtorKind {
Expand All @@ -3869,13 +3869,24 @@ impl DtorKind {
pub fn is_present(&const self) -> bool {
!self.is_not_present()
}

pub fn has_drop_flag(&self) -> bool {
match self {
&NoDtor => false,
&TraitDtor(_, flag) => flag
}
}
}

/* If struct_id names a struct with a dtor, return Some(the dtor's id).
Otherwise return none. */
pub fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
match cx.destructor_for_type.find(&struct_id) {
Some(&method_def_id) => TraitDtor(method_def_id),
Some(&method_def_id) => {
let flag = has_attr(cx, struct_id, "no_drop_flag");

TraitDtor(method_def_id, flag)
}
None => NoDtor,
}
}
Expand Down

0 comments on commit 0cca08a

Please sign in to comment.