diff --git a/src/librustc/back/abi.rs b/src/librustc/back/abi.rs index 2d5a4b4edb7..945ee645414 100644 --- a/src/librustc/back/abi.rs +++ b/src/librustc/back/abi.rs @@ -44,11 +44,10 @@ pub static tydesc_field_size: uint = 0u; pub static tydesc_field_align: uint = 1u; pub static tydesc_field_take_glue: uint = 2u; pub static tydesc_field_drop_glue: uint = 3u; -pub static tydesc_field_free_glue: uint = 4u; -pub static tydesc_field_visit_glue: uint = 5u; -pub static tydesc_field_borrow_offset: uint = 6u; -pub static tydesc_field_name_offset: uint = 7u; -pub static n_tydesc_fields: uint = 8u; +pub static tydesc_field_visit_glue: uint = 4u; +pub static tydesc_field_borrow_offset: uint = 5u; +pub static tydesc_field_name_offset: uint = 6u; +pub static n_tydesc_fields: uint = 7u; // The two halves of a closure: code and environment. pub static fn_field_code: uint = 0u; diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs index 5a9d7b0a283..2cb3f8bcfac 100644 --- a/src/librustc/middle/trans/closure.rs +++ b/src/librustc/middle/trans/closure.rs @@ -474,7 +474,7 @@ pub fn make_opaque_cbox_drop_glue<'a>( bcx.tcx().sess.bug("trying to trans drop glue of @fn") } ast::OwnedSigil => { - glue::free_ty( + glue::make_free_glue( bcx, cboxptr, ty::mk_opaque_closure_ptr(bcx.tcx(), sigil)) } diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 8636a87819c..b31c03eb184 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -94,7 +94,6 @@ pub struct tydesc_info { name: ValueRef, take_glue: Cell>, drop_glue: Cell>, - free_glue: Cell>, visit_glue: Cell>, } diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 5a7a2ba7ffd..3063fbcecaf 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -23,13 +23,13 @@ use middle::trans::base::*; use middle::trans::callee; use middle::trans::closure; use middle::trans::common::*; +use middle::trans::datum::immediate_rvalue; use middle::trans::build::*; use middle::trans::expr; use middle::trans::machine::*; use middle::trans::reflect; use middle::trans::tvec; use middle::trans::type_of::type_of; -use middle::trans::uniq; use middle::ty; use util::ppaux; use util::ppaux::ty_to_short_str; @@ -86,47 +86,16 @@ pub fn drop_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) drop_ty(bcx, vp, t) } -pub fn free_ty<'a>(cx: &'a Block<'a>, v: ValueRef, t: ty::t) - -> &'a Block<'a> { - // NB: v is an *alias* of type t here, not a direct value. - let _icx = push_ctxt("free_ty"); - if ty::type_needs_drop(cx.tcx(), t) { - return call_tydesc_glue(cx, v, t, abi::tydesc_field_free_glue); - } - return cx; -} - -pub fn free_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) - -> &'a Block<'a> { - let _icx = push_ctxt("free_ty_immediate"); - match ty::get(t).sty { - ty::ty_uniq(_) | - ty::ty_vec(_, ty::vstore_uniq) | - ty::ty_str(ty::vstore_uniq) | - ty::ty_box(_) | ty::ty_opaque_box | - ty::ty_vec(_, ty::vstore_box) | - ty::ty_str(ty::vstore_box) | - ty::ty_opaque_closure_ptr(_) => { - let vp = alloca(bcx, type_of(bcx.ccx(), t), ""); - Store(bcx, v, vp); - free_ty(bcx, vp, t) - } - _ => bcx.tcx().sess.bug("free_ty_immediate: non-box ty") - } -} - pub fn lazily_emit_all_tydesc_glue(ccx: @CrateContext, static_ti: @tydesc_info) { lazily_emit_tydesc_glue(ccx, abi::tydesc_field_take_glue, static_ti); lazily_emit_tydesc_glue(ccx, abi::tydesc_field_drop_glue, static_ti); - lazily_emit_tydesc_glue(ccx, abi::tydesc_field_free_glue, static_ti); lazily_emit_tydesc_glue(ccx, abi::tydesc_field_visit_glue, static_ti); } pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t { if (field == abi::tydesc_field_take_glue || - field == abi::tydesc_field_drop_glue || - field == abi::tydesc_field_free_glue) && + field == abi::tydesc_field_drop_glue) && ! ty::type_needs_drop(tcx, t) { return ty::mk_u32(); } @@ -146,22 +115,7 @@ pub fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t { return ty::mk_imm_box(tcx, ty::mk_u32()); } - if field == abi::tydesc_field_free_glue { - match ty::get(t).sty { - ty::ty_bare_fn(..) | - ty::ty_closure(..) | - ty::ty_box(..) | - ty::ty_opaque_box | - ty::ty_uniq(..) | - ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) | - ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) | - ty::ty_opaque_closure_ptr(..) => (), - _ => { return ty::mk_u32(); } - } - } - - if (field == abi::tydesc_field_free_glue || - field == abi::tydesc_field_drop_glue) { + if field == abi::tydesc_field_drop_glue { match ty::get(t).sty { ty::ty_box(typ) if ! ty::type_needs_drop(tcx, typ) => @@ -197,8 +151,6 @@ pub fn lazily_emit_simplified_tydesc_glue(ccx: @CrateContext, ti.take_glue.set(simpl_ti.take_glue.get()); } else if field == abi::tydesc_field_drop_glue { ti.drop_glue.set(simpl_ti.drop_glue.get()); - } else if field == abi::tydesc_field_free_glue { - ti.free_glue.set(simpl_ti.free_glue.get()); } else if field == abi::tydesc_field_visit_glue { ti.visit_glue.set(simpl_ti.visit_glue.get()); } @@ -245,19 +197,6 @@ pub fn lazily_emit_tydesc_glue(ccx: @CrateContext, ppaux::ty_to_str(ccx.tcx, ti.ty)); } } - } else if field == abi::tydesc_field_free_glue { - match ti.free_glue.get() { - Some(_) => (), - None => { - debug!("+++ lazily_emit_tydesc_glue FREE {}", - ppaux::ty_to_str(ccx.tcx, ti.ty)); - let glue_fn = declare_generic_glue(ccx, ti.ty, llfnty, "free"); - ti.free_glue.set(Some(glue_fn)); - make_generic_glue(ccx, ti.ty, glue_fn, make_free_glue, "free"); - debug!("--- lazily_emit_tydesc_glue FREE {}", - ppaux::ty_to_str(ccx.tcx, ti.ty)); - } - } } else if field == abi::tydesc_field_visit_glue { match ti.visit_glue.get() { Some(_) => (), @@ -294,8 +233,6 @@ pub fn call_tydesc_glue_full(bcx: &Block, sti.take_glue.get() } else if field == abi::tydesc_field_drop_glue { sti.drop_glue.get() - } else if field == abi::tydesc_field_free_glue { - sti.free_glue.get() } else if field == abi::tydesc_field_visit_glue { sti.visit_glue.get() } else { @@ -346,8 +283,8 @@ pub fn call_tydesc_glue<'a>( return cx; } -pub fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) - -> &'a Block<'a> { +fn make_visit_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) + -> &'a Block<'a> { let _icx = push_ctxt("make_visit_glue"); with_scope(bcx, None, "visitor cleanup", |bcx| { let mut bcx = bcx; @@ -371,31 +308,32 @@ pub fn make_free_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) // NB: v0 is an *alias* of type t here, not a direct value. let _icx = push_ctxt("make_free_glue"); match ty::get(t).sty { + ty::ty_opaque_box => bcx.tcx().sess.fatal("found ty_opaque_box in make_free_glue"), ty::ty_box(body_ty) => { let v = Load(bcx, v); let body = GEPi(bcx, v, [0u, abi::box_field_body]); let bcx = drop_ty(bcx, body, body_ty); trans_free(bcx, v) } - ty::ty_opaque_box => { - let v = Load(bcx, v); - let td = Load(bcx, GEPi(bcx, v, [0u, abi::box_field_tydesc])); - let valptr = GEPi(bcx, v, [0u, abi::box_field_body]); - // Generate code that, dynamically, indexes into the - // tydesc and calls the drop glue that got set dynamically - call_tydesc_glue_full(bcx, valptr, td, abi::tydesc_field_drop_glue, - None); - trans_free(bcx, v) - } ty::ty_uniq(..) => { - uniq::make_free_glue(bcx, v, t) + let box_datum = immediate_rvalue(Load(bcx, v), t); + let not_null = IsNotNull(bcx, box_datum.val); + with_cond(bcx, not_null, |bcx| { + let body_datum = box_datum.box_body(bcx); + let bcx = drop_ty(bcx, body_datum.to_ref_llval(bcx), body_datum.ty); + if ty::type_contents(bcx.tcx(), t).owns_managed() { + trans_free(bcx, box_datum.val) + } else { + trans_exchange_free(bcx, box_datum.val) + } + }) } ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) | ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => { make_free_glue(bcx, v, tvec::expand_boxed_vec_ty(bcx.tcx(), t)) } ty::ty_closure(_) => { - closure::make_closure_glue(bcx, v, t, free_ty) + closure::make_closure_glue(bcx, v, t, make_free_glue) } ty::ty_opaque_closure_ptr(ck) => { closure::make_opaque_cbox_free_glue(bcx, ck, v) @@ -469,13 +407,14 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) let _icx = push_ctxt("make_drop_glue"); let ccx = bcx.ccx(); match ty::get(t).sty { - ty::ty_box(_) | ty::ty_opaque_box | + ty::ty_opaque_box => bcx.tcx().sess.fatal("found ty_opaque_box in make_drop_glue"), + ty::ty_box(_) | ty::ty_str(ty::vstore_box) | ty::ty_vec(_, ty::vstore_box) => { - decr_refcnt_maybe_free(bcx, Load(bcx, v0), Some(v0), t) + decr_refcnt_maybe_free(bcx, v0, Some(t)) } ty::ty_uniq(_) | ty::ty_vec(_, ty::vstore_uniq) | ty::ty_str(ty::vstore_uniq) => { - free_ty(bcx, v0, t) + make_free_glue(bcx, v0, t) } ty::ty_unboxed_vec(_) => { tvec::make_drop_glue_unboxed(bcx, v0, t) @@ -500,9 +439,7 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) } ty::ty_trait(_, _, ty::BoxTraitStore, _, _) => { let llbox_ptr = GEPi(bcx, v0, [0u, abi::trt_field_box]); - let llbox = Load(bcx, llbox_ptr); - decr_refcnt_maybe_free(bcx, llbox, Some(llbox_ptr), - ty::mk_opaque_box(ccx.tcx)) + decr_refcnt_maybe_free(bcx, llbox_ptr, None) } ty::ty_trait(_, _, ty::UniqTraitStore, _, _) => { let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]); @@ -517,7 +454,7 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) call_tydesc_glue_full(bcx, lluniquevalue, lltydesc, - abi::tydesc_field_free_glue, + abi::tydesc_field_drop_glue, None); bcx }) @@ -534,44 +471,46 @@ pub fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) } } -// box_ptr_ptr is optional, it is constructed if not supplied. -pub fn decr_refcnt_maybe_free<'a>( - bcx: &'a Block<'a>, - box_ptr: ValueRef, - box_ptr_ptr: Option, - t: ty::t) - -> &'a Block<'a> { +fn decr_refcnt_maybe_free<'a>(bcx: &'a Block<'a>, box_ptr_ptr: ValueRef, + t: Option) -> &'a Block<'a> { let _icx = push_ctxt("decr_refcnt_maybe_free"); let ccx = bcx.ccx(); let decr_bcx = sub_block(bcx, "decr"); let free_bcx = sub_block(decr_bcx, "free"); let next_bcx = sub_block(bcx, "next"); + let box_ptr = Load(bcx, box_ptr_ptr); let llnotnull = IsNotNull(bcx, box_ptr); CondBr(bcx, llnotnull, decr_bcx.llbb, next_bcx.llbb); let rc_ptr = GEPi(decr_bcx, box_ptr, [0u, abi::box_field_refcnt]); let rc = Sub(decr_bcx, Load(decr_bcx, rc_ptr), C_int(ccx, 1)); Store(decr_bcx, rc, rc_ptr); - let llisnull = IsNull(decr_bcx, rc); - CondBr(decr_bcx, llisnull, free_bcx.llbb, next_bcx.llbb); + CondBr(decr_bcx, IsNull(decr_bcx, rc), free_bcx.llbb, next_bcx.llbb); - let free_bcx = match box_ptr_ptr { - Some(p) => free_ty(free_bcx, p, t), - None => free_ty_immediate(free_bcx, box_ptr, t) + let free_bcx = match t { + Some(t) => make_free_glue(free_bcx, box_ptr_ptr, t), + None => { + let v = Load(free_bcx, box_ptr_ptr); + let td = Load(free_bcx, GEPi(free_bcx, v, [0u, abi::box_field_tydesc])); + let valptr = GEPi(free_bcx, v, [0u, abi::box_field_body]); + // Generate code that, dynamically, indexes into the + // tydesc and calls the drop glue that got set dynamically + call_tydesc_glue_full(free_bcx, valptr, td, abi::tydesc_field_drop_glue, None); + trans_free(free_bcx, v) + } }; Br(free_bcx, next_bcx.llbb); next_bcx } - -pub fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) - -> &'a Block<'a> { +fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) -> &'a Block<'a> { let _icx = push_ctxt("make_take_glue"); // NB: v is a *pointer* to type t here, not a direct value. match ty::get(t).sty { - ty::ty_box(_) | ty::ty_opaque_box | + ty::ty_opaque_box => bcx.tcx().sess.fatal("found ty_opaque_box in make_take_glue"), + ty::ty_box(_) | ty::ty_vec(_, ty::vstore_box) | ty::ty_str(ty::vstore_box) => { incr_refcnt_of_boxed(bcx, Load(bcx, v)); bcx } @@ -608,7 +547,7 @@ pub fn make_take_glue<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) } } -pub fn incr_refcnt_of_boxed(cx: &Block, box_ptr: ValueRef) { +fn incr_refcnt_of_boxed(cx: &Block, box_ptr: ValueRef) { let _icx = push_ctxt("incr_refcnt_of_boxed"); let ccx = cx.ccx(); let rc_ptr = GEPi(cx, box_ptr, [0u, abi::box_field_refcnt]); @@ -665,7 +604,6 @@ pub fn declare_tydesc(ccx: &CrateContext, t: ty::t) -> @tydesc_info { name: ty_name, take_glue: Cell::new(None), drop_glue: Cell::new(None), - free_glue: Cell::new(None), visit_glue: Cell::new(None), }; debug!("--- declare_tydesc {}", ppaux::ty_to_str(ccx.tcx, t)); @@ -770,21 +708,6 @@ pub fn emit_tydescs(ccx: &CrateContext) { } } }; - let free_glue = - match ti.free_glue.get() { - None => { - ccx.stats.n_null_glues.set(ccx.stats.n_null_glues.get() + - 1u); - C_null(glue_fn_ty) - } - Some(v) => { - unsafe { - ccx.stats.n_real_glues.set(ccx.stats.n_real_glues.get() + - 1); - llvm::LLVMConstPointerCast(v, glue_fn_ty.to_ref()) - } - } - }; let visit_glue = match ti.visit_glue.get() { None => { @@ -808,7 +731,6 @@ pub fn emit_tydescs(ccx: &CrateContext) { ti.align, // align take_glue, // take_glue drop_glue, // drop_glue - free_glue, // free_glue visit_glue, // visit_glue ti.borrow_offset, // borrow_offset ti.name]); // name diff --git a/src/librustc/middle/trans/mod.rs b/src/librustc/middle/trans/mod.rs index f55360213c6..e534e087cb8 100644 --- a/src/librustc/middle/trans/mod.rs +++ b/src/librustc/middle/trans/mod.rs @@ -25,7 +25,6 @@ pub mod build; pub mod builder; pub mod base; pub mod _match; -pub mod uniq; pub mod closure; pub mod tvec; pub mod meth; diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs index e2338c1ad81..d4ba4a76f81 100644 --- a/src/librustc/middle/trans/type_.rs +++ b/src/librustc/middle/trans/type_.rs @@ -219,7 +219,6 @@ impl Type { int_ty, // align glue_fn_ty, // take glue_fn_ty, // drop - glue_fn_ty, // free glue_fn_ty, // visit int_ty, // borrow_offset Type::struct_([Type::i8p(), Type::int(arch)], false)]; // name diff --git a/src/librustc/middle/trans/uniq.rs b/src/librustc/middle/trans/uniq.rs deleted file mode 100644 index 91ac5f9f3b4..00000000000 --- a/src/librustc/middle/trans/uniq.rs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2012 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -use lib::llvm::ValueRef; -use middle::trans::base::*; -use middle::trans::build::*; -use middle::trans::common::*; -use middle::trans::datum::immediate_rvalue; -use middle::trans::glue; -use middle::ty; - -pub fn make_free_glue<'a>( - bcx: &'a Block<'a>, - vptrptr: ValueRef, - box_ty: ty::t) - -> &'a Block<'a> { - let _icx = push_ctxt("uniq::make_free_glue"); - let box_datum = immediate_rvalue(Load(bcx, vptrptr), box_ty); - - let not_null = IsNotNull(bcx, box_datum.val); - with_cond(bcx, not_null, |bcx| { - let body_datum = box_datum.box_body(bcx); - let bcx = glue::drop_ty(bcx, body_datum.to_ref_llval(bcx), - body_datum.ty); - if ty::type_contents(bcx.tcx(), box_ty).owns_managed() { - glue::trans_free(bcx, box_datum.val) - } else { - glue::trans_exchange_free(bcx, box_datum.val) - } - }) -} diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index d6b33fda745..acd1cfcf901 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -47,9 +47,9 @@ pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor, TypeId}; pub type GlueFn = extern "Rust" fn(*i8); -// NB: this has to be kept in sync with `type_desc` in `rt` +// NOTE remove after next snapshot #[lang="ty_desc"] -#[cfg(not(test))] +#[cfg(not(test), stage0)] pub struct TyDesc { // sizeof(T) size: uint, @@ -80,6 +80,35 @@ pub struct TyDesc { name: &'static str } +#[lang="ty_desc"] +#[cfg(not(test), not(stage0))] +pub struct TyDesc { + // sizeof(T) + size: uint, + + // alignof(T) + align: uint, + + // Called on a copy of a value of type `T` *after* memcpy + take_glue: GlueFn, + + // Called when a value of type `T` is no longer needed + drop_glue: GlueFn, + + // Called by reflection visitor to visit a value of type `T` + visit_glue: GlueFn, + + // If T represents a box pointer (`@U` or `~U`), then + // `borrow_offset` is the amount that the pointer must be adjusted + // to find the payload. This is always derivable from the type + // `U`, but in the case of `@Trait` or `~Trait` objects, the type + // `U` is unknown. + borrow_offset: uint, + + // Name corresponding to the type + name: &'static str +} + #[lang="opaque"] #[cfg(not(test))] pub enum Opaque { }