From 010702899197b3305126746adb4278d9da370808 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 11 Sep 2013 10:06:16 -0700 Subject: [PATCH] Resume inlining globals across crates In #8185 cross-crate condition handlers were fixed by ensuring that globals didn't start appearing in different crates with different addressed. An unfortunate side effect of that pull request is that constants weren't inlined across crates (uint::bits is unknown to everything but libstd). This commit fixes this inlining by using the `available_eternally` linkage provided by LLVM. It partially reverts #8185, and then adds support for this linkage type. The main caveat is that not all statics could be inlined into other crates. Before this patch, all statics were considered "inlineable items", but an unfortunate side effect of how we deal with `&static` and `&[static]` means that these two cases cannot be inlined across crates. The translation of constants was modified to propogate this condition of whether a constant should be considered inlineable into other crates. Closes #9036 --- src/librustc/metadata/encoder.rs | 8 +- src/librustc/middle/trans/_match.rs | 7 +- src/librustc/middle/trans/base.rs | 24 +++- src/librustc/middle/trans/consts.rs | 121 +++++++++++------- src/librustc/middle/trans/context.rs | 9 ++ src/librustc/middle/trans/expr.rs | 14 +- src/librustc/middle/trans/inline.rs | 23 +++- src/test/auxiliary/xcrate_static_addresses.rs | 9 ++ src/test/run-pass/xcrate-static-addresses.rs | 1 + 9 files changed, 157 insertions(+), 59 deletions(-) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 692e4e345df63..9e65e4ec18a97 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -60,6 +60,7 @@ pub struct EncodeParams<'self> { reexports2: middle::resolve::ExportMap2, item_symbols: &'self HashMap, discrim_symbols: &'self HashMap, + non_inlineable_statics: &'self HashSet, link_meta: &'self LinkMeta, cstore: @mut cstore::CStore, encode_inlined_item: encode_inlined_item<'self>, @@ -89,6 +90,7 @@ pub struct EncodeContext<'self> { reexports2: middle::resolve::ExportMap2, item_symbols: &'self HashMap, discrim_symbols: &'self HashMap, + non_inlineable_statics: &'self HashSet, link_meta: &'self LinkMeta, cstore: &'self cstore::CStore, encode_inlined_item: encode_inlined_item<'self>, @@ -907,7 +909,9 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_name(ecx, ebml_w, item.ident); let elt = ast_map::path_pretty_name(item.ident, item.id as u64); encode_path(ecx, ebml_w, path, elt); - (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item)); + if !ecx.non_inlineable_statics.contains(&item.id) { + (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item)); + } ebml_w.end_tag(); } item_fn(_, purity, _, ref generics, _) => { @@ -1728,6 +1732,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] { encode_inlined_item, link_meta, reachable, + non_inlineable_statics, _ } = parms; let type_abbrevs = @mut HashMap::new(); @@ -1739,6 +1744,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] { reexports2: reexports2, item_symbols: item_symbols, discrim_symbols: discrim_symbols, + non_inlineable_statics: non_inlineable_statics, link_meta: link_meta, cstore: cstore, encode_inlined_item: encode_inlined_item, diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 62fbdc41b0e70..d27bcde20649c 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -324,15 +324,16 @@ fn trans_opt(bcx: @mut Block, o: &Opt) -> opt_result { return single_result(datumblock.to_result(bcx)); } lit(ConstLit(lit_id)) => { - let llval = consts::get_const_val(bcx.ccx(), lit_id); + let (llval, _) = consts::get_const_val(bcx.ccx(), lit_id); return single_result(rslt(bcx, llval)); } var(disr_val, repr) => { return adt::trans_case(bcx, repr, disr_val); } range(l1, l2) => { - return range_result(rslt(bcx, consts::const_expr(ccx, l1)), - rslt(bcx, consts::const_expr(ccx, l2))); + let (l1, _) = consts::const_expr(ccx, l1); + let (l2, _) = consts::const_expr(ccx, l2); + return range_result(rslt(bcx, l1), rslt(bcx, l2)); } vec_len(n, vec_len_eq, _) => { return single_result(rslt(bcx, C_int(ccx, n as int))); diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index f0238e8f5c550..823825b519ee1 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2494,12 +2494,29 @@ pub fn get_item_val(ccx: @mut CrateContext, id: ast::NodeId) -> ValueRef { let sym = exported_name(ccx, my_path, ty, i.attrs); let v = match i.node { - ast::item_static(_, m, expr) => { + ast::item_static(_, _, expr) => { + // If this static came from an external crate, then + // we need to get the symbol from csearch instead of + // using the current crate's name/version + // information in the hash of the symbol + debug!("making %s", sym); + let sym = match ccx.external_srcs.find(&i.id) { + Some(&did) => { + debug!("but found in other crate..."); + csearch::get_symbol(ccx.sess.cstore, did) + } + None => sym + }; + // We need the translated value here, because for enums the // LLVM type is not fully determined by the Rust type. - let v = consts::const_expr(ccx, expr); + let (v, inlineable) = consts::const_expr(ccx, expr); ccx.const_values.insert(id, v); - exprt = (m == ast::MutMutable || i.vis == ast::public); + if !inlineable { + debug!("%s not inlined", sym); + ccx.non_inlineable_statics.insert(id); + } + exprt = true; unsafe { let llty = llvm::LLVMTypeOf(v); @@ -2950,6 +2967,7 @@ pub fn crate_ctxt_to_encode_parms<'r>(cx: &'r CrateContext, ie: encoder::encode_ reexports2: cx.exp_map2, item_symbols: item_symbols, discrim_symbols: discrim_symbols, + non_inlineable_statics: &cx.non_inlineable_statics, link_meta: link_meta, cstore: cx.sess.cstore, encode_inlined_item: ie, diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 78d2228ff041c..a7a04627981a9 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -84,21 +84,21 @@ pub fn const_ptrcast(cx: &mut CrateContext, a: ValueRef, t: Type) -> ValueRef { } pub fn const_vec(cx: @mut CrateContext, e: &ast::Expr, es: &[@ast::Expr]) - -> (ValueRef, ValueRef, Type) { + -> (ValueRef, ValueRef, Type, bool) { unsafe { let vec_ty = ty::expr_ty(cx.tcx, e); let unit_ty = ty::sequence_element_type(cx.tcx, vec_ty); let llunitty = type_of::type_of(cx, unit_ty); let unit_sz = machine::llsize_of(cx, llunitty); let sz = llvm::LLVMConstMul(C_uint(cx, es.len()), unit_sz); - let vs = es.map(|e| const_expr(cx, *e)); + let (vs, inlineable) = vec::unzip(es.iter().map(|e| const_expr(cx, *e))); // If the vector contains enums, an LLVM array won't work. let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) { C_struct(vs) } else { C_array(llunitty, vs) }; - return (v, sz, llunitty); + return (v, sz, llunitty, inlineable.iter().fold(true, |a, &b| a && b)); } } @@ -157,7 +157,8 @@ fn const_deref(cx: &mut CrateContext, v: ValueRef, t: ty::t, explicit: bool) } } -pub fn get_const_val(cx: @mut CrateContext, mut def_id: ast::DefId) -> ValueRef { +pub fn get_const_val(cx: @mut CrateContext, + mut def_id: ast::DefId) -> (ValueRef, bool) { let contains_key = cx.const_values.contains_key(&def_id.node); if !ast_util::is_local(def_id) || !contains_key { if !ast_util::is_local(def_id) { @@ -172,11 +173,14 @@ pub fn get_const_val(cx: @mut CrateContext, mut def_id: ast::DefId) -> ValueRef _ => cx.tcx.sess.bug("expected a const to be an item") } } - cx.const_values.get_copy(&def_id.node) + (cx.const_values.get_copy(&def_id.node), + !cx.non_inlineable_statics.contains(&def_id.node)) } -pub fn const_expr(cx: @mut CrateContext, e: @ast::Expr) -> ValueRef { - let mut llconst = const_expr_unadjusted(cx, e); +pub fn const_expr(cx: @mut CrateContext, e: @ast::Expr) -> (ValueRef, bool) { + let (llconst, inlineable) = const_expr_unadjusted(cx, e); + let mut llconst = llconst; + let mut inlineable = inlineable; let ety = ty::expr_ty(cx.tcx, e); let adjustment = cx.tcx.adjustments.find_copy(&e.id); match adjustment { @@ -204,7 +208,10 @@ pub fn const_expr(cx: @mut CrateContext, e: @ast::Expr) -> ValueRef { // Don't copy data to do a deref+ref. let llptr = match maybe_ptr { Some(ptr) => ptr, - None => const_addr_of(cx, llconst) + None => { + inlineable = false; + const_addr_of(cx, llconst) + } }; match *autoref { ty::AutoUnsafe(m) | @@ -250,17 +257,27 @@ pub fn const_expr(cx: @mut CrateContext, e: @ast::Expr) -> ValueRef { e.repr(cx.tcx), ty_to_str(cx.tcx, ety), csize, tsize)); } - llconst + (llconst, inlineable) } -fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { +// the bool returned is whether this expression can be inlined into other crates +// if it's assigned to a static. +fn const_expr_unadjusted(cx: @mut CrateContext, + e: &ast::Expr) -> (ValueRef, bool) { + fn map_list(cx: @mut CrateContext, + exprs: &[@ast::Expr]) -> (~[ValueRef], bool) { + exprs.iter().map(|&e| const_expr(cx, e)) + .fold((~[], true), |(L, all_inlineable), (val, inlineable)| { + (vec::append_one(L, val), all_inlineable && inlineable) + }) + } unsafe { let _icx = push_ctxt("const_expr"); return match e.node { - ast::ExprLit(lit) => consts::const_lit(cx, e, *lit), + ast::ExprLit(lit) => (consts::const_lit(cx, e, *lit), true), ast::ExprBinary(_, b, e1, e2) => { - let te1 = const_expr(cx, e1); - let te2 = const_expr(cx, e2); + let (te1, _) = const_expr(cx, e1); + let (te2, _) = const_expr(cx, e2); let te2 = base::cast_shift_const_rhs(b, te1, te2); @@ -269,7 +286,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { let ty = ty::expr_ty(cx.tcx, e1); let is_float = ty::type_is_fp(ty); let signed = ty::type_is_signed(ty); - return match b { + return (match b { ast::BiAdd => { if is_float { llvm::LLVMConstFAdd(te1, te2) } else { llvm::LLVMConstAdd(te1, te2) } @@ -338,13 +355,13 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { else { ConstICmp(IntUGT, te1, te2) } } }, - }; + }, true) }, ast::ExprUnary(_, u, e) => { - let te = const_expr(cx, e); + let (te, _) = const_expr(cx, e); let ty = ty::expr_ty(cx.tcx, e); let is_float = ty::type_is_fp(ty); - return match u { + return (match u { ast::UnBox(_) | ast::UnUniq | ast::UnDeref => { @@ -367,21 +384,21 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { if is_float { llvm::LLVMConstFNeg(te) } else { llvm::LLVMConstNeg(te) } } - } + }, true) } ast::ExprField(base, field, _) => { let bt = ty::expr_ty_adjusted(cx.tcx, base); let brepr = adt::represent_type(cx, bt); - let bv = const_expr(cx, base); + let (bv, inlineable) = const_expr(cx, base); do expr::with_field_tys(cx.tcx, bt, None) |discr, field_tys| { let ix = ty::field_idx_strict(cx.tcx, field.name, field_tys); - adt::const_get_field(cx, brepr, bv, discr, ix) + (adt::const_get_field(cx, brepr, bv, discr, ix), inlineable) } } ast::ExprIndex(_, base, index) => { let bt = ty::expr_ty_adjusted(cx.tcx, base); - let bv = const_expr(cx, base); + let (bv, inlineable) = const_expr(cx, base); let iv = match const_eval::eval_const_expr(cx.tcx, index) { const_eval::const_int(i) => i as u64, const_eval::const_uint(u) => u, @@ -422,15 +439,15 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { cx.sess.span_err(e.span, "const index-expr is out of bounds"); } - const_get_elt(cx, arr, [iv as c_uint]) + (const_get_elt(cx, arr, [iv as c_uint]), inlineable) } ast::ExprCast(base, _) => { let ety = ty::expr_ty(cx.tcx, e); let llty = type_of::type_of(cx, ety); let basety = ty::expr_ty(cx.tcx, base); - let v = const_expr(cx, base); - match (expr::cast_type_kind(basety), - expr::cast_type_kind(ety)) { + let (v, inlineable) = const_expr(cx, base); + return (match (expr::cast_type_kind(basety), + expr::cast_type_kind(ety)) { (expr::cast_integral, expr::cast_integral) => { let s = ty::type_is_signed(basety) as Bool; @@ -476,17 +493,17 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { cx.sess.impossible_case(e.span, "bad combination of types for cast") } - } + }, inlineable) } ast::ExprAddrOf(ast::MutImmutable, sub) => { - let e = const_expr(cx, sub); - const_addr_of(cx, e) + let (e, _) = const_expr(cx, sub); + (const_addr_of(cx, e), false) } ast::ExprTup(ref es) => { let ety = ty::expr_ty(cx.tcx, e); let repr = adt::represent_type(cx, ety); - let vals = es.map(|&e| const_expr(cx, e)); - adt::trans_const(cx, repr, 0, vals) + let (vals, inlineable) = map_list(cx, *es); + (adt::trans_const(cx, repr, 0, vals), inlineable) } ast::ExprStruct(_, ref fs, ref base_opt) => { let ety = ty::expr_ty(cx.tcx, e); @@ -500,24 +517,29 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { do expr::with_field_tys(tcx, ety, Some(e.id)) |discr, field_tys| { - let cs: ~[ValueRef] = field_tys.iter().enumerate() + let cs = field_tys.iter().enumerate() .map(|(ix, &field_ty)| { match fs.iter().find(|f| field_ty.ident.name == f.ident.name) { Some(f) => const_expr(cx, (*f).expr), None => { match base_val { - Some(bv) => adt::const_get_field(cx, repr, bv, discr, ix), + Some((bv, inlineable)) => { + (adt::const_get_field(cx, repr, bv, discr, ix), + inlineable) + } None => cx.tcx.sess.span_bug(e.span, "missing struct field") } } } - }).collect(); - adt::trans_const(cx, repr, discr, cs) + }).to_owned_vec(); + let (cs, inlineable) = vec::unzip(cs.move_iter()); + (adt::trans_const(cx, repr, discr, cs), + inlineable.iter().fold(true, |a, &b| a && b)) } } ast::ExprVec(ref es, ast::MutImmutable) => { - let (v, _, _) = const_vec(cx, e, *es); - v + let (v, _, _, inlineable) = const_vec(cx, e, *es); + (v, inlineable) } ast::ExprVstore(sub, ast::ExprVstoreSlice) => { match sub.node { @@ -528,7 +550,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { } } ast::ExprVec(ref es, ast::MutImmutable) => { - let (cv, sz, llunitty) = const_vec(cx, e, *es); + let (cv, sz, llunitty, _) = const_vec(cx, e, *es); let llty = val_ty(cv); let gv = do "const".with_c_str |name| { llvm::LLVMAddGlobal(cx.llmod, llty.to_ref(), name) @@ -537,7 +559,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { llvm::LLVMSetGlobalConstant(gv, True); SetLinkage(gv, PrivateLinkage); let p = const_ptrcast(cx, gv, llunitty); - C_struct([p, sz]) + (C_struct([p, sz]), false) } _ => cx.sess.span_bug(e.span, "bad const-slice expr") } @@ -551,13 +573,13 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { const_eval::const_uint(i) => i as uint, _ => cx.sess.span_bug(count.span, "count must be integral const expression.") }; - let vs = vec::from_elem(n, const_expr(cx, elem)); + let vs = vec::from_elem(n, const_expr(cx, elem).first()); let v = if vs.iter().any(|vi| val_ty(*vi) != llunitty) { C_struct(vs) } else { C_array(llunitty, vs) }; - v + (v, true) } ast::ExprPath(ref pth) => { // Assert that there are no type parameters in this path. @@ -568,10 +590,10 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { Some(&ast::DefFn(def_id, _purity)) => { if !ast_util::is_local(def_id) { let ty = csearch::get_type(cx.tcx, def_id).ty; - base::trans_external_path(cx, def_id, ty) + (base::trans_external_path(cx, def_id, ty), true) } else { assert!(ast_util::is_local(def_id)); - base::get_item_val(cx, def_id.node) + (base::get_item_val(cx, def_id.node), true) } } Some(&ast::DefStatic(def_id, false)) => { @@ -583,12 +605,12 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { let vinfo = ty::enum_variant_with_id(cx.tcx, enum_did, variant_did); - adt::trans_const(cx, repr, vinfo.disr_val, []) + (adt::trans_const(cx, repr, vinfo.disr_val, []), true) } Some(&ast::DefStruct(_)) => { let ety = ty::expr_ty(cx.tcx, e); let llty = type_of::type_of(cx, ety); - C_null(llty) + (C_null(llty), true) } _ => { cx.sess.span_bug(e.span, "expected a const, fn, struct, or variant def") @@ -601,8 +623,8 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { Some(&ast::DefStruct(_)) => { let ety = ty::expr_ty(cx.tcx, e); let repr = adt::represent_type(cx, ety); - let arg_vals = args.map(|a| const_expr(cx, *a)); - adt::trans_const(cx, repr, 0, arg_vals) + let (arg_vals, inlineable) = map_list(cx, *args); + (adt::trans_const(cx, repr, 0, arg_vals), inlineable) } Some(&ast::DefVariant(enum_did, variant_did, _)) => { let ety = ty::expr_ty(cx.tcx, e); @@ -610,13 +632,14 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::Expr) -> ValueRef { let vinfo = ty::enum_variant_with_id(cx.tcx, enum_did, variant_did); - let arg_vals = args.map(|a| const_expr(cx, *a)); - adt::trans_const(cx, repr, vinfo.disr_val, arg_vals) + let (arg_vals, inlineable) = map_list(cx, *args); + (adt::trans_const(cx, repr, vinfo.disr_val, arg_vals), + inlineable) } _ => cx.sess.span_bug(e.span, "expected a struct or variant def") } } - ast::ExprParen(e) => { return const_expr(cx, e); } + ast::ExprParen(e) => { const_expr(cx, e) } _ => cx.sess.span_bug(e.span, "bad constant expression type in consts::const_expr") }; diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index 6eb2fcf25fd3c..9ee7f09253b54 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -61,6 +61,13 @@ pub struct CrateContext { finished_tydescs: bool, // Track mapping of external ids to local items imported for inlining external: HashMap>, + // Backwards version of the `external` map (inlined items to where they + // came from) + external_srcs: HashMap, + // A set of static items which cannot be inlined into other crates. This + // will pevent in ii_item() structures from being encoded into the metadata + // that is generated + non_inlineable_statics: HashSet, // Cache instances of monomorphized functions monomorphized: HashMap, monomorphizing: HashMap, @@ -189,6 +196,8 @@ impl CrateContext { tydescs: HashMap::new(), finished_tydescs: false, external: HashMap::new(), + external_srcs: HashMap::new(), + non_inlineable_statics: HashSet::new(), monomorphized: HashMap::new(), monomorphizing: HashMap::new(), type_use_cache: HashMap::new(), diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index b351fe91e6f1c..0a55786975832 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -116,7 +116,7 @@ return type, such as `while` loops or assignments (`a = b`). use back::abi; use back::link; -use lib::llvm::{ValueRef, llvm, SetLinkage, ExternalLinkage, False}; +use lib::llvm::{ValueRef, llvm, SetLinkage, False}; use lib; use metadata::csearch; use middle::trans::_match; @@ -135,6 +135,7 @@ use middle::trans::datum::*; use middle::trans::debuginfo; use middle::trans::machine; use middle::trans::meth; +use middle::trans::inline; use middle::trans::tvec; use middle::trans::type_of; use middle::ty::struct_fields; @@ -987,6 +988,15 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: @ast::Expr) -> DatumBlock { ast::DefStatic(did, _) => { let const_ty = expr_ty(bcx, ref_expr); + fn get_did(ccx: @mut CrateContext, did: ast::DefId) + -> ast::DefId { + if did.crate != ast::LOCAL_CRATE { + inline::maybe_instantiate_inline(ccx, did) + } else { + did + } + } + fn get_val(bcx: @mut Block, did: ast::DefId, const_ty: ty::t) -> ValueRef { // For external constants, we don't inline. @@ -1018,7 +1028,6 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: @ast::Expr) -> DatumBlock { llty.to_ref(), buf) }; - SetLinkage(llval, ExternalLinkage); let extern_const_values = &mut bcx.ccx().extern_const_values; extern_const_values.insert(did, llval); llval @@ -1026,6 +1035,7 @@ fn trans_lvalue_unadjusted(bcx: @mut Block, expr: @ast::Expr) -> DatumBlock { } } + let did = get_did(bcx.ccx(), did); let val = get_val(bcx, did, const_ty); DatumBlock { bcx: bcx, diff --git a/src/librustc/middle/trans/inline.rs b/src/librustc/middle/trans/inline.rs index cfc9c8a2e17cf..a571e56a48ec0 100644 --- a/src/librustc/middle/trans/inline.rs +++ b/src/librustc/middle/trans/inline.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - +use lib::llvm::{AvailableExternallyLinkage, SetLinkage}; use metadata::csearch; use middle::astencode; use middle::trans::base::{push_ctxt, impl_self, no_self}; @@ -53,16 +53,36 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId) } csearch::found(ast::ii_item(item)) => { ccx.external.insert(fn_id, Some(item.id)); + ccx.external_srcs.insert(item.id, fn_id); ccx.stats.n_inlines += 1; trans_item(ccx, item); + + // We're bringing an external global into this crate, but we don't + // want to create two copies of the global. If we do this, then if + // you take the address of the global in two separate crates you get + // two different addresses. This is bad for things like conditions, + // but it could possibly have other adverse side effects. We still + // want to achieve the optimizations related to this global, + // however, so we use the available_externally linkage which llvm + // provides + match item.node { + ast::item_static(*) => { + let g = get_item_val(ccx, item.id); + SetLinkage(g, AvailableExternallyLinkage); + } + _ => {} + } + local_def(item.id) } csearch::found(ast::ii_foreign(item)) => { ccx.external.insert(fn_id, Some(item.id)); + ccx.external_srcs.insert(item.id, fn_id); local_def(item.id) } csearch::found_parent(parent_id, ast::ii_item(item)) => { ccx.external.insert(parent_id, Some(item.id)); + ccx.external_srcs.insert(item.id, parent_id); let mut my_id = 0; match item.node { ast::item_enum(_, _) => { @@ -86,6 +106,7 @@ pub fn maybe_instantiate_inline(ccx: @mut CrateContext, fn_id: ast::DefId) csearch::found(ast::ii_method(impl_did, is_provided, mth)) => { ccx.stats.n_inlines += 1; ccx.external.insert(fn_id, Some(mth.id)); + ccx.external_srcs.insert(mth.id, fn_id); // If this is a default method, we can't look up the // impl type. But we aren't going to translate anyways, so don't. if is_provided { return local_def(mth.id); } diff --git a/src/test/auxiliary/xcrate_static_addresses.rs b/src/test/auxiliary/xcrate_static_addresses.rs index 3a05462d856da..f0df2b1e71ede 100644 --- a/src/test/auxiliary/xcrate_static_addresses.rs +++ b/src/test/auxiliary/xcrate_static_addresses.rs @@ -10,12 +10,21 @@ pub static global: int = 3; +static global0: int = 4; +pub static global2: &'static int = &global0; + pub fn verify_same(a: &'static int) { let a = a as *int as uint; let b = &global as *int as uint; assert_eq!(a, b); } +pub fn verify_same2(a: &'static int) { + let a = a as *int as uint; + let b = global2 as *int as uint; + assert_eq!(a, b); +} + condition!{ pub test: int -> (); } pub fn raise() { diff --git a/src/test/run-pass/xcrate-static-addresses.rs b/src/test/run-pass/xcrate-static-addresses.rs index 059a6f75ac82e..7eb4adfd06757 100644 --- a/src/test/run-pass/xcrate-static-addresses.rs +++ b/src/test/run-pass/xcrate-static-addresses.rs @@ -17,6 +17,7 @@ use other = xcrate_static_addresses; pub fn main() { other::verify_same(&other::global); + other::verify_same2(other::global2); // Previously this fail'd because there were two addresses that were being // used when declaring constants.