about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-06-17 11:45:07 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-06-17 11:45:51 -0700
commit5bdbe1dfc217b77ff6ff5c0d67b8ac274b50f2d3 (patch)
tree614f3257e5d662440dcb0006018712eac237ed25 /src/comp
parente8228e1260d6568b143d9b2067293f53cb2d20c4 (diff)
downloadrust-5bdbe1dfc217b77ff6ff5c0d67b8ac274b50f2d3.tar.gz
rust-5bdbe1dfc217b77ff6ff5c0d67b8ac274b50f2d3.zip
rustc: Copy the contents of generic interior vectors
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/middle/trans.rs114
-rw-r--r--src/comp/middle/ty.rs42
2 files changed, 73 insertions, 83 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index b0381684626..6c824d9626f 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -1321,6 +1321,15 @@ fn dynamic_size_of(&@block_ctxt cx, ty::t t) -> result {
             auto total_size = bcx.build.Add(max_size_val, llsize_of(T_int()));
             ret res(bcx, total_size);
         }
+        case (ty::ty_ivec(?mt)) {
+            auto rslt = field_of_tydesc(cx, mt.ty, false,
+                                        abi::tydesc_field_size);
+            auto bcx = rslt.bcx;
+            auto llunitszptr = rslt.val;
+            auto llunitsz = bcx.build.Load(llunitszptr);
+            auto llsz = bcx.build.Add(llsize_of(T_opaque_ivec()), llunitsz);
+            ret res(bcx, llsz);
+        }
     }
 }
 
@@ -1353,7 +1362,13 @@ fn dynamic_align_of(&@block_ctxt cx, &ty::t t) -> result {
         }
         case (ty::ty_tag(_, _)) {
             ret res(cx, C_int(1)); // FIXME: stub
-
+        }
+        case (ty::ty_ivec(?tm)) {
+            auto rslt = align_of(cx, tm.ty);
+            auto bcx = rslt.bcx;
+            auto llunitalign = rslt.val;
+            auto llalign = umax(bcx, llalign_of(T_int()), llunitalign);
+            ret res(bcx, llalign);
         }
     }
 }
