]> git.proxmox.com Git - rustc.git/blame - src/librustc/metadata/cstore.rs
Imported Upstream version 1.3.0+dfsg1
[rustc.git] / src / librustc / metadata / cstore.rs
CommitLineData
1a4d82fc 1// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
223e47cc
LB
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
1a4d82fc 11#![allow(non_camel_case_types)]
223e47cc
LB
12
13// The crate store - a central repo for information collected about external
14// crates and libraries
15
1a4d82fc
JJ
16pub use self::MetadataBlob::*;
17pub use self::LinkagePreference::*;
18pub use self::NativeLibraryKind::*;
223e47cc 19
1a4d82fc 20use back::svh::Svh;
62682a34 21use metadata::{creader, decoder, loader};
85aaf69f 22use session::search_paths::PathKind;
1a4d82fc 23use util::nodemap::{FnvHashMap, NodeMap};
223e47cc 24
62682a34 25use std::cell::{RefCell, Ref};
1a4d82fc 26use std::rc::Rc;
c34b1796 27use std::path::PathBuf;
1a4d82fc 28use flate::Bytes;
223e47cc 29use syntax::ast;
c34b1796 30use syntax::codemap;
1a4d82fc 31use syntax::parse::token::IdentInterner;
223e47cc
LB
32
33// A map from external crate numbers (as decoded from some crate file) to
34// local crate numbers (as generated during this session). Each external
35// crate may refer to types in other external crates, and each has their
36// own crate numbers.
1a4d82fc 37pub type cnum_map = FnvHashMap<ast::CrateNum, ast::CrateNum>;
223e47cc 38
1a4d82fc
JJ
39pub enum MetadataBlob {
40 MetadataVec(Bytes),
41 MetadataArchive(loader::ArchiveMetadata),
223e47cc
LB
42}
43
c34b1796
AL
44/// Holds information about a codemap::FileMap imported from another crate.
45/// See creader::import_codemap() for more information.
46pub struct ImportedFileMap {
47 /// This FileMap's byte-offset within the codemap of its original crate
48 pub original_start_pos: codemap::BytePos,
49 /// The end of this FileMap within the codemap of its original crate
50 pub original_end_pos: codemap::BytePos,
51 /// The imported FileMap's representation within the local codemap
52 pub translated_filemap: Rc<codemap::FileMap>
53}
54
1a4d82fc
JJ
55pub struct crate_metadata {
56 pub name: String,
57 pub data: MetadataBlob,
58 pub cnum_map: cnum_map,
59 pub cnum: ast::CrateNum,
62682a34 60 pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
c34b1796 61 pub span: codemap::Span,
223e47cc
LB
62}
63
85aaf69f 64#[derive(Copy, Debug, PartialEq, Clone)]
1a4d82fc
JJ
65pub enum LinkagePreference {
66 RequireDynamic,
67 RequireStatic,
223e47cc
LB
68}
69
9346a6ac
AL
70enum_from_u32! {
71 #[derive(Copy, Clone, PartialEq)]
72 pub enum NativeLibraryKind {
73 NativeStatic, // native static library (.a archive)
74 NativeFramework, // OSX-specific
75 NativeUnknown, // default way to specify a dynamic library
76 }
223e47cc
LB
77}
78
1a4d82fc
JJ
79// Where a crate came from on the local filesystem. One of these two options
80// must be non-None.
81#[derive(PartialEq, Clone)]
82pub struct CrateSource {
c34b1796
AL
83 pub dylib: Option<(PathBuf, PathKind)>,
84 pub rlib: Option<(PathBuf, PathKind)>,
1a4d82fc 85 pub cnum: ast::CrateNum,
223e47cc
LB
86}
87
1a4d82fc
JJ
88pub struct CStore {
89 metas: RefCell<FnvHashMap<ast::CrateNum, Rc<crate_metadata>>>,
90 /// Map from NodeId's of local extern crate statements to crate numbers
91 extern_mod_crate_map: RefCell<NodeMap<ast::CrateNum>>,
92 used_crate_sources: RefCell<Vec<CrateSource>>,
93 used_libraries: RefCell<Vec<(String, NativeLibraryKind)>>,
94 used_link_args: RefCell<Vec<String>>,
95 pub intr: Rc<IdentInterner>,
96}
97
98impl CStore {
99 pub fn new(intr: Rc<IdentInterner>) -> CStore {
100 CStore {
85aaf69f
SL
101 metas: RefCell::new(FnvHashMap()),
102 extern_mod_crate_map: RefCell::new(FnvHashMap()),
1a4d82fc
JJ
103 used_crate_sources: RefCell::new(Vec::new()),
104 used_libraries: RefCell::new(Vec::new()),
105 used_link_args: RefCell::new(Vec::new()),
106 intr: intr
107 }
108 }
223e47cc 109
1a4d82fc
JJ
110 pub fn next_crate_num(&self) -> ast::CrateNum {
111 self.metas.borrow().len() as ast::CrateNum + 1
112 }
223e47cc 113
1a4d82fc 114 pub fn get_crate_data(&self, cnum: ast::CrateNum) -> Rc<crate_metadata> {
c34b1796 115 self.metas.borrow().get(&cnum).unwrap().clone()
1a4d82fc 116 }
223e47cc 117
1a4d82fc
JJ
118 pub fn get_crate_hash(&self, cnum: ast::CrateNum) -> Svh {
119 let cdata = self.get_crate_data(cnum);
120 decoder::get_crate_hash(cdata.data())
223e47cc 121 }
223e47cc 122
1a4d82fc
JJ
123 pub fn set_crate_data(&self, cnum: ast::CrateNum, data: Rc<crate_metadata>) {
124 self.metas.borrow_mut().insert(cnum, data);
223e47cc 125 }
223e47cc 126
1a4d82fc
JJ
127 pub fn iter_crate_data<I>(&self, mut i: I) where
128 I: FnMut(ast::CrateNum, &crate_metadata),
129 {
62682a34 130 for (&k, v) in self.metas.borrow().iter() {
1a4d82fc
JJ
131 i(k, &**v);
132 }
133 }
223e47cc 134
1a4d82fc
JJ
135 /// Like `iter_crate_data`, but passes source paths (if available) as well.
136 pub fn iter_crate_data_origins<I>(&self, mut i: I) where
137 I: FnMut(ast::CrateNum, &crate_metadata, Option<CrateSource>),
138 {
62682a34 139 for (&k, v) in self.metas.borrow().iter() {
1a4d82fc
JJ
140 let origin = self.get_used_crate_source(k);
141 origin.as_ref().map(|cs| { assert!(k == cs.cnum); });
142 i(k, &**v, origin);
143 }
144 }
223e47cc 145
1a4d82fc
JJ
146 pub fn add_used_crate_source(&self, src: CrateSource) {
147 let mut used_crate_sources = self.used_crate_sources.borrow_mut();
148 if !used_crate_sources.contains(&src) {
149 used_crate_sources.push(src);
150 }
151 }
223e47cc 152
1a4d82fc
JJ
153 pub fn get_used_crate_source(&self, cnum: ast::CrateNum)
154 -> Option<CrateSource> {
155 self.used_crate_sources.borrow_mut()
85aaf69f 156 .iter().find(|source| source.cnum == cnum).cloned()
1a4d82fc 157 }
223e47cc 158
1a4d82fc
JJ
159 pub fn reset(&self) {
160 self.metas.borrow_mut().clear();
161 self.extern_mod_crate_map.borrow_mut().clear();
162 self.used_crate_sources.borrow_mut().clear();
163 self.used_libraries.borrow_mut().clear();
164 self.used_link_args.borrow_mut().clear();
223e47cc 165 }
223e47cc 166
1a4d82fc
JJ
167 // This method is used when generating the command line to pass through to
168 // system linker. The linker expects undefined symbols on the left of the
169 // command line to be defined in libraries on the right, not the other way
170 // around. For more info, see some comments in the add_used_library function
171 // below.
172 //
173 // In order to get this left-to-right dependency ordering, we perform a
174 // topological sort of all crates putting the leaves at the right-most
175 // positions.
176 pub fn get_used_crates(&self, prefer: LinkagePreference)
c34b1796 177 -> Vec<(ast::CrateNum, Option<PathBuf>)> {
1a4d82fc
JJ
178 let mut ordering = Vec::new();
179 fn visit(cstore: &CStore, cnum: ast::CrateNum,
180 ordering: &mut Vec<ast::CrateNum>) {
181 if ordering.contains(&cnum) { return }
182 let meta = cstore.get_crate_data(cnum);
85aaf69f 183 for (_, &dep) in &meta.cnum_map {
1a4d82fc
JJ
184 visit(cstore, dep, ordering);
185 }
186 ordering.push(cnum);
187 };
62682a34 188 for (&num, _) in self.metas.borrow().iter() {
1a4d82fc
JJ
189 visit(self, num, &mut ordering);
190 }
191 ordering.reverse();
192 let mut libs = self.used_crate_sources.borrow()
193 .iter()
194 .map(|src| (src.cnum, match prefer {
85aaf69f
SL
195 RequireDynamic => src.dylib.clone().map(|p| p.0),
196 RequireStatic => src.rlib.clone().map(|p| p.0),
1a4d82fc 197 }))
85aaf69f 198 .collect::<Vec<_>>();
1a4d82fc 199 libs.sort_by(|&(a, _), &(b, _)| {
c1a9b12d
SL
200 let a = ordering.iter().position(|x| *x == a);
201 let b = ordering.iter().position(|x| *x == b);
202 a.cmp(&b)
1a4d82fc
JJ
203 });
204 libs
205 }
223e47cc 206
1a4d82fc
JJ
207 pub fn add_used_library(&self, lib: String, kind: NativeLibraryKind) {
208 assert!(!lib.is_empty());
209 self.used_libraries.borrow_mut().push((lib, kind));
210 }
223e47cc 211
1a4d82fc
JJ
212 pub fn get_used_libraries<'a>(&'a self)
213 -> &'a RefCell<Vec<(String,
214 NativeLibraryKind)>> {
215 &self.used_libraries
216 }
223e47cc 217
1a4d82fc
JJ
218 pub fn add_used_link_args(&self, args: &str) {
219 for s in args.split(' ').filter(|s| !s.is_empty()) {
220 self.used_link_args.borrow_mut().push(s.to_string());
221 }
222 }
223
224 pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell<Vec<String> > {
225 &self.used_link_args
223e47cc
LB
226 }
227
1a4d82fc
JJ
228 pub fn add_extern_mod_stmt_cnum(&self,
229 emod_id: ast::NodeId,
230 cnum: ast::CrateNum) {
231 self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
232 }
223e47cc 233
1a4d82fc
JJ
234 pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId)
235 -> Option<ast::CrateNum> {
85aaf69f 236 self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
223e47cc 237 }
1a4d82fc 238}
223e47cc 239
1a4d82fc
JJ
240impl crate_metadata {
241 pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
242 pub fn name(&self) -> String { decoder::get_crate_name(self.data()) }
243 pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
62682a34
SL
244 pub fn imported_filemaps<'a>(&'a self, codemap: &codemap::CodeMap)
245 -> Ref<'a, Vec<ImportedFileMap>> {
246 let filemaps = self.codemap_import_info.borrow();
247 if filemaps.is_empty() {
248 drop(filemaps);
249 let filemaps = creader::import_codemap(codemap, &self.data);
250
251 // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
252 *self.codemap_import_info.borrow_mut() = filemaps;
253 self.codemap_import_info.borrow()
254 } else {
255 filemaps
256 }
257 }
1a4d82fc
JJ
258}
259
260impl MetadataBlob {
261 pub fn as_slice<'a>(&'a self) -> &'a [u8] {
262 let slice = match *self {
c34b1796 263 MetadataVec(ref vec) => &vec[..],
1a4d82fc
JJ
264 MetadataArchive(ref ar) => ar.as_slice(),
265 };
266 if slice.len() < 4 {
267 &[] // corrupt metadata
268 } else {
269 let len = (((slice[0] as u32) << 24) |
270 ((slice[1] as u32) << 16) |
271 ((slice[2] as u32) << 8) |
c34b1796 272 ((slice[3] as u32) << 0)) as usize;
1a4d82fc 273 if len + 4 <= slice.len() {
85aaf69f 274 &slice[4.. len + 4]
1a4d82fc
JJ
275 } else {
276 &[] // corrupt or old metadata
277 }
278 }
279 }
223e47cc 280}