]> git.proxmox.com Git - rustc.git/blame - src/librustc_metadata/index.rs
New upstream version 1.17.0+dfsg2
[rustc.git] / src / librustc_metadata / index.rs
CommitLineData
e9174d1e
SL
1// Copyright 2015 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.
4//
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.
10
9e0c209e
SL
11use schema::*;
12
54a0048b 13use rustc::hir::def_id::{DefId, DefIndex};
e9174d1e
SL
14use std::io::{Cursor, Write};
15use std::slice;
16use std::u32;
e9174d1e 17
b039eaaf
SL
18/// While we are generating the metadata, we also track the position
19/// of each DefIndex. It is not required that all definitions appear
20/// in the metadata, nor that they are serialized in order, and
21/// therefore we first allocate the vector here and fill it with
22/// `u32::MAX`. Whenever an index is visited, we fill in the
23/// appropriate spot by calling `record_position`. We should never
24/// visit the same index twice.
9e0c209e 25pub struct Index {
b039eaaf 26 positions: Vec<u32>,
e9174d1e
SL
27}
28
9e0c209e
SL
29impl Index {
30 pub fn new(max_index: usize) -> Index {
c30ab7b3 31 Index { positions: vec![u32::MAX; max_index] }
b039eaaf
SL
32 }
33
9e0c209e 34 pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry>) {
b039eaaf 35 assert!(def_id.is_local());
9e0c209e 36 self.record_index(def_id.index, entry);
b039eaaf
SL
37 }
38
9e0c209e 39 pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry>) {
b039eaaf
SL
40 let item = item.as_usize();
41
9e0c209e
SL
42 assert!(entry.position < (u32::MAX as usize));
43 let position = entry.position as u32;
e9174d1e 44
b039eaaf
SL
45 assert!(self.positions[item] == u32::MAX,
46 "recorded position for item {:?} twice, first at {:?} and now at {:?}",
c30ab7b3
SL
47 item,
48 self.positions[item],
49 position);
e9174d1e 50
9e0c209e 51 self.positions[item] = position.to_le();
e9174d1e
SL
52 }
53
9e0c209e
SL
54 pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) -> LazySeq<Index> {
55 let pos = buf.position();
56 buf.write_all(words_to_bytes(&self.positions)).unwrap();
57 LazySeq::with_position_and_length(pos as usize, self.positions.len())
e9174d1e 58 }
b039eaaf 59}
e9174d1e 60
9e0c209e
SL
61impl<'tcx> LazySeq<Index> {
62 /// Given the metadata, extract out the offset of a particular
63 /// DefIndex (if any).
64 #[inline(never)]
65 pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
66 let words = &bytes_to_words(&bytes[self.position..])[..self.len];
67 let index = def_index.as_usize();
e9174d1e 68
9e0c209e 69 debug!("Index::lookup: index={:?} words.len={:?}",
c30ab7b3
SL
70 index,
71 words.len());
9e0c209e 72
476ff2be 73 let position = u32::from_le(words[index].get());
9e0c209e
SL
74 if position == u32::MAX {
75 debug!("Index::lookup: position=u32::MAX");
76 None
77 } else {
78 debug!("Index::lookup: position={:?}", position);
79 Some(Lazy::with_position(position as usize))
e9174d1e
SL
80 }
81 }
e9174d1e 82
c30ab7b3
SL
83 pub fn iter_enumerated<'a>(&self,
84 bytes: &'a [u8])
85 -> impl Iterator<Item = (DefIndex, Lazy<Entry<'tcx>>)> + 'a {
9e0c209e 86 let words = &bytes_to_words(&bytes[self.position..])[..self.len];
476ff2be 87 words.iter().map(|word| word.get()).enumerate().filter_map(|(index, position)| {
9e0c209e
SL
88 if position == u32::MAX {
89 None
90 } else {
91 let position = u32::from_le(position) as usize;
92 Some((DefIndex::new(index), Lazy::with_position(position)))
93 }
94 })
e9174d1e 95 }
e9174d1e
SL
96}
97
476ff2be 98#[repr(packed)]
8bb4bdeb 99#[derive(Copy)]
476ff2be
SL
100struct Unaligned<T>(T);
101
8bb4bdeb
XL
102// The derived Clone impl is unsafe for this packed struct since it needs to pass a reference to
103// the field to `T::clone`, but this reference may not be properly aligned.
104impl<T: Copy> Clone for Unaligned<T> {
105 fn clone(&self) -> Self {
106 *self
107 }
108}
109
476ff2be
SL
110impl<T> Unaligned<T> {
111 fn get(self) -> T { self.0 }
112}
113
114fn bytes_to_words(b: &[u8]) -> &[Unaligned<u32>] {
115 unsafe { slice::from_raw_parts(b.as_ptr() as *const Unaligned<u32>, b.len() / 4) }
e9174d1e
SL
116}
117
9e0c209e
SL
118fn words_to_bytes(w: &[u32]) -> &[u8] {
119 unsafe { slice::from_raw_parts(w.as_ptr() as *const u8, w.len() * 4) }
e9174d1e 120}