Add support for #[no_drop_flag] attribute

This commit is contained in:
James Miller 2013-06-23 14:41:45 +12:00 committed by James Miller
parent c6515ee6a7
commit 0cca08a21a
3 changed files with 63 additions and 11 deletions

View file

@ -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)

View file

@ -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| {
@ -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.
@ -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 => {

View file

@ -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 {
@ -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,
}
}