Skip to content

Commit 880fd78

Browse files
committed
rustc: Add an extra flag to object tydescs so that shapes know how to find the captured subtydescs
1 parent 2f7c583 commit 880fd78

11 files changed

+103
-72
lines changed

src/comp/back/abi.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ const tydesc_field_cmp_glue: int = 10;
6060
const tydesc_field_shape: int = 11;
6161
const tydesc_field_shape_tables: int = 12;
6262
const tydesc_field_n_params: int = 13;
63-
const n_tydesc_fields: int = 14;
63+
const tydesc_field_obj_params: int = 14;
64+
const n_tydesc_fields: int = 15;
6465

6566
const cmp_glue_op_eq: uint = 0u;
6667

src/comp/back/upcall.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ fn declare_upcalls(_tn: type_names, tydesc_type: TypeRef,
9191
get_type_desc:
9292
d("get_type_desc",
9393
[T_ptr(T_nil()), T_size_t(), T_size_t(), T_size_t(),
94-
T_ptr(T_ptr(tydesc_type))], T_ptr(tydesc_type)),
94+
T_ptr(T_ptr(tydesc_type)), T_int()], T_ptr(tydesc_type)),
9595
ivec_resize:
9696
d("ivec_resize", [T_ptr(T_opaque_ivec()), T_int()], T_void()),
9797
ivec_spill:

