use rustc::middle::cstore::{LinkMeta, LinkagePreference, NativeLibrary,
EncodedMetadata};
use rustc::hir::def::CtorKind;
-use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE};
+use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, LOCAL_CRATE};
use rustc::hir::map::definitions::DefPathTable;
use rustc::ich::Fingerprint;
use rustc::middle::dependency_format::Linkage;
+use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel,
+ metadata_symbol_name};
use rustc::middle::lang_items;
-use rustc::mir;
+use rustc::mir::{self, interpret};
use rustc::traits::specialization_graph;
-use rustc::ty::{self, Ty, TyCtxt, ReprOptions};
+use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName};
use rustc::ty::codec::{self as ty_codec, TyEncoder};
use rustc::session::config::{self, CrateTypeProcMacro};
-use rustc::util::nodemap::{FxHashMap, NodeSet};
+use rustc::util::nodemap::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque};
use std::io::prelude::*;
use std::io::Cursor;
use std::path::Path;
-use std::rc::Rc;
+use rustc_data_structures::sync::Lrc;
use std::u32;
use syntax::ast::{self, CRATE_NODE_ID};
use syntax::codemap::Spanned;
opaque: opaque::Encoder<'a>,
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
link_meta: &'a LinkMeta,
- exported_symbols: &'a NodeSet,
lazy_state: LazyState,
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
predicate_shorthands: FxHashMap<ty::Predicate<'tcx>, usize>,
+ interpret_alloc_shorthands: FxHashMap<interpret::AllocId, usize>,
// This is used to speed up Span encoding.
- filemap_cache: Rc<FileMap>,
+ filemap_cache: Lrc<FileMap>,
}
macro_rules! encoder_methods {
}
}
+impl<'a, 'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'a, 'tcx> {
+ #[inline]
+ fn specialized_encode(&mut self, def_id: &LocalDefId) -> Result<(), Self::Error> {
+ self.specialized_encode(&def_id.to_def_id())
+ }
+}
+
impl<'a, 'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'a, 'tcx> {
fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands)
}
}
+impl<'a, 'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'a, 'tcx> {
+ fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Self::Error> {
+ trace!("encoding {:?} at {}", alloc_id, self.position());
+ if let Some(shorthand) = self.interpret_alloc_shorthands.get(alloc_id).cloned() {
+ trace!("encoding {:?} as shorthand to {}", alloc_id, shorthand);
+ return shorthand.encode(self);
+ }
+ let start = self.position();
+ // cache the allocation shorthand now, because the allocation itself might recursively
+ // point to itself.
+ self.interpret_alloc_shorthands.insert(*alloc_id, start);
+ let interpret_interner = self.tcx.interpret_interner.borrow();
+ if let Some(alloc) = interpret_interner.get_alloc(*alloc_id) {
+ trace!("encoding {:?} with {:#?}", alloc_id, alloc);
+ usize::max_value().encode(self)?;
+ alloc.encode(self)?;
+ let globals = interpret_interner.get_globals(*alloc_id);
+ globals.len().encode(self)?;
+ for glob in globals {
+ glob.encode(self)?;
+ }
+ } else if let Some(fn_instance) = interpret_interner.get_fn(*alloc_id) {
+ trace!("encoding {:?} with {:#?}", alloc_id, fn_instance);
+ (usize::max_value() - 1).encode(self)?;
+ fn_instance.encode(self)?;
+ } else {
+ bug!("alloc id without corresponding allocation: {}", alloc_id);
+ }
+ Ok(())
+ }
+}
+
impl<'a, 'tcx> SpecializedEncoder<ty::GenericPredicates<'tcx>> for EncodeContext<'a, 'tcx> {
fn specialized_encode(&mut self,
predicates: &ty::GenericPredicates<'tcx>)
// paths because any relative paths are potentially relative to
// a wrong directory.
// However, if a path has been modified via
- // `-Zremap-path-prefix` we assume the user has already set
+ // `--remap-path-prefix` we assume the user has already set
// things up the way they want and don't touch the path values
// anymore.
match filemap.name {
adapted.name.hash(&mut hasher);
hasher.finish()
};
- Rc::new(adapted)
+ Lrc::new(adapted)
}
},
// expanded code, not from a file
// Encode exported symbols info.
i = self.position();
+ let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE);
let exported_symbols = self.tracked(
IsolatedEncoder::encode_exported_symbols,
- self.exported_symbols);
+ &exported_symbols);
let exported_symbols_bytes = self.position() - i;
// Encode and index the items.
} else if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
let generics = self.tcx.generics_of(def_id);
let types = generics.parent_types as usize + generics.types.len();
- let needs_inline = types > 0 || attr::requests_inline(&ast_item.attrs);
+ let needs_inline = types > 0 || tcx.trans_fn_attrs(def_id).requests_inline();
let is_const_fn = sig.constness == hir::Constness::Const;
let ast = if is_const_fn { Some(body) } else { None };
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
hir::ItemConst(..) => self.encode_optimized_mir(def_id),
hir::ItemFn(_, _, constness, _, ref generics, _) => {
let has_tps = generics.ty_params().next().is_some();
- let needs_inline = has_tps || attr::requests_inline(&item.attrs);
+ let needs_inline = has_tps || tcx.trans_fn_attrs(def_id).requests_inline();
let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir;
if needs_inline || constness == hir::Constness::Const || always_encode_mir {
self.encode_optimized_mir(def_id)
// middle::reachable module but filters out items that either don't have a
// symbol associated with them (they weren't translated) or if they're an FFI
// definition (as that's not defined in this crate).
- fn encode_exported_symbols(&mut self, exported_symbols: &NodeSet) -> LazySeq<DefIndex> {
- let tcx = self.tcx;
- self.lazy_seq(exported_symbols.iter().map(|&id| tcx.hir.local_def_id(id).index))
+ fn encode_exported_symbols(&mut self,
+ exported_symbols: &[(ExportedSymbol, SymbolExportLevel)])
+ -> LazySeq<(ExportedSymbol, SymbolExportLevel)> {
+
+ // The metadata symbol name is special. It should not show up in
+ // downstream crates.
+ let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx));
+
+ self.lazy_seq(exported_symbols
+ .iter()
+ .filter(|&&(ref exported_symbol, _)| {
+ match *exported_symbol {
+ ExportedSymbol::NoDefId(symbol_name) => {
+ symbol_name != metadata_symbol_name
+ },
+ _ => true,
+ }
+ })
+ .cloned())
}
fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq<Option<LinkagePreference>> {
// generated regardless of trailing bytes that end up in it.
pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- link_meta: &LinkMeta,
- exported_symbols: &NodeSet)
+ link_meta: &LinkMeta)
-> EncodedMetadata
{
let mut cursor = Cursor::new(vec![]);
opaque: opaque::Encoder::new(&mut cursor),
tcx,
link_meta,
- exported_symbols,
lazy_state: LazyState::NoNode,
type_shorthands: Default::default(),
predicate_shorthands: Default::default(),
filemap_cache: tcx.sess.codemap().files()[0].clone(),
+ interpret_alloc_shorthands: Default::default(),
};
// Encode the rustc version string in a predictable location.