@@ -2044,8 +2059,15 @@ fn make_drop_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
         case (ty::ty_str) { rslt = decr_refcnt_maybe_free(cx, v0, v0, t); }
         case (ty::ty_vec(_)) { rslt = decr_refcnt_maybe_free(cx, v0, v0, t); }
         case (ty::ty_ivec(?tm)) {
-            rslt = iter_structural_ty(cx, v0, t, drop_ty);
-            rslt = maybe_free_ivec_heap_part(rslt.bcx, v0, tm.ty);
+            auto v1;
+            if (ty::type_has_dynamic_size(cx.fcx.lcx.ccx.tcx, tm.ty)) {
+                v1 = cx.build.PointerCast(v0, T_ptr(T_opaque_ivec()));
+            } else {
+                v1 = v0;
+            }
+
+            rslt = iter_structural_ty(cx, v1, t, drop_ty);
+            rslt = maybe_free_ivec_heap_part(rslt.bcx, v1, tm.ty);
         }
         case (ty::ty_box(_)) { rslt = decr_refcnt_maybe_free(cx, v0, v0, t); }
         case (ty::ty_port(_)) {
@@ -2396,74 +2418,6 @@ fn make_numerical_cmp_glue(&@block_ctxt cx, ValueRef lhs, ValueRef rhs,
 }
 
 
-// Returns the length of an interior vector and a pointer to its first
-// element, in that order.
-fn get_len_and_data(&@block_ctxt bcx, ValueRef v, ty::t unit_ty) ->
-   tup(ValueRef, ValueRef, @block_ctxt) {
-    auto llunitty = type_of_or_i8(bcx, unit_ty);
-    auto stack_len =
-        bcx.build.Load(bcx.build.InBoundsGEP(v,
-                                             [C_int(0),
-                                              C_uint(abi::ivec_elt_len)]));
-    auto stack_elem =
-        bcx.build.InBoundsGEP(v,
-                              [C_int(0), C_uint(abi::ivec_elt_elems),
-                               C_int(0)]);
-    auto on_heap = bcx.build.ICmp(lib::llvm::LLVMIntEQ, stack_len, C_int(0));
-    auto on_heap_cx = new_sub_block_ctxt(bcx, "on_heap");
-    auto next_cx = new_sub_block_ctxt(bcx, "next");
-    bcx.build.CondBr(on_heap, on_heap_cx.llbb, next_cx.llbb);
-    auto heap_stub =
-        on_heap_cx.build.PointerCast(v, T_ptr(T_ivec_heap(llunitty)));
-    auto heap_ptr =
-        {
-            auto v = [C_int(0), C_uint(abi::ivec_heap_stub_elt_ptr)];
-            on_heap_cx.build.Load(on_heap_cx.build.InBoundsGEP(heap_stub, v))
-        };
-    // Check whether the heap pointer is null. If it is, the vector length is
-    // truly zero.
-
-    auto llstubty = T_ivec_heap(llunitty);
-    auto llheapptrty = struct_elt(llstubty, abi::ivec_heap_stub_elt_ptr);
-    auto heap_ptr_is_null =
-        on_heap_cx.build.ICmp(lib::llvm::LLVMIntEQ, heap_ptr,
-                              C_null(T_ptr(llheapptrty)));
-    auto zero_len_cx = new_sub_block_ctxt(bcx, "zero_len");
-    auto nonzero_len_cx = new_sub_block_ctxt(bcx, "nonzero_len");
-    on_heap_cx.build.CondBr(heap_ptr_is_null, zero_len_cx.llbb,
-                            nonzero_len_cx.llbb);
-    // Technically this context is unnecessary, but it makes this function
-    // clearer.
-
-    auto zero_len = C_int(0);
-    auto zero_elem = C_null(T_ptr(llunitty));
-    zero_len_cx.build.Br(next_cx.llbb);
-    // If we're here, then we actually have a heapified vector.
-
-    auto heap_len =
-        {
-            auto v = [C_int(0), C_uint(abi::ivec_heap_elt_len)];
-            auto m = nonzero_len_cx.build.InBoundsGEP(heap_ptr, v);
-            nonzero_len_cx.build.Load(m)
-        };
-    auto heap_elem =
-        nonzero_len_cx.build.InBoundsGEP(heap_ptr,
-                                         [C_int(0),
-                                          C_uint(abi::ivec_heap_elt_elems),
-                                          C_int(0)]);
-    nonzero_len_cx.build.Br(next_cx.llbb);
-    // Now we can figure out the length of `v` and get a pointer to its first
-    // element.
-
-    auto len =
-        next_cx.build.Phi(T_int(), [stack_len, zero_len, heap_len],
-                          [bcx.llbb, zero_len_cx.llbb, nonzero_len_cx.llbb]);
-    auto elem =
-        next_cx.build.Phi(T_ptr(llunitty), [stack_elem, zero_elem, heap_elem],
-                          [bcx.llbb, zero_len_cx.llbb, nonzero_len_cx.llbb]);
-    ret tup(len, elem, next_cx);
-}
-
 type val_pair_fn = fn(&@block_ctxt, ValueRef, ValueRef) -> result ;
 
 type val_and_ty_fn = fn(&@block_ctxt, ValueRef, ty::t) -> result ;
@@ -3017,8 +2971,10 @@ fn memmove_ty(&@block_ctxt cx, ValueRef dst, ValueRef src, &ty::t t) ->
 
 tag copy_action { INIT; DROP_EXISTING; }
 
+// FIXME: This should copy the contents of the heap part for ivecs.
 fn copy_val(&@block_ctxt cx, copy_action action, ValueRef dst, ValueRef src,
             &ty::t t) -> result {
+
     if (ty::type_is_scalar(cx.fcx.lcx.ccx.tcx, t) ||
             ty::type_is_native(cx.fcx.lcx.ccx.tcx, t)) {
         ret res(cx, cx.build.Store(src, dst));
@@ -3245,8 +3201,18 @@ mod ivec {
 
     // Returns the length of an interior vector and a pointer to its first
     // element, in that order.
-    fn get_len_and_data(&@block_ctxt bcx, ValueRef v, ty::t unit_ty) ->
-       tup(ValueRef, ValueRef, @block_ctxt) {
+    fn get_len_and_data(&@block_ctxt bcx, ValueRef orig_v, ty::t unit_ty)
+            -> tup(ValueRef, ValueRef, @block_ctxt) {
+        // If this interior vector has dynamic size, we can't assume anything
+        // about the LLVM type of the value passed in, so we cast it to an
+        // opaque vector type.
+        auto v;
+        if (ty::type_has_dynamic_size(bcx.fcx.lcx.ccx.tcx, unit_ty)) {
+            v = bcx.build.PointerCast(orig_v, T_ptr(T_opaque_ivec()));
+        } else {
+            v = orig_v;
+        }
+
         auto llunitty = type_of_or_i8(bcx, unit_ty);
         auto stack_len =
             {
@@ -4715,7 +4681,7 @@ fn trans_index(&@block_ctxt cx, &span sp, &@ast::expr base, &@ast::expr idx,
     maybe_name_value(cx.fcx.lcx.ccx, scaled_ix, "scaled_ix");
     auto interior_len_and_data;
     if (is_interior) {
-        auto rslt = get_len_and_data(bcx, v, unit_ty);
+        auto rslt = ivec::get_len_and_data(bcx, v, unit_ty);
         interior_len_and_data = some(tup(rslt._0, rslt._1));
         bcx = rslt._2;
     } else { interior_len_and_data = none; }
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index deaf925f0b8..c2c46cb7e07 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -883,12 +883,38 @@ fn type_is_native(&ctxt cx, &t ty) -> bool {
 
 fn type_has_dynamic_size(&ctxt cx, &t ty) -> bool {
     alt (struct(cx, ty)) {
+        case (ty_nil) { ret false; }
+        case (ty_bot) { ret false; }
+        case (ty_bool) { ret false; }
+        case (ty_int) { ret false; }
+        case (ty_float) { ret false; }
+        case (ty_uint) { ret false; }
+        case (ty_machine(_)) { ret false; }
+        case (ty_char) { ret false; }
+        case (ty_str) { ret false; }
+        case (ty_istr) { ret false; }
+        case (ty_tag(_, ?subtys)) {
+            auto i = 0u;
+            while (i < vec::len[t](subtys)) {
+                if (type_has_dynamic_size(cx, subtys.(i))) { ret true; }
+                i += 1u;
+            }
+            ret false;
+        }
+        case (ty_box(_)) { ret false; }
+        case (ty_vec(_)) { ret false; }
+        case (ty_ivec(?mt)) { ret type_has_dynamic_size(cx, mt.ty); }
+        case (ty_ptr(_)) { ret false; }
+        case (ty_port(_)) { ret false; }
+        case (ty_chan(_)) { ret false; }
+        case (ty_task) { ret false; }
         case (ty_tup(?mts)) {
             auto i = 0u;
             while (i < vec::len[mt](mts)) {
                 if (type_has_dynamic_size(cx, mts.(i).ty)) { ret true; }
                 i += 1u;
             }
+            ret false;
         }
         case (ty_rec(?fields)) {
             auto i = 0u;
@@ -896,18 +922,16 @@ fn type_has_dynamic_size(&ctxt cx, &t ty) -> bool {
                 if (type_has_dynamic_size(cx, fields.(i).mt.ty)) { ret true; }
                 i += 1u;
             }
+            ret false;
         }
-        case (ty_tag(_, ?subtys)) {
-            auto i = 0u;
-            while (i < vec::len[t](subtys)) {
-                if (type_has_dynamic_size(cx, subtys.(i))) { ret true; }
-                i += 1u;
-            }
-        }
+        case (ty_fn(_,_,_,_,_)) { ret false; }
+        case (ty_native_fn(_,_,_)) { ret false; }
+        case (ty_obj(_)) { ret false; }
+        case (ty_var(_)) { fail "ty_var in type_has_dynamic_size()"; }
         case (ty_param(_)) { ret true; }
-        case (_) {/* fall through */ }
+        case (ty_type) { ret false; }
+        case (ty_native) { ret false; }
     }
-    ret false;
 }
 
 fn type_is_integral(&ctxt cx, &t ty) -> bool {