]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/trans/tvec.rs
introduce `base_and_len` fns for element length
[rust.git] / src / librustc / middle / trans / tvec.rs
index eab642ccb91de7a381dfb2084ed534aa0987ff44..bde98eff41ce777a45d1edce4a05fcf29bd545e0 100644 (file)
@@ -77,8 +77,8 @@ pub fn get_dataptr(bcx: @mut Block, vptr: ValueRef) -> ValueRef {
     GEPi(bcx, vptr, [0u, abi::vec_elt_elems, 0u])
 }
 
-pub fn pointer_add(bcx: @mut Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
-    let _icx = push_ctxt("tvec::pointer_add");
+pub fn pointer_add_byte(bcx: @mut Block, ptr: ValueRef, bytes: ValueRef) -> ValueRef {
+    let _icx = push_ctxt("tvec::pointer_add_byte");
     let old_ty = val_ty(ptr);
     let bptr = PointerCast(bcx, ptr, Type::i8p());
     return PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty);
@@ -501,8 +501,7 @@ pub fn elements_required(bcx: @mut Block, content_expr: &ast::Expr) -> uint {
     }
 }
 
-pub fn get_base_and_byte_len(bcx: @mut Block,
-                        llval: ValueRef,
+pub fn get_base_and_byte_len(bcx: @mut Block, llval: ValueRef,
                         vec_ty: ty::t) -> (ValueRef, ValueRef) {
     //!
     //
@@ -539,6 +538,40 @@ pub fn get_base_and_byte_len(bcx: @mut Block,
     }
 }
 
+pub fn get_base_and_len(bcx: @mut Block, llval: ValueRef, vec_ty: ty::t) -> (ValueRef, ValueRef) {
+    //!
+    //
+    // Converts a vector into the slice pair.  The vector should be stored in
+    // `llval` which should be either immediate or by-ref as appropriate for
+    // the vector type.  If you have a datum, you would probably prefer to
+    // call `Datum::get_base_and_len()` which will handle any conversions for
+    // you.
+
+    let ccx = bcx.ccx();
+    let vt = vec_types(bcx, vec_ty);
+
+    let vstore = match ty::get(vt.vec_ty).sty {
+      ty::ty_estr(vst) | ty::ty_evec(_, vst) => vst,
+      _ => ty::vstore_uniq
+    };
+
+    match vstore {
+        ty::vstore_fixed(n) => {
+            let base = GEPi(bcx, llval, [0u, 0u]);
+            (base, C_uint(ccx, n))
+        }
+        ty::vstore_slice(_) => {
+            let base = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_base]));
+            let count = Load(bcx, GEPi(bcx, llval, [0u, abi::slice_elt_len]));
+            (base, count)
+        }
+        ty::vstore_uniq | ty::vstore_box => {
+            let body = get_bodyptr(bcx, llval, vec_ty);
+            (get_dataptr(bcx, body), UDiv(bcx, get_fill(bcx, body), vt.llunit_size))
+        }
+    }
+}
+
 pub type iter_vec_block<'self> = &'self fn(@mut Block, ValueRef, ty::t) -> @mut Block;
 
 pub fn iter_vec_raw(bcx: @mut Block, data_ptr: ValueRef, vec_ty: ty::t,
@@ -551,7 +584,7 @@ pub fn iter_vec_raw(bcx: @mut Block, data_ptr: ValueRef, vec_ty: ty::t,
     // FIXME (#3729): Optimize this when the size of the unit type is
     // statically known to not use pointer casts, which tend to confuse
     // LLVM.
-    let data_end_ptr = pointer_add(bcx, data_ptr, fill);
+    let data_end_ptr = pointer_add_byte(bcx, data_ptr, fill);
 
     // Now perform the iteration.
     let header_bcx = base::sub_block(bcx, "iter_vec_loop_header");