about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-08-24 20:30:20 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-08-24 20:30:20 +0200
commitfa97793139a6b055eb0fba91ef7d64f6a545ca99 (patch)
tree1dec35c744ab29903926a7e2465f4415995a7161 /src/comp
parent60547f6500b0bf726e675b058ad0bdfe21455c11 (diff)
downloadrust-fa97793139a6b055eb0fba91ef7d64f6a545ca99.tar.gz
rust-fa97793139a6b055eb0fba91ef7d64f6a545ca99.zip
Revert "Back out copy-glue"
This reverts commit 629ee94a0b360e2df1a1bbf7bf61ef346adf36ad.
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/back/abi.rs2
-rw-r--r--src/comp/middle/trans.rs85
-rw-r--r--src/comp/middle/trans_common.rs14
-rw-r--r--src/comp/middle/trans_ivec.rs1
-rw-r--r--src/comp/middle/ty.rs12
5 files changed, 108 insertions, 6 deletions
diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs
index 68ca5160e95..2e2bddba592 100644
--- a/src/comp/back/abi.rs
+++ b/src/comp/back/abi.rs
@@ -52,7 +52,7 @@ const tydesc_field_align: int = 2;
 const tydesc_field_take_glue: int = 3;
 const tydesc_field_drop_glue: int = 4;
 const tydesc_field_free_glue: int = 5;
-const tydesc_field_unused: int = 6;
+const tydesc_field_copy_glue: int = 6;
 const tydesc_field_sever_glue: int = 7;
 const tydesc_field_mark_glue: int = 8;
 const tydesc_field_is_stateful: int = 9;
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 1f37f81e52e..7d41a1e6bd7 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -1122,6 +1122,7 @@ fn declare_tydesc(cx: &@local_ctxt, sp: &span, t: ty::t, ty_params: &[uint])
           mutable drop_glue: none::<ValueRef>,
           mutable free_glue: none::<ValueRef>,
           mutable cmp_glue: none::<ValueRef>,
+          mutable copy_glue: none::<ValueRef>,
           ty_params: ty_params};
     log "--- declare_tydesc " + ty_to_str(cx.ccx.tcx, t);
     ret info;
@@ -1215,6 +1216,7 @@ fn emit_tydescs(ccx: &@crate_ctxt) {
     for each pair: @{key: ty::t, val: @tydesc_info} in ccx.tydescs.items() {
         let glue_fn_ty = T_ptr(T_glue_fn(*ccx));
         let cmp_fn_ty = T_ptr(T_cmp_glue_fn(*ccx));
+        let copy_fn_ty = T_ptr(T_copy_glue_fn(*ccx));
         let ti = pair.val;
         let take_glue =
             alt { ti.take_glue } {
@@ -1236,6 +1238,11 @@ fn emit_tydescs(ccx: &@crate_ctxt) {
               none. { ccx.stats.n_null_glues += 1u; C_null(cmp_fn_ty) }
               some(v) { ccx.stats.n_real_glues += 1u; v }
             };
+        let copy_glue =
+            alt { ti.copy_glue } {
+              none. { ccx.stats.n_null_glues += 1u; C_null(copy_fn_ty) }
+              some(v) { ccx.stats.n_real_glues += 1u; v }
+            };
 
         let shape = shape::shape_of(ccx, pair.key);
         let shape_tables =
@@ -1250,7 +1257,7 @@ fn emit_tydescs(ccx: &@crate_ctxt) {
                             take_glue, // take_glue
                             drop_glue, // drop_glue
                             free_glue, // free_glue
-                            C_null(T_ptr(T_i8())), // unused
+                            copy_glue, // copy_glue
                             C_null(glue_fn_ty), // sever_glue
                             C_null(glue_fn_ty), // mark_glue
                             C_null(glue_fn_ty), // is_stateful
@@ -1267,6 +1274,14 @@ fn emit_tydescs(ccx: &@crate_ctxt) {
     }
 }
 
+// NOTE this is currently just a complicated way to do memmove. I'm working on
+// a representation of ivecs that will need pointers into itself, which must
+// be adjusted when copying. Will flesh this out when the time comes.
+fn make_copy_glue(cx: &@block_ctxt, src: ValueRef, dst: ValueRef, t: ty::t) {
+    let bcx = memmove_ty(cx, dst, src, t).bcx;
+    build_return(bcx);
+}
+
 fn make_take_glue(cx: &@block_ctxt, v: ValueRef, t: ty::t) {
     // NB: v is an *alias* of type t here, not a direct value.
 
@@ -1988,6 +2003,7 @@ fn lazily_emit_all_tydesc_glue(cx: &@block_ctxt,
     lazily_emit_tydesc_glue(cx, abi::tydesc_field_drop_glue, static_ti);
     lazily_emit_tydesc_glue(cx, abi::tydesc_field_free_glue, static_ti);
     lazily_emit_tydesc_glue(cx, abi::tydesc_field_cmp_glue, static_ti);
+    lazily_emit_tydesc_glue(cx, abi::tydesc_field_copy_glue, static_ti);
 }
 
 fn lazily_emit_all_generic_info_tydesc_glues(cx: &@block_ctxt,
@@ -2067,6 +2083,20 @@ fn lazily_emit_tydesc_glue(cx: &@block_ctxt, field: int,
                          ty_to_str(bcx_tcx(cx), ti.ty)];
               }
             }
+        } else if field == abi::tydesc_field_copy_glue {
+            alt { ti.copy_glue } {
+              some(_) {}
+              none. {
+                let lcx = cx.fcx.lcx;
+                let glue_fn =
+                    declare_generic_glue(lcx, ti.ty, T_copy_glue_fn(*lcx.ccx),
+                                         "copy");
+                ti.copy_glue = some(glue_fn);
+                make_generic_glue(lcx, cx.sp, ti.ty, glue_fn,
+                                  copy_helper(make_copy_glue),
+                                  ti.ty_params, "copy");
+              }
+            }
         }
       }
     }
