Skip to content

Commit

Permalink
rustc: Break cyclical dependence between emit_tydescs and gen_shape_t…
Browse files Browse the repository at this point in the history
…ables.

Force all tydescs to be emitted before emit_tydescs to avoid linker
failures.
  • Loading branch information
Elliott Slaughter committed Aug 27, 2012
1 parent 785c524 commit 5593add
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/rustc/middle/trans/base.rs
Expand Up @@ -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() {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions src/rustc/middle/trans/common.rs
Expand Up @@ -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
Expand Down
28 changes: 28 additions & 0 deletions src/rustc/middle/trans/shape.rs
Expand Up @@ -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);
Expand Down

0 comments on commit 5593add

Please sign in to comment.