diff --git a/src/librustc/front/intrinsic.rs b/src/librustc/front/intrinsic.rs index fcb08180a5ea..f19e37062535 100644 --- a/src/librustc/front/intrinsic.rs +++ b/src/librustc/front/intrinsic.rs @@ -20,14 +20,22 @@ pub mod intrinsic { // version in sys is no longer present. pub fn get_tydesc() -> *TyDesc { unsafe { - rusti::get_tydesc::() as *TyDesc + rusti::get_tydesc::() } } + pub type GlueFn = extern "Rust" fn(**TyDesc, *i8); + + // NB: this has to be kept in sync with the Rust ABI. pub struct TyDesc { size: uint, - align: uint - // Remaining fields not listed + align: uint, + take_glue: GlueFn, + drop_glue: GlueFn, + free_glue: GlueFn, + visit_glue: GlueFn, + shape: *i8, + shape_tables: *i8 } pub enum Opaque { } @@ -133,7 +141,7 @@ pub mod intrinsic { #[abi = "rust-intrinsic"] pub extern "rust-intrinsic" { - pub fn get_tydesc() -> *(); + pub fn get_tydesc() -> *TyDesc; pub fn visit_tydesc(td: *TyDesc, tv: @TyVisitor); } } diff --git a/src/librustc/middle/trans/foreign.rs b/src/librustc/middle/trans/foreign.rs index 10e63e6af777..855610510bd9 100644 --- a/src/librustc/middle/trans/foreign.rs +++ b/src/librustc/middle/trans/foreign.rs @@ -681,9 +681,12 @@ pub fn trans_intrinsic(ccx: @mut CrateContext, let static_ti = get_tydesc(ccx, tp_ty); glue::lazily_emit_all_tydesc_glue(ccx, static_ti); - // FIXME (#3727): change this to ccx.tydesc_ty.ptr_to() when the - // core::sys copy of the get_tydesc interface dies off. - let td = PointerCast(bcx, static_ti.tydesc, Type::nil().ptr_to()); + // FIXME (#3730): ideally this shouldn't need a cast, + // but there's a circularity between translating rust types to llvm + // types and having a tydesc type available. So I can't directly access + // the llvm type of intrinsic::TyDesc struct. + let userland_tydesc_ty = type_of::type_of(ccx, output_type); + let td = PointerCast(bcx, static_ti.tydesc, userland_tydesc_ty); Store(bcx, td, fcx.llretptr.get()); } "init" => { diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index e9febb51005c..0930d3550353 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -789,7 +789,6 @@ pub fn emit_tydescs(ccx: &mut CrateContext) { }; } -fn type_of_glue_fn(ccx: &CrateContext) -> Type { - let tydescpp = ccx.tydesc_type.ptr_to().ptr_to(); - Type::func([ Type::nil().ptr_to(), tydescpp, Type::i8p() ], &Type::void()) +pub fn type_of_glue_fn(ccx: &CrateContext) -> Type { + Type::glue_fn(ccx.tydesc_type) } diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs index 34a150331091..764bdb026f47 100644 --- a/src/librustc/middle/trans/type_.rs +++ b/src/librustc/middle/trans/type_.rs @@ -189,18 +189,23 @@ impl Type { None => () } + // Bit of a kludge: pick the fn typeref out of the tydesc.. let ty = cx.tydesc_type.get_field(abi::tydesc_field_drop_glue); cx.tn.associate_type("glue_fn", &ty); return ty; } + pub fn glue_fn(tydesc: Type) -> Type { + let tydescpp = tydesc.ptr_to().ptr_to(); + Type::func([ Type::nil().ptr_to(), tydescpp, Type::i8p() ], + &Type::void()) + } + pub fn tydesc(arch: Architecture) -> Type { let mut tydesc = Type::named_struct("tydesc"); - let tydescpp = tydesc.ptr_to().ptr_to(); let pvoid = Type::i8p(); - let glue_fn_ty = Type::func([ Type::nil().ptr_to(), tydescpp, pvoid ], - &Type::void()).ptr_to(); + let glue_fn_ty = Type::glue_fn(tydesc).ptr_to(); let int_ty = Type::int(arch); diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index fa7959c7872b..4c074ce197ed 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3506,8 +3506,14 @@ pub fn check_intrinsic_type(ccx: @mut CrateCtxt, it: @ast::foreign_item) { } "get_tydesc" => { - // FIXME (#3730): return *intrinsic::tydesc, not *() - (1u, ~[], ty::mk_nil_ptr(ccx.tcx)) + let tydesc_name = special_idents::tydesc; + assert!(tcx.intrinsic_defs.contains_key(&tydesc_name)); + let (_, tydesc_ty) = tcx.intrinsic_defs.get_copy(&tydesc_name); + let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt { + ty: tydesc_ty, + mutbl: ast::m_imm + }); + (1u, ~[], td_ptr) } "visit_tydesc" => { let tydesc_name = special_idents::tydesc; diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs index c38b013a75aa..08fc90fa908c 100644 --- a/src/libstd/unstable/intrinsics.rs +++ b/src/libstd/unstable/intrinsics.rs @@ -209,6 +209,9 @@ pub extern "rust-intrinsic" { pub fn pref_align_of() -> uint; /// Get a static pointer to a type descriptor. + #[cfg(not(stage0))] + pub fn get_tydesc() -> *::intrinsic::TyDesc; + #[cfg(stage0)] pub fn get_tydesc() -> *(); /// Create a value initialized to zero.