about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-01-05 12:05:22 -0800
committerNiko Matsakis <niko@alum.mit.edu>2012-01-06 22:40:31 -0800
commit7db640e63d36a1c812295e88a3d059ce5c70115d (patch)
treebf85cee1c084d5d8426a476ab2dfbc76c0cc05b9
parent4f52e5a5ecfb0ec47f3c225f0f0f90adc12c0335 (diff)
downloadrust-7db640e63d36a1c812295e88a3d059ce5c70115d.tar.gz
rust-7db640e63d36a1c812295e88a3d059ce5c70115d.zip
collapse sizeof, alignof into metrics, pass along an instance if avail
-rw-r--r--src/comp/middle/trans.rs110
-rw-r--r--src/comp/middle/trans_uniq.rs5
-rw-r--r--src/comp/middle/ty.rs10
3 files changed, 78 insertions, 47 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index e5abe49f8ed..03adeb6843d 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -414,14 +414,26 @@ fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
                                False);
 }
 
-fn size_of(cx: @block_ctxt, t: ty::t) -> result {
-    let {bcx, sz, align} = metrics(cx, t, none);
-    rslt(bcx, align)
+fn size_of(bcx: @block_ctxt, t: ty::t) -> result {
+    assert !ty::type_has_opaque_size(bcx_tcx(bcx), t);
+    let {bcx, sz, align: _} = metrics(bcx, t, none);
+    rslt(bcx, sz)
 }
 
-fn align_of(cx: @block_ctxt, t: ty::t) -> result {
-    let {bcx, sz, align} = metrics(cx, t, none);
-    rslt(bcx, align)
+fn align_of(bcx: @block_ctxt, t: ty::t) -> result {
+    assert !ty::type_has_opaque_size(bcx_tcx(bcx), t);
+    alt ty::struct(ccx.tcx, t) {
+      ty::ty_opaque_closure. {
+        // Hack: the alignment of an opaque closure is always defined as the
+        // alignment of a pointer.  This is not, however, strictly correct,
+        // depending on your point of view.  
+        llalign_of(bcx, T_ptr(T_i8()));
+      }
+      _ {
+        let {bcx, sz: _, align} = metrics(bcx, t, none);
+        rslt(bcx, align)
+      }
+    }
 }
 
 // Computes the size/alignment of the type `t`.  `opt_v`, if provided, should
@@ -431,11 +443,13 @@ fn align_of(cx: @block_ctxt, t: ty::t) -> result {
 // instance is required.
 fn metrics(bcx: @block_ctxt, t: ty::t, opt_v: option<ValueRef>)
     -> metrics_result {
-    let ccx = bcx_ccx(cx);
+    assert (option::is_some(opt_v) ||
+            !ty::type_has_opaque_size(bcx_tcx(bcx), t));
+    let ccx = bcx_ccx(bcx);
     if check type_has_static_size(ccx, t) {
-        let sp = cx.sp;
-        let sz = llsize_of(bcx_ccx(cx), type_of(ccx, sp, t));
-        let align = llalign_of(bcx_ccx(cx), type_of(ccx, sp, t));
+        let sp = bcx.sp;
+        let sz = llsize_of(bcx_ccx(bcx), type_of(ccx, sp, t));
+        let align = llalign_of(bcx_ccx(bcx), type_of(ccx, sp, t));
         ret {bcx: bcx, sz: sz, align: align};
     } else {
         ret dynamic_metrics(bcx, t, opt_v);
@@ -552,11 +566,11 @@ type metrics_result = {
 };
 
 fn dynamic_metrics(bcx: @block_ctxt,
-                   elts: [ty::t],
-                   opts_v: option<ValueRef>) -> metrics_result {
-    fn compute_elements_metrics(bcx: @block_ctxt,
-                                elts: [ty::t],
-                                opt_v: option<ValueRef>) -> metrics_result {
+                   t: ty::t,
+                   opt_v: option<ValueRef>) -> metrics_result {
+    fn c_struct_metrics(bcx: @block_ctxt,
+                        elts: [ty::t],
+                        opt_v: option<ValueRef>) -> metrics_result {
         //
         // C padding rules:
         //
@@ -570,40 +584,40 @@ fn dynamic_metrics(bcx: @block_ctxt,
         let max_align = C_int(bcx_ccx(bcx), 1);
         for e: ty::t in elts {
             let opt_ev = option::map(opt_v) {|v| ptr_offs(bcx, v, off) };
-            let elt_align = align_of(bcx, e, opt_ev);
-            bcx = elt_align.bcx;
-            let elt_size = size_of(bcx, e, opt_ev);
-            bcx = elt_size.bcx;
-            let aligned_off = align_to(bcx, off, elt_align.val);
-            off = Add(bcx, aligned_off, elt_size.val);
-            max_align = umax(bcx, max_align, elt_align.val);
+            let elt_metrics = metrics(bcx, e, opt_ev);
+            bcx = elt_metrics.bcx;
+            let aligned_off = align_to(bcx, off, elt_metrics.align);
+            off = Add(bcx, aligned_off, elt_metrics.sz);
+            max_align = umax(bcx, max_align, elt_metrics.align);
         }
+        off = align_to(bcx, off, max_align);
         ret { bcx: bcx, sz: off, align: max_align };
     }
 
     alt ty::struct(bcx_tcx(bcx), t) {
       ty::ty_param(p, _) {
-        let {bcx, value: szptr} =
-            field_of_tydesc(bcx, t, false, abi::tydesc_field_size);
-        let {bcx, value: aptr} =
-            field_of_tydesc(bcx, t, false, abi::tydesc_field_align);
-        ret { bcx: bcx, sz: Load(szptr), align: Load(align) };
+        let ti = none::<@tydesc_info>;
+        let {bcx, val: tydesc} =
+            get_tydesc(bcx, t, false, tps_normal, ti).result;
+        let sz = Load(bcx, GEPi(bcx, tydesc, [0, abi::tydesc_field_size]));
+        let al = Load(bcx, GEPi(bcx, tydesc, [0, abi::tydesc_field_align]));
+        ret { bcx: bcx, sz: sz, align: al };
       }
       ty::ty_rec(flds) {
         let tys: [ty::t] = [];
         for f: ty::field in flds { tys += [f.mt.ty]; }
-        ret compute_elements_metrics(bcx, tys, opt_v);
+        ret c_struct_metrics(bcx, tys, opt_v);
       }
       ty::ty_tup(elts) {
         let tys = [];
         for tp in elts { tys += [tp]; }
-        ret compute_elements_metrics(bcx, tys, opt_v);
+        ret c_struct_metrics(bcx, tys, opt_v);
       }
       ty::ty_tag(tid, tps) {
         let bcx = bcx;
         let ccx = bcx_ccx(bcx);
-        // Compute max(variant sizes) and max(variant alignments).
 
+        // Compute max(variant sizes) and max(variant alignments).
         let max_size: ValueRef = alloca(bcx, ccx.int_type);
         Store(bcx, C_int(ccx, 0), max_size);
         let variants = ty::tag_variants(bcx_tcx(bcx), tid);
@@ -616,9 +630,16 @@ fn dynamic_metrics(bcx: @block_ctxt,
                 let t = ty::substitute_type_params(bcx_tcx(bcx), tps, raw_ty);
                 tys += [t];
             }
-            let rslt = align_elements(bcx, tys, opt_v);
+
+            // Note: we do not pass in opt_v here for the value but rather
+            // none.  The reason is that what we would want to pass in is a
+            // ptr to the blob data of the tag, but this is impossible until
+            // we know the size/alignment of the blob data.  Therefore, it is
+            // not legal to have a tag type that contains an interior opaque
+            // type.  Fortunately this will never happen.
+            let rslt = c_struct_metrics(bcx, tys, none);
             bcx = rslt.bcx;
-            let this_size = rslt.val;
+            let this_size = rslt.sz;
             let old_max_size = Load(bcx, max_size);
             Store(bcx, umax(bcx, this_size, old_max_size), max_size);
         }
@@ -651,7 +672,7 @@ fn dynamic_metrics(bcx: @block_ctxt,
         let tdptr = Load(bcx, tdptrptr);
         let sz = Load(bcx, GEPi(bcx, tdptr, [0, abi::tydesc_field_size]));
         let align = Load(bcx, GEPi(bcx, tdptr, [0, abi::tydesc_field_align]));
-        ret { bcx: bcx, sz: sz, align: sz };
+        ret { bcx: bcx, sz: sz, align: align };
       }
     }
 }
@@ -661,7 +682,7 @@ fn dynamic_metrics(bcx: @block_ctxt,
 // return type, use bump_ptr().
 fn ptr_offs(bcx: @block_ctxt, base: ValueRef, sz: ValueRef) -> ValueRef {
     let raw = PointerCast(bcx, base, T_ptr(T_i8()));
-    GEP(bcx, raw, [sz]);
+    GEP(bcx, raw, [sz])
 }
 
 // Increment a pointer by a given amount and then cast it to be a pointer
@@ -760,7 +781,7 @@ fn GEP_tup_like(bcx: @block_ctxt, t: ty::t, base: ValueRef, ixs: [int])
     let args = [];
     for typ: ty::t in s.prefix { args += [typ]; }
     let prefix_ty = ty::mk_tup(bcx_tcx(bcx), args);
-    let {bcx, val: prefix_sz} = size_of(bcx, prefix_ty);
+    let {bcx, sz: prefix_sz, align: _} = metrics(bcx, prefix_ty, some(base));
     let {bcx, val: align} = align_of(bcx, s.target);
     let sz = align_to(bcx, prefix_sz, align);
     ret rslt(bcx, bump_ptr(bcx, s.target, base, sz));
@@ -898,7 +919,6 @@ fn field_of_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool, field: int) ->
              GEPi(tydesc.bcx, tydesc.val, [0, field]));
 }
 
-
 // Given a type containing ty params, build a vector containing a ValueRef for
 // each of the ty params it uses (from the current frame) and a vector of the
 // indices of the ty params present in the type. This is used solely for
@@ -2003,21 +2023,21 @@ fn call_bzero(cx: @block_ctxt, dst: ValueRef, n_bytes: ValueRef,
              Call(cx, memset, [dst_ptr, C_u8(0u), size, align, volatile]));
 }
 
-fn memmove_ty(cx: @block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t) ->
+fn memmove_ty(bcx: @block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t) ->
     @block_ctxt {
-    let ccx = bcx_ccx(cx);
+    let ccx = bcx_ccx(bcx);
     if check type_has_static_size(ccx, t) {
-        if ty::type_is_structural(bcx_tcx(cx), t) {
-            let sp = cx.sp;
+        if ty::type_is_structural(bcx_tcx(bcx), t) {
+            let sp = bcx.sp;
             let llsz = llsize_of(ccx, type_of(ccx, sp, t));
-            ret call_memmove(cx, dst, src, llsz).bcx;
+            ret call_memmove(bcx, dst, src, llsz).bcx;
         }
-        Store(cx, Load(cx, src), dst);
-        ret cx;
+        Store(bcx, Load(bcx, src), dst);
+        ret bcx;
     }
 
-    let llsz = size_of(cx, t);
-    ret call_memmove(llsz.bcx, dst, src, llsz.val).bcx;
+    let {bcx, sz: llsz, align: _} = metrics(bcx, t, some(src));
+    ret call_memmove(bcx, dst, src, llsz).bcx;
 }
 
 tag copy_action { INIT; DROP_EXISTING; }
diff --git a/src/comp/middle/trans_uniq.rs b/src/comp/middle/trans_uniq.rs
index 2b97f7b3255..a7b6f58d393 100644
--- a/src/comp/middle/trans_uniq.rs
+++ b/src/comp/middle/trans_uniq.rs
@@ -5,6 +5,7 @@ import trans_build::*;
 import trans::{
     trans_shared_malloc,
     type_of_inner,
+    metrics,
     size_of,
     node_id_type,
     INIT,
@@ -39,7 +40,7 @@ fn alloc_uniq(cx: @block_ctxt, uniq_ty: ty::t)
 }
 
 fn alloc_uniq_(bcx: @block_ctxt, uniq_ty: ty::t, opt_v: option<ValueRef>)
-    : type_is_unique_box(cx, uniq_ty) -> result {
+    : type_is_unique_box(bcx, uniq_ty) -> result {
     let contents_ty = content_ty(bcx, uniq_ty);
     let {bcx, sz: llsz, align: _} = metrics(bcx, contents_ty, opt_v);
     let ccx = bcx_ccx(bcx);
@@ -83,7 +84,7 @@ fn duplicate(bcx: @block_ctxt, v: ValueRef, t: ty::t)
     : type_is_unique_box(bcx, t) -> result {
 
     let content_ty = content_ty(bcx, t);
-    let {bcx, val: llptr} = alloc_uniq_(bcx, t, v);
+    let {bcx, val: llptr} = alloc_uniq_(bcx, t, some(v));
 
     let src = load_if_immediate(bcx, v, content_ty);
     let dst = llptr;
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index 3732bdd203a..bcf0cfb69ea 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -149,6 +149,7 @@ export kind_can_be_copied, kind_can_be_sent, proto_kind, kind_lteq, type_kind;
 export type_err;
 export type_err_to_str;
 export type_has_dynamic_size;
+export type_has_opaque_size;
 export type_needs_drop;
 export type_is_bool;
 export type_is_bot;
@@ -1140,6 +1141,15 @@ fn type_structurally_contains(cx: ctxt, ty: t, test: fn(sty) -> bool) ->
     }
 }
 
+pure fn type_has_opaque_size(cx: ctxt, ty: t) -> bool unchecked {
+    type_structurally_contains(cx, ty, fn (sty: sty) -> bool {
+        alt sty {
+          ty_opaque_closure. { true}
+          _ { false }
+        }
+    })
+}
+
 pure fn type_has_dynamic_size(cx: ctxt, ty: t) -> bool unchecked {
 
     /* type_structurally_contains can't be declared pure