diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index fb05cf0b739..cfbd59073fe 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2540,8 +2540,9 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::node_id) -> ValueRef { } } - _ => { - ccx.sess.bug(~"get_item_val(): unexpected variant") + ref variant => { + ccx.sess.bug(fmt!("get_item_val(): unexpected variant: %?", + variant)) } }; if !(exprt || ccx.reachable.contains(&id)) { @@ -3085,6 +3086,7 @@ pub fn trans_crate(sess: session::Session, const_cstr_cache: @mut LinearMap::new(), const_globals: @mut LinearMap::new(), const_values: @mut LinearMap::new(), + extern_const_values: @mut LinearMap::new(), module_data: @mut LinearMap::new(), lltypes: @mut LinearMap::new(), llsizingtypes: @mut LinearMap::new(), diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 5805f7fbe3a..541a950fb55 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -201,6 +201,10 @@ pub struct CrateContext { // Cache of emitted const values const_values: @mut LinearMap, + + // Cache of external const values + extern_const_values: @mut LinearMap, + module_data: @mut LinearMap<~str, ValueRef>, lltypes: @mut LinearMap, llsizingtypes: @mut LinearMap, diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 4ee63f8bf33..c6eec22ef2c 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -124,6 +124,7 @@ use back::abi; use lib; use lib::llvm::{ValueRef, TypeRef, llvm, True}; +use metadata::csearch; use middle::borrowck::root_map_key; use middle::trans::_match; use middle::trans::adt; @@ -150,6 +151,7 @@ use util::common::indenter; use util::ppaux::ty_to_str; +use core::cast::transmute; use core::hashmap::linear::LinearMap; use syntax::print::pprust::{expr_to_str}; use syntax::ast; @@ -1079,11 +1081,35 @@ fn get_did(ccx: @CrateContext, did: ast::def_id) fn get_val(bcx: block, did: ast::def_id, const_ty: ty::t) -> ValueRef { - // The LLVM global has the type of its initializer, - // which may not be equal to the enum's type for - // non-C-like enums. - PointerCast(bcx, base::get_item_val(bcx.ccx(), did.node), - T_ptr(type_of(bcx.ccx(), const_ty))) + if did.crate == ast::local_crate { + // The LLVM global has the type of its initializer, + // which may not be equal to the enum's type for + // non-C-like enums. + PointerCast(bcx, + base::get_item_val(bcx.ccx(), did.node), + T_ptr(type_of(bcx.ccx(), const_ty))) + } else { + // For external constants, we don't inline. + match bcx.ccx().extern_const_values.find(&did) { + None => { + unsafe { + let llty = type_of(bcx.ccx(), const_ty); + let symbol = csearch::get_symbol( + bcx.ccx().sess.cstore, + did); + let llval = llvm::LLVMAddGlobal( + bcx.ccx().llmod, + llty, + transmute::<&u8,*i8>(&symbol[0])); + bcx.ccx().extern_const_values.insert( + did, + llval); + llval + } + } + Some(llval) => *llval + } + } } let did = get_did(ccx, did);