about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2012-03-22 16:02:34 +0100
committerMarijn Haverbeke <marijnh@gmail.com>2012-03-23 10:49:47 +0100
commit16ca6e8d7f79bb778b8ac3ab5867abf399a2408d (patch)
treed3cd2195c95f377c0be47bc59b75737b1298341f /src/rustc
parent0545e4a9200a9c971f8b5f95aa9a439ea0c20116 (diff)
downloadrust-16ca6e8d7f79bb778b8ac3ab5867abf399a2408d.tar.gz
rust-16ca6e8d7f79bb778b8ac3ab5867abf399a2408d.zip
Change vector append to no longer rely on an intrinsic
Issue #1981
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/middle/trans/tvec.rs40
1 files changed, 27 insertions, 13 deletions
diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs
index 7c58c5c8e54..b2153a5b035 100644
--- a/src/rustc/middle/trans/tvec.rs
+++ b/src/rustc/middle/trans/tvec.rs
@@ -14,6 +14,12 @@ fn get_fill(bcx: block, vptr: ValueRef) -> ValueRef {
     let _icx = bcx.insn_ctxt("tvec::get_fill");
     Load(bcx, GEPi(bcx, vptr, [0, abi::vec_elt_fill]))
 }
+fn set_fill(bcx: block, vptr: ValueRef, fill: ValueRef) {
+    Store(bcx, fill, GEPi(bcx, vptr, [0, abi::vec_elt_fill]));
+}
+fn get_alloc(bcx: block, vptr: ValueRef) -> ValueRef {
+    Load(bcx, GEPi(bcx, vptr, [0, abi::vec_elt_alloc]))
+}
 fn get_dataptr(bcx: block, vptr: ValueRef, unit_ty: TypeRef)
     -> ValueRef {
     let _icx = bcx.insn_ctxt("tvec::get_dataptr");
@@ -185,21 +191,29 @@ fn trans_append_literal(bcx: block, vptrptr: ValueRef, vec_ty: ty::t,
     let _icx = bcx.insn_ctxt("tvec::trans_append_literal");
     let mut bcx = bcx, ccx = bcx.ccx();
     let elt_ty = ty::sequence_element_type(bcx.tcx(), vec_ty);
-    let mut ti = none;
-    let td = get_tydesc(ccx, elt_ty, ti);
-    base::lazily_emit_tydesc_glue(ccx, abi::tydesc_field_take_glue, ti);
-    let opaque_v = PointerCast(bcx, vptrptr,
-                               T_ptr(T_ptr(ccx.opaque_vec_type)));
+    let elt_llty = type_of::type_of(ccx, elt_ty);
+    let elt_sz = shape::llsize_of(ccx, elt_llty);
+    let scratch = base::alloca(bcx, elt_llty);
     for val in vals {
-        let {bcx: e_bcx, val: elt} = base::trans_temp_expr(bcx, val);
-        bcx = e_bcx;
-        let r = base::spill_if_immediate(bcx, elt, elt_ty);
-        let spilled = r.val;
-        bcx = r.bcx;
-        Call(bcx, bcx.ccx().upcalls.vec_push,
-             [opaque_v, td, PointerCast(bcx, spilled, T_ptr(T_i8()))]);
+        bcx = base::trans_expr_save_in(bcx, val, scratch);
+        let vptr = Load(bcx, vptrptr);
+        let old_fill = get_fill(bcx, vptr);
+        let new_fill = Add(bcx, old_fill, elt_sz);
+        let do_grow = ICmp(bcx, lib::llvm::IntUGT, new_fill,
+                           get_alloc(bcx, vptr));
+        bcx = base::with_cond(bcx, do_grow) {|bcx|
+            let pt = PointerCast(bcx, vptrptr,
+                                 T_ptr(T_ptr(ccx.opaque_vec_type)));
+            Call(bcx, ccx.upcalls.vec_grow, [pt, new_fill]);
+            bcx
+        };
+        let vptr = Load(bcx, vptrptr);
+        set_fill(bcx, vptr, new_fill);
+        let targetptr = pointer_add(bcx, get_dataptr(bcx, vptr, elt_llty),
+                                    old_fill);
+        bcx = call_memmove(bcx, targetptr, scratch, elt_sz).bcx;
     }
-    ret bcx;
+    bcx
 }
 
 fn trans_add(bcx: block, vec_ty: ty::t, lhs: ValueRef,