1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use context::SharedCrateContext;
use monomorphize::Instance;
use rustc::ty::TyCtxt;
use std::borrow::Cow;
use syntax::codemap::Span;
use trans_item::TransItem;
use util::nodemap::FxHashMap;
pub struct SymbolMap<'tcx> {
index: FxHashMap<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>>
{
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);
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: FxHashMap(),
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.hir.as_local_node_id(def)
}
TransItem::Static(node_id) => Some(node_id),
TransItem::DropGlue(_) => None,
}.map(|node_id| {
tcx.hir.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]
})
}
pub fn get_or_compute<'map, 'scx>(&'map self,
scx: &SharedCrateContext<'scx, 'tcx>,
trans_item: TransItem<'tcx>)
-> Cow<'map, str> {
if let Some(sym) = self.get(trans_item) {
Cow::from(sym)
} else {
Cow::from(trans_item.compute_symbol_name(scx))
}
}
}