@@ -2156,6 +2186,45 @@ fn call_cmp_glue(cx: &@block_ctxt, lhs: ValueRef, rhs: ValueRef, t: ty::t,
     ret rslt(r.bcx, bld::Load(r.bcx, llcmpresultptr));
 }
 
+fn call_copy_glue(cx: &@block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t,
+                  take: bool) -> @block_ctxt {
+    // You can't call this on immediate types. Those are simply copied with
+    // Load/Store.
+    assert !type_is_immediate(bcx_ccx(cx), t);
+    let srcptr = bld::BitCast(cx, src, T_ptr(T_i8()));
+    let dstptr = bld::BitCast(cx, dst, T_ptr(T_i8()));
+    let ti = none;
+    let {bcx, val: lltydesc} = get_tydesc(cx, t, false, ti).result;
+    lazily_emit_tydesc_glue(cx, abi::tydesc_field_copy_glue, ti);
+    let lltydescs = bld::GEP
+        (bcx, lltydesc, [C_int(0), C_int(abi::tydesc_field_first_param)]);
+    lltydescs = bld::Load(bcx, lltydescs);
+
+    let llfn = alt ti {
+      none. {
+        bld::Load(bcx, bld::GEP
+            (bcx, lltydesc, [C_int(0), C_int(abi::tydesc_field_copy_glue)]))
+      }
+      some(sti) { option::get(sti.copy_glue) }
+    };
+    bld::Call(bcx, llfn, [C_null(T_ptr(T_nil())), bcx.fcx.lltaskptr,
+                          C_null(T_ptr(T_nil())), lltydescs, srcptr, dstptr]);
+    if take {
+        lazily_emit_tydesc_glue(cx, abi::tydesc_field_take_glue, ti);
+        llfn = alt ti {
+          none. {
+            bld::Load(bcx, bld::GEP(bcx, lltydesc,
+                                    [C_int(0),
+                                     C_int(abi::tydesc_field_take_glue)]))
+          }
+          some(sti) { option::get(sti.take_glue) }
+        };
+        bld::Call(bcx, llfn, [C_null(T_ptr(T_nil())), bcx.fcx.lltaskptr,
+                              C_null(T_ptr(T_nil())), lltydescs, dstptr]);
+    }
+    ret bcx;
+}
+
 
 // Compares two values. Performs the simple scalar comparison if the types are
 // scalar and calls to comparison glue otherwise.
@@ -2310,8 +2379,12 @@ fn copy_val_no_check(cx: &@block_ctxt, action: copy_action, dst: ValueRef,
         let bcx = if action == DROP_EXISTING {
             drop_ty(cx, dst, t).bcx
         } else { cx };
-        bcx = memmove_ty(bcx, dst, src, t).bcx;
-        ret take_ty(bcx, dst, t).bcx;
+        if ty::type_needs_copy_glue(ccx.tcx, t) {
+            ret call_copy_glue(bcx, dst, src, t, true);
+        } else {
+            bcx = memmove_ty(bcx, dst, src, t).bcx;
+            ret take_ty(bcx, dst, t).bcx;
+        }
     }
     ccx.sess.bug("unexpected type in trans::copy_val_no_check: " +
                      ty_to_str(ccx.tcx, t));
