Build SymbolMap for symbol name conflict checking and caching.
This commit is contained in:
parent
87c1c87dd7
commit
b38e0d0d44
|
@ -80,6 +80,7 @@ use meth;
|
||||||
use mir;
|
use mir;
|
||||||
use monomorphize::{self, Instance};
|
use monomorphize::{self, Instance};
|
||||||
use partitioning::{self, PartitioningStrategy, CodegenUnit};
|
use partitioning::{self, PartitioningStrategy, CodegenUnit};
|
||||||
|
use symbol_map::SymbolMap;
|
||||||
use symbol_names_test;
|
use symbol_names_test;
|
||||||
use trans_item::TransItem;
|
use trans_item::TransItem;
|
||||||
use tvec;
|
use tvec;
|
||||||
|
@ -97,6 +98,7 @@ use libc::c_uint;
|
||||||
use std::ffi::{CStr, CString};
|
use std::ffi::{CStr, CString};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::rc::Rc;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::{i8, i16, i32, i64};
|
use std::{i8, i16, i32, i64};
|
||||||
use syntax_pos::{Span, DUMMY_SP};
|
use syntax_pos::{Span, DUMMY_SP};
|
||||||
|
@ -2588,14 +2590,18 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
};
|
};
|
||||||
let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
|
let no_builtins = attr::contains_name(&krate.attrs, "no_builtins");
|
||||||
|
|
||||||
let codegen_units = collect_and_partition_translation_items(&shared_ccx);
|
let (codegen_units, symbol_map) =
|
||||||
|
collect_and_partition_translation_items(&shared_ccx);
|
||||||
let codegen_unit_count = codegen_units.len();
|
let codegen_unit_count = codegen_units.len();
|
||||||
|
|
||||||
assert!(tcx.sess.opts.cg.codegen_units == codegen_unit_count ||
|
assert!(tcx.sess.opts.cg.codegen_units == codegen_unit_count ||
|
||||||
tcx.sess.opts.debugging_opts.incremental.is_some());
|
tcx.sess.opts.debugging_opts.incremental.is_some());
|
||||||
|
|
||||||
let crate_context_list = CrateContextList::new(&shared_ccx, codegen_units);
|
let symbol_map = Rc::new(symbol_map);
|
||||||
|
|
||||||
|
let crate_context_list = CrateContextList::new(&shared_ccx,
|
||||||
|
codegen_units,
|
||||||
|
symbol_map.clone());
|
||||||
let modules = crate_context_list.iter()
|
let modules = crate_context_list.iter()
|
||||||
.map(|ccx| ModuleTranslation {
|
.map(|ccx| ModuleTranslation {
|
||||||
name: String::from(&ccx.codegen_unit().name[..]),
|
name: String::from(&ccx.codegen_unit().name[..]),
|
||||||
|
@ -2693,8 +2699,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
let sess = shared_ccx.sess();
|
let sess = shared_ccx.sess();
|
||||||
let mut reachable_symbols = shared_ccx.reachable().iter().map(|&id| {
|
let mut reachable_symbols = shared_ccx.reachable().iter().map(|&id| {
|
||||||
let def_id = shared_ccx.tcx().map.local_def_id(id);
|
let def_id = shared_ccx.tcx().map.local_def_id(id);
|
||||||
Instance::mono(&shared_ccx, def_id).symbol_name(&shared_ccx)
|
symbol_for_def_id(def_id, &shared_ccx, &symbol_map)
|
||||||
}).collect::<Vec<_>>();
|
}).collect::<Vec<_>>();
|
||||||
|
|
||||||
if sess.entry_fn.borrow().is_some() {
|
if sess.entry_fn.borrow().is_some() {
|
||||||
reachable_symbols.push("main".to_string());
|
reachable_symbols.push("main".to_string());
|
||||||
}
|
}
|
||||||
|
@ -2716,7 +2723,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
reachable_symbols.extend(syms.into_iter().filter(|did| {
|
reachable_symbols.extend(syms.into_iter().filter(|did| {
|
||||||
sess.cstore.is_extern_item(shared_ccx.tcx(), *did)
|
sess.cstore.is_extern_item(shared_ccx.tcx(), *did)
|
||||||
}).map(|did| {
|
}).map(|did| {
|
||||||
Instance::mono(&shared_ccx, did).symbol_name(&shared_ccx)
|
symbol_for_def_id(did, &shared_ccx, &symbol_map)
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2810,7 +2817,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TransItemsWithinModVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>)
|
fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>)
|
||||||
-> Vec<CodegenUnit<'tcx>> {
|
-> (Vec<CodegenUnit<'tcx>>, SymbolMap<'tcx>) {
|
||||||
let time_passes = scx.sess().time_passes();
|
let time_passes = scx.sess().time_passes();
|
||||||
|
|
||||||
let collection_mode = match scx.sess().opts.debugging_opts.print_trans_items {
|
let collection_mode = match scx.sess().opts.debugging_opts.print_trans_items {
|
||||||
|
@ -2833,10 +2840,13 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
|
||||||
None => TransItemCollectionMode::Lazy
|
None => TransItemCollectionMode::Lazy
|
||||||
};
|
};
|
||||||
|
|
||||||
let (items, inlining_map) = time(time_passes, "translation item collection", || {
|
let (items, inlining_map) =
|
||||||
collector::collect_crate_translation_items(&scx, collection_mode)
|
time(time_passes, "translation item collection", || {
|
||||||
|
collector::collect_crate_translation_items(&scx, collection_mode)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let symbol_map = SymbolMap::build(scx, items.iter().cloned());
|
||||||
|
|
||||||
let strategy = if scx.sess().opts.debugging_opts.incremental.is_some() {
|
let strategy = if scx.sess().opts.debugging_opts.incremental.is_some() {
|
||||||
PartitioningStrategy::PerModule
|
PartitioningStrategy::PerModule
|
||||||
} else {
|
} else {
|
||||||
|
@ -2910,5 +2920,24 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
codegen_units
|
(codegen_units, symbol_map)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn symbol_for_def_id<'a, 'tcx>(def_id: DefId,
|
||||||
|
scx: &SharedCrateContext<'a, 'tcx>,
|
||||||
|
symbol_map: &SymbolMap<'tcx>)
|
||||||
|
-> String {
|
||||||
|
// Just try to look things up in the symbol map. If nothing's there, we
|
||||||
|
// recompute.
|
||||||
|
if let Some(node_id) = scx.tcx().map.as_local_node_id(def_id) {
|
||||||
|
if let Some(sym) = symbol_map.get(TransItem::Static(node_id)) {
|
||||||
|
return sym.to_owned();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let instance = Instance::mono(scx, def_id);
|
||||||
|
|
||||||
|
symbol_map.get(TransItem::Fn(instance))
|
||||||
|
.map(str::to_owned)
|
||||||
|
.unwrap_or_else(|| instance.symbol_name(scx))
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ use intrinsic;
|
||||||
use machine::llalign_of_min;
|
use machine::llalign_of_min;
|
||||||
use meth;
|
use meth;
|
||||||
use monomorphize::{self, Instance};
|
use monomorphize::{self, Instance};
|
||||||
|
use trans_item::TransItem;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use type_of;
|
use type_of;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
@ -536,11 +537,18 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
// reference. It also occurs when testing libcore and in some
|
// reference. It also occurs when testing libcore and in some
|
||||||
// other weird situations. Annoying.
|
// other weird situations. Annoying.
|
||||||
|
|
||||||
let sym = instance.symbol_name(ccx.shared());
|
// Let's see if we can get the symbol name from the symbol_map, so we don't
|
||||||
|
// have to recompute it.
|
||||||
|
let mut sym_data = String::new();
|
||||||
|
let sym = ccx.symbol_map().get(TransItem::Fn(instance)).unwrap_or_else(|| {
|
||||||
|
sym_data = instance.symbol_name(ccx.shared());
|
||||||
|
&sym_data[..]
|
||||||
|
});
|
||||||
|
|
||||||
let llptrty = type_of::type_of(ccx, fn_ptr_ty);
|
let llptrty = type_of::type_of(ccx, fn_ptr_ty);
|
||||||
let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
|
let llfn = if let Some(llfn) = declare::get_declared_value(ccx, sym) {
|
||||||
if let Some(span) = local_item {
|
if let Some(span) = local_item {
|
||||||
if declare::get_defined_value(ccx, &sym).is_some() {
|
if declare::get_defined_value(ccx, sym).is_some() {
|
||||||
ccx.sess().span_fatal(span,
|
ccx.sess().span_fatal(span,
|
||||||
&format!("symbol `{}` is already defined", sym));
|
&format!("symbol `{}` is already defined", sym));
|
||||||
}
|
}
|
||||||
|
@ -558,7 +566,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
llfn
|
llfn
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let llfn = declare::declare_fn(ccx, &sym, ty);
|
let llfn = declare::declare_fn(ccx, sym, ty);
|
||||||
assert_eq!(common::val_ty(llfn), llptrty);
|
assert_eq!(common::val_ty(llfn), llptrty);
|
||||||
debug!("get_fn: not casting pointer!");
|
debug!("get_fn: not casting pointer!");
|
||||||
|
|
||||||
|
|
|
@ -1013,14 +1013,16 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
|
||||||
return Datum::new(g, ty, Lvalue::new("static"));
|
return Datum::new(g, ty, Lvalue::new("static"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let sym = instance.symbol_name(ccx.shared());
|
|
||||||
|
|
||||||
let g = if let Some(id) = ccx.tcx().map.as_local_node_id(def_id) {
|
let g = if let Some(id) = ccx.tcx().map.as_local_node_id(def_id) {
|
||||||
|
|
||||||
let llty = type_of::type_of(ccx, ty);
|
let llty = type_of::type_of(ccx, ty);
|
||||||
let (g, attrs) = match ccx.tcx().map.get(id) {
|
let (g, attrs) = match ccx.tcx().map.get(id) {
|
||||||
hir_map::NodeItem(&hir::Item {
|
hir_map::NodeItem(&hir::Item {
|
||||||
ref attrs, span, node: hir::ItemStatic(..), ..
|
ref attrs, span, node: hir::ItemStatic(..), ..
|
||||||
}) => {
|
}) => {
|
||||||
|
let sym = ccx.symbol_map()
|
||||||
|
.get(TransItem::Static(id))
|
||||||
|
.expect("Local statics should always be in the SymbolMap");
|
||||||
// Make sure that this is never executed for something inlined.
|
// Make sure that this is never executed for something inlined.
|
||||||
assert!(!ccx.external_srcs().borrow().contains_key(&id));
|
assert!(!ccx.external_srcs().borrow().contains_key(&id));
|
||||||
|
|
||||||
|
@ -1028,16 +1030,16 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
|
||||||
.items
|
.items
|
||||||
.contains_key(&TransItem::Static(id));
|
.contains_key(&TransItem::Static(id));
|
||||||
if defined_in_current_codegen_unit {
|
if defined_in_current_codegen_unit {
|
||||||
if declare::get_declared_value(ccx, &sym).is_none() {
|
if declare::get_declared_value(ccx, sym).is_none() {
|
||||||
span_bug!(span, "trans: Static not properly pre-defined?");
|
span_bug!(span, "trans: Static not properly pre-defined?");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if declare::get_declared_value(ccx, &sym).is_some() {
|
if declare::get_declared_value(ccx, sym).is_some() {
|
||||||
span_bug!(span, "trans: Conflicting symbol names for static?");
|
span_bug!(span, "trans: Conflicting symbol names for static?");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let g = declare::define_global(ccx, &sym, llty).unwrap();
|
let g = declare::define_global(ccx, sym, llty).unwrap();
|
||||||
|
|
||||||
(g, attrs)
|
(g, attrs)
|
||||||
}
|
}
|
||||||
|
@ -1045,6 +1047,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
|
||||||
hir_map::NodeForeignItem(&hir::ForeignItem {
|
hir_map::NodeForeignItem(&hir::ForeignItem {
|
||||||
ref attrs, span, node: hir::ForeignItemStatic(..), ..
|
ref attrs, span, node: hir::ForeignItemStatic(..), ..
|
||||||
}) => {
|
}) => {
|
||||||
|
let sym = instance.symbol_name(ccx.shared());
|
||||||
let g = if let Some(name) =
|
let g = if let Some(name) =
|
||||||
attr::first_attr_value_str_by_name(&attrs, "linkage") {
|
attr::first_attr_value_str_by_name(&attrs, "linkage") {
|
||||||
// If this is a static with a linkage specified, then we need to handle
|
// If this is a static with a linkage specified, then we need to handle
|
||||||
|
@ -1079,7 +1082,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
|
||||||
real_name.push_str(&sym);
|
real_name.push_str(&sym);
|
||||||
let g2 = declare::define_global(ccx, &real_name, llty).unwrap_or_else(||{
|
let g2 = declare::define_global(ccx, &real_name, llty).unwrap_or_else(||{
|
||||||
ccx.sess().span_fatal(span,
|
ccx.sess().span_fatal(span,
|
||||||
&format!("symbol `{}` is already defined", sym))
|
&format!("symbol `{}` is already defined", &sym))
|
||||||
});
|
});
|
||||||
llvm::SetLinkage(g2, llvm::InternalLinkage);
|
llvm::SetLinkage(g2, llvm::InternalLinkage);
|
||||||
llvm::LLVMSetInitializer(g2, g1);
|
llvm::LLVMSetInitializer(g2, g1);
|
||||||
|
@ -1104,6 +1107,8 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
|
||||||
|
|
||||||
g
|
g
|
||||||
} else {
|
} else {
|
||||||
|
let sym = instance.symbol_name(ccx.shared());
|
||||||
|
|
||||||
// FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
|
// FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
|
||||||
// FIXME(nagisa): investigate whether it can be changed into define_global
|
// FIXME(nagisa): investigate whether it can be changed into define_global
|
||||||
let g = declare::declare_global(ccx, &sym, type_of::type_of(ccx, ty));
|
let g = declare::declare_global(ccx, &sym, type_of::type_of(ccx, ty));
|
||||||
|
|
|
@ -35,6 +35,7 @@ use rustc::ty::subst::{Substs, VecPerParamSpace};
|
||||||
use rustc::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use session::config::NoDebugInfo;
|
use session::config::NoDebugInfo;
|
||||||
use session::Session;
|
use session::Session;
|
||||||
|
use symbol_map::SymbolMap;
|
||||||
use util::sha2::Sha256;
|
use util::sha2::Sha256;
|
||||||
use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap};
|
use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap};
|
||||||
|
|
||||||
|
@ -171,6 +172,8 @@ pub struct LocalCrateContext<'tcx> {
|
||||||
|
|
||||||
/// Depth of the current type-of computation - used to bail out
|
/// Depth of the current type-of computation - used to bail out
|
||||||
type_of_depth: Cell<usize>,
|
type_of_depth: Cell<usize>,
|
||||||
|
|
||||||
|
symbol_map: Rc<SymbolMap<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement DepTrackingMapConfig for `trait_cache`
|
// Implement DepTrackingMapConfig for `trait_cache`
|
||||||
|
@ -197,12 +200,13 @@ pub struct CrateContextList<'a, 'tcx: 'a> {
|
||||||
impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> {
|
impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> {
|
||||||
|
|
||||||
pub fn new(shared_ccx: &'a SharedCrateContext<'a, 'tcx>,
|
pub fn new(shared_ccx: &'a SharedCrateContext<'a, 'tcx>,
|
||||||
codegen_units: Vec<CodegenUnit<'tcx>>)
|
codegen_units: Vec<CodegenUnit<'tcx>>,
|
||||||
|
symbol_map: Rc<SymbolMap<'tcx>>)
|
||||||
-> CrateContextList<'a, 'tcx> {
|
-> CrateContextList<'a, 'tcx> {
|
||||||
CrateContextList {
|
CrateContextList {
|
||||||
shared: shared_ccx,
|
shared: shared_ccx,
|
||||||
local_ccxs: codegen_units.into_iter().map(|codegen_unit| {
|
local_ccxs: codegen_units.into_iter().map(|codegen_unit| {
|
||||||
LocalCrateContext::new(shared_ccx, codegen_unit)
|
LocalCrateContext::new(shared_ccx, codegen_unit, symbol_map.clone())
|
||||||
}).collect()
|
}).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -512,7 +516,8 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
|
||||||
|
|
||||||
impl<'tcx> LocalCrateContext<'tcx> {
|
impl<'tcx> LocalCrateContext<'tcx> {
|
||||||
fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
|
fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
|
||||||
codegen_unit: CodegenUnit<'tcx>)
|
codegen_unit: CodegenUnit<'tcx>,
|
||||||
|
symbol_map: Rc<SymbolMap<'tcx>>)
|
||||||
-> LocalCrateContext<'tcx> {
|
-> LocalCrateContext<'tcx> {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Append ".rs" to LLVM module identifier.
|
// Append ".rs" to LLVM module identifier.
|
||||||
|
@ -571,6 +576,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
|
||||||
intrinsics: RefCell::new(FnvHashMap()),
|
intrinsics: RefCell::new(FnvHashMap()),
|
||||||
n_llvm_insns: Cell::new(0),
|
n_llvm_insns: Cell::new(0),
|
||||||
type_of_depth: Cell::new(0),
|
type_of_depth: Cell::new(0),
|
||||||
|
symbol_map: symbol_map,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (int_type, opaque_vec_type, str_slice_ty, mut local_ccx) = {
|
let (int_type, opaque_vec_type, str_slice_ty, mut local_ccx) = {
|
||||||
|
@ -890,6 +896,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
||||||
self.shared.get_mir(def_id)
|
self.shared.get_mir(def_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn symbol_map(&self) -> &SymbolMap<'tcx> {
|
||||||
|
&*self.local().symbol_map
|
||||||
|
}
|
||||||
|
|
||||||
pub fn translation_items(&self) -> &RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>> {
|
pub fn translation_items(&self) -> &RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>> {
|
||||||
&self.shared.translation_items
|
&self.shared.translation_items
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,6 +122,7 @@ mod meth;
|
||||||
mod mir;
|
mod mir;
|
||||||
mod monomorphize;
|
mod monomorphize;
|
||||||
mod partitioning;
|
mod partitioning;
|
||||||
|
mod symbol_map;
|
||||||
mod symbol_names_test;
|
mod symbol_names_test;
|
||||||
mod trans_item;
|
mod trans_item;
|
||||||
mod tvec;
|
mod tvec;
|
||||||
|
|
|
@ -84,19 +84,24 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||||
monomorphizing.insert(fn_id, depth + 1);
|
monomorphizing.insert(fn_id, depth + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let symbol = instance.symbol_name(ccx.shared());
|
// Let's see if we can get the symbol name from the symbol_map, so we don't
|
||||||
|
// have to recompute it.
|
||||||
|
let mut sym_data = String::new();
|
||||||
|
let symbol = ccx.symbol_map().get(TransItem::Fn(instance)).unwrap_or_else(|| {
|
||||||
|
sym_data = instance.symbol_name(ccx.shared());
|
||||||
|
&sym_data[..]
|
||||||
|
});
|
||||||
|
|
||||||
debug!("monomorphize_fn mangled to {}", symbol);
|
debug!("monomorphize_fn mangled to {}", symbol);
|
||||||
assert!(declare::get_defined_value(ccx, &symbol).is_none());
|
assert!(declare::get_defined_value(ccx, symbol).is_none());
|
||||||
|
|
||||||
// FIXME(nagisa): perhaps needs a more fine grained selection?
|
// FIXME(nagisa): perhaps needs a more fine grained selection?
|
||||||
let lldecl = declare::define_internal_fn(ccx, &symbol, mono_ty);
|
let lldecl = declare::define_internal_fn(ccx, symbol, mono_ty);
|
||||||
// FIXME(eddyb) Doubt all extern fn should allow unwinding.
|
// FIXME(eddyb) Doubt all extern fn should allow unwinding.
|
||||||
attributes::unwind(lldecl, true);
|
attributes::unwind(lldecl, true);
|
||||||
|
|
||||||
ccx.instances().borrow_mut().insert(instance, lldecl);
|
ccx.instances().borrow_mut().insert(instance, lldecl);
|
||||||
|
|
||||||
|
|
||||||
// we can only monomorphize things in this crate (or inlined into it)
|
// we can only monomorphize things in this crate (or inlined into it)
|
||||||
let fn_node_id = ccx.tcx().map.as_local_node_id(fn_id).unwrap();
|
let fn_node_id = ccx.tcx().map.as_local_node_id(fn_id).unwrap();
|
||||||
let map_node = errors::expect(
|
let map_node = errors::expect(
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
use context::SharedCrateContext;
|
||||||
|
use monomorphize::Instance;
|
||||||
|
use rustc::ty::TyCtxt;
|
||||||
|
use syntax::codemap::Span;
|
||||||
|
use trans_item::TransItem;
|
||||||
|
use util::nodemap::FnvHashMap;
|
||||||
|
|
||||||
|
|
||||||
|
// In the SymbolMap we collect the symbol names of all translation items of
|
||||||
|
// the current crate.
|
||||||
|
|
||||||
|
pub struct SymbolMap<'tcx> {
|
||||||
|
index: FnvHashMap<TransItem<'tcx>, (usize, usize)>,
|
||||||
|
arena: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> SymbolMap<'tcx> {
|
||||||
|
|
||||||
|
pub fn build<'a, I>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||||
|
trans_items: I)
|
||||||
|
-> SymbolMap<'tcx>
|
||||||
|
where I: Iterator<Item=TransItem<'tcx>>
|
||||||
|
{
|
||||||
|
// Check for duplicate symbol names
|
||||||
|
let mut symbols: Vec<_> = trans_items.map(|trans_item| {
|
||||||
|
(trans_item, trans_item.compute_symbol_name(scx))
|
||||||
|
}).collect();
|
||||||
|
|
||||||
|
(&mut symbols[..]).sort_by(|&(_, ref sym1), &(_, ref sym2)|{
|
||||||
|
sym1.cmp(sym2)
|
||||||
|
});
|
||||||
|
|
||||||
|
for pair in (&symbols[..]).windows(2) {
|
||||||
|
let sym1 = &pair[0].1;
|
||||||
|
let sym2 = &pair[1].1;
|
||||||
|
|
||||||
|
if *sym1 == *sym2 {
|
||||||
|
let trans_item1 = pair[0].0;
|
||||||
|
let trans_item2 = pair[1].0;
|
||||||
|
|
||||||
|
let span1 = get_span(scx.tcx(), trans_item1);
|
||||||
|
let span2 = get_span(scx.tcx(), trans_item2);
|
||||||
|
|
||||||
|
// Deterministically select one of the spans for error reporting
|
||||||
|
let span = match (span1, span2) {
|
||||||
|
(Some(span1), Some(span2)) => {
|
||||||
|
Some(if span1.lo.0 > span2.lo.0 {
|
||||||
|
span1
|
||||||
|
} else {
|
||||||
|
span2
|
||||||
|
})
|
||||||
|
}
|
||||||
|
(Some(span), None) |
|
||||||
|
(None, Some(span)) => Some(span),
|
||||||
|
_ => None
|
||||||
|
};
|
||||||
|
|
||||||
|
let error_message = format!("symbol `{}` is already defined", sym1);
|
||||||
|
|
||||||
|
if let Some(span) = span {
|
||||||
|
scx.sess().span_fatal(span, &error_message)
|
||||||
|
} else {
|
||||||
|
scx.sess().fatal(&error_message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut symbol_map = SymbolMap {
|
||||||
|
index: FnvHashMap(),
|
||||||
|
arena: String::with_capacity(1024),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (trans_item, symbol) in symbols {
|
||||||
|
let start_index = symbol_map.arena.len();
|
||||||
|
symbol_map.arena.push_str(&symbol[..]);
|
||||||
|
let end_index = symbol_map.arena.len();
|
||||||
|
let prev_entry = symbol_map.index.insert(trans_item,
|
||||||
|
(start_index, end_index));
|
||||||
|
if prev_entry.is_some() {
|
||||||
|
bug!("TransItem encountered twice?")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
|
trans_item: TransItem<'tcx>) -> Option<Span> {
|
||||||
|
match trans_item {
|
||||||
|
TransItem::Fn(Instance { def, .. }) => {
|
||||||
|
tcx.map.as_local_node_id(def)
|
||||||
|
}
|
||||||
|
TransItem::Static(node_id) => Some(node_id),
|
||||||
|
TransItem::DropGlue(_) => None,
|
||||||
|
}.map(|node_id| {
|
||||||
|
tcx.map.span(node_id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol_map
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get(&self, trans_item: TransItem<'tcx>) -> Option<&str> {
|
||||||
|
self.index.get(&trans_item).map(|&(start_index, end_index)| {
|
||||||
|
&self.arena[start_index .. end_index]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
use attributes;
|
use attributes;
|
||||||
use base;
|
use base;
|
||||||
use consts;
|
use consts;
|
||||||
use context::CrateContext;
|
use context::{CrateContext, SharedCrateContext};
|
||||||
use declare;
|
use declare;
|
||||||
use glue::DropGlueKind;
|
use glue::DropGlueKind;
|
||||||
use llvm;
|
use llvm;
|
||||||
|
@ -64,7 +64,6 @@ impl<'tcx> Hash for TransItem<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<'a, 'tcx> TransItem<'tcx> {
|
impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
|
|
||||||
pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
|
pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
|
||||||
|
@ -108,15 +107,20 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
self.to_raw_string(),
|
self.to_raw_string(),
|
||||||
ccx.codegen_unit().name);
|
ccx.codegen_unit().name);
|
||||||
|
|
||||||
|
let symbol_name = ccx.symbol_map()
|
||||||
|
.get(*self)
|
||||||
|
.expect("Name not present in SymbolMap?");
|
||||||
|
debug!("symbol {}", symbol_name);
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
TransItem::Static(node_id) => {
|
TransItem::Static(node_id) => {
|
||||||
TransItem::predefine_static(ccx, node_id, linkage);
|
TransItem::predefine_static(ccx, node_id, linkage, symbol_name);
|
||||||
}
|
}
|
||||||
TransItem::Fn(instance) => {
|
TransItem::Fn(instance) => {
|
||||||
TransItem::predefine_fn(ccx, instance, linkage);
|
TransItem::predefine_fn(ccx, instance, linkage, symbol_name);
|
||||||
}
|
}
|
||||||
TransItem::DropGlue(dg) => {
|
TransItem::DropGlue(dg) => {
|
||||||
TransItem::predefine_drop_glue(ccx, dg, linkage);
|
TransItem::predefine_drop_glue(ccx, dg, linkage, symbol_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +132,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
|
|
||||||
fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
|
fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
|
||||||
node_id: ast::NodeId,
|
node_id: ast::NodeId,
|
||||||
linkage: llvm::Linkage) {
|
linkage: llvm::Linkage,
|
||||||
|
symbol_name: &str) {
|
||||||
let def_id = ccx.tcx().map.local_def_id(node_id);
|
let def_id = ccx.tcx().map.local_def_id(node_id);
|
||||||
let ty = ccx.tcx().lookup_item_type(def_id).ty;
|
let ty = ccx.tcx().lookup_item_type(def_id).ty;
|
||||||
let llty = type_of::type_of(ccx, ty);
|
let llty = type_of::type_of(ccx, ty);
|
||||||
|
@ -137,13 +142,9 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
hir::map::NodeItem(&hir::Item {
|
hir::map::NodeItem(&hir::Item {
|
||||||
span, node: hir::ItemStatic(..), ..
|
span, node: hir::ItemStatic(..), ..
|
||||||
}) => {
|
}) => {
|
||||||
let instance = Instance::mono(ccx.shared(), def_id);
|
let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| {
|
||||||
let sym = instance.symbol_name(ccx.shared());
|
|
||||||
debug!("symbol {}", sym);
|
|
||||||
|
|
||||||
let g = declare::define_global(ccx, &sym, llty).unwrap_or_else(|| {
|
|
||||||
ccx.sess().span_fatal(span,
|
ccx.sess().span_fatal(span,
|
||||||
&format!("symbol `{}` is already defined", sym))
|
&format!("symbol `{}` is already defined", symbol_name))
|
||||||
});
|
});
|
||||||
|
|
||||||
llvm::SetLinkage(g, linkage);
|
llvm::SetLinkage(g, linkage);
|
||||||
|
@ -155,7 +156,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
|
|
||||||
fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
|
fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
|
||||||
instance: Instance<'tcx>,
|
instance: Instance<'tcx>,
|
||||||
linkage: llvm::Linkage) {
|
linkage: llvm::Linkage,
|
||||||
|
symbol_name: &str) {
|
||||||
assert!(!instance.substs.types.needs_infer() &&
|
assert!(!instance.substs.types.needs_infer() &&
|
||||||
!instance.substs.types.has_param_types());
|
!instance.substs.types.has_param_types());
|
||||||
|
|
||||||
|
@ -186,10 +188,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
hir_map::NodeImplItem(&hir::ImplItem {
|
hir_map::NodeImplItem(&hir::ImplItem {
|
||||||
ref attrs, node: hir::ImplItemKind::Method(..), ..
|
ref attrs, node: hir::ImplItemKind::Method(..), ..
|
||||||
}) => {
|
}) => {
|
||||||
let symbol = instance.symbol_name(ccx.shared());
|
let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
|
||||||
debug!("symbol {}", symbol);
|
|
||||||
|
|
||||||
let lldecl = declare::declare_fn(ccx, &symbol, mono_ty);
|
|
||||||
llvm::SetLinkage(lldecl, linkage);
|
llvm::SetLinkage(lldecl, linkage);
|
||||||
attributes::from_fn_attrs(ccx, attrs, lldecl);
|
attributes::from_fn_attrs(ccx, attrs, lldecl);
|
||||||
base::set_link_section(ccx, lldecl, attrs);
|
base::set_link_section(ccx, lldecl, attrs);
|
||||||
|
@ -203,7 +202,8 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
|
|
||||||
fn predefine_drop_glue(ccx: &CrateContext<'a, 'tcx>,
|
fn predefine_drop_glue(ccx: &CrateContext<'a, 'tcx>,
|
||||||
dg: glue::DropGlueKind<'tcx>,
|
dg: glue::DropGlueKind<'tcx>,
|
||||||
linkage: llvm::Linkage) {
|
linkage: llvm::Linkage,
|
||||||
|
symbol_name: &str) {
|
||||||
let tcx = ccx.tcx();
|
let tcx = ccx.tcx();
|
||||||
assert_eq!(dg.ty(), glue::get_drop_glue_type(tcx, dg.ty()));
|
assert_eq!(dg.ty(), glue::get_drop_glue_type(tcx, dg.ty()));
|
||||||
let t = dg.ty();
|
let t = dg.ty();
|
||||||
|
@ -220,21 +220,31 @@ impl<'a, 'tcx> TransItem<'tcx> {
|
||||||
fn_ty.args[0].original_ty = type_of::type_of(ccx, t).ptr_to();
|
fn_ty.args[0].original_ty = type_of::type_of(ccx, t).ptr_to();
|
||||||
let llfnty = fn_ty.llvm_type(ccx);
|
let llfnty = fn_ty.llvm_type(ccx);
|
||||||
|
|
||||||
let prefix = match dg {
|
assert!(declare::get_defined_value(ccx, symbol_name).is_none());
|
||||||
DropGlueKind::Ty(_) => "drop",
|
let llfn = declare::declare_cfn(ccx, symbol_name, llfnty);
|
||||||
DropGlueKind::TyContents(_) => "drop_contents",
|
llvm::SetLinkage(llfn, linkage);
|
||||||
};
|
|
||||||
|
|
||||||
let symbol =
|
|
||||||
symbol_names::exported_name_from_type_and_prefix(ccx.shared(), t, prefix);
|
|
||||||
debug!(" symbol: {}", symbol);
|
|
||||||
assert!(declare::get_defined_value(ccx, &symbol).is_none());
|
|
||||||
let llfn = declare::declare_cfn(ccx, &symbol, llfnty);
|
|
||||||
attributes::set_frame_pointer_elimination(ccx, llfn);
|
attributes::set_frame_pointer_elimination(ccx, llfn);
|
||||||
llvm::SetLinkage(llfn, linkage);
|
|
||||||
ccx.drop_glues().borrow_mut().insert(dg, (llfn, fn_ty));
|
ccx.drop_glues().borrow_mut().insert(dg, (llfn, fn_ty));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn compute_symbol_name(&self,
|
||||||
|
scx: &SharedCrateContext<'a, 'tcx>) -> String {
|
||||||
|
match *self {
|
||||||
|
TransItem::Fn(instance) => instance.symbol_name(scx),
|
||||||
|
TransItem::Static(node_id) => {
|
||||||
|
let def_id = scx.tcx().map.local_def_id(node_id);
|
||||||
|
Instance::mono(scx, def_id).symbol_name(scx)
|
||||||
|
}
|
||||||
|
TransItem::DropGlue(dg) => {
|
||||||
|
let prefix = match dg {
|
||||||
|
DropGlueKind::Ty(_) => "drop",
|
||||||
|
DropGlueKind::TyContents(_) => "drop_contents",
|
||||||
|
};
|
||||||
|
symbol_names::exported_name_from_type_and_prefix(scx, dg.ty(), prefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
|
pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
TransItem::Fn(ref instance) => {
|
TransItem::Fn(ref instance) => {
|
||||||
|
|
Loading…
Reference in New Issue