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:
@@ -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.
|
// Generates the declaration for (but doesn't emit) a type descriptor.
|
||||||
fn declare_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info {
|
fn declare_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info {
|
||||||
let _icx = ccx.insn_ctxt("declare_tydesc");
|
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);
|
let llty = type_of(ccx, t);
|
||||||
|
|
||||||
if ccx.sess.count_type_sizes() {
|
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) {
|
fn emit_tydescs(ccx: @crate_ctxt) {
|
||||||
let _icx = ccx.insn_ctxt("emit_tydescs");
|
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| {
|
for ccx.tydescs.each |key, val| {
|
||||||
let glue_fn_ty = T_ptr(T_generic_glue_fn(ccx));
|
let glue_fn_ty = T_ptr(T_generic_glue_fn(ccx));
|
||||||
let ti = val;
|
let ti = val;
|
||||||
@@ -5927,6 +5933,7 @@ fn trans_crate(sess: session::session,
|
|||||||
discrims: ast_util::new_def_hash::<ValueRef>(),
|
discrims: ast_util::new_def_hash::<ValueRef>(),
|
||||||
discrim_symbols: int_hash::<~str>(),
|
discrim_symbols: int_hash::<~str>(),
|
||||||
tydescs: ty::new_ty_hash(),
|
tydescs: ty::new_ty_hash(),
|
||||||
|
mut finished_tydescs: false,
|
||||||
external: ast_util::new_def_hash(),
|
external: ast_util::new_def_hash(),
|
||||||
monomorphized: map::hashmap(hash_mono_id, sys::shape_eq),
|
monomorphized: map::hashmap(hash_mono_id, sys::shape_eq),
|
||||||
monomorphizing: ast_util::new_def_hash(),
|
monomorphizing: ast_util::new_def_hash(),
|
||||||
@@ -5982,6 +5989,9 @@ fn trans_crate(sess: session::session,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fill_crate_map(ccx, crate_map);
|
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);
|
emit_tydescs(ccx);
|
||||||
gen_shape_tables(ccx);
|
gen_shape_tables(ccx);
|
||||||
write_abi_version(ccx);
|
write_abi_version(ccx);
|
||||||
|
|||||||
@@ -117,6 +117,9 @@ type crate_ctxt = {
|
|||||||
discrims: hashmap<ast::def_id, ValueRef>,
|
discrims: hashmap<ast::def_id, ValueRef>,
|
||||||
discrim_symbols: hashmap<ast::node_id, ~str>,
|
discrim_symbols: hashmap<ast::node_id, ~str>,
|
||||||
tydescs: hashmap<ty::t, @tydesc_info>,
|
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
|
// Track mapping of external ids to local items imported for inlining
|
||||||
external: hashmap<ast::def_id, Option<ast::node_id>>,
|
external: hashmap<ast::def_id, Option<ast::node_id>>,
|
||||||
// Cache instances of monomorphized functions
|
// 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);
|
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) {
|
fn gen_shape_tables(ccx: @crate_ctxt) {
|
||||||
let lltagstable = gen_enum_shapes(ccx);
|
let lltagstable = gen_enum_shapes(ccx);
|
||||||
let llresourcestable = gen_resource_shapes(ccx);
|
let llresourcestable = gen_resource_shapes(ccx);
|
||||||
|
|||||||
Reference in New Issue
Block a user