@@ -1122,6 +1122,7 @@ fn declare_tydesc(cx: &@local_ctxt, sp: &span, t: ty::t, ty_params: &[uint])
1122
1122
mutable drop_glue: none :: < ValueRef > ,
1123
1123
mutable free_glue: none :: < ValueRef > ,
1124
1124
mutable cmp_glue: none :: < ValueRef > ,
1125
+ mutable copy_glue: none :: < ValueRef > ,
1125
1126
ty_params: ty_params} ;
1126
1127
log "--- declare_tydesc " + ty_to_str ( cx. ccx . tcx , t) ;
1127
1128
ret info;
@@ -1215,6 +1216,7 @@ fn emit_tydescs(ccx: &@crate_ctxt) {
1215
1216
for each pair: @{ key : ty:: t, val : @tydesc_info} in ccx. tydescs . items ( ) {
1216
1217
let glue_fn_ty = T_ptr ( T_glue_fn ( * ccx) ) ;
1217
1218
let cmp_fn_ty = T_ptr ( T_cmp_glue_fn ( * ccx) ) ;
1219
+ let copy_fn_ty = T_ptr ( T_copy_glue_fn ( * ccx) ) ;
1218
1220
let ti = pair. val ;
1219
1221
let take_glue =
1220
1222
alt { ti. take_glue } {
@@ -1236,6 +1238,11 @@ fn emit_tydescs(ccx: &@crate_ctxt) {
1236
1238
none. { ccx . stats . n_null_glues += 1 u; C_null ( cmp_fn_ty) }
1237
1239
some ( v) { ccx. stats . n_real_glues += 1 u; v }
1238
1240
} ;
1241
+ let copy_glue =
1242
+ alt { ti. copy_glue } {
1243
+ none. { ccx . stats . n_null_glues += 1 u; C_null ( copy_fn_ty) }
1244
+ some ( v) { ccx. stats . n_real_glues += 1 u; v }
1245
+ } ;
1239
1246
1240
1247
let shape = shape:: shape_of ( ccx, pair. key ) ;
1241
1248
let shape_tables =
@@ -1250,7 +1257,7 @@ fn emit_tydescs(ccx: &@crate_ctxt) {
1250
1257
take_glue, // take_glue
1251
1258
drop_glue, // drop_glue
1252
1259
free_glue, // free_glue
1253
- C_null ( T_ptr ( T_i8 ( ) ) ) , // unused
1260
+ copy_glue , // copy_glue
1254
1261
C_null ( glue_fn_ty) , // sever_glue
1255
1262
C_null ( glue_fn_ty) , // mark_glue
1256
1263
C_null ( glue_fn_ty) , // is_stateful
@@ -1267,6 +1274,14 @@ fn emit_tydescs(ccx: &@crate_ctxt) {
1267
1274
}
1268
1275
}
1269
1276
1277
+ // NOTE this is currently just a complicated way to do memmove. I'm working on
1278
+ // a representation of ivecs that will need pointers into itself, which must
1279
+ // be adjusted when copying. Will flesh this out when the time comes.
1280
+ fn make_copy_glue ( cx : & @block_ctxt , src : ValueRef , dst : ValueRef , t : ty:: t ) {
1281
+ let bcx = memmove_ty ( cx, dst, src, t) . bcx ;
1282
+ build_return ( bcx) ;
1283
+ }
1284
+
1270
1285
fn make_take_glue ( cx : & @block_ctxt , v : ValueRef , t : ty:: t ) {
1271
1286
// NB: v is an *alias* of type t here, not a direct value.
1272
1287
@@ -1988,6 +2003,7 @@ fn lazily_emit_all_tydesc_glue(cx: &@block_ctxt,
1988
2003
lazily_emit_tydesc_glue ( cx, abi:: tydesc_field_drop_glue, static_ti) ;
1989
2004
lazily_emit_tydesc_glue ( cx, abi:: tydesc_field_free_glue, static_ti) ;
1990
2005
lazily_emit_tydesc_glue ( cx, abi:: tydesc_field_cmp_glue, static_ti) ;
2006
+ lazily_emit_tydesc_glue ( cx, abi:: tydesc_field_copy_glue, static_ti) ;
1991
2007
}
1992
2008
1993
2009
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,
2067
2083
ty_to_str ( bcx_tcx ( cx) , ti. ty ) ] ;
2068
2084
}
2069
2085
}
2086
+ } else if field == abi:: tydesc_field_copy_glue {
2087
+ alt { ti. copy_glue } {
2088
+ some ( _) { }
2089
+ none. {
2090
+ let lcx = cx. fcx . lcx ;
2091
+ let glue_fn =
2092
+ declare_generic_glue ( lcx, ti. ty , T_copy_glue_fn ( * lcx. ccx ) ,
2093
+ "copy" ) ;
2094
+ ti. copy_glue = some ( glue_fn) ;
2095
+ make_generic_glue ( lcx, cx. sp , ti. ty , glue_fn,
2096
+ copy_helper ( make_copy_glue) ,
2097
+ ti. ty_params , "copy" ) ;
2098
+ }
2099
+ }
2070
2100
}
2071
2101
}
2072
2102
}
@@ -2156,6 +2186,45 @@ fn call_cmp_glue(cx: &@block_ctxt, lhs: ValueRef, rhs: ValueRef, t: ty::t,
2156
2186
ret rslt( r. bcx , bld:: Load ( r. bcx , llcmpresultptr) ) ;
2157
2187
}
2158
2188
2189
+ fn call_copy_glue ( cx : & @block_ctxt , dst : ValueRef , src : ValueRef , t : ty:: t ,
2190
+ take : bool ) -> @block_ctxt {
2191
+ // You can't call this on immediate types. Those are simply copied with
2192
+ // Load/Store.
2193
+ assert ! type_is_immediate( bcx_ccx( cx) , t) ;
2194
+ let srcptr = bld:: BitCast ( cx, src, T_ptr ( T_i8 ( ) ) ) ;
2195
+ let dstptr = bld:: BitCast ( cx, dst, T_ptr ( T_i8 ( ) ) ) ;
2196
+ let ti = none;
2197
+ let { bcx, val: lltydesc } = get_tydesc ( cx, t, false , ti) . result ;
2198
+ lazily_emit_tydesc_glue ( cx, abi:: tydesc_field_copy_glue, ti) ;
2199
+ let lltydescs = bld:: GEP
2200
+ ( bcx, lltydesc, [ C_int ( 0 ) , C_int ( abi:: tydesc_field_first_param) ] ) ;
2201
+ lltydescs = bld:: Load ( bcx, lltydescs) ;
2202
+
2203
+ let llfn = alt ti {
2204
+ none. {
2205
+ bld : : Load ( bcx, bld:: GEP
2206
+ ( bcx, lltydesc, [ C_int ( 0 ) , C_int ( abi:: tydesc_field_copy_glue) ] ) )
2207
+ }
2208
+ some( sti) { option:: get ( sti. copy_glue ) }
2209
+ } ;
2210
+ bld:: Call ( bcx, llfn, [ C_null ( T_ptr ( T_nil ( ) ) ) , bcx. fcx . lltaskptr ,
2211
+ C_null ( T_ptr ( T_nil ( ) ) ) , lltydescs, srcptr, dstptr] ) ;
2212
+ if take {
2213
+ lazily_emit_tydesc_glue ( cx, abi:: tydesc_field_take_glue, ti) ;
2214
+ llfn = alt ti {
2215
+ none. {
2216
+ bld : : Load ( bcx, bld:: GEP ( bcx, lltydesc,
2217
+ [ C_int ( 0 ) ,
2218
+ C_int ( abi:: tydesc_field_take_glue) ] ) )
2219
+ }
2220
+ some( sti) { option:: get ( sti. take_glue ) }
2221
+ } ;
2222
+ bld:: Call ( bcx, llfn, [ C_null ( T_ptr ( T_nil ( ) ) ) , bcx. fcx . lltaskptr ,
2223
+ C_null ( T_ptr ( T_nil ( ) ) ) , lltydescs, dstptr] ) ;
2224
+ }
2225
+ ret bcx;
2226
+ }
2227
+
2159
2228
2160
2229
// Compares two values. Performs the simple scalar comparison if the types are
2161
2230
// scalar and calls to comparison glue otherwise.
@@ -2310,8 +2379,12 @@ fn copy_val_no_check(cx: &@block_ctxt, action: copy_action, dst: ValueRef,
2310
2379
let bcx = if action == DROP_EXISTING {
2311
2380
drop_ty ( cx, dst, t) . bcx
2312
2381
} else { cx } ;
2313
- bcx = memmove_ty ( bcx, dst, src, t) . bcx ;
2314
- ret take_ty( bcx, dst, t) . bcx ;
2382
+ if ty:: type_needs_copy_glue ( ccx. tcx , t) {
2383
+ ret call_copy_glue ( bcx, dst, src, t, true ) ;
2384
+ } else {
2385
+ bcx = memmove_ty ( bcx, dst, src, t) . bcx ;
2386
+ ret take_ty( bcx, dst, t) . bcx ;
2387
+ }
2315
2388
}
2316
2389
ccx. sess . bug ( "unexpected type in trans::copy_val_no_check: " +
2317
2390
ty_to_str ( ccx. tcx , t) ) ;
@@ -2348,7 +2421,11 @@ fn move_val(cx: @block_ctxt, action: copy_action, dst: ValueRef,
2348
2421
ret cx;
2349
2422
} else if type_is_structural_or_param ( tcx, t) {
2350
2423
if action == DROP_EXISTING { cx = drop_ty ( cx, dst, t) . bcx ; }
2351
- cx = memmove_ty ( cx, dst, src_val, t) . bcx ;
2424
+ if ty:: type_needs_copy_glue ( tcx, t) {
2425
+ cx = call_copy_glue ( cx, dst, src_val, t, false ) ;
2426
+ } else {
2427
+ cx = memmove_ty ( cx, dst, src_val, t) . bcx ;
2428
+ }
2352
2429
if src. is_mem {
2353
2430
ret zero_alloca ( cx, src_val, t) . bcx ;
2354
2431
} else { // Temporary value
0 commit comments