Skip to content

Commit 117d21d

Browse files
committed
rustc: Stub stack map generation machinery
1 parent 51af43f commit 117d21d

File tree

5 files changed

+124
-46
lines changed

5 files changed

+124
-46
lines changed

src/comp/middle/gc.rs

+75-13
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,96 @@
11
// Routines useful for garbage collection.
22

3+
import lib::llvm::False;
4+
import lib::llvm::True;
35
import lib::llvm::llvm::ValueRef;
46
import middle::trans::get_tydesc;
57
import middle::trans_common::*;
68
import middle::ty;
79
import std::option::none;
10+
import std::option::some;
811
import std::ptr;
912
import std::str;
1013
import std::unsafe;
14+
import std::vec;
1115

1216
import lll = lib::llvm::llvm;
1317

18+
type ctxt = @{ mutable next_tydesc_num: uint };
19+
20+
fn mk_ctxt() -> ctxt {
21+
ret @{ mutable next_tydesc_num: 0u };
22+
}
23+
24+
fn add_global(ccx: &@crate_ctxt, llval: ValueRef, name: str) -> ValueRef {
25+
let llglobal = lll::LLVMAddGlobal(ccx.llmod, val_ty(llval),
26+
str::buf(name));
27+
lll::LLVMSetInitializer(llglobal, llval);
28+
lll::LLVMSetGlobalConstant(llglobal, True);
29+
ret llglobal;
30+
}
31+
1432
fn add_gc_root(cx: &@block_ctxt, llval: ValueRef, ty: ty::t) -> @block_ctxt {
1533
let bcx = cx;
16-
if !type_is_gc_relevant(bcx_tcx(cx), ty) { ret bcx; }
34+
if !type_is_gc_relevant(bcx_tcx(cx), ty) ||
35+
ty::type_has_dynamic_size(bcx_tcx(cx), ty) {
36+
ret bcx;
37+
}
1738

18-
let md_kind_name = "rusttydesc";
19-
let md_kind = lll::LLVMGetMDKindID(str::buf(md_kind_name),
20-
str::byte_len(md_kind_name));
39+
let gc_cx = bcx_ccx(cx).gc_cx;
2140

2241
let ti = none;
23-
let r = get_tydesc(bcx, ty, false, ti);
24-
bcx = r.bcx;
25-
let lltydesc = r.val;
42+
let td_r = get_tydesc(bcx, ty, false, ti);
43+
bcx = td_r.result.bcx;
44+
let lltydesc = td_r.result.val;
45+
46+
let gcroot = bcx_ccx(bcx).intrinsics.get("llvm.gcroot");
47+
let llvalptr = bcx.build.PointerCast(llval, T_ptr(T_ptr(T_i8())));
48+
49+
alt td_r.kind {
50+
tk_derived. {
51+
// It's a derived type descriptor. First, spill it.
52+
let lltydescptr = trans::alloca(bcx, val_ty(lltydesc));
53+
bcx.build.Store(lltydesc, lltydescptr);
54+
55+
let number = gc_cx.next_tydesc_num;
56+
gc_cx.next_tydesc_num += 1u;
57+
58+
let lldestindex = add_global(bcx_ccx(bcx),
59+
C_struct(~[C_int(0),
60+
C_uint(number)]),
61+
"rust_gc_tydesc_dest_index");
62+
let llsrcindex = add_global(bcx_ccx(bcx),
63+
C_struct(~[C_int(1), C_uint(number)]),
64+
"rust_gc_tydesc_src_index");
65+
66+
lldestindex = lll::LLVMConstPointerCast(lldestindex,
67+
T_ptr(T_i8()));
68+
llsrcindex = lll::LLVMConstPointerCast(llsrcindex,
69+
T_ptr(T_i8()));
70+
71+
lltydescptr = bcx.build.PointerCast(lltydescptr,
72+
T_ptr(T_ptr(T_i8())));
73+
74+
bcx.build.Call(gcroot, ~[ lltydescptr, lldestindex ]);
75+
bcx.build.Call(gcroot, ~[ llvalptr, llsrcindex ]);
76+
}
77+
tk_param. {
78+
bcx_tcx(cx).sess.bug("we should never be trying to root values " +
79+
"of a type parameter");
80+
}
81+
tk_static. {
82+
// Static type descriptor.
83+
84+
let llstaticgcmeta = add_global(bcx_ccx(bcx),
85+
C_struct(~[C_int(2), lltydesc]),
86+
"rust_gc_tydesc_static_gc_meta");
87+
let llstaticgcmetaptr = lll::LLVMConstPointerCast(llstaticgcmeta,
88+
T_ptr(T_i8()));
89+
90+
bcx.build.Call(gcroot, ~[ llvalptr, llstaticgcmetaptr ]);
91+
}
92+
}
2693

27-
let llmdnode =
28-
lll::LLVMMDNode(unsafe::reinterpret_cast(ptr::addr_of(lltydesc)), 1u);
29-
lll::LLVMSetMetadata(llval, md_kind, llmdnode);
3094
ret bcx;
3195
}
3296

@@ -57,9 +121,7 @@ fn type_is_gc_relevant(cx: &ty::ctxt, ty: &ty::t) -> bool {
57121
for variant in variants {
58122
for aty in variant.args {
59123
let arg_ty = ty::substitute_type_params(cx, tps, aty);
60-
if type_is_gc_relevant(cx, arg_ty) {
61-
ret true;
62-
}
124+
if type_is_gc_relevant(cx, arg_ty) { ret true; }
63125
}
64126
}
65127
ret false;

src/comp/middle/trans.rs

+30-18
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import std::option::some;
2323
import std::option::none;
2424
import std::fs;
2525
import std::time;
26+
import std::vec;
2627
import syntax::ast;
2728
import driver::session;
2829
import middle::ty;
@@ -901,7 +902,7 @@ fn trans_malloc_boxed(cx: &@block_ctxt, t: ty::t) ->
901902
fn field_of_tydesc(cx: &@block_ctxt, t: &ty::t, escapes: bool, field: int) ->
902903
result {
903904
let ti = none::<@tydesc_info>;
904-
let tydesc = get_tydesc(cx, t, escapes, ti);
905+
let tydesc = get_tydesc(cx, t, escapes, ti).result;
905906
ret rslt(tydesc.bcx,
906907
tydesc.bcx.build.GEP(tydesc.val, ~[C_int(0), C_int(field)]));
907908
}
@@ -1028,16 +1029,19 @@ fn get_derived_tydesc(cx: &@block_ctxt, t: &ty::t, escapes: bool,
10281029
ret rslt(cx, v);
10291030
}
10301031

1032+
type get_tydesc_result = { kind: tydesc_kind, result: result };
1033+
10311034
fn get_tydesc(cx: &@block_ctxt, orig_t: &ty::t, escapes: bool,
1032-
static_ti: &mutable option::t<@tydesc_info>) -> result {
1035+
static_ti: &mutable option::t<@tydesc_info>)
1036+
-> get_tydesc_result {
10331037

10341038
let t = ty::strip_cname(bcx_tcx(cx), orig_t);
10351039

10361040
// Is the supplied type a type param? If so, return the passed-in tydesc.
10371041
alt ty::type_param(bcx_tcx(cx), t) {
10381042
some(id) {
1039-
if id < std::vec::len(cx.fcx.lltydescs) {
1040-
ret rslt(cx, cx.fcx.lltydescs.(id));
1043+
if id < vec::len(cx.fcx.lltydescs) {
1044+
ret { kind: tk_param, result: rslt(cx, cx.fcx.lltydescs.(id)) };
10411045
}
10421046
else {
10431047
bcx_tcx(cx).sess.span_bug(cx.sp, "Unbound typaram in get_tydesc: "
@@ -1050,13 +1054,16 @@ fn get_tydesc(cx: &@block_ctxt, orig_t: &ty::t, escapes: bool,
10501054

10511055
// Does it contain a type param? If so, generate a derived tydesc.
10521056
if ty::type_contains_params(bcx_tcx(cx), t) {
1053-
ret get_derived_tydesc(cx, t, escapes, static_ti);
1057+
ret {
1058+
kind: tk_derived,
1059+
result: get_derived_tydesc(cx, t, escapes, static_ti)
1060+
};
10541061
}
10551062

10561063
// Otherwise, generate a tydesc if necessary, and return it.
10571064
let info = get_static_tydesc(cx, t, ~[]);
10581065
static_ti = some::<@tydesc_info>(info);
1059-
ret rslt(cx, info.tydesc);
1066+
ret { kind: tk_static, result: rslt(cx, info.tydesc) };
10601067
}
10611068

10621069
fn get_static_tydesc(cx: &@block_ctxt, orig_t: &ty::t, ty_params: &[uint]) ->
@@ -1484,9 +1491,9 @@ fn trans_res_drop(cx: @block_ctxt, rs: ValueRef, did: &ast::def_id,
14841491
cx.build.Load(cx.build.GEP(dtor_pair,
14851492
~[C_int(0), C_int(abi::fn_field_box)]));
14861493
let args = ~[cx.fcx.llretptr, cx.fcx.lltaskptr, dtor_env];
1487-
for tp: ty::t in tps {
1494+
for tp: ty::t in tps {
14881495
let ti: option::t<@tydesc_info> = none;
1489-
let td = get_tydesc(cx, tp, false, ti);
1496+
let td = get_tydesc(cx, tp, false, ti).result;
14901497
args += ~[td.val];
14911498
cx = td.bcx;
14921499
}
@@ -2130,7 +2137,7 @@ fn call_tydesc_glue_full(cx: &@block_ctxt, v: ValueRef, tydesc: ValueRef,
21302137
fn call_tydesc_glue(cx: &@block_ctxt, v: ValueRef, t: &ty::t, field: int) ->
21312138
result {
21322139
let ti: option::t<@tydesc_info> = none::<@tydesc_info>;
2133-
let td = get_tydesc(cx, t, false, ti);
2140+
let td = get_tydesc(cx, t, false, ti).result;
21342141
call_tydesc_glue_full(td.bcx, spill_if_immediate(td.bcx, v, t), td.val,
21352142
field, ti);
21362143
ret rslt(td.bcx, C_nil());
@@ -2146,7 +2153,7 @@ fn call_cmp_glue(cx: &@block_ctxt, lhs: ValueRef, rhs: ValueRef, t: &ty::t,
21462153
let llrawlhsptr = cx.build.BitCast(lllhs, T_ptr(T_i8()));
21472154
let llrawrhsptr = cx.build.BitCast(llrhs, T_ptr(T_i8()));
21482155
let ti = none::<@tydesc_info>;
2149-
let r = get_tydesc(cx, t, false, ti);
2156+
let r = get_tydesc(cx, t, false, ti).result;
21502157
lazily_emit_tydesc_glue(cx, abi::tydesc_field_cmp_glue, ti);
21512158
let lltydesc = r.val;
21522159
let lltydescs =
@@ -2561,10 +2568,10 @@ fn trans_vec_append(cx: &@block_ctxt, t: &ty::t, lhs: ValueRef, rhs: ValueRef)
25612568
}
25622569
let bcx = cx;
25632570
let ti = none::<@tydesc_info>;
2564-
let llvec_tydesc = get_tydesc(bcx, t, false, ti);
2571+
let llvec_tydesc = get_tydesc(bcx, t, false, ti).result;
25652572
bcx = llvec_tydesc.bcx;
25662573
ti = none::<@tydesc_info>;
2567-
let llelt_tydesc = get_tydesc(bcx, elt_ty, false, ti);
2574+
let llelt_tydesc = get_tydesc(bcx, elt_ty, false, ti).result;
25682575
lazily_emit_tydesc_glue(cx, abi::tydesc_field_copy_glue, ti);
25692576
lazily_emit_tydesc_glue(cx, abi::tydesc_field_drop_glue, ti);
25702577
lazily_emit_tydesc_glue(cx, abi::tydesc_field_free_glue, ti);
@@ -2819,9 +2826,9 @@ mod ivec {
28192826
// FIXME (issue #511): This is needed to prevent a leak.
28202827
let no_tydesc_info = none;
28212828

2822-
rs = get_tydesc(bcx, t, false, no_tydesc_info);
2829+
rs = get_tydesc(bcx, t, false, no_tydesc_info).result;
28232830
bcx = rs.bcx;
2824-
rs = get_tydesc(bcx, unit_ty, false, no_tydesc_info);
2831+
rs = get_tydesc(bcx, unit_ty, false, no_tydesc_info).result;
28252832
bcx = rs.bcx;
28262833
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_copy_glue, none);
28272834
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, none);
@@ -3527,7 +3534,7 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef],
35273534
if copying {
35283535
let bound_tydesc = GEPi(bcx, closure, ~[0, abi::closure_elt_tydesc]);
35293536
let ti = none;
3530-
let bindings_tydesc = get_tydesc(bcx, bindings_ty, true, ti);
3537+
let bindings_tydesc = get_tydesc(bcx, bindings_ty, true, ti).result;
35313538
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
35323539
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);
35333540
bcx = bindings_tydesc.bcx;
@@ -3848,7 +3855,7 @@ fn lval_generic_fn(cx: &@block_ctxt, tpt: &ty::ty_param_kinds_and_ty,
38483855
// TODO: Doesn't always escape.
38493856

38503857
let ti = none::<@tydesc_info>;
3851-
let td = get_tydesc(bcx, t, true, ti);
3858+
let td = get_tydesc(bcx, t, true, ti).result;
38523859
tis += ~[ti];
38533860
bcx = td.bcx;
38543861
tydescs += ~[td.val];
@@ -5254,7 +5261,7 @@ fn trans_log(lvl: int, cx: &@block_ctxt, e: &@ast::expr) -> result {
52545261
let log_bcx = sub.bcx;
52555262

52565263
let ti = none::<@tydesc_info>;
5257-
let r = get_tydesc(log_bcx, e_ty, false, ti);
5264+
let r = get_tydesc(log_bcx, e_ty, false, ti).result;
52585265
log_bcx = r.bcx;
52595266

52605267
// Call the polymorphic log function.
@@ -6926,6 +6933,9 @@ fn declare_intrinsics(llmod: ModuleRef) -> hashmap<str, ValueRef> {
69266933
let T_memset64_args: [TypeRef] =
69276934
~[T_ptr(T_i8()), T_i8(), T_i64(), T_i32(), T_i1()];
69286935
let T_trap_args: [TypeRef] = ~[];
6936+
let gcroot =
6937+
decl_cdecl_fn(llmod, "llvm.gcroot",
6938+
T_fn(~[T_ptr(T_ptr(T_i8())), T_ptr(T_i8())], T_void()));
69296939
let gcread =
69306940
decl_cdecl_fn(llmod, "llvm.gcread",
69316941
T_fn(~[T_ptr(T_i8()), T_ptr(T_ptr(T_i8()))], T_void()));
@@ -6943,6 +6953,7 @@ fn declare_intrinsics(llmod: ModuleRef) -> hashmap<str, ValueRef> {
69436953
T_fn(T_memset64_args, T_void()));
69446954
let trap = decl_cdecl_fn(llmod, "llvm.trap", T_fn(T_trap_args, T_void()));
69456955
let intrinsics = new_str_hash::<ValueRef>();
6956+
intrinsics.insert("llvm.gcroot", gcroot);
69466957
intrinsics.insert("llvm.gcread", gcread);
69476958
intrinsics.insert("llvm.memmove.p0i8.p0i8.i32", memmove32);
69486959
intrinsics.insert("llvm.memmove.p0i8.p0i8.i64", memmove64);
@@ -7142,7 +7153,8 @@ fn trans_crate(sess: &session::session, crate: &@ast::crate, tcx: &ty::ctxt,
71427153
rust_object_type: T_rust_object(),
71437154
tydesc_type: tydesc_type,
71447155
task_type: task_type,
7145-
shape_cx: shape::mk_ctxt(llmod)};
7156+
shape_cx: shape::mk_ctxt(llmod),
7157+
gc_cx: gc::mk_ctxt()};
71467158
let cx = new_local_ctxt(ccx);
71477159
collect_items(ccx, crate);
71487160
collect_tag_ctors(ccx, crate);

src/comp/middle/trans_common.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ type derived_tydesc_info = {lltydesc: ValueRef, escapes: bool};
7070

7171
type glue_fns = {no_op_type_glue: ValueRef};
7272

73+
tag tydesc_kind {
74+
tk_static; // Static (monomorphic) type descriptor.
75+
tk_param; // Type parameter.
76+
tk_derived; // Derived from a typaram or another derived tydesc.
77+
}
78+
7379
type tydesc_info =
7480
{ty: ty::t,
7581
tydesc: ValueRef,
@@ -142,7 +148,8 @@ type crate_ctxt = {
142148
rust_object_type: TypeRef,
143149
tydesc_type: TypeRef,
144150
task_type: TypeRef,
145-
shape_cx: shape::ctxt
151+
shape_cx: shape::ctxt,
152+
gc_cx: gc::ctxt
146153
};
147154

148155
type local_ctxt =

src/comp/middle/trans_objects.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ fn trans_obj(cx: @local_ctxt, sp: &span, ob: &ast::_obj,
133133
~[0, abi::obj_body_elt_tydesc]);
134134
bcx = body_tydesc.bcx;
135135
let ti = none::<@tydesc_info>;
136-
let body_td = get_tydesc(bcx, body_ty, true, ti);
136+
let body_td = get_tydesc(bcx, body_ty, true, ti).result;
137137
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
138138
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);
139139
bcx = body_td.bcx;
@@ -327,7 +327,7 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: &span, anon_obj: &ast::anon_obj,
327327
~[0, abi::obj_body_elt_tydesc]);
328328
bcx = body_tydesc.bcx;
329329
let ti = none::<@tydesc_info>;
330-
let body_td = get_tydesc(bcx, body_ty, true, ti);
330+
let body_td = get_tydesc(bcx, body_ty, true, ti).result;
331331
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
332332
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_free_glue, ti);
333333
bcx = body_td.bcx;

src/rustllvm/RustGCStrategy.cpp

+9-12
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,16 @@
1616

1717
using namespace llvm;
1818

19-
namespace {
20-
class RustGCStrategy : public GCStrategy {
21-
public:
22-
RustGCStrategy();
23-
};
24-
}
19+
class RustGCStrategy : public GCStrategy {
20+
public:
21+
RustGCStrategy() {
22+
NeededSafePoints = 1 << GC::PostCall;
23+
UsesMetadata = true;
24+
InitRoots = false; // LLVM crashes with this on due to bitcasts.
25+
}
26+
};
2527

2628
static GCRegistry::Add<RustGCStrategy>
27-
X("rust", "Rust GC");
28-
29-
RustGCStrategy::RustGCStrategy() {
30-
NeededSafePoints = 1 << GC::PostCall;
31-
UsesMetadata = true;
32-
}
29+
RustGCStrategyRegistration("rust", "Rust GC");
3330

3431

0 commit comments

Comments
 (0)