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.
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.
13 use rustc
::hir
::def_id
::{DefId, DefIndex}
;
14 use std
::io
::{Cursor, Write}
;
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.
30 pub fn new(max_index
: usize) -> Index
{
31 Index { positions: vec![u32::MAX; max_index] }
34 pub fn record(&mut self, def_id
: DefId
, entry
: Lazy
<Entry
>) {
35 assert
!(def_id
.is_local());
36 self.record_index(def_id
.index
, entry
);
39 pub fn record_index(&mut self, item
: DefIndex
, entry
: Lazy
<Entry
>) {
40 let item
= item
.as_usize();
42 assert
!(entry
.position
< (u32::MAX
as usize));
43 let position
= entry
.position
as u32;
45 assert
!(self.positions
[item
] == u32::MAX
,
46 "recorded position for item {:?} twice, first at {:?} and now at {:?}",
51 self.positions
[item
] = position
.to_le();
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())
61 impl<'tcx
> LazySeq
<Index
> {
62 /// Given the metadata, extract out the offset of a particular
63 /// DefIndex (if any).
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();
69 debug
!("Index::lookup: index={:?} words.len={:?}",
73 let position
= u32::from_le(words
[index
].get());
74 if position
== u32::MAX
{
75 debug
!("Index::lookup: position=u32::MAX");
78 debug
!("Index::lookup: position={:?}", position
);
79 Some(Lazy
::with_position(position
as usize))
83 pub fn iter_enumerated
<'a
>(&self,
85 -> impl Iterator
<Item
= (DefIndex
, Lazy
<Entry
<'tcx
>>)> + 'a
{
86 let words
= &bytes_to_words(&bytes
[self.position
..])[..self.len
];
87 words
.iter().map(|word
| word
.get()).enumerate().filter_map(|(index
, position
)| {
88 if position
== u32::MAX
{
91 let position
= u32::from_le(position
) as usize;
92 Some((DefIndex
::new(index
), Lazy
::with_position(position
)))
100 struct Unaligned
<T
>(T
);
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.
104 impl<T
: Copy
> Clone
for Unaligned
<T
> {
105 fn clone(&self) -> Self {
110 impl<T
> Unaligned
<T
> {
111 fn get(self) -> T { self.0 }
114 fn bytes_to_words(b
: &[u8]) -> &[Unaligned
<u32>] {
115 unsafe { slice::from_raw_parts(b.as_ptr() as *const Unaligned<u32>, b.len() / 4) }
118 fn words_to_bytes(w
: &[u32]) -> &[u8] {
119 unsafe { slice::from_raw_parts(w.as_ptr() as *const u8, w.len() * 4) }