]> git.proxmox.com Git - rustc.git/blame - src/librustc_metadata/index.rs
New upstream version 1.25.0+dfsg1
[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
cc61c64b 13use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace};
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 {
cc61c64b 26 positions: [Vec<u32>; 2]
e9174d1e
SL
27}
28
9e0c209e 29impl Index {
cc61c64b
XL
30 pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Index {
31 Index {
32 positions: [vec![u32::MAX; max_index_lo],
33 vec![u32::MAX; max_index_hi]],
34 }
b039eaaf
SL
35 }
36
9e0c209e 37 pub fn record(&mut self, def_id: DefId, entry: Lazy<Entry>) {
b039eaaf 38 assert!(def_id.is_local());
9e0c209e 39 self.record_index(def_id.index, entry);
b039eaaf
SL
40 }
41
9e0c209e 42 pub fn record_index(&mut self, item: DefIndex, entry: Lazy<Entry>) {
9e0c209e
SL
43 assert!(entry.position < (u32::MAX as usize));
44 let position = entry.position as u32;
cc61c64b
XL
45 let space_index = item.address_space().index();
46 let array_index = item.as_array_index();
e9174d1e 47
cc61c64b 48 assert!(self.positions[space_index][array_index] == u32::MAX,
b039eaaf 49 "recorded position for item {:?} twice, first at {:?} and now at {:?}",
c30ab7b3 50 item,
cc61c64b 51 self.positions[space_index][array_index],
c30ab7b3 52 position);
e9174d1e 53
cc61c64b 54 self.positions[space_index][array_index] = position.to_le();
e9174d1e
SL
55 }
56
9e0c209e
SL
57 pub fn write_index(&self, buf: &mut Cursor<Vec<u8>>) -> LazySeq<Index> {
58 let pos = buf.position();
cc61c64b
XL
59
60 // First we write the length of the lower range ...
61 buf.write_all(words_to_bytes(&[(self.positions[0].len() as u32).to_le()])).unwrap();
62 // ... then the values in the lower range ...
63 buf.write_all(words_to_bytes(&self.positions[0][..])).unwrap();
64 // ... then the values in the higher range.
65 buf.write_all(words_to_bytes(&self.positions[1][..])).unwrap();
66 LazySeq::with_position_and_length(pos as usize,
67 self.positions[0].len() + self.positions[1].len() + 1)
e9174d1e 68 }
b039eaaf 69}
e9174d1e 70
9e0c209e
SL
71impl<'tcx> LazySeq<Index> {
72 /// Given the metadata, extract out the offset of a particular
73 /// DefIndex (if any).
74 #[inline(never)]
75 pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
76 let words = &bytes_to_words(&bytes[self.position..])[..self.len];
e9174d1e 77
9e0c209e 78 debug!("Index::lookup: index={:?} words.len={:?}",
2c00a5a8 79 def_index,
c30ab7b3 80 words.len());
9e0c209e 81
cc61c64b
XL
82 let positions = match def_index.address_space() {
83 DefIndexAddressSpace::Low => &words[1..],
84 DefIndexAddressSpace::High => {
85 // This is a DefIndex in the higher range, so find out where
86 // that starts:
87 let lo_count = u32::from_le(words[0].get()) as usize;
88 &words[lo_count + 1 .. ]
89 }
90 };
91
92 let array_index = def_index.as_array_index();
93 let position = u32::from_le(positions[array_index].get());
9e0c209e
SL
94 if position == u32::MAX {
95 debug!("Index::lookup: position=u32::MAX");
96 None
97 } else {
98 debug!("Index::lookup: position={:?}", position);
99 Some(Lazy::with_position(position as usize))
e9174d1e
SL
100 }
101 }
e9174d1e
SL
102}
103
476ff2be 104#[repr(packed)]
8bb4bdeb 105#[derive(Copy)]
476ff2be
SL
106struct Unaligned<T>(T);
107
8bb4bdeb
XL
108// The derived Clone impl is unsafe for this packed struct since it needs to pass a reference to
109// the field to `T::clone`, but this reference may not be properly aligned.
110impl<T: Copy> Clone for Unaligned<T> {
111 fn clone(&self) -> Self {
112 *self
113 }
114}
115
476ff2be
SL
116impl<T> Unaligned<T> {
117 fn get(self) -> T { self.0 }
118}
119
120fn bytes_to_words(b: &[u8]) -> &[Unaligned<u32>] {
121 unsafe { slice::from_raw_parts(b.as_ptr() as *const Unaligned<u32>, b.len() / 4) }
e9174d1e
SL
122}
123
9e0c209e
SL
124fn words_to_bytes(w: &[u32]) -> &[u8] {
125 unsafe { slice::from_raw_parts(w.as_ptr() as *const u8, w.len() * 4) }
e9174d1e 126}