]> git.proxmox.com Git - rustc.git/blob - src/librustc/middle/lang_items.rs
Merge tag 'debian/0.7-0_exp1'
[rustc.git] / src / librustc / middle / lang_items.rs
1 // Copyright 2012 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
11 // Detecting language items.
12 //
13 // Language items are items that represent concepts intrinsic to the language
14 // itself. Examples are:
15 //
16 // * Traits that specify "kinds"; e.g. "Freeze", "Copy", "Send".
17 //
18 // * Traits that represent operators; e.g. "Add", "Sub", "Index".
19 //
20 // * Functions called by the compiler itself.
21
22
23 use driver::session::Session;
24 use metadata::csearch::each_lang_item;
25 use metadata::cstore::iter_crate_data;
26 use syntax::ast::{crate, def_id, lit_str, meta_item};
27 use syntax::ast::{meta_list, meta_name_value, meta_word};
28 use syntax::ast_util::local_def;
29 use syntax::visit::{default_simple_visitor, mk_simple_visitor, SimpleVisitor};
30 use syntax::visit::visit_crate;
31
32 use std::hashmap::HashMap;
33
34 pub enum LangItem {
35 FreezeTraitLangItem, // 0
36 CopyTraitLangItem, // 1
37 SendTraitLangItem, // 2
38 SizedTraitLangItem, // 3
39
40 DropTraitLangItem, // 4
41
42 AddTraitLangItem, // 5
43 SubTraitLangItem, // 6
44 MulTraitLangItem, // 7
45 DivTraitLangItem, // 8
46 RemTraitLangItem, // 9
47 NegTraitLangItem, // 10
48 NotTraitLangItem, // 11
49 BitXorTraitLangItem, // 11
50 BitAndTraitLangItem, // 13
51 BitOrTraitLangItem, // 14
52 ShlTraitLangItem, // 15
53 ShrTraitLangItem, // 16
54 IndexTraitLangItem, // 17
55
56 EqTraitLangItem, // 18
57 OrdTraitLangItem, // 19
58
59 StrEqFnLangItem, // 20
60 UniqStrEqFnLangItem, // 21
61 AnnihilateFnLangItem, // 22
62 LogTypeFnLangItem, // 23
63 FailFnLangItem, // 24
64 FailBoundsCheckFnLangItem, // 25
65 ExchangeMallocFnLangItem, // 26
66 ClosureExchangeMallocFnLangItem, // 27
67 ExchangeFreeFnLangItem, // 28
68 MallocFnLangItem, // 29
69 FreeFnLangItem, // 30
70 BorrowAsImmFnLangItem, // 31
71 BorrowAsMutFnLangItem, // 32
72 ReturnToMutFnLangItem, // 33
73 CheckNotBorrowedFnLangItem, // 34
74 StrDupUniqFnLangItem, // 35
75 RecordBorrowFnLangItem, // 36
76 UnrecordBorrowFnLangItem, // 37
77
78 StartFnLangItem, // 38
79
80 TyDescStructLangItem, // 39
81 TyVisitorTraitLangItem, // 40
82 OpaqueStructLangItem, // 41
83 }
84
85 pub struct LanguageItems {
86 items: [Option<def_id>, ..42]
87 }
88
89 impl LanguageItems {
90 pub fn new() -> LanguageItems {
91 LanguageItems {
92 items: [ None, ..42 ]
93 }
94 }
95
96 pub fn each_item(&self, f: &fn(def_id: def_id, i: uint) -> bool) -> bool {
97 self.items.iter().enumerate().advance(|(i, &item)| f(item.get(), i))
98 }
99
100 pub fn item_name(index: uint) -> &'static str {
101 match index {
102 0 => "freeze",
103 1 => "copy",
104 2 => "send",
105 3 => "sized",
106
107 4 => "drop",
108
109 5 => "add",
110 6 => "sub",
111 7 => "mul",
112 8 => "div",
113 9 => "rem",
114 10 => "neg",
115 11 => "not",
116 12 => "bitxor",
117 13 => "bitand",
118 14 => "bitor",
119 15 => "shl",
120 16 => "shr",
121 17 => "index",
122 18 => "eq",
123 19 => "ord",
124
125 20 => "str_eq",
126 21 => "uniq_str_eq",
127 22 => "annihilate",
128 23 => "log_type",
129 24 => "fail_",
130 25 => "fail_bounds_check",
131 26 => "exchange_malloc",
132 27 => "closure_exchange_malloc",
133 28 => "exchange_free",
134 29 => "malloc",
135 30 => "free",
136 31 => "borrow_as_imm",
137 32 => "borrow_as_mut",
138 33 => "return_to_mut",
139 34 => "check_not_borrowed",
140 35 => "strdup_uniq",
141 36 => "record_borrow",
142 37 => "unrecord_borrow",
143
144 38 => "start",
145
146 39 => "ty_desc",
147 40 => "ty_visitor",
148 41 => "opaque",
149
150 _ => "???"
151 }
152 }
153
154 // FIXME #4621: Method macros sure would be nice here.
155
156 pub fn freeze_trait(&self) -> def_id {
157 self.items[FreezeTraitLangItem as uint].get()
158 }
159 pub fn copy_trait(&self) -> def_id {
160 self.items[CopyTraitLangItem as uint].get()
161 }
162 pub fn send_trait(&self) -> def_id {
163 self.items[SendTraitLangItem as uint].get()
164 }
165 pub fn sized_trait(&self) -> def_id {
166 self.items[SizedTraitLangItem as uint].get()
167 }
168
169 pub fn drop_trait(&self) -> def_id {
170 self.items[DropTraitLangItem as uint].get()
171 }
172
173 pub fn add_trait(&self) -> def_id {
174 self.items[AddTraitLangItem as uint].get()
175 }
176 pub fn sub_trait(&self) -> def_id {
177 self.items[SubTraitLangItem as uint].get()
178 }
179 pub fn mul_trait(&self) -> def_id {
180 self.items[MulTraitLangItem as uint].get()
181 }
182 pub fn div_trait(&self) -> def_id {
183 self.items[DivTraitLangItem as uint].get()
184 }
185 pub fn rem_trait(&self) -> def_id {
186 self.items[RemTraitLangItem as uint].get()
187 }
188 pub fn neg_trait(&self) -> def_id {
189 self.items[NegTraitLangItem as uint].get()
190 }
191 pub fn not_trait(&self) -> def_id {
192 self.items[NotTraitLangItem as uint].get()
193 }
194 pub fn bitxor_trait(&self) -> def_id {
195 self.items[BitXorTraitLangItem as uint].get()
196 }
197 pub fn bitand_trait(&self) -> def_id {
198 self.items[BitAndTraitLangItem as uint].get()
199 }
200 pub fn bitor_trait(&self) -> def_id {
201 self.items[BitOrTraitLangItem as uint].get()
202 }
203 pub fn shl_trait(&self) -> def_id {
204 self.items[ShlTraitLangItem as uint].get()
205 }
206 pub fn shr_trait(&self) -> def_id {
207 self.items[ShrTraitLangItem as uint].get()
208 }
209 pub fn index_trait(&self) -> def_id {
210 self.items[IndexTraitLangItem as uint].get()
211 }
212
213 pub fn eq_trait(&self) -> def_id {
214 self.items[EqTraitLangItem as uint].get()
215 }
216 pub fn ord_trait(&self) -> def_id {
217 self.items[OrdTraitLangItem as uint].get()
218 }
219
220 pub fn str_eq_fn(&self) -> def_id {
221 self.items[StrEqFnLangItem as uint].get()
222 }
223 pub fn uniq_str_eq_fn(&self) -> def_id {
224 self.items[UniqStrEqFnLangItem as uint].get()
225 }
226 pub fn annihilate_fn(&self) -> def_id {
227 self.items[AnnihilateFnLangItem as uint].get()
228 }
229 pub fn log_type_fn(&self) -> def_id {
230 self.items[LogTypeFnLangItem as uint].get()
231 }
232 pub fn fail_fn(&self) -> def_id {
233 self.items[FailFnLangItem as uint].get()
234 }
235 pub fn fail_bounds_check_fn(&self) -> def_id {
236 self.items[FailBoundsCheckFnLangItem as uint].get()
237 }
238 pub fn exchange_malloc_fn(&self) -> def_id {
239 self.items[ExchangeMallocFnLangItem as uint].get()
240 }
241 pub fn closure_exchange_malloc_fn(&self) -> def_id {
242 self.items[ClosureExchangeMallocFnLangItem as uint].get()
243 }
244 pub fn exchange_free_fn(&self) -> def_id {
245 self.items[ExchangeFreeFnLangItem as uint].get()
246 }
247 pub fn malloc_fn(&self) -> def_id {
248 self.items[MallocFnLangItem as uint].get()
249 }
250 pub fn free_fn(&self) -> def_id {
251 self.items[FreeFnLangItem as uint].get()
252 }
253 pub fn borrow_as_imm_fn(&self) -> def_id {
254 self.items[BorrowAsImmFnLangItem as uint].get()
255 }
256 pub fn borrow_as_mut_fn(&self) -> def_id {
257 self.items[BorrowAsMutFnLangItem as uint].get()
258 }
259 pub fn return_to_mut_fn(&self) -> def_id {
260 self.items[ReturnToMutFnLangItem as uint].get()
261 }
262 pub fn check_not_borrowed_fn(&self) -> def_id {
263 self.items[CheckNotBorrowedFnLangItem as uint].get()
264 }
265 pub fn strdup_uniq_fn(&self) -> def_id {
266 self.items[StrDupUniqFnLangItem as uint].get()
267 }
268 pub fn record_borrow_fn(&self) -> def_id {
269 self.items[RecordBorrowFnLangItem as uint].get()
270 }
271 pub fn unrecord_borrow_fn(&self) -> def_id {
272 self.items[UnrecordBorrowFnLangItem as uint].get()
273 }
274 pub fn start_fn(&self) -> def_id {
275 self.items[StartFnLangItem as uint].get()
276 }
277 pub fn ty_desc(&const self) -> def_id {
278 self.items[TyDescStructLangItem as uint].get()
279 }
280 pub fn ty_visitor(&const self) -> def_id {
281 self.items[TyVisitorTraitLangItem as uint].get()
282 }
283 pub fn opaque(&const self) -> def_id {
284 self.items[OpaqueStructLangItem as uint].get()
285 }
286 }
287
288 struct LanguageItemCollector<'self> {
289 items: LanguageItems,
290
291 crate: &'self crate,
292 session: Session,
293
294 item_refs: HashMap<@str, uint>,
295 }
296
297 impl<'self> LanguageItemCollector<'self> {
298 pub fn new<'a>(crate: &'a crate, session: Session)
299 -> LanguageItemCollector<'a> {
300 let mut item_refs = HashMap::new();
301
302 item_refs.insert(@"freeze", FreezeTraitLangItem as uint);
303 item_refs.insert(@"copy", CopyTraitLangItem as uint);
304 item_refs.insert(@"send", SendTraitLangItem as uint);
305 item_refs.insert(@"sized", SizedTraitLangItem as uint);
306
307 item_refs.insert(@"drop", DropTraitLangItem as uint);
308
309 item_refs.insert(@"add", AddTraitLangItem as uint);
310 item_refs.insert(@"sub", SubTraitLangItem as uint);
311 item_refs.insert(@"mul", MulTraitLangItem as uint);
312 item_refs.insert(@"div", DivTraitLangItem as uint);
313 item_refs.insert(@"rem", RemTraitLangItem as uint);
314 item_refs.insert(@"neg", NegTraitLangItem as uint);
315 item_refs.insert(@"not", NotTraitLangItem as uint);
316 item_refs.insert(@"bitxor", BitXorTraitLangItem as uint);
317 item_refs.insert(@"bitand", BitAndTraitLangItem as uint);
318 item_refs.insert(@"bitor", BitOrTraitLangItem as uint);
319 item_refs.insert(@"shl", ShlTraitLangItem as uint);
320 item_refs.insert(@"shr", ShrTraitLangItem as uint);
321 item_refs.insert(@"index", IndexTraitLangItem as uint);
322
323 item_refs.insert(@"eq", EqTraitLangItem as uint);
324 item_refs.insert(@"ord", OrdTraitLangItem as uint);
325
326 item_refs.insert(@"str_eq", StrEqFnLangItem as uint);
327 item_refs.insert(@"uniq_str_eq", UniqStrEqFnLangItem as uint);
328 item_refs.insert(@"annihilate", AnnihilateFnLangItem as uint);
329 item_refs.insert(@"log_type", LogTypeFnLangItem as uint);
330 item_refs.insert(@"fail_", FailFnLangItem as uint);
331 item_refs.insert(@"fail_bounds_check",
332 FailBoundsCheckFnLangItem as uint);
333 item_refs.insert(@"exchange_malloc", ExchangeMallocFnLangItem as uint);
334 item_refs.insert(@"closure_exchange_malloc", ClosureExchangeMallocFnLangItem as uint);
335 item_refs.insert(@"exchange_free", ExchangeFreeFnLangItem as uint);
336 item_refs.insert(@"malloc", MallocFnLangItem as uint);
337 item_refs.insert(@"free", FreeFnLangItem as uint);
338 item_refs.insert(@"borrow_as_imm", BorrowAsImmFnLangItem as uint);
339 item_refs.insert(@"borrow_as_mut", BorrowAsMutFnLangItem as uint);
340 item_refs.insert(@"return_to_mut", ReturnToMutFnLangItem as uint);
341 item_refs.insert(@"check_not_borrowed",
342 CheckNotBorrowedFnLangItem as uint);
343 item_refs.insert(@"strdup_uniq", StrDupUniqFnLangItem as uint);
344 item_refs.insert(@"record_borrow", RecordBorrowFnLangItem as uint);
345 item_refs.insert(@"unrecord_borrow", UnrecordBorrowFnLangItem as uint);
346 item_refs.insert(@"start", StartFnLangItem as uint);
347 item_refs.insert(@"ty_desc", TyDescStructLangItem as uint);
348 item_refs.insert(@"ty_visitor", TyVisitorTraitLangItem as uint);
349 item_refs.insert(@"opaque", OpaqueStructLangItem as uint);
350
351 LanguageItemCollector {
352 crate: crate,
353 session: session,
354 items: LanguageItems::new(),
355 item_refs: item_refs
356 }
357 }
358
359 pub fn match_and_collect_meta_item(&mut self,
360 item_def_id: def_id,
361 meta_item: &meta_item) {
362 match meta_item.node {
363 meta_name_value(key, literal) => {
364 match literal.node {
365 lit_str(value) => {
366 self.match_and_collect_item(item_def_id, key, value);
367 }
368 _ => {} // Skip.
369 }
370 }
371 meta_word(*) | meta_list(*) => {} // Skip.
372 }
373 }
374
375 pub fn collect_item(&mut self, item_index: uint, item_def_id: def_id) {
376 // Check for duplicates.
377 match self.items.items[item_index] {
378 Some(original_def_id) if original_def_id != item_def_id => {
379 self.session.err(fmt!("duplicate entry for `%s`",
380 LanguageItems::item_name(item_index)));
381 }
382 Some(_) | None => {
383 // OK.
384 }
385 }
386
387 // Matched.
388 self.items.items[item_index] = Some(item_def_id);
389 }
390
391 pub fn match_and_collect_item(&mut self,
392 item_def_id: def_id,
393 key: &str,
394 value: @str) {
395 if "lang" != key {
396 return; // Didn't match.
397 }
398
399 let item_index = self.item_refs.find(&value).map(|x| **x);
400 // prevent borrow checker from considering ^~~~~~~~~~~
401 // self to be borrowed (annoying)
402
403 match item_index {
404 Some(item_index) => {
405 self.collect_item(item_index, item_def_id);
406 }
407 None => {
408 // Didn't match.
409 return;
410 }
411 }
412 }
413
414 pub fn collect_local_language_items(&mut self) {
415 let this: *mut LanguageItemCollector = &mut *self;
416 visit_crate(self.crate, ((), mk_simple_visitor(@SimpleVisitor {
417 visit_item: |item| {
418 for item.attrs.iter().advance |attribute| {
419 unsafe {
420 (*this).match_and_collect_meta_item(
421 local_def(item.id),
422 attribute.node.value
423 );
424 }
425 }
426 },
427 .. *default_simple_visitor()
428 })));
429 }
430
431 pub fn collect_external_language_items(&mut self) {
432 let crate_store = self.session.cstore;
433 do iter_crate_data(crate_store) |crate_number, _crate_metadata| {
434 for each_lang_item(crate_store, crate_number)
435 |node_id, item_index| {
436 let def_id = def_id { crate: crate_number, node: node_id };
437 self.collect_item(item_index, def_id);
438 }
439 }
440 }
441
442 pub fn check_completeness(&self) {
443 for self.item_refs.iter().advance |(&key, &item_ref)| {
444 match self.items.items[item_ref] {
445 None => {
446 self.session.err(fmt!("no item found for `%s`", key));
447 }
448 Some(_) => {
449 // OK.
450 }
451 }
452 }
453 }
454
455 pub fn collect(&mut self) {
456 self.collect_local_language_items();
457 self.collect_external_language_items();
458 self.check_completeness();
459 }
460 }
461
462 pub fn collect_language_items(crate: &crate,
463 session: Session)
464 -> LanguageItems {
465 let mut collector = LanguageItemCollector::new(crate, session);
466 collector.collect();
467 let LanguageItemCollector { items, _ } = collector;
468 session.abort_if_errors();
469 items
470 }