about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2013-08-11 13:29:14 -0400
committerNiko Matsakis <niko@alum.mit.edu>2013-08-11 13:59:45 -0400
commit6fe59bf8776f8913aacfb00a2281c94a117b95d1 (patch)
treec149a22cd433599e96bd44250533351826888525
parent3aefb9649d15c16acef4eb465b06b598b3a1f179 (diff)
downloadrust-6fe59bf8776f8913aacfb00a2281c94a117b95d1.tar.gz
rust-6fe59bf8776f8913aacfb00a2281c94a117b95d1.zip
Add a field `borrow_offset` to the type descriptor indicating
what amount a T* pointer must be adjusted to reach the contents
of the box. For `~T` types, this requires knowing the type `T`,
which is not known in the case of objects.
-rw-r--r--src/librustc/back/abi.rs3
-rw-r--r--src/librustc/middle/trans/common.rs1
-rw-r--r--src/librustc/middle/trans/context.rs30
-rw-r--r--src/librustc/middle/trans/glue.rs27
-rw-r--r--src/librustc/middle/trans/type_.rs22
-rw-r--r--src/librustc/middle/ty.rs5
-rw-r--r--src/libstd/unstable/intrinsics.rs20
-rw-r--r--src/rt/rust_type.h1
-rw-r--r--src/rt/rust_util.cpp1
9 files changed, 94 insertions, 16 deletions
diff --git a/src/librustc/back/abi.rs b/src/librustc/back/abi.rs
index 05b6e90c682..dae0ceed22d 100644
--- a/src/librustc/back/abi.rs
+++ b/src/librustc/back/abi.rs
@@ -46,7 +46,8 @@ 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 n_tydesc_fields: uint = 6u;
+pub static tydesc_field_borrow_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/common.rs b/src/librustc/middle/trans/common.rs
index 40a83eb9770..61ec4b2fedb 100644
--- a/src/librustc/middle/trans/common.rs
+++ b/src/librustc/middle/trans/common.rs
@@ -54,6 +54,7 @@ pub struct tydesc_info {
     tydesc: ValueRef,
     size: ValueRef,
     align: ValueRef,
+    borrow_offset: ValueRef,
     take_glue: Option<ValueRef>,
     drop_glue: Option<ValueRef>,
     free_glue: Option<ValueRef>,
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index a644174731a..0a69f25c42c 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -236,6 +236,36 @@ impl CrateContext {
     pub fn builder(@mut self) -> Builder {
         Builder::new(self)
     }
+
+    pub fn const_inbounds_gepi(&self,
+                               pointer: ValueRef,
+                               indices: &[uint]) -> ValueRef {
+        debug!("const_inbounds_gepi: pointer=%s indices=%?",
+               self.tn.val_to_str(pointer), indices);
+        let v: ~[ValueRef] =
+            indices.iter().transform(|i| C_i32(*i as i32)).collect();
+        unsafe {
+            llvm::LLVMConstInBoundsGEP(pointer,
+                                       vec::raw::to_ptr(v),
+                                       indices.len() as c_uint)
+        }
+    }
+
+    pub fn offsetof_gep(&self,
+                        llptr_ty: Type,
+                        indices: &[uint]) -> ValueRef {
+        /*!
+         * Returns the offset of applying the given GEP indices
+         * to an instance of `llptr_ty`. Similar to `offsetof` in C,
+         * except that `llptr_ty` must be a pointer type.
+         */
+
+        unsafe {
+            let null = C_null(llptr_ty);
+            llvm::LLVMConstPtrToInt(self.const_inbounds_gepi(null, indices),
+                                    self.int_type.to_ref())
+        }
+    }
 }
 
 #[unsafe_destructor]
diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs
index a70b907f262..c65d8d31b74 100644
--- a/src/librustc/middle/trans/glue.rs
+++ b/src/librustc/middle/trans/glue.rs
@@ -655,6 +655,18 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
                   ppaux::ty_to_str(ccx.tcx, t));
     }
 
+    let has_header = match ty::get(t).sty {
+        ty::ty_box(*) => true,
+        ty::ty_uniq(*) => ty::type_contents(ccx.tcx, t).contains_managed(),
+        _ => false
+    };
+
+    let borrow_offset = if has_header {
+        ccx.offsetof_gep(llty, [0u, abi::box_field_body])
+    } else {
+        C_uint(ccx, 0)
+    };
+
     let llsize = llsize_of(ccx, llty);
     let llalign = llalign_of(ccx, llty);
     let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc").to_managed();
