rustc: Break cyclical dependence between emit_tydescs and gen_shape_tables.
Force all tydescs to be emitted before emit_tydescs to avoid linker failures.
This commit is contained in:
parent
785c524d3e
commit
5593add3a8
@ -531,6 +531,10 @@ fn declare_tydesc_addrspace(ccx: @crate_ctxt, t: ty::t) -> addrspace {
|
||||
// Generates the declaration for (but doesn't emit) a type descriptor.
|
||||
fn declare_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info {
|
||||
let _icx = ccx.insn_ctxt("declare_tydesc");
|
||||
// If emit_tydescs already ran, then we shouldn't be creating any new
|
||||
// tydescs.
|
||||
assert !ccx.finished_tydescs;
|
||||
|
||||
let llty = type_of(ccx, t);
|
||||
|
||||
if ccx.sess.count_type_sizes() {
|
||||
@ -624,6 +628,8 @@ fn make_generic_glue(ccx: @crate_ctxt, t: ty::t, llfn: ValueRef,
|
||||
|
||||
fn emit_tydescs(ccx: @crate_ctxt) {
|
||||
let _icx = ccx.insn_ctxt("emit_tydescs");
|
||||
// As of this point, allow no more tydescs to be created.
|
||||
ccx.finished_tydescs = true;
|
||||
for ccx.tydescs.each |key, val| {
|
||||
let glue_fn_ty = T_ptr(T_generic_glue_fn(ccx));
|
||||
let ti = val;
|
||||
@ -5927,6 +5933,7 @@ fn trans_crate(sess: session::session,
|
||||
discrims: ast_util::new_def_hash::<ValueRef>(),
|
||||
discrim_symbols: int_hash::<~str>(),
|
||||
tydescs: ty::new_ty_hash(),
|
||||
mut finished_tydescs: false,
|
||||
external: ast_util::new_def_hash(),
|
||||
monomorphized: map::hashmap(hash_mono_id, sys::shape_eq),
|
||||
monomorphizing: ast_util::new_def_hash(),
|
||||
@ -5982,6 +5989,9 @@ fn trans_crate(sess: session::session,
|
||||
}
|
||||
|
||||
fill_crate_map(ccx, crate_map);
|
||||
// NB: Must call force_declare_tydescs before emit_tydescs to break
|
||||
// cyclical dependency with shape code! See shape.rs for details.
|
||||
force_declare_tydescs(ccx);
|
||||
emit_tydescs(ccx);
|
||||
gen_shape_tables(ccx);
|
||||
write_abi_version(ccx);
|
||||
|
@ -117,6 +117,9 @@ type crate_ctxt = {
|
||||
discrims: hashmap<ast::def_id, ValueRef>,
|
||||
discrim_symbols: hashmap<ast::node_id, ~str>,
|
||||
tydescs: hashmap<ty::t, @tydesc_info>,
|
||||
// Set when running emit_tydescs to enforce that no more tydescs are
|
||||
// created.
|
||||
mut finished_tydescs: bool,
|
||||
// Track mapping of external ids to local items imported for inlining
|
||||
external: hashmap<ast::def_id, Option<ast::node_id>>,
|
||||
// Cache instances of monomorphized functions
|
||||
|
@ -584,6 +584,34 @@ fn gen_resource_shapes(ccx: @crate_ctxt) -> ValueRef {
|
||||
return mk_global(ccx, ~"resource_shapes", C_struct(dtors), true);
|
||||
}
|
||||
|
||||
// This function serves to break a cyclical dependence between
|
||||
// emit_tydescs and gen_shape_tables.
|
||||
//
|
||||
// * emit_tydescs calls shape_of, which causes changes to the shape
|
||||
// tables
|
||||
// * gen_shape_tables transitively calls get_tydesc, which causes new
|
||||
// tydescs to be created
|
||||
//
|
||||
// We force those tydescs to be emitted now, thus breaking the
|
||||
// dependency.
|
||||
fn force_declare_tydescs(ccx: @crate_ctxt) {
|
||||
// Walk all known tydescs first to force shape code to declare
|
||||
// dependencies.
|
||||
for ccx.tydescs.each |key, _val| {
|
||||
shape_of(ccx, key);
|
||||
}
|
||||
|
||||
// Then walk all resource shapes to force emit all dtors.
|
||||
let len = ccx.shape_cx.resources.len();
|
||||
for uint::range(0u, len) |i| {
|
||||
let ri = ccx.shape_cx.resources.get(i);
|
||||
for ri.tps.each() |s| { assert !ty::type_has_params(s); }
|
||||
do option::iter(ri.parent_id) |id| {
|
||||
trans::base::get_res_dtor(ccx, ri.did, id, ri.tps);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_shape_tables(ccx: @crate_ctxt) {
|
||||
let lltagstable = gen_enum_shapes(ccx);
|
||||
let llresourcestable = gen_resource_shapes(ccx);
|
||||
|
Loading…
Reference in New Issue
Block a user