src/comp/middle/gc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import lib::llvm::False;
44
import lib::llvm::True;
55
import lib::llvm::llvm::ValueRef;
66
import middle::trans;
7-
import middle::trans::get_tydesc;
7+
import middle::trans::{ get_tydesc, tps_normal };
88
import middle::trans_common::*;
99
import middle::ty;
1010
import std::option::none;
@@ -43,7 +43,7 @@ fn add_gc_root(cx: &@block_ctxt, llval: ValueRef, ty: ty::t) -> @block_ctxt {
4343
bcx = trans::zero_alloca(bcx, llval, ty).bcx;
4444

4545
let ti = none;
46-
let td_r = get_tydesc(bcx, ty, false, ti);
46+
let td_r = get_tydesc(bcx, ty, false, tps_normal, ti);
4747
bcx = td_r.result.bcx;
4848
let lltydesc = td_r.result.val;
4949

src/comp/middle/trans.rs

Lines changed: 69 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ fn trans_malloc_boxed(cx: &@block_ctxt, t: ty::t) ->
884884
fn field_of_tydesc(cx: &@block_ctxt, t: ty::t, escapes: bool, field: int) ->
885885
result {
886886
let ti = none::<@tydesc_info>;
887-
let tydesc = get_tydesc(cx, t, escapes, ti).result;
887+
let tydesc = get_tydesc(cx, t, escapes, tps_normal, ti).result;
888888
ret rslt(tydesc.bcx,
889889
bld::GEP(tydesc.bcx, tydesc.val, [C_int(0), C_int(field)]));
890890
}
@@ -919,16 +919,16 @@ fn linearize_ty_params(cx: &@block_ctxt, t: ty::t) ->
919919

920920
fn trans_stack_local_derived_tydesc(cx: &@block_ctxt, llsz: ValueRef,
921921
llalign: ValueRef, llroottydesc: ValueRef,
922-
llparamtydescs: ValueRef, n_params: uint)
922+
llfirstparam: ValueRef, n_params: uint,
923+
obj_params: uint)
923924
-> ValueRef {
924925
let llmyroottydesc = alloca(cx, bcx_ccx(cx).tydesc_type);
925-
// By convention, desc 0 is the root descriptor.
926926

927+
// By convention, desc 0 is the root descriptor.
927928
llroottydesc = bld::Load(cx, llroottydesc);
928929
bld::Store(cx, llroottydesc, llmyroottydesc);
929-
// Store a pointer to the rest of the descriptors.
930930

931-
let llfirstparam = bld::GEP(cx, llparamtydescs, [C_int(0), C_int(0)]);
931+
// Store a pointer to the rest of the descriptors.
932932
store_inbounds(cx, llfirstparam, llmyroottydesc,
933933
[C_int(0), C_int(abi::tydesc_field_first_param)]);
934934
store_inbounds(cx, C_uint(n_params), llmyroottydesc,
@@ -937,10 +937,20 @@ fn trans_stack_local_derived_tydesc(cx: &@block_ctxt, llsz: ValueRef,
937937
[C_int(0), C_int(abi::tydesc_field_size)]);
938938
store_inbounds(cx, llalign, llmyroottydesc,
939939
[C_int(0), C_int(abi::tydesc_field_align)]);
940+
store_inbounds(cx, C_uint(obj_params), llmyroottydesc,
941+
[C_int(0), C_int(abi::tydesc_field_obj_params)]);
940942
ret llmyroottydesc;
941943
}
942944

945+
// Objects store their type parameters differently (in the object itself
946+
// rather than in the type descriptor).
947+
tag ty_param_storage {
948+
tps_normal;
949+
tps_obj(uint);
950+
}
951+
943952
fn get_derived_tydesc(cx: &@block_ctxt, t: ty::t, escapes: bool,
953+
storage: ty_param_storage,
944954
static_ti: &mutable option::t<@tydesc_info>) -> result {
945955
alt cx.fcx.derived_tydescs.find(t) {
946956
some(info) {
@@ -954,10 +964,7 @@ fn get_derived_tydesc(cx: &@block_ctxt, t: ty::t, escapes: bool,
954964
}
955965
bcx_ccx(cx).stats.n_derived_tydescs += 1u;
956966
let bcx = new_raw_block_ctxt(cx.fcx, cx.fcx.llderivedtydescs);
957-
let n_params: uint = ty::count_ty_params(bcx_tcx(bcx), t);
958967
let tys = linearize_ty_params(bcx, t);
959-
assert (n_params == std::vec::len::<uint>(tys.params));
960-
assert (n_params == std::vec::len::<ValueRef>(tys.descs));
961968
let root_ti = get_static_tydesc(bcx, t, tys.params);
962969
static_ti = some::<@tydesc_info>(root_ti);
963970
lazily_emit_all_tydesc_glue(cx, static_ti);
@@ -966,43 +973,52 @@ fn get_derived_tydesc(cx: &@block_ctxt, t: ty::t, escapes: bool,
966973
bcx = sz.bcx;
967974
let align = align_of(bcx, t);
968975
bcx = align.bcx;
969-
let v;
976+
977+
// Store the captured type descriptors in an alloca if the caller isn't
978+
// promising to do so itself.
979+
let n_params = ty::count_ty_params(bcx_tcx(bcx), t);
980+
981+
assert (n_params == std::vec::len::<uint>(tys.params));
982+
assert (n_params == std::vec::len::<ValueRef>(tys.descs));
983+
984+
let llparamtydescs =
985+
alloca(bcx, T_array(T_ptr(bcx_ccx(bcx).tydesc_type), n_params + 1u));
986+
let i = 0;
987+
988+
// If the type descriptor escapes, we need to add in the root as
989+
// the first parameter, because upcall_get_type_desc() expects it.
970990
if escapes {
971-
/* for root*/
972-
let tydescs =
973-
alloca(bcx,
974-
T_array(T_ptr(bcx_ccx(bcx).tydesc_type), 1u + n_params));
975-
let i = 0;
976-
let tdp = bld::GEP(bcx, tydescs, [C_int(0), C_int(i)]);
977-
bld::Store(bcx, root, tdp);
991+
bld::Store(bcx, root, GEPi(bcx, llparamtydescs, [0, 0]));
978992
i += 1;
979-
for td: ValueRef in tys.descs {
980-
let tdp = bld::GEP(bcx, tydescs, [C_int(0), C_int(i)]);
981-
bld::Store(bcx, td, tdp);
982-
i += 1;
983-
}
984-
let lltydescsptr =
985-
bld::PointerCast(bcx, tydescs,
986-
T_ptr(T_ptr(bcx_ccx(bcx).tydesc_type)));
993+
}
994+
995+
for td: ValueRef in tys.descs {
996+
bld::Store(bcx, td, GEPi(bcx, llparamtydescs, [0, i]));
997+
i += 1;
998+
}
999+
1000+
let llfirstparam =
1001+
bld::PointerCast(bcx, llparamtydescs,
1002+
T_ptr(T_ptr(bcx_ccx(bcx).tydesc_type)));
1003+
1004+
let obj_params;
1005+
alt storage {
1006+
tps_normal. { obj_params = 0u; }
1007+
tps_obj(np) { obj_params = np; }
1008+
}
1009+
1010+
let v;
1011+
if escapes {
9871012
let td_val =
9881013
bld::Call(bcx, bcx_ccx(bcx).upcalls.get_type_desc,
9891014
[bcx.fcx.lltaskptr, C_null(T_ptr(T_nil())), sz.val,
990-
align.val, C_int(1u + n_params as int),
991-
lltydescsptr]);
1015+
align.val, C_uint(1u + n_params),
1016+
llfirstparam, C_uint(obj_params)]);
9921017
v = td_val;
9931018
} else {
994-
let llparamtydescs =
995-
alloca(bcx,
996-
T_array(T_ptr(bcx_ccx(bcx).tydesc_type), n_params + 1u));
997-
let i = 0;
998-
for td: ValueRef in tys.descs {
999-
let tdp = bld::GEP(bcx, llparamtydescs, [C_int(0), C_int(i)]);
1000-
bld::Store(bcx, td, tdp);
1001-
i += 1;
1002-
}
1003-
v =
1004-
trans_stack_local_derived_tydesc(bcx, sz.val, align.val, root,
1005-
llparamtydescs, n_params);
1019+
v = trans_stack_local_derived_tydesc(bcx, sz.val, align.val, root,
1020+
llfirstparam, n_params,
1021+
obj_params);
10061022
}
10071023
bcx.fcx.derived_tydescs.insert(t, {lltydesc: v, escapes: escapes});
10081024
ret rslt(cx, v);
@@ -1011,6 +1027,7 @@ fn get_derived_tydesc(cx: &@block_ctxt, t: ty::t, escapes: bool,
10111027
type get_tydesc_result = {kind: tydesc_kind, result: result};
10121028

10131029
fn get_tydesc(cx: &@block_ctxt, orig_t: ty::t, escapes: bool,
1030+
storage: ty_param_storage,
10141031
static_ti: &mutable option::t<@tydesc_info>) ->
10151032
get_tydesc_result {
10161033

@@ -1036,7 +1053,7 @@ fn get_tydesc(cx: &@block_ctxt, orig_t: ty::t, escapes: bool,
10361053
// Does it contain a type param? If so, generate a derived tydesc.
10371054
if ty::type_contains_params(bcx_tcx(cx), t) {
10381055
ret {kind: tk_derived,
1039-
result: get_derived_tydesc(cx, t, escapes, static_ti)};
1056+
result: get_derived_tydesc(cx, t, escapes, storage, static_ti)};
10401057
}
10411058

10421059
// Otherwise, generate a tydesc if necessary, and return it.
@@ -1264,7 +1281,8 @@ fn emit_tydescs(ccx: &@crate_ctxt) {
12641281
cmp_glue, // cmp_glue
12651282
C_shape(ccx, shape), // shape
12661283
shape_tables, // shape_tables
1267-
C_int(0)]); // n_params
1284+
C_int(0), // n_params
1285+
C_int(0)]); // n_obj_params
12681286

12691287
let gvar = ti.tydesc;
12701288
llvm::LLVMSetInitializer(gvar, tydesc);
@@ -1483,7 +1501,7 @@ fn trans_res_drop(cx: @block_ctxt, rs: ValueRef, did: &ast::def_id,
14831501
let args = [cx.fcx.llretptr, cx.fcx.lltaskptr, dtor_env];
14841502
for tp: ty::t in tps {
14851503
let ti: option::t<@tydesc_info> = none;
1486-
let td = get_tydesc(cx, tp, false, ti).result;
1504+
let td = get_tydesc(cx, tp, false, tps_normal, ti).result;
14871505
args += [td.val];
14881506
cx = td.bcx;
14891507
}
@@ -2143,7 +2161,7 @@ fn call_tydesc_glue_full(cx: &@block_ctxt, v: ValueRef, tydesc: ValueRef,
21432161
fn call_tydesc_glue(cx: &@block_ctxt, v: ValueRef, t: ty::t, field: int) ->
21442162
result {
21452163
let ti: option::t<@tydesc_info> = none::<@tydesc_info>;
2146-
let td = get_tydesc(cx, t, false, ti).result;
2164+
let td = get_tydesc(cx, t, false, tps_normal, ti).result;
21472165
call_tydesc_glue_full(td.bcx, spill_if_immediate(td.bcx, v, t), td.val,
21482166
field, ti);
21492167
ret rslt(td.bcx, C_nil());
@@ -2159,7 +2177,7 @@ fn call_cmp_glue(cx: &@block_ctxt, lhs: ValueRef, rhs: ValueRef, t: ty::t,
21592177
let llrawlhsptr = bld::BitCast(cx, lllhs, T_ptr(T_i8()));
21602178
let llrawrhsptr = bld::BitCast(cx, llrhs, T_ptr(T_i8()));
21612179
let ti = none::<@tydesc_info>;
2162-
let r = get_tydesc(cx, t, false, ti).result;
2180+
let r = get_tydesc(cx, t, false, tps_normal, ti).result;
21632181
lazily_emit_tydesc_glue(cx, abi::tydesc_field_cmp_glue, ti);
21642182
let lltydesc = r.val;
21652183
let lltydescs =
@@ -2194,7 +2212,8 @@ fn call_copy_glue(cx: &@block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t,
21942212
let srcptr = bld::BitCast(cx, src, T_ptr(T_i8()));
21952213
let dstptr = bld::BitCast(cx, dst, T_ptr(T_i8()));
21962214
let ti = none;
2197-
let {bcx, val: lltydesc} = get_tydesc(cx, t, false, ti).result;
2215+
let {bcx, val: lltydesc} =
2216+
get_tydesc(cx, t, false, tps_normal, ti).result;
21982217
lazily_emit_tydesc_glue(cx, abi::tydesc_field_copy_glue, ti);
21992218
let lltydescs = bld::GEP
22002219
(bcx, lltydesc, [C_int(0), C_int(abi::tydesc_field_first_param)]);
@@ -2594,10 +2613,10 @@ fn trans_evec_append(cx: &@block_ctxt, t: ty::t, lhs: ValueRef,
25942613
}
25952614
let bcx = cx;
25962615
let ti = none::<@tydesc_info>;
2597-
let llvec_tydesc = get_tydesc(bcx, t, false, ti).result;
2616+
let llvec_tydesc = get_tydesc(bcx, t, false, tps_normal, ti).result;
25982617
bcx = llvec_tydesc.bcx;
25992618
ti = none::<@tydesc_info>;
2600-
let llelt_tydesc = get_tydesc(bcx, elt_ty, false, ti).result;
2619+
let llelt_tydesc = get_tydesc(bcx, elt_ty, false, tps_normal, ti).result;
26012620
lazily_emit_tydesc_glue(cx, abi::tydesc_field_take_glue, ti);
26022621
lazily_emit_tydesc_glue(cx, abi::tydesc_field_drop_glue, ti);
26032622
lazily_emit_tydesc_glue(cx, abi::tydesc_field_free_glue, ti);
@@ -2956,7 +2975,8 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
29562975
if copying {
29572976
let bound_tydesc = GEPi(bcx, closure, [0, abi::closure_elt_tydesc]);
29582977
let ti = none;
2959-
let bindings_tydesc = get_tydesc(bcx, bindings_ty, true, ti).result;
2978+
let bindings_tydesc =
2979+
get_tydesc(bcx, bindings_ty, true, tps_normal, ti).result;
29602980
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
29612981
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);
29622982
bcx = bindings_tydesc.bcx;
@@ -3273,7 +3293,7 @@ fn lval_generic_fn(cx: &@block_ctxt, tpt: &ty::ty_param_kinds_and_ty,
32733293
// TODO: Doesn't always escape.
32743294

32753295
let ti = none::<@tydesc_info>;
3276-
let td = get_tydesc(bcx, t, true, ti).result;
3296+
let td = get_tydesc(bcx, t, true, tps_normal, ti).result;
32773297
tis += [ti];
32783298
bcx = td.bcx;
32793299
tydescs += [td.val];
@@ -4526,7 +4546,7 @@ fn trans_log(lvl: int, cx: &@block_ctxt, e: &@ast::expr) -> result {
45264546
let log_bcx = sub.bcx;
45274547

45284548
let ti = none::<@tydesc_info>;
4529-
let r = get_tydesc(log_bcx, e_ty, false, ti).result;
4549+
let r = get_tydesc(log_bcx, e_ty, false, tps_normal, ti).result;
45304550
log_bcx = r.bcx;
45314551

45324552
// Call the polymorphic log function.

src/comp/middle/trans_common.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ fn T_tydesc(taskptr_type: TypeRef) -> TypeRef {
640640
let elems =
641641
[tydescpp, T_int(), T_int(), glue_fn_ty, glue_fn_ty, glue_fn_ty,
642642
copy_glue_fn_ty, glue_fn_ty, glue_fn_ty, glue_fn_ty, cmp_glue_fn_ty,
643-
T_ptr(T_i8()), T_ptr(T_i8()), T_int()];
643+
T_ptr(T_i8()), T_ptr(T_i8()), T_int(), T_int()];
644644
set_struct_body(tydesc, elems);
645645
ret tydesc;
646646
}

src/comp/middle/trans_ivec.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import trans::{call_memmove, trans_shared_malloc, llsize_of,
88
alloca, array_alloca, size_of, llderivedtydescs_block_ctxt,
99
lazily_emit_tydesc_glue, get_tydesc, load_inbounds,
1010
move_val_if_temp, trans_lval, node_id_type,
11-
new_sub_block_ctxt};
11+
new_sub_block_ctxt, tps_normal};
1212
import bld = trans_build;
1313
import trans_common::*;
1414

@@ -360,9 +360,9 @@ fn trans_append(cx: &@block_ctxt, t: ty::t, lhs: ValueRef,
360360
// FIXME (issue #511): This is needed to prevent a leak.
361361
let no_tydesc_info = none;
362362

363-
rs = get_tydesc(bcx, t, false, no_tydesc_info).result;
363+
rs = get_tydesc(bcx, t, false, tps_normal, no_tydesc_info).result;
364364
bcx = rs.bcx;
365-
rs = get_tydesc(bcx, unit_ty, false, no_tydesc_info).result;
365+
rs = get_tydesc(bcx, unit_ty, false, tps_normal, no_tydesc_info).result;
366366
bcx = rs.bcx;
367367
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_take_glue, none);
368368
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, none);
@@ -448,7 +448,8 @@ fn trans_append_literal(bcx: &@block_ctxt, v: ValueRef, vec_ty: ty::t,
448448
vals: &[@ast::expr]) -> @block_ctxt {
449449
let elt_ty = ty::sequence_element_type(bcx_tcx(bcx), vec_ty);
450450
let ti = none;
451-
let {bcx, val: td} = get_tydesc(bcx, elt_ty, false, ti).result;
451+
let {bcx, val: td} =
452+
get_tydesc(bcx, elt_ty, false, tps_normal, ti).result;
452453
trans::lazily_emit_all_tydesc_glue(bcx, ti);
453454
let opaque_v = bld::PointerCast(bcx, v, T_ptr(T_opaque_ivec()));
454455
for val in vals {

src/comp/middle/trans_objects.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import std::str;
44
import std::option;
5+
import std::vec;
56
import option::none;
67
import option::some;
78

@@ -133,7 +134,14 @@ fn trans_obj(cx: @local_ctxt, sp: &span, ob: &ast::_obj,
133134
GEP_tup_like(bcx, body_ty, body, [0, abi::obj_body_elt_tydesc]);
134135
bcx = body_tydesc.bcx;
135136
let ti = none::<@tydesc_info>;
136-
let body_td = get_tydesc(bcx, body_ty, true, ti).result;
137+
138+
let r = GEP_tup_like(bcx, body_ty, body,
139+
[0, abi::obj_body_elt_typarams]);
140+
bcx = r.bcx;
141+
let body_typarams = r.val;
142+
143+
let storage = tps_obj(vec::len(ty_params));
144+
let body_td = get_tydesc(bcx, body_ty, true, storage, ti).result;
137145
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
138146
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);
139147
bcx = body_td.bcx;
@@ -147,16 +155,13 @@ fn trans_obj(cx: @local_ctxt, sp: &span, ob: &ast::_obj,
147155
// Likewise for the object's fields.)
148156

149157
// Copy typarams into captured typarams.
150-
let body_typarams =
151-
GEP_tup_like(bcx, body_ty, body, [0, abi::obj_body_elt_typarams]);
152-
bcx = body_typarams.bcx;
153158
// TODO: can we just get typarams_ty out of body_ty instead?
154159
let typarams_ty: ty::t = ty::mk_tup(ccx.tcx, tps);
155160
let i: int = 0;
156161
for tp: ast::ty_param in ty_params {
157162
let typaram = bcx.fcx.lltydescs[i];
158163
let capture =
159-
GEP_tup_like(bcx, typarams_ty, body_typarams.val, [0, i]);
164+
GEP_tup_like(bcx, typarams_ty, body_typarams, [0, i]);
160165
bcx = capture.bcx;
161166
bcx = copy_val(bcx, INIT, capture.val, typaram, tydesc_ty);
162167
i += 1;
@@ -323,7 +328,7 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: &span, anon_obj: &ast::anon_obj,
323328
GEP_tup_like(bcx, body_ty, body, [0, abi::obj_body_elt_tydesc]);
324329
bcx = body_tydesc.bcx;
325330
let ti = none::<@tydesc_info>;
326-
let body_td = get_tydesc(bcx, body_ty, true, ti).result;
331+
let body_td = get_tydesc(bcx, body_ty, true, tps_normal, ti).result;
327332
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
328333
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);
329334
bcx = body_td.bcx;

src/rt/rust_crate_cache.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ type_desc *
55
rust_crate_cache::get_type_desc(size_t size,
66
size_t align,
77
size_t n_descs,
8-
type_desc const **descs)
8+
type_desc const **descs,
9+
uintptr_t n_obj_params)
910
{
1011
I(sched, n_descs > 1);
1112
type_desc *td = NULL;
@@ -35,6 +36,7 @@ rust_crate_cache::get_type_desc(size_t size,
3536
// FIXME (issue #136): Below is a miscalculation.
3637
td->is_stateful |= descs[i]->is_stateful;
3738
}
39+
td->n_obj_params = n_obj_params;
3840
HASH_ADD(hh, this->type_descs, descs, keysz, td);
3941
return td;
4042
}

0 commit comments

Comments
 (0)