@@ -670,6 +682,7 @@ pub fn declare_tydesc(ccx: &mut CrateContext, t: ty::t) -> @mut tydesc_info {
         tydesc: gvar,
         size: llsize,
         align: llalign,
+        borrow_offset: borrow_offset,
         take_glue: None,
         drop_glue: None,
         free_glue: None,
@@ -785,13 +798,17 @@ pub fn emit_tydescs(ccx: &mut CrateContext) {
               }
             };
 
+        debug!("ti.borrow_offset: %s",
+               ccx.tn.val_to_str(ti.borrow_offset));
+
         let tydesc = C_named_struct(ccx.tydesc_type,
                                     [ti.size, // size
-                                    ti.align, // align
-                                    take_glue, // take_glue
-                                    drop_glue, // drop_glue
-                                    free_glue, // free_glue
-                                    visit_glue]); // visit_glue
+                                     ti.align, // align
+                                     take_glue, // take_glue
+                                     drop_glue, // drop_glue
+                                     free_glue, // free_glue
+                                     visit_glue, // visit_glue
+                                     ti.borrow_offset]); // borrow_offset
 
         unsafe {
             let gvar = ti.tydesc;
diff --git a/src/librustc/middle/trans/type_.rs b/src/librustc/middle/trans/type_.rs
index 110febfcc9f..8d94a0d10d6 100644
--- a/src/librustc/middle/trans/type_.rs
+++ b/src/librustc/middle/trans/type_.rs
@@ -205,10 +205,18 @@ impl Type {
 
         let int_ty = Type::int(arch);
 
-        let elems = [
-            int_ty, int_ty,
-            glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty
-        ];
+        // Must mirror:
+        //
+        // std::unstable::intrinsics::TyDesc
+        // type_desc in rt
+
+        let elems = [int_ty,     // size
+                     int_ty,     // align
+                     glue_fn_ty, // take
+                     glue_fn_ty, // drop
+                     glue_fn_ty, // free
+                     glue_fn_ty, // visit
+                     int_ty];    // borrow_offset
 
         tydesc.set_struct_body(elems, false);
 
@@ -249,8 +257,12 @@ impl Type {
         Type::struct_(Type::box_header_fields(ctx) + &[*ty], false)
     }
 
+    pub fn opaque() -> Type {
+        Type::i8()
+    }
+
     pub fn opaque_box(ctx: &CrateContext) -> Type {
-        Type::box(ctx, &Type::i8())
+        Type::box(ctx, &Type::opaque())
     }
 
     pub fn unique(ctx: &CrateContext, ty: &Type) -> Type {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 5685af2b74e..b91984f9b21 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -226,10 +226,7 @@ pub enum AutoRef {
     AutoBorrowFn(Region),
 
     /// Convert from T to *T
-    AutoUnsafe(ast::mutability),
-
-    /// Convert from @Trait/~Trait/&Trait to &Trait
-    AutoBorrowObj(Region, ast::mutability),
+    AutoUnsafe(ast::mutability)
 }
 
 pub type ctxt = @ctxt_;
diff --git a/src/libstd/unstable/intrinsics.rs b/src/libstd/unstable/intrinsics.rs
index c60edad3dbd..d2807303fb2 100644
--- a/src/libstd/unstable/intrinsics.rs
+++ b/src/libstd/unstable/intrinsics.rs
@@ -38,16 +38,34 @@ pub use realstd::unstable::intrinsics::{TyDesc, Opaque, TyVisitor};
 
 pub type GlueFn = extern "Rust" fn(*i8);
 
-// NB: this has to be kept in sync with the Rust ABI.
+// NB: this has to be kept in sync with `type_desc` in `rt`
 #[lang="ty_desc"]
 #[cfg(not(test))]
 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 drop glue when a value of type `T` can be freed
     free_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,
 }
 
 #[lang="opaque"]
diff --git a/src/rt/rust_type.h b/src/rt/rust_type.h
index 60ca5674b01..57538f1ec75 100644
--- a/src/rt/rust_type.h
+++ b/src/rt/rust_type.h
@@ -58,6 +58,7 @@ struct type_desc {
     glue_fn *drop_glue;
     glue_fn *free_glue;
     glue_fn *visit_glue;
+    size_t borrow_offset;
 };
 
 extern "C" type_desc *rust_clone_type_desc(type_desc*);
diff --git a/src/rt/rust_util.cpp b/src/rt/rust_util.cpp
index 4a15830e529..28c69af427a 100644
--- a/src/rt/rust_util.cpp
+++ b/src/rt/rust_util.cpp
@@ -21,6 +21,7 @@ struct type_desc str_body_tydesc = {
     NULL, // drop_glue
     NULL, // free_glue
     NULL, // visit_glue
+    0, // borrow_offset
 };
 
 //