about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2014-01-01 14:45:31 +0200
committerEduard Burtescu <edy.burt@gmail.com>2014-01-11 16:40:23 +0200
commit7a305f9e832901018e5f1aa1901eff04652fdbbd (patch)
tree3ccab1847d0885f6e661a57b58b9a1c64e695148
parent5ad2a7825bd9821b8ef554046c8d81eb94ab7dfe (diff)
downloadrust-7a305f9e832901018e5f1aa1901eff04652fdbbd.tar.gz
rust-7a305f9e832901018e5f1aa1901eff04652fdbbd.zip
Removed free_glue from tydesc (the code is still generated, but inlined in drop_glue).
-rw-r--r--src/librustc/back/abi.rs9
-rw-r--r--src/librustc/middle/trans/closure.rs2
-rw-r--r--src/librustc/middle/trans/common.rs1
-rw-r--r--src/librustc/middle/trans/glue.rs166
-rw-r--r--src/librustc/middle/trans/mod.rs1
-rw-r--r--src/librustc/middle/trans/type_.rs1
-rw-r--r--src/librustc/middle/trans/uniq.rs39
-rw-r--r--src/libstd/unstable/intrinsics.rs33
8 files changed, 80 insertions, 172 deletions
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<Option<ValueRef>>,
     drop_glue: Cell<Option<ValueRef>>,
-    free_glue: Cell<Option<ValueRef>>,
     visit_glue: Cell<Option<ValueRef>>,
 }
 
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<ValueRef>,
-                              t: ty::t)
-                              -> &'a Block<'a> {
+fn decr_refcnt_maybe_free<'a>(bcx: &'a Block<'a>, box_ptr_ptr: ValueRef,
+                              t: Option<ty::t>) -> &'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);
-
-    let free_bcx = match box_ptr_ptr {
-        Some(p) => free_ty(free_bcx, p, t),
-        None => free_ty_immediate(free_bcx, box_ptr, t)
+    CondBr(decr_bcx, IsNull(decr_bcx, rc), free_bcx.llbb, next_bcx.llbb);
+
+    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 <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.
-
-
-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 { }