]>
git.proxmox.com Git - rustc.git/blob - src/librustc_trans/symbol_map.rs
1 // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 use context
::SharedCrateContext
;
12 use monomorphize
::Instance
;
13 use rustc
::ty
::TyCtxt
;
15 use syntax
::codemap
::Span
;
16 use trans_item
::TransItem
;
17 use util
::nodemap
::FnvHashMap
;
19 // In the SymbolMap we collect the symbol names of all translation items of
20 // the current crate. This map exists as a performance optimization. Symbol
21 // names of translation items are deterministic and fully defined by the item.
22 // Thus they could also always be recomputed if needed.
24 pub struct SymbolMap
<'tcx
> {
25 index
: FnvHashMap
<TransItem
<'tcx
>, (usize, usize)>,
29 impl<'tcx
> SymbolMap
<'tcx
> {
31 pub fn build
<'a
, I
>(scx
: &SharedCrateContext
<'a
, 'tcx
>,
34 where I
: Iterator
<Item
=TransItem
<'tcx
>>
36 // Check for duplicate symbol names
37 let mut symbols
: Vec
<_
> = trans_items
.map(|trans_item
| {
38 (trans_item
, trans_item
.compute_symbol_name(scx
))
41 (&mut symbols
[..]).sort_by(|&(_
, ref sym1
), &(_
, ref sym2
)|{
45 for pair
in (&symbols
[..]).windows(2) {
46 let sym1
= &pair
[0].1;
47 let sym2
= &pair
[1].1;
50 let trans_item1
= pair
[0].0;
51 let trans_item2
= pair
[1].0;
53 let span1
= get_span(scx
.tcx(), trans_item1
);
54 let span2
= get_span(scx
.tcx(), trans_item2
);
56 // Deterministically select one of the spans for error reporting
57 let span
= match (span1
, span2
) {
58 (Some(span1
), Some(span2
)) => {
59 Some(if span1
.lo
.0 > span2
.lo
.0 {
66 (None
, Some(span
)) => Some(span
),
70 let error_message
= format
!("symbol `{}` is already defined", sym1
);
72 if let Some(span
) = span
{
73 scx
.sess().span_fatal(span
, &error_message
)
75 scx
.sess().fatal(&error_message
)
80 let mut symbol_map
= SymbolMap
{
82 arena
: String
::with_capacity(1024),
85 for (trans_item
, symbol
) in symbols
{
86 let start_index
= symbol_map
.arena
.len();
87 symbol_map
.arena
.push_str(&symbol
[..]);
88 let end_index
= symbol_map
.arena
.len();
89 let prev_entry
= symbol_map
.index
.insert(trans_item
,
90 (start_index
, end_index
));
91 if prev_entry
.is_some() {
92 bug
!("TransItem encountered twice?")
96 fn get_span
<'a
, 'tcx
>(tcx
: TyCtxt
<'a
, 'tcx
, 'tcx
>,
97 trans_item
: TransItem
<'tcx
>) -> Option
<Span
> {
99 TransItem
::Fn(Instance { def, .. }
) => {
100 tcx
.map
.as_local_node_id(def
)
102 TransItem
::Static(node_id
) => Some(node_id
),
103 TransItem
::DropGlue(_
) => None
,
105 tcx
.map
.span(node_id
)
112 pub fn get(&self, trans_item
: TransItem
<'tcx
>) -> Option
<&str> {
113 self.index
.get(&trans_item
).map(|&(start_index
, end_index
)| {
114 &self.arena
[start_index
.. end_index
]
118 pub fn get_or_compute
<'map
, 'scx
>(&'map
self,
119 scx
: &SharedCrateContext
<'scx
, 'tcx
>,
120 trans_item
: TransItem
<'tcx
>)
122 if let Some(sym
) = self.get(trans_item
) {
125 Cow
::from(trans_item
.compute_symbol_name(scx
))