@@ -2348,7 +2421,11 @@ fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
         ret cx;
     } else if type_is_structural_or_param(tcx, t) {
         if action == DROP_EXISTING { cx = drop_ty(cx, dst, t).bcx; }
-        cx = memmove_ty(cx, dst, src_val, t).bcx;
+        if ty::type_needs_copy_glue(tcx, t) {
+            cx = call_copy_glue(cx, dst, src_val, t, false);
+        } else {
+            cx = memmove_ty(cx, dst, src_val, t).bcx;
+        }
         if src.is_mem {
             ret zero_alloca(cx, src_val, t).bcx;
         } else { // Temporary value
diff --git a/src/comp/middle/trans_common.rs b/src/comp/middle/trans_common.rs
index 1a6d23b3d09..b457ff22b30 100644
--- a/src/comp/middle/trans_common.rs
+++ b/src/comp/middle/trans_common.rs
@@ -85,6 +85,7 @@ type tydesc_info =
      mutable drop_glue: option::t<ValueRef>,
      mutable free_glue: option::t<ValueRef>,
      mutable cmp_glue: option::t<ValueRef>,
+     mutable copy_glue: option::t<ValueRef>,
      ty_params: [uint]};
 
 /*
@@ -614,6 +615,14 @@ fn T_cmp_glue_fn(cx: &crate_ctxt) -> TypeRef {
     ret t;
 }
 
+fn T_copy_glue_fn(cx: &crate_ctxt) -> TypeRef {
+    let s = "copy_glue_fn";
+    if cx.tn.name_has_type(s) { ret cx.tn.get_type(s); }
+    let t = T_tydesc_field(cx, abi::tydesc_field_copy_glue);
+    cx.tn.associate(s, t);
+    ret t;
+}
+
 fn T_tydesc(taskptr_type: TypeRef) -> TypeRef {
     let tydesc = T_named_struct("tydesc");
     let tydescpp = T_ptr(T_ptr(tydesc));
@@ -624,10 +633,13 @@ fn T_tydesc(taskptr_type: TypeRef) -> TypeRef {
     let cmp_glue_fn_ty =
         T_ptr(T_fn([T_ptr(T_i1()), taskptr_type, T_ptr(tydesc), tydescpp,
                     pvoid, pvoid, T_i8()], T_void()));
+    let copy_glue_fn_ty =
+        T_ptr(T_fn([T_ptr(T_nil()), taskptr_type, T_ptr(T_nil()), tydescpp,
+                    pvoid, pvoid], T_void()));
 
     let elems =
         [tydescpp, T_int(), T_int(), glue_fn_ty, glue_fn_ty, glue_fn_ty,
-         T_ptr(T_i8()), glue_fn_ty, glue_fn_ty, glue_fn_ty, cmp_glue_fn_ty,
+         copy_glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty, cmp_glue_fn_ty,
          T_ptr(T_i8()), T_ptr(T_i8()), T_int()];
     set_struct_body(tydesc, elems);
     ret tydesc;
diff --git a/src/comp/middle/trans_ivec.rs b/src/comp/middle/trans_ivec.rs
index 4820d5af69c..b0c18dbc522 100644
--- a/src/comp/middle/trans_ivec.rs
+++ b/src/comp/middle/trans_ivec.rs
@@ -367,6 +367,7 @@ fn trans_append(cx: &@block_ctxt, t: ty::t, lhs: ValueRef,
     lazily_emit_tydesc_glue(bcx, abi::tydesc_field_take_glue, none);
     lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, none);
     lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, none);
+    lazily_emit_tydesc_glue(bcx, abi::tydesc_field_copy_glue, none);
     let rhs_len_and_data = get_len_and_data(bcx, rhs, unit_ty);
     let rhs_len = rhs_len_and_data.len;
     let rhs_data = rhs_len_and_data.data;
diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs
index bb1c1c59422..5d448825b89 100644
--- a/src/comp/middle/ty.rs
+++ b/src/comp/middle/ty.rs
@@ -156,6 +156,7 @@ export type_kind;
 export type_err;
 export type_err_to_str;
 export type_has_dynamic_size;
+export type_needs_copy_glue;
 export type_has_pointers;
 export type_needs_drop;
 export type_is_bool;
@@ -1177,6 +1178,17 @@ fn type_has_dynamic_size(cx: &ctxt, ty: t) -> bool {
     });
 }
 
+fn type_needs_copy_glue(cx: &ctxt, ty: t) -> bool {
+    ret type_structurally_contains(cx, ty, fn(sty: &sty) -> bool {
+        ret alt sty {
+          ty_param(_, _) { true }
+          ty_vec(_) { true }
+          ty_istr. { true }
+          _ { false }
+        };
+    });
+}
+
 fn type_is_integral(cx: &ctxt, ty: t) -> bool {
     alt struct(cx, ty) {
       ty_int. { ret true; }