Add stats option and lazily emit glue.

This commit is contained in:
Graydon Hoare 2011-05-12 15:42:12 -07:00
parent 295c037aac
commit 5ceaf345ed
3 changed files with 267 additions and 84 deletions

View File

@ -158,6 +158,7 @@ options:
-S compile only; do not assemble or link
-c compile and assemble, but do not link
--save-temps write intermediate files in addition to normal output
--stats gather and report various compilation statistics
--time-passes time the individual phases of the compiler
--time-llvm-passes time the individual phases of the LLVM backend
--sysroot <path> override the system root (default: rustc's directory)
@ -212,6 +213,7 @@ fn main(vec[str] args) {
optflag("O"), optflag("shared"), optmulti("L"),
optflag("S"), optflag("c"), optopt("o"), optflag("g"),
optflag("save-temps"), optopt("sysroot"),
optflag("stats"),
optflag("time-passes"), optflag("time-llvm-passes"),
optflag("no-typestate"), optflag("noverify"));
auto binary = _vec::shift[str](args);
@ -256,6 +258,7 @@ fn main(vec[str] args) {
// FIXME: Maybe we should support -O0, -O1, -Os, etc
auto optimize = opt_present(match, "O");
auto debuginfo = opt_present(match, "g");
auto stats = opt_present(match, "stats");
auto time_passes = opt_present(match, "time-passes");
auto time_llvm_passes = opt_present(match, "time-llvm-passes");
auto run_typestate = !opt_present(match, "no-typestate");
@ -274,6 +277,7 @@ fn main(vec[str] args) {
verify = verify,
run_typestate = run_typestate,
save_temps = save_temps,
stats = stats,
time_passes = time_passes,
time_llvm_passes = time_llvm_passes,
output_type = output_type,

View File

@ -31,6 +31,7 @@ type options = rec(bool shared,
bool verify,
bool run_typestate,
bool save_temps,
bool stats,
bool time_passes,
bool time_llvm_passes,
back::Link::output_type output_type,

View File

@ -63,10 +63,14 @@ type glue_fns = rec(ValueRef activate_glue,
ValueRef no_op_type_glue,
ValueRef vec_append_glue);
type tydesc_info = rec(ValueRef tydesc,
ValueRef take_glue,
ValueRef drop_glue,
ValueRef cmp_glue);
type tydesc_info = rec(ty::t ty,
ValueRef tydesc,
ValueRef size,
ValueRef align,
mutable option::t[ValueRef] take_glue,
mutable option::t[ValueRef] drop_glue,
mutable option::t[ValueRef] cmp_glue,
vec[uint] ty_params);
/*
* A note on nomenclature of linking: "upcall", "extern" and "native".
@ -87,6 +91,12 @@ type tydesc_info = rec(ValueRef tydesc,
*
*/
type stats = rec(mutable uint n_static_tydescs,
mutable uint n_derived_tydescs,
mutable uint n_glues_created,
mutable uint n_null_glues,
mutable uint n_real_glues);
state type crate_ctxt = rec(session::session sess,
ModuleRef llmod,
target_data td,
@ -117,6 +127,7 @@ state type crate_ctxt = rec(session::session sess,
hashmap[ty::t, metadata::ty_abbrev] type_abbrevs,
hashmap[ty::t, str] type_short_names,
ty::ctxt tcx,
stats stats,
@upcall::upcalls upcalls);
type local_ctxt = rec(vec[str] path,
@ -1576,7 +1587,8 @@ fn trans_malloc_boxed(&@block_ctxt cx, ty::t t) -> result {
// tydesc if necessary.
fn field_of_tydesc(&@block_ctxt cx, &ty::t t, bool escapes, int field)
-> result {
auto tydesc = get_tydesc(cx, t, escapes);
auto ti = none[@tydesc_info];
auto tydesc = get_tydesc(cx, t, escapes, ti);
ret res(tydesc.bcx,
tydesc.bcx.build.GEP(tydesc.val, vec(C_int(0), C_int(field))));
}
@ -1658,7 +1670,8 @@ fn trans_stack_local_derived_tydesc(&@block_ctxt cx, ValueRef llsz,
ret llmyroottydesc;
}
fn mk_derived_tydesc(&@block_ctxt cx, &ty::t t, bool escapes) -> result {
fn get_derived_tydesc(&@block_ctxt cx, &ty::t t, bool escapes,
&mutable option::t[@tydesc_info] static_ti) -> result {
alt (cx.fcx.derived_tydescs.find(t)) {
case (some[derived_tydesc_info](?info)) {
// If the tydesc escapes in this context, the cached derived
@ -1668,6 +1681,8 @@ fn mk_derived_tydesc(&@block_ctxt cx, &ty::t t, bool escapes) -> result {
case (none[derived_tydesc_info]) { /* fall through */ }
}
cx.fcx.lcx.ccx.stats.n_derived_tydescs += 1u;
auto bcx = new_raw_block_ctxt(cx.fcx, cx.fcx.llderivedtydescs);
let uint n_params = ty::count_ty_params(bcx.fcx.lcx.ccx.tcx, t);
@ -1676,7 +1691,10 @@ fn mk_derived_tydesc(&@block_ctxt cx, &ty::t t, bool escapes) -> result {
assert (n_params == _vec::len[uint](tys._0));
assert (n_params == _vec::len[ValueRef](tys._1));
auto root = get_static_tydesc(bcx, t, tys._0).tydesc;
auto root_ti = get_static_tydesc(bcx, t, tys._0);
static_ti = some[@tydesc_info](root_ti);
lazily_emit_all_tydesc_glue(cx, static_ti);
auto root = root_ti.tydesc;
auto sz = size_of(bcx, t);
bcx = sz.bcx;
@ -1737,7 +1755,8 @@ fn mk_derived_tydesc(&@block_ctxt cx, &ty::t t, bool escapes) -> result {
ret res(cx, v);
}
fn get_tydesc(&@block_ctxt cx, &ty::t t, bool escapes) -> result {
fn get_tydesc(&@block_ctxt cx, &ty::t t, bool escapes,
&mutable option::t[@tydesc_info] static_ti) -> result {
// Is the supplied type a type param? If so, return the passed-in tydesc.
alt (ty::type_param(cx.fcx.lcx.ccx.tcx, t)) {
case (some[uint](?id)) { ret res(cx, cx.fcx.lltydescs.(id)); }
@ -1747,13 +1766,14 @@ fn get_tydesc(&@block_ctxt cx, &ty::t t, bool escapes) -> result {
// Does it contain a type param? If so, generate a derived tydesc.
if (ty::type_contains_params(cx.fcx.lcx.ccx.tcx, t)) {
ret mk_derived_tydesc(cx, t, escapes);
ret get_derived_tydesc(cx, t, escapes, static_ti);
}
// Otherwise, generate a tydesc if necessary, and return it.
let vec[uint] tps = vec();
auto st = get_static_tydesc(cx, t, tps).tydesc;
ret res(cx, st);
auto info = get_static_tydesc(cx, t, tps);
static_ti = some[@tydesc_info](info);
ret res(cx, info.tydesc);
}
fn get_static_tydesc(&@block_ctxt cx,
@ -1763,34 +1783,18 @@ fn get_static_tydesc(&@block_ctxt cx,
ret info;
}
case (none[@tydesc_info]) {
// FIXME: Use of a simplified tydesc (w/o names) removes a lot of
// generated glue, but the compile time goes way down due to
// greatly increasing the miss rate on the type_of cache elsewhere
// in this file. Experiment with other approaches to this.
/*
fn simplifier(ty::t typ) -> ty::t {
ret @rec(cname=none[str] with *typ);
}
auto f = simplifier;
auto t_simplified = ty::fold_ty(cx.fcx.lcx.ccx.tcx, f, t);
auto info = declare_tydesc(cx.fcx.lcx, t_simplified);
cx.fcx.lcx.ccx.tydescs.insert(t_simplified, info);
*/
auto info = declare_tydesc(cx.fcx.lcx, t);
cx.fcx.lcx.ccx.stats.n_static_tydescs += 1u;
auto info = declare_tydesc(cx.fcx.lcx, t, ty_params);
cx.fcx.lcx.ccx.tydescs.insert(t, info);
define_tydesc(cx.fcx.lcx, t, ty_params);
ret info;
}
}
}
// Generates the declaration for (but doesn't fill in) a type descriptor. This
// needs to be separate from make_tydesc() below, because sometimes type glue
// functions needs to refer to their own type descriptors.
fn declare_tydesc(&@local_ctxt cx, &ty::t t) -> @tydesc_info {
// Generates the declaration for (but doesn't emit) a type descriptor.
fn declare_tydesc(&@local_ctxt cx, &ty::t t,
vec[uint] ty_params) -> @tydesc_info {
log "+++ declare_tydesc " + ty::ty_to_str(cx.ccx.tcx, t);
auto take_glue = declare_generic_glue(cx, t, T_glue_fn(cx.ccx.tn),
"take");
auto drop_glue = declare_generic_glue(cx, t, T_glue_fn(cx.ccx.tn),
@ -1812,8 +1816,6 @@ fn declare_tydesc(&@local_ctxt cx, &ty::t t) -> @tydesc_info {
llalign = C_int(0);
}
auto glue_fn_ty = T_ptr(T_glue_fn(ccx.tn));
auto name;
if (cx.ccx.sess.get_opts().debuginfo) {
name = mangle_name_by_type_only(cx.ccx, t, "tydesc");
@ -1823,31 +1825,18 @@ fn declare_tydesc(&@local_ctxt cx, &ty::t t) -> @tydesc_info {
}
auto gvar = llvm::LLVMAddGlobal(ccx.llmod, T_tydesc(ccx.tn),
_str::buf(name));
auto tydesc = C_struct(vec(C_null(T_ptr(T_ptr(T_tydesc(ccx.tn)))),
llsize,
llalign,
take_glue, // take_glue
drop_glue, // drop_glue
C_null(glue_fn_ty), // free_glue
C_null(glue_fn_ty), // sever_glue
C_null(glue_fn_ty), // mark_glue
C_null(glue_fn_ty), // obj_drop_glue
C_null(glue_fn_ty), // is_stateful
cmp_glue)); // cmp_glue
_str::buf(name));
llvm::LLVMSetInitializer(gvar, tydesc);
llvm::LLVMSetGlobalConstant(gvar, True);
llvm::LLVMSetLinkage(gvar, lib::llvm::LLVMInternalLinkage
as llvm::Linkage);
auto info = @rec(
tydesc=gvar,
take_glue=take_glue,
drop_glue=drop_glue,
cmp_glue=cmp_glue
);
auto info = @rec(ty = t,
tydesc = gvar,
size = llsize,
align = llalign,
mutable take_glue = none[ValueRef],
mutable drop_glue = none[ValueRef],
mutable cmp_glue = none[ValueRef],
ty_params = ty_params);
log "--- declare_tydesc " + ty::ty_to_str(cx.ccx.tcx, t);
ret info;
}
@ -1856,18 +1845,6 @@ tag make_generic_glue_helper_fn {
mgghf_cmp;
}
// declare_tydesc() above must have been called first.
fn define_tydesc(&@local_ctxt cx, &ty::t t, &vec[uint] ty_params) {
auto info = cx.ccx.tydescs.get(t);
auto gvar = info.tydesc;
auto tg = make_take_glue;
make_generic_glue(cx, t, info.take_glue, mgghf_single(tg), ty_params);
auto dg = make_drop_glue;
make_generic_glue(cx, t, info.drop_glue, mgghf_single(dg), ty_params);
make_generic_glue(cx, t, info.cmp_glue, mgghf_cmp, ty_params);
}
fn declare_generic_glue(&@local_ctxt cx,
&ty::t t,
TypeRef llfnty,
@ -1890,6 +1867,8 @@ fn make_generic_glue(&@local_ctxt cx,
&vec[uint] ty_params) -> ValueRef {
auto fcx = new_fn_ctxt(cx, llfn);
cx.ccx.stats.n_glues_created += 1u;
// Any nontrivial glue is with values passed *by alias*; this is a
// requirement since in many contexts glue is invoked indirectly and
// the caller has no idea if it's dealing with something that can be
@ -1945,6 +1924,70 @@ fn make_generic_glue(&@local_ctxt cx,
ret llfn;
}
fn emit_tydescs(&@crate_ctxt ccx) {
for each (@tup(ty::t, @tydesc_info) pair in ccx.tydescs.items()) {
auto glue_fn_ty = T_ptr(T_glue_fn(ccx.tn));
auto cmp_fn_ty = T_ptr(T_cmp_glue_fn(ccx.tn));
auto ti = pair._1;
auto take_glue = alt (ti.take_glue) {
case (none[ValueRef]) {
ccx.stats.n_null_glues += 1u;
C_null(glue_fn_ty)
}
case (some[ValueRef](?v)) {
ccx.stats.n_real_glues += 1u;
v
}
};
auto drop_glue = alt (ti.drop_glue) {
case (none[ValueRef]) {
ccx.stats.n_null_glues += 1u;
C_null(glue_fn_ty)
}
case (some[ValueRef](?v)) {
ccx.stats.n_real_glues += 1u;
v
}
};
auto cmp_glue = alt (ti.cmp_glue) {
case (none[ValueRef]) {
ccx.stats.n_null_glues += 1u;
C_null(cmp_fn_ty)
}
case (some[ValueRef](?v)) {
ccx.stats.n_real_glues += 1u;
v
}
};
auto tydesc = C_struct(vec(C_null(T_ptr(T_ptr(T_tydesc(ccx.tn)))),
ti.size,
ti.align,
take_glue, // take_glue
drop_glue, // drop_glue
C_null(glue_fn_ty), // free_glue
C_null(glue_fn_ty), // sever_glue
C_null(glue_fn_ty), // mark_glue
C_null(glue_fn_ty), // obj_drop_glue
C_null(glue_fn_ty), // is_stateful
cmp_glue)); // cmp_glue
auto gvar = ti.tydesc;
llvm::LLVMSetInitializer(gvar, tydesc);
llvm::LLVMSetGlobalConstant(gvar, True);
llvm::LLVMSetLinkage(gvar, lib::llvm::LLVMInternalLinkage
as llvm::Linkage);
}
}
fn make_take_glue(&@block_ctxt cx, ValueRef v, &ty::t t) {
// NB: v is an *alias* of type t here, not a direct value.
auto bcx;
@ -2068,8 +2111,9 @@ fn make_drop_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
auto cx_ = maybe_call_dtor(cx, o);
// Call through the obj's own fields-drop glue first.
auto ti = none[@tydesc_info];
call_tydesc_glue_full(cx_, body, tydesc,
abi::tydesc_field_drop_glue);
abi::tydesc_field_drop_glue, ti);
// Then free the body.
// FIXME: switch gc/non-gc on layer of the type.
@ -2106,8 +2150,9 @@ fn make_drop_glue(&@block_ctxt cx, ValueRef v0, &ty::t t) {
vec(C_int(0),
C_int(abi::closure_elt_tydesc)));
auto ti = none[@tydesc_info];
call_tydesc_glue_full(cx, bindings, cx.build.Load(tydescptr),
abi::tydesc_field_drop_glue);
abi::tydesc_field_drop_glue, ti);
// Then free the body.
@ -2210,7 +2255,10 @@ fn make_cmp_glue(&@block_ctxt cx,
} else if (ty::type_is_box(cx.fcx.lcx.ccx.tcx, t)) {
lhs = cx.build.GEP(lhs, vec(C_int(0), C_int(abi::box_rc_field_body)));
rhs = cx.build.GEP(rhs, vec(C_int(0), C_int(abi::box_rc_field_body)));
auto rslt = call_cmp_glue(cx, lhs, rhs, t, llop);
auto t_inner = alt (ty::struct(cx.fcx.lcx.ccx.tcx, t)) {
case (ty::ty_box(?ti)) { ti.ty }
};
auto rslt = call_cmp_glue(cx, lhs, rhs, t_inner, llop);
rslt.bcx.build.Store(rslt.val, cx.fcx.llretptr);
rslt.bcx.build.RetVoid();
@ -2838,8 +2886,97 @@ fn iter_sequence(@block_ctxt cx,
fail;
}
fn lazily_emit_all_tydesc_glue(&@block_ctxt cx,
&option::t[@tydesc_info] static_ti) {
lazily_emit_tydesc_glue(cx, abi::tydesc_field_take_glue, static_ti);
lazily_emit_tydesc_glue(cx, abi::tydesc_field_drop_glue, static_ti);
lazily_emit_tydesc_glue(cx, abi::tydesc_field_cmp_glue, static_ti);
}
fn lazily_emit_all_generic_info_tydesc_glues(&@block_ctxt cx,
&generic_info gi) {
for (option::t[@tydesc_info] ti in gi. static_tis) {
lazily_emit_all_tydesc_glue(cx, ti);
}
}
fn lazily_emit_tydesc_glue(&@block_ctxt cx, int field,
&option::t[@tydesc_info] static_ti) {
alt (static_ti) {
case (none[@tydesc_info]) { }
case (some[@tydesc_info](?ti)) {
if(field == abi::tydesc_field_take_glue) {
alt (ti.take_glue) {
case (some[ValueRef](_)) {}
case (none[ValueRef]) {
log #fmt("+++ lazily_emit_tydesc_glue TAKE %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
auto lcx = cx.fcx.lcx;
auto glue_fn =
declare_generic_glue(lcx, ti.ty,
T_glue_fn(lcx.ccx.tn),
"take");
ti.take_glue = some[ValueRef](glue_fn);
auto tg = make_take_glue;
make_generic_glue(lcx, ti.ty, glue_fn,
mgghf_single(tg), ti.ty_params);
log #fmt("--- lazily_emit_tydesc_glue TAKE %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
}
}
} else if (field == abi::tydesc_field_drop_glue) {
alt (ti.drop_glue) {
case (some[ValueRef](_)) { }
case (none[ValueRef]) {
log #fmt("+++ lazily_emit_tydesc_glue DROP %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
auto lcx = cx.fcx.lcx;
auto glue_fn =
declare_generic_glue(lcx, ti.ty,
T_glue_fn(lcx.ccx.tn),
"drop");
ti.drop_glue = some[ValueRef](glue_fn);
auto dg = make_drop_glue;
make_generic_glue(lcx, ti.ty, glue_fn,
mgghf_single(dg), ti.ty_params);
log #fmt("--- lazily_emit_tydesc_glue DROP %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
}
}
} else if (field == abi::tydesc_field_cmp_glue) {
alt (ti.cmp_glue) {
case (some[ValueRef](_)) { }
case (none[ValueRef]) {
log #fmt("+++ lazily_emit_tydesc_glue CMP %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
auto lcx = cx.fcx.lcx;
auto glue_fn =
declare_generic_glue(lcx, ti.ty,
T_cmp_glue_fn(lcx.ccx.tn),
"cmp");
ti.cmp_glue = some[ValueRef](glue_fn);
make_generic_glue(lcx, ti.ty, glue_fn,
mgghf_cmp, ti.ty_params);
log #fmt("--- lazily_emit_tydesc_glue CMP %s",
ty::ty_to_str(cx.fcx.lcx.ccx.tcx, ti.ty));
}
}
}
}
}
}
fn call_tydesc_glue_full(&@block_ctxt cx, ValueRef v,
ValueRef tydesc, int field) {
ValueRef tydesc, int field,
&option::t[@tydesc_info] static_ti) {
lazily_emit_tydesc_glue(cx, field, static_ti);
auto llrawptr = cx.build.BitCast(v, T_ptr(T_i8()));
auto lltydescs = cx.build.GEP(tydesc,
vec(C_int(0),
@ -2857,10 +2994,13 @@ fn call_tydesc_glue_full(&@block_ctxt cx, ValueRef v,
fn call_tydesc_glue(&@block_ctxt cx, ValueRef v,
&ty::t t, bool escapes, int field) -> result {
auto td = get_tydesc(cx, t, escapes);
let option::t[@tydesc_info] ti = none[@tydesc_info];
auto td = get_tydesc(cx, t, escapes, ti);
call_tydesc_glue_full(td.bcx,
spill_if_immediate(td.bcx, v, t),
td.val, field);
td.val, field, ti);
ret res(td.bcx, C_nil());
}
@ -2900,7 +3040,11 @@ fn call_cmp_glue(&@block_ctxt cx,
auto llrawlhsptr = cx.build.BitCast(lllhs, T_ptr(T_i8()));
auto llrawrhsptr = cx.build.BitCast(llrhs, T_ptr(T_i8()));
auto r = get_tydesc(cx, t, false);
auto ti = none[@tydesc_info];
auto r = get_tydesc(cx, t, false, ti);
lazily_emit_tydesc_glue(cx, abi::tydesc_field_cmp_glue, ti);
auto lltydescs =
r.bcx.build.GEP(r.val, vec(C_int(0),
C_int(abi::tydesc_field_first_param)));
@ -3268,11 +3412,14 @@ fn trans_vec_append(&@block_ctxt cx, &ty::t t,
}
auto bcx = cx;
auto llvec_tydesc = get_tydesc(bcx, t, false);
auto ti = none[@tydesc_info];
auto llvec_tydesc = get_tydesc(bcx, t, false, ti);
bcx = llvec_tydesc.bcx;
auto llelt_tydesc = get_tydesc(bcx, elt_ty, false);
ti = none[@tydesc_info];
auto llelt_tydesc = get_tydesc(bcx, elt_ty, false, ti);
lazily_emit_tydesc_glue(cx, abi::tydesc_field_take_glue, ti);
lazily_emit_tydesc_glue(cx, abi::tydesc_field_drop_glue, ti);
bcx = llelt_tydesc.bcx;
auto dst = bcx.build.PointerCast(lhs, T_ptr(T_opaque_vec_ptr()));
@ -4105,6 +4252,7 @@ fn trans_alt(&@block_ctxt cx, &@ast::expr expr,
}
type generic_info = rec(ty::t item_type,
vec[option::t[@tydesc_info]] static_tis,
vec[ValueRef] tydescs);
type lval_result = rec(result res,
@ -4169,13 +4317,17 @@ fn lval_generic_fn(&@block_ctxt cx,
if (_vec::len[ty::t](tys) != 0u) {
auto bcx = lv.res.bcx;
let vec[ValueRef] tydescs = vec();
let vec[option::t[@tydesc_info]] tis = vec();
for (ty::t t in tys) {
// TODO: Doesn't always escape.
auto td = get_tydesc(bcx, t, true);
auto ti = none[@tydesc_info];
auto td = get_tydesc(bcx, t, true, ti);
tis += vec(ti);
bcx = td.bcx;
_vec::push[ValueRef](tydescs, td.val);
}
auto gen = rec( item_type = tpt._1,
static_tis = tis,
tydescs = tydescs );
lv = rec(res = res(bcx, lv.res.val),
generic = some[generic_info](gen)
@ -4664,6 +4816,7 @@ fn trans_bind(&@block_ctxt cx, &@ast::expr f,
lltydescs = vec();
}
case (some[generic_info](?ginfo)) {
lazily_emit_all_generic_info_tydesc_glues(cx, ginfo);
outgoing_fty = ginfo.item_type;
lltydescs = ginfo.tydescs;
}
@ -4731,7 +4884,9 @@ fn trans_bind(&@block_ctxt cx, &@ast::expr f,
bcx.build.GEP(closure,
vec(C_int(0),
C_int(abi::closure_elt_tydesc)));
auto bindings_tydesc = get_tydesc(bcx, bindings_ty, true);
auto ti = none[@tydesc_info];
auto bindings_tydesc = get_tydesc(bcx, bindings_ty, true, ti);
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
bcx = bindings_tydesc.bcx;
bcx.build.Store(bindings_tydesc.val, bound_tydesc);
@ -4772,9 +4927,11 @@ fn trans_bind(&@block_ctxt cx, &@ast::expr f,
// If necessary, copy tydescs describing type parameters into the
// appropriate slot in the closure.
alt (f_res.generic) {
case (none[generic_info]) { /* nothing to do */ }
case (some[generic_info](?ginfo)) {
lazily_emit_all_generic_info_tydesc_glues(cx, ginfo);
auto ty_params_slot =
bcx.build.GEP(closure,
vec(C_int(0),
@ -4920,6 +5077,7 @@ fn trans_args(&@block_ctxt cx,
alt (gen) {
case (some[generic_info](?g)) {
lazily_emit_all_generic_info_tydesc_glues(cx, g);
lltydescs = g.tydescs;
args = ty::ty_fn_args(cx.fcx.lcx.ccx.tcx, g.item_type);
retty = ty::ty_fn_ret(cx.fcx.lcx.ccx.tcx, g.item_type);
@ -6554,7 +6712,10 @@ fn trans_obj(@local_ctxt cx, &ast::_obj ob, ast::def_id oid,
vec(0, abi::obj_body_elt_tydesc));
bcx = body_tydesc.bcx;
auto body_td = get_tydesc(bcx, body_ty, true);
auto ti = none[@tydesc_info];
auto body_td = get_tydesc(bcx, body_ty, true, ti);
lazily_emit_tydesc_glue(bcx, abi::tydesc_field_drop_glue, ti);
auto dtor = C_null(T_ptr(T_glue_fn(ccx.tn)));
alt (ob.dtor) {
case (some[@ast::method](?d)) {
@ -7603,9 +7764,10 @@ fn trans_vec_append_glue(@local_ctxt cx) {
fn take_one(ValueRef elt_tydesc,
&@block_ctxt cx,
ValueRef dst, ValueRef src) -> result {
auto ti = none[@tydesc_info];
call_tydesc_glue_full(cx, src,
elt_tydesc,
abi::tydesc_field_take_glue);
abi::tydesc_field_take_glue, ti);
ret res(cx, src);
}
@ -7811,6 +7973,11 @@ fn trans_crate(&session::session sess, &@ast::crate crate, &ty::ctxt tcx,
type_abbrevs = abbrevs,
type_short_names = short_names,
tcx = tcx,
stats = rec(mutable n_static_tydescs = 0u,
mutable n_derived_tydescs = 0u,
mutable n_glues_created = 0u,
mutable n_null_glues = 0u,
mutable n_real_glues = 0u),
upcalls = upcall::declare_upcalls(tn, llmod));
auto cx = new_local_ctxt(ccx);
@ -7826,9 +7993,20 @@ fn trans_crate(&session::session sess, &@ast::crate crate, &ty::ctxt tcx,
trans_main_fn(cx, crate_ptr, crate_map);
}
emit_tydescs(ccx);
// Translate the metadata:
middle::metadata::write_metadata(cx.ccx, crate);
if (ccx.sess.get_opts().stats) {
log_err "--- trans stats ---";
log_err #fmt("n_static_tydescs: %u", ccx.stats.n_static_tydescs);
log_err #fmt("n_derived_tydescs: %u", ccx.stats.n_derived_tydescs);
log_err #fmt("n_glues_created: %u", ccx.stats.n_glues_created);
log_err #fmt("n_null_glues: %u", ccx.stats.n_null_glues);
log_err #fmt("n_real_glues: %u", ccx.stats.n_real_glues);
}
ret llmod;
}