about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-06-30 19:08:57 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-06-30 19:09:52 -0700
commitb773f8d22b7e132aa9dd59090b939bc612ac8d83 (patch)
tree61048f9268298677eb3e142607dec60010861f4d /src/comp
parent0eb257e864a36a459110a1d27f6447a770d855a7 (diff)
downloadrust-b773f8d22b7e132aa9dd59090b939bc612ac8d83.tar.gz
rust-b773f8d22b7e132aa9dd59090b939bc612ac8d83.zip
rustc: Duplicate heap data of interior vectors when passing them by value
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/middle/trans.rs16
1 files changed, 15 insertions, 1 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index b20074a7716..6da9a578510 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -5515,7 +5515,21 @@ fn trans_arg_expr(&@block_ctxt cx, &ty::arg arg, TypeRef lldestty0,
             val = do_spill(lv.res.bcx, lv.res.val);
         }
     } else { auto re = trans_expr(bcx, e); val = re.val; bcx = re.bcx; }
-    if (arg.mode == ty::mo_val) { bcx = copy_ty(bcx, val, e_ty).bcx; }
+
+    // Make a copy here if the type is structural and we're passing by value.
+    if (arg.mode == ty::mo_val) {
+        if (ty::type_owns_heap_mem(cx.fcx.lcx.ccx.tcx, e_ty)) {
+            auto rslt = alloc_ty(bcx, e_ty);
+            bcx = rslt.bcx;
+            auto dst = rslt.val;
+            rslt = copy_val(bcx, INIT, dst, val, e_ty);
+            bcx = rslt.bcx;
+            val = dst;
+        } else {
+            bcx = copy_ty(bcx, val, e_ty).bcx;
+        }
+    }
+
     if (ty::type_is_bot(cx.fcx.lcx.ccx.tcx, e_ty)) {
         // For values of type _|_, we generate an
         // "undef" value, as such a value should never