1 // Copyright 2012-2014 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 #![allow(unused_must_use)] // everything is just a MemWriter, can't fail
14 #![allow(non_camel_case_types)]
17 use metadata::common::*;
19 use metadata::decoder;
20 use metadata::tyencode;
21 use middle::ty::{node_id_to_type, lookup_item_type};
22 use middle::astencode;
26 use util::nodemap::{NodeMap, NodeSet};
28 use serialize::Encodable;
30 use std::cell::{Cell, RefCell};
33 use std::io::MemWriter;
35 use collections::HashMap;
39 use syntax::ast_map::{PathElem, PathElems};
41 use syntax::ast_util::*;
43 use syntax::attr::AttrMetaMethods;
45 use syntax::crateid::CrateId;
46 use syntax::diagnostic::SpanHandler;
47 use syntax::parse::token::InternedString;
48 use syntax::parse::token::special_idents;
49 use syntax::parse::token;
50 use syntax::visit::Visitor;
53 use writer = serialize::ebml::writer;
56 pub type abbrev_map = @RefCell<HashMap<ty::t, tyencode::ty_abbrev>>;
58 /// A borrowed version of ast::InlinedItem.
59 pub enum InlinedItemRef<'a> {
60 IIItemRef(&'a ast::Item),
61 IIMethodRef(ast::DefId, bool, &'a ast::Method),
62 IIForeignRef(&'a ast::ForeignItem)
65 pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
67 pub type EncodeInlinedItem<'a> = 'a |ecx: &EncodeContext,
71 pub struct EncodeParams<'a> {
72 pub diag: &'a SpanHandler,
73 pub tcx: &'a ty::ctxt,
74 pub reexports2: middle::resolve::ExportMap2,
75 pub item_symbols: &'a RefCell<NodeMap<~str>>,
76 pub non_inlineable_statics: &'a RefCell<NodeSet>,
77 pub link_meta: &'a LinkMeta,
78 pub cstore: &'a cstore::CStore,
79 pub encode_inlined_item: EncodeInlinedItem<'a>,
83 inline_bytes: Cell<u64>,
84 attr_bytes: Cell<u64>,
86 lang_item_bytes: Cell<u64>,
87 native_lib_bytes: Cell<u64>,
88 macro_registrar_fn_bytes: Cell<u64>,
89 macro_defs_bytes: Cell<u64>,
90 impl_bytes: Cell<u64>,
91 misc_bytes: Cell<u64>,
92 item_bytes: Cell<u64>,
93 index_bytes: Cell<u64>,
94 zero_bytes: Cell<u64>,
95 total_bytes: Cell<u64>,
98 pub struct EncodeContext<'a> {
99 pub diag: &'a SpanHandler,
100 pub tcx: &'a ty::ctxt,
102 pub reexports2: middle::resolve::ExportMap2,
103 pub item_symbols: &'a RefCell<NodeMap<~str>>,
104 pub non_inlineable_statics: &'a RefCell<NodeSet>,
105 pub link_meta: &'a LinkMeta,
106 pub cstore: &'a cstore::CStore,
107 pub encode_inlined_item: EncodeInlinedItem<'a>,
108 pub type_abbrevs: abbrev_map,
111 fn encode_name(ebml_w: &mut Encoder, name: Name) {
112 ebml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
115 fn encode_impl_type_basename(ebml_w: &mut Encoder, name: Ident) {
116 ebml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
119 pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
120 ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
129 fn encode_trait_ref(ebml_w: &mut Encoder,
131 trait_ref: &ty::TraitRef,
133 let ty_str_ctxt = &tyencode::ctxt {
137 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
140 ebml_w.start_tag(tag);
141 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
145 fn encode_impl_vtables(ebml_w: &mut Encoder,
147 vtables: &typeck::impl_res) {
148 ebml_w.start_tag(tag_item_impl_vtables);
149 astencode::encode_vtable_res(ecx, ebml_w, vtables.trait_vtables);
150 astencode::encode_vtable_param_res(ecx, ebml_w, vtables.self_vtables);
154 // Item info table encoding
155 fn encode_family(ebml_w: &mut Encoder, c: char) {
156 ebml_w.start_tag(tag_items_data_item_family);
157 ebml_w.writer.write(&[c as u8]);
161 pub fn def_to_str(did: DefId) -> ~str {
162 format!("{}:{}", did.krate, did.node)
165 fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
167 params: &[ty::TypeParameterDef],
169 let ty_str_ctxt = &tyencode::ctxt {
173 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
175 for param in params.iter() {
176 ebml_w.start_tag(tag);
177 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
182 fn encode_region_param_defs(ebml_w: &mut Encoder,
183 params: &[ty::RegionParameterDef]) {
184 for param in params.iter() {
185 ebml_w.start_tag(tag_region_param_def);
187 ebml_w.start_tag(tag_region_param_def_ident);
188 encode_name(ebml_w, param.name);
191 ebml_w.wr_tagged_str(tag_region_param_def_def_id,
192 def_to_str(param.def_id));
198 fn encode_item_variances(ebml_w: &mut Encoder,
201 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
202 ebml_w.start_tag(tag_item_variances);
207 fn encode_bounds_and_type(ebml_w: &mut Encoder,
209 tpt: &ty::ty_param_bounds_and_ty) {
210 encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs(),
211 tag_items_data_item_ty_param_bounds);
212 encode_region_param_defs(ebml_w, tpt.generics.region_param_defs());
213 encode_type(ecx, ebml_w, tpt.ty);
216 fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
217 ebml_w.start_tag(tag_items_data_item_variant);
218 let s = def_to_str(vid);
219 ebml_w.writer.write(s.as_bytes());
223 pub fn write_type(ecx: &EncodeContext,
224 ebml_w: &mut Encoder,
226 let ty_str_ctxt = &tyencode::ctxt {
230 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
232 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
235 pub fn write_vstore(ecx: &EncodeContext,
236 ebml_w: &mut Encoder,
237 vstore: ty::vstore) {
238 let ty_str_ctxt = &tyencode::ctxt {
242 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
244 tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
247 fn encode_type(ecx: &EncodeContext,
248 ebml_w: &mut Encoder,
250 ebml_w.start_tag(tag_items_data_item_type);
251 write_type(ecx, ebml_w, typ);
255 fn encode_method_fty(ecx: &EncodeContext,
256 ebml_w: &mut Encoder,
257 typ: &ty::BareFnTy) {
258 ebml_w.start_tag(tag_item_method_fty);
260 let ty_str_ctxt = &tyencode::ctxt {
264 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
266 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
271 fn encode_symbol(ecx: &EncodeContext,
272 ebml_w: &mut Encoder,
274 ebml_w.start_tag(tag_items_data_item_symbol);
275 match ecx.item_symbols.borrow().find(&id) {
277 debug!("encode_symbol(id={:?}, str={})", id, *x);
278 ebml_w.writer.write(x.as_bytes());
281 ecx.diag.handler().bug(
282 format!("encode_symbol: id not found {}", id));
288 fn encode_disr_val(_: &EncodeContext,
289 ebml_w: &mut Encoder,
290 disr_val: ty::Disr) {
291 ebml_w.start_tag(tag_disr_val);
292 let s = disr_val.to_str();
293 ebml_w.writer.write(s.as_bytes());
297 fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
298 ebml_w.start_tag(tag_items_data_parent_item);
299 let s = def_to_str(id);
300 ebml_w.writer.write(s.as_bytes());
304 fn encode_struct_fields(ebml_w: &mut Encoder,
306 for f in def.fields.iter() {
308 NamedField(ident, vis) => {
309 ebml_w.start_tag(tag_item_field);
310 encode_struct_field_family(ebml_w, vis);
311 encode_name(ebml_w, ident.name);
312 encode_def_id(ebml_w, local_def(f.node.id));
315 UnnamedField(vis) => {
316 ebml_w.start_tag(tag_item_unnamed_field);
317 encode_struct_field_family(ebml_w, vis);
318 encode_def_id(ebml_w, local_def(f.node.id));
325 fn encode_enum_variant_info(ecx: &EncodeContext,
326 ebml_w: &mut Encoder,
328 variants: &[P<Variant>],
329 index: @RefCell<Vec<entry<i64>> >,
330 generics: &ast::Generics) {
331 debug!("encode_enum_variant_info(id={:?})", id);
333 let mut disr_val = 0;
335 let vi = ty::enum_variants(ecx.tcx,
336 ast::DefId { krate: LOCAL_CRATE, node: id });
337 for variant in variants.iter() {
338 let def_id = local_def(variant.node.id);
339 index.borrow_mut().push(entry {
340 val: variant.node.id as i64,
341 pos: ebml_w.writer.tell().unwrap(),
343 ebml_w.start_tag(tag_items_data_item);
344 encode_def_id(ebml_w, def_id);
345 match variant.node.kind {
346 ast::TupleVariantKind(_) => encode_family(ebml_w, 'v'),
347 ast::StructVariantKind(_) => encode_family(ebml_w, 'V')
349 encode_name(ebml_w, variant.node.name.name);
350 encode_parent_item(ebml_w, local_def(id));
351 encode_visibility(ebml_w, variant.node.vis);
352 encode_attributes(ebml_w, variant.node.attrs.as_slice());
353 match variant.node.kind {
354 ast::TupleVariantKind(ref args)
355 if args.len() > 0 && generics.ty_params.len() == 0 => {
356 encode_symbol(ecx, ebml_w, variant.node.id);
358 ast::TupleVariantKind(_) => {},
359 ast::StructVariantKind(def) => {
360 let idx = encode_info_for_struct(ecx,
362 def.fields.as_slice(),
364 encode_struct_fields(ebml_w, def);
365 let bkts = create_index(idx);
366 encode_index(ebml_w, bkts, write_i64);
369 if vi.get(i).disr_val != disr_val {
370 encode_disr_val(ecx, ebml_w, vi.get(i).disr_val);
371 disr_val = vi.get(i).disr_val;
373 encode_bounds_and_type(ebml_w, ecx,
374 &lookup_item_type(ecx.tcx, def_id));
376 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(ebml_w, path));
383 fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
385 ebml_w.start_tag(tag_path);
386 ebml_w.wr_tagged_u32(tag_path_len, path.clone().len() as u32);
389 ast_map::PathMod(_) => tag_path_elem_mod,
390 ast_map::PathName(_) => tag_path_elem_name
392 ebml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
397 fn encode_reexported_static_method(ebml_w: &mut Encoder,
398 exp: &middle::resolve::Export2,
399 method_def_id: DefId,
400 method_ident: Ident) {
401 debug!("(encode reexported static method) {}::{}",
402 exp.name, token::get_ident(method_ident));
403 ebml_w.start_tag(tag_items_data_item_reexport);
404 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
405 ebml_w.wr_str(def_to_str(method_def_id));
407 ebml_w.start_tag(tag_items_data_item_reexport_name);
408 ebml_w.wr_str(format!("{}::{}", exp.name, token::get_ident(method_ident)));
413 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
414 ebml_w: &mut Encoder,
415 exp: &middle::resolve::Export2)
417 match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
418 Some(implementations) => {
419 for &base_impl in implementations.borrow().iter() {
420 for &m in base_impl.methods.iter() {
421 if m.explicit_self == ast::SelfStatic {
422 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
433 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
434 ebml_w: &mut Encoder,
435 exp: &middle::resolve::Export2)
437 match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
439 for &m in methods.iter() {
440 if m.explicit_self == ast::SelfStatic {
441 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
451 fn encode_reexported_static_methods(ecx: &EncodeContext,
452 ebml_w: &mut Encoder,
454 exp: &middle::resolve::Export2) {
455 match ecx.tcx.map.find(exp.def_id.node) {
456 Some(ast_map::NodeItem(item)) => {
457 let original_name = token::get_ident(item.ident);
459 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
460 let (mut a, mut b) = (path, mod_path.clone());
462 match (a.next(), b.next()) {
463 (None, None) => return true,
464 (None, _) | (_, None) => return false,
465 (Some(x), Some(y)) => if x != y { return false },
471 // We don't need to reexport static methods on items
472 // declared in the same module as our `pub use ...` since
473 // that's done when we encode the item itself.
475 // The only exception is when the reexport *changes* the
476 // name e.g. `pub use Foo = self::Bar` -- we have
477 // encoded metadata for static methods relative to Bar,
478 // but not yet for Foo.
480 if path_differs || original_name.get() != exp.name {
481 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
482 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
483 debug!("(encode reexported static methods) {} \
489 debug!("(encode reexported static methods) {} [base]",
498 /// Iterates through "auxiliary node IDs", which are node IDs that describe
499 /// top-level items that are sub-items of the given item. Specifically:
501 /// * For enums, iterates through the node IDs of the variants.
503 /// * For newtype structs, iterates through the node ID of the constructor.
504 fn each_auxiliary_node_id(item: @Item, callback: |NodeId| -> bool) -> bool {
505 let mut continue_ = true;
507 ItemEnum(ref enum_def, _) => {
508 for variant in enum_def.variants.iter() {
509 continue_ = callback(variant.node.id);
515 ItemStruct(struct_def, _) => {
516 // If this is a newtype struct, return the constructor.
517 match struct_def.ctor_id {
518 Some(ctor_id) if struct_def.fields.len() > 0 &&
519 struct_def.fields.get(0).node.kind.is_unnamed() => {
520 continue_ = callback(ctor_id);
531 fn encode_reexports(ecx: &EncodeContext,
532 ebml_w: &mut Encoder,
535 debug!("(encoding info for module) encoding reexports for {}", id);
536 match ecx.reexports2.borrow().find(&id) {
537 Some(ref exports) => {
538 debug!("(encoding info for module) found reexports for {}", id);
539 for exp in exports.iter() {
540 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
546 ebml_w.start_tag(tag_items_data_item_reexport);
547 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
548 ebml_w.wr_str(def_to_str(exp.def_id));
550 ebml_w.start_tag(tag_items_data_item_reexport_name);
551 ebml_w.wr_str(exp.name);
554 encode_reexported_static_methods(ecx, ebml_w, path.clone(), exp);
558 debug!("(encoding info for module) found no reexports for {}",
564 fn encode_info_for_mod(ecx: &EncodeContext,
565 ebml_w: &mut Encoder,
571 ebml_w.start_tag(tag_items_data_item);
572 encode_def_id(ebml_w, local_def(id));
573 encode_family(ebml_w, 'm');
574 encode_name(ebml_w, name.name);
575 debug!("(encoding info for module) encoding info for module ID {}", id);
577 // Encode info about all the module children.
578 for item in md.items.iter() {
579 ebml_w.start_tag(tag_mod_child);
580 ebml_w.wr_str(def_to_str(local_def(item.id)));
583 each_auxiliary_node_id(*item, |auxiliary_node_id| {
584 ebml_w.start_tag(tag_mod_child);
585 ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
592 let (ident, did) = (item.ident, item.id);
593 debug!("(encoding info for module) ... encoding impl {} \
595 token::get_ident(ident),
596 did, ecx.tcx.map.node_to_str(did));
598 ebml_w.start_tag(tag_mod_impl);
599 ebml_w.wr_str(def_to_str(local_def(did)));
606 encode_path(ebml_w, path.clone());
607 encode_visibility(ebml_w, vis);
609 // Encode the reexports of this module, if this module is public.
611 debug!("(encoding info for module) encoding reexports for {}", id);
612 encode_reexports(ecx, ebml_w, id, path);
618 fn encode_struct_field_family(ebml_w: &mut Encoder,
619 visibility: Visibility) {
620 encode_family(ebml_w, match visibility {
627 fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
628 ebml_w.start_tag(tag_items_data_item_visibility);
629 let ch = match visibility {
634 ebml_w.wr_str(str::from_char(ch));
638 fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_) {
639 ebml_w.start_tag(tag_item_trait_method_explicit_self);
641 // Encode the base self type.
642 match explicit_self {
643 SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
644 SelfValue => { ebml_w.writer.write(&[ 'v' as u8 ]); }
645 SelfUniq => { ebml_w.writer.write(&[ '~' as u8 ]); }
646 SelfRegion(_, m) => {
647 // FIXME(#4846) encode custom lifetime
648 ebml_w.writer.write(&['&' as u8]);
649 encode_mutability(ebml_w, m);
655 fn encode_mutability(ebml_w: &mut Encoder,
656 m: ast::Mutability) {
658 MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
659 MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); }
664 fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
665 ebml_w.start_tag(tag_item_trait_method_sort);
666 ebml_w.writer.write(&[ sort as u8 ]);
670 fn encode_provided_source(ebml_w: &mut Encoder,
671 source_opt: Option<DefId>) {
672 for source in source_opt.iter() {
673 ebml_w.start_tag(tag_item_method_provided_source);
674 let s = def_to_str(*source);
675 ebml_w.writer.write(s.as_bytes());
680 /* Returns an index of items in this class */
681 fn encode_info_for_struct(ecx: &EncodeContext,
682 ebml_w: &mut Encoder,
683 fields: &[StructField],
684 global_index: @RefCell<Vec<entry<i64>> >)
686 /* Each class has its own index, since different classes
687 may have fields with the same name */
688 let mut index = Vec::new();
690 /* We encode both private and public fields -- need to include
691 private fields to get the offsets right */
692 for field in fields.iter() {
693 let (nm, vis) = match field.node.kind {
694 NamedField(nm, vis) => (nm, vis),
695 UnnamedField(vis) => (special_idents::unnamed_field, vis)
698 let id = field.node.id;
699 index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
700 global_index.borrow_mut().push(entry {
702 pos: ebml_w.writer.tell().unwrap(),
704 ebml_w.start_tag(tag_items_data_item);
705 debug!("encode_info_for_struct: doing {} {}",
706 token::get_ident(nm), id);
707 encode_struct_field_family(ebml_w, vis);
708 encode_name(ebml_w, nm.name);
709 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
710 encode_def_id(ebml_w, local_def(id));
716 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
717 ebml_w: &mut Encoder,
720 index: @RefCell<Vec<entry<i64>> >,
722 index.borrow_mut().push(entry {
724 pos: ebml_w.writer.tell().unwrap(),
727 ebml_w.start_tag(tag_items_data_item);
728 encode_def_id(ebml_w, local_def(ctor_id));
729 encode_family(ebml_w, 'f');
730 encode_bounds_and_type(ebml_w, ecx,
731 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
732 encode_name(ebml_w, name.name);
733 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
734 ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
735 encode_parent_item(ebml_w, local_def(struct_id));
737 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
738 encode_symbol(ecx, ebml_w, ctor_id);
741 // indicate that this is a tuple struct ctor, because downstream users will normally want
742 // the tuple struct definition, but without this there is no way for them to tell that
743 // they actually have a ctor rather than a normal function
744 ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
750 fn encode_method_ty_fields(ecx: &EncodeContext,
751 ebml_w: &mut Encoder,
752 method_ty: &ty::Method) {
753 encode_def_id(ebml_w, method_ty.def_id);
754 encode_name(ebml_w, method_ty.ident.name);
755 encode_ty_type_param_defs(ebml_w, ecx,
756 method_ty.generics.type_param_defs(),
757 tag_item_method_tps);
758 encode_method_fty(ecx, ebml_w, &method_ty.fty);
759 encode_visibility(ebml_w, method_ty.vis);
760 encode_explicit_self(ebml_w, method_ty.explicit_self);
761 let purity = method_ty.fty.purity;
762 match method_ty.explicit_self {
764 encode_family(ebml_w, purity_static_method_family(purity));
766 _ => encode_family(ebml_w, purity_fn_family(purity))
768 encode_provided_source(ebml_w, method_ty.provided_source);
771 fn encode_info_for_method(ecx: &EncodeContext,
772 ebml_w: &mut Encoder,
774 impl_path: PathElems,
775 is_default_impl: bool,
777 ast_method_opt: Option<@Method>) {
779 debug!("encode_info_for_method: {:?} {}", m.def_id,
780 token::get_ident(m.ident));
781 ebml_w.start_tag(tag_items_data_item);
783 encode_method_ty_fields(ecx, ebml_w, m);
784 encode_parent_item(ebml_w, local_def(parent_id));
786 // The type for methods gets encoded twice, which is unfortunate.
787 let tpt = lookup_item_type(ecx.tcx, m.def_id);
788 encode_bounds_and_type(ebml_w, ecx, &tpt);
790 let elem = ast_map::PathName(m.ident.name);
791 encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
792 match ast_method_opt {
793 Some(ast_method) => {
794 encode_attributes(ebml_w, ast_method.attrs.as_slice())
799 for &ast_method in ast_method_opt.iter() {
800 let num_params = tpt.generics.type_param_defs().len();
801 if num_params > 0u ||
803 should_inline(ast_method.attrs.as_slice()) {
804 (ecx.encode_inlined_item)(
805 ecx, ebml_w, IIMethodRef(local_def(parent_id), false, ast_method));
807 encode_symbol(ecx, ebml_w, m.def_id.node);
814 fn purity_fn_family(p: Purity) -> char {
822 fn purity_static_method_family(p: Purity) -> char {
826 _ => fail!("extern fn can't be static")
831 fn should_inline(attrs: &[Attribute]) -> bool {
833 match find_inline_attr(attrs) {
834 InlineNone | InlineNever => false,
835 InlineHint | InlineAlways => true
839 // Encodes the inherent implementations of a structure, enumeration, or trait.
840 fn encode_inherent_implementations(ecx: &EncodeContext,
841 ebml_w: &mut Encoder,
843 match ecx.tcx.inherent_impls.borrow().find(&def_id) {
845 Some(&implementations) => {
846 for implementation in implementations.borrow().iter() {
847 ebml_w.start_tag(tag_items_data_item_inherent_impl);
848 encode_def_id(ebml_w, implementation.did);
855 // Encodes the implementations of a trait defined in this crate.
856 fn encode_extension_implementations(ecx: &EncodeContext,
857 ebml_w: &mut Encoder,
858 trait_def_id: DefId) {
859 match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
861 Some(&implementations) => {
862 for implementation in implementations.borrow().iter() {
863 ebml_w.start_tag(tag_items_data_item_extension_impl);
864 encode_def_id(ebml_w, implementation.did);
871 fn encode_info_for_item(ecx: &EncodeContext,
872 ebml_w: &mut Encoder,
874 index: @RefCell<Vec<entry<i64>> >,
876 vis: ast::Visibility) {
879 fn add_to_index(item: &Item, ebml_w: &Encoder,
880 index: @RefCell<Vec<entry<i64>> >) {
881 index.borrow_mut().push(entry {
883 pos: ebml_w.writer.tell().unwrap(),
887 debug!("encoding info for item at {}",
888 ecx.tcx.sess.codemap().span_to_str(item.span));
890 let def_id = local_def(item.id);
892 ItemStatic(_, m, _) => {
893 add_to_index(item, ebml_w, index);
894 ebml_w.start_tag(tag_items_data_item);
895 encode_def_id(ebml_w, def_id);
896 if m == ast::MutMutable {
897 encode_family(ebml_w, 'b');
899 encode_family(ebml_w, 'c');
901 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
902 encode_symbol(ecx, ebml_w, item.id);
903 encode_name(ebml_w, item.ident.name);
904 encode_path(ebml_w, path);
906 let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
909 (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
911 encode_visibility(ebml_w, vis);
914 ItemFn(_, purity, _, ref generics, _) => {
915 add_to_index(item, ebml_w, index);
916 ebml_w.start_tag(tag_items_data_item);
917 encode_def_id(ebml_w, def_id);
918 encode_family(ebml_w, purity_fn_family(purity));
919 let tps_len = generics.ty_params.len();
920 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
921 encode_name(ebml_w, item.ident.name);
922 encode_path(ebml_w, path);
923 encode_attributes(ebml_w, item.attrs.as_slice());
924 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
925 (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
927 encode_symbol(ecx, ebml_w, item.id);
929 encode_visibility(ebml_w, vis);
933 add_to_index(item, ebml_w, index);
934 encode_info_for_mod(ecx,
942 ItemForeignMod(ref fm) => {
943 add_to_index(item, ebml_w, index);
944 ebml_w.start_tag(tag_items_data_item);
945 encode_def_id(ebml_w, def_id);
946 encode_family(ebml_w, 'n');
947 encode_name(ebml_w, item.ident.name);
948 encode_path(ebml_w, path);
950 // Encode all the items in this module.
951 for foreign_item in fm.items.iter() {
952 ebml_w.start_tag(tag_mod_child);
953 ebml_w.wr_str(def_to_str(local_def(foreign_item.id)));
956 encode_visibility(ebml_w, vis);
960 add_to_index(item, ebml_w, index);
961 ebml_w.start_tag(tag_items_data_item);
962 encode_def_id(ebml_w, def_id);
963 encode_family(ebml_w, 'y');
964 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
965 encode_name(ebml_w, item.ident.name);
966 encode_path(ebml_w, path);
967 encode_visibility(ebml_w, vis);
970 ItemEnum(ref enum_definition, ref generics) => {
971 add_to_index(item, ebml_w, index);
973 ebml_w.start_tag(tag_items_data_item);
974 encode_def_id(ebml_w, def_id);
975 encode_family(ebml_w, 't');
976 encode_item_variances(ebml_w, ecx, item.id);
977 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
978 encode_name(ebml_w, item.ident.name);
979 encode_attributes(ebml_w, item.attrs.as_slice());
980 for v in (*enum_definition).variants.iter() {
981 encode_variant_id(ebml_w, local_def(v.node.id));
983 (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
984 encode_path(ebml_w, path);
986 // Encode inherent implementations for this enumeration.
987 encode_inherent_implementations(ecx, ebml_w, def_id);
989 encode_visibility(ebml_w, vis);
992 encode_enum_variant_info(ecx,
995 (*enum_definition).variants.as_slice(),
999 ItemStruct(struct_def, _) => {
1000 /* First, encode the fields
1001 These come first because we need to write them to make
1002 the index, and the index needs to be in the item for the
1004 let idx = encode_info_for_struct(ecx, ebml_w,
1005 struct_def.fields.as_slice(), index);
1007 /* Index the class*/
1008 add_to_index(item, ebml_w, index);
1010 /* Now, make an item for the class itself */
1011 ebml_w.start_tag(tag_items_data_item);
1012 encode_def_id(ebml_w, def_id);
1013 encode_family(ebml_w, 'S');
1014 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1016 encode_item_variances(ebml_w, ecx, item.id);
1017 encode_name(ebml_w, item.ident.name);
1018 encode_attributes(ebml_w, item.attrs.as_slice());
1019 encode_path(ebml_w, path.clone());
1020 encode_visibility(ebml_w, vis);
1022 /* Encode def_ids for each field and method
1023 for methods, write all the stuff get_trait_method
1025 encode_struct_fields(ebml_w, struct_def);
1027 (ecx.encode_inlined_item)(ecx, ebml_w, IIItemRef(item));
1029 // Encode inherent implementations for this structure.
1030 encode_inherent_implementations(ecx, ebml_w, def_id);
1032 /* Each class has its own index -- encode it */
1033 let bkts = create_index(idx);
1034 encode_index(ebml_w, bkts, write_i64);
1037 // If this is a tuple-like struct, encode the type of the constructor.
1038 match struct_def.ctor_id {
1040 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1041 ctor_id, index, def_id.node);
1046 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1047 // We need to encode information about the default methods we
1048 // have inherited, so we drive this based on the impl structure.
1049 let impls = tcx.impls.borrow();
1050 let imp = impls.get(&def_id);
1052 add_to_index(item, ebml_w, index);
1053 ebml_w.start_tag(tag_items_data_item);
1054 encode_def_id(ebml_w, def_id);
1055 encode_family(ebml_w, 'i');
1056 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1057 encode_name(ebml_w, item.ident.name);
1058 encode_attributes(ebml_w, item.attrs.as_slice());
1060 ast::TyPath(ref path, ref bounds, _) if path.segments
1062 assert!(bounds.is_none());
1063 encode_impl_type_basename(ebml_w, ast_util::path_to_ident(path));
1067 for method in imp.methods.iter() {
1068 ebml_w.start_tag(tag_item_impl_method);
1069 let s = def_to_str(method.def_id);
1070 ebml_w.writer.write(s.as_bytes());
1073 for ast_trait_ref in opt_trait.iter() {
1074 let trait_ref = ty::node_id_to_trait_ref(
1075 tcx, ast_trait_ref.ref_id);
1076 encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
1077 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1078 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1080 encode_path(ebml_w, path.clone());
1083 // Iterate down the methods, emitting them. We rely on the
1084 // assumption that all of the actually implemented methods
1085 // appear first in the impl structure, in the same order they do
1086 // in the ast. This is a little sketchy.
1087 let num_implemented_methods = ast_methods.len();
1088 for (i, m) in imp.methods.iter().enumerate() {
1089 let ast_method = if i < num_implemented_methods {
1090 Some(*ast_methods.get(i))
1093 index.borrow_mut().push(entry {
1094 val: m.def_id.node as i64,
1095 pos: ebml_w.writer.tell().unwrap(),
1097 encode_info_for_method(ecx,
1106 ItemTrait(_, ref super_traits, ref ms) => {
1107 add_to_index(item, ebml_w, index);
1108 ebml_w.start_tag(tag_items_data_item);
1109 encode_def_id(ebml_w, def_id);
1110 encode_family(ebml_w, 'I');
1111 encode_item_variances(ebml_w, ecx, item.id);
1112 let trait_def = ty::lookup_trait_def(tcx, def_id);
1113 encode_ty_type_param_defs(ebml_w, ecx,
1114 trait_def.generics.type_param_defs(),
1115 tag_items_data_item_ty_param_bounds);
1116 encode_region_param_defs(ebml_w, trait_def.generics.region_param_defs());
1117 encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
1118 encode_name(ebml_w, item.ident.name);
1119 encode_attributes(ebml_w, item.attrs.as_slice());
1120 encode_visibility(ebml_w, vis);
1121 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1122 ebml_w.start_tag(tag_item_trait_method);
1123 encode_def_id(ebml_w, method_def_id);
1126 ebml_w.start_tag(tag_mod_child);
1127 ebml_w.wr_str(def_to_str(method_def_id));
1130 encode_path(ebml_w, path.clone());
1131 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1132 // reading the AST's list, because the former has already filtered out
1133 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1134 for ast_trait_ref in super_traits.iter() {
1135 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1136 encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
1139 // Encode the implementations of this trait.
1140 encode_extension_implementations(ecx, ebml_w, def_id);
1144 // Now output the method info for each method.
1145 let r = ty::trait_method_def_ids(tcx, def_id);
1146 for (i, &method_def_id) in r.iter().enumerate() {
1147 assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1149 let method_ty = ty::method(tcx, method_def_id);
1151 index.borrow_mut().push(entry {
1152 val: method_def_id.node as i64,
1153 pos: ebml_w.writer.tell().unwrap(),
1156 ebml_w.start_tag(tag_items_data_item);
1158 encode_method_ty_fields(ecx, ebml_w, method_ty);
1160 encode_parent_item(ebml_w, def_id);
1162 let elem = ast_map::PathName(method_ty.ident.name);
1163 encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1165 match method_ty.explicit_self {
1167 encode_family(ebml_w,
1168 purity_static_method_family(
1169 method_ty.fty.purity));
1171 let tpt = ty::lookup_item_type(tcx, method_def_id);
1172 encode_bounds_and_type(ebml_w, ecx, &tpt);
1176 encode_family(ebml_w,
1178 method_ty.fty.purity));
1183 &Required(ref tm) => {
1184 encode_attributes(ebml_w, tm.attrs.as_slice());
1185 encode_method_sort(ebml_w, 'r');
1189 encode_attributes(ebml_w, m.attrs.as_slice());
1190 // If this is a static method, we've already encoded
1192 if method_ty.explicit_self != SelfStatic {
1193 // FIXME: I feel like there is something funny going on.
1194 let tpt = ty::lookup_item_type(tcx, method_def_id);
1195 encode_bounds_and_type(ebml_w, ecx, &tpt);
1197 encode_method_sort(ebml_w, 'p');
1198 (ecx.encode_inlined_item)(
1199 ecx, ebml_w, IIMethodRef(def_id, true, m));
1206 // Encode inherent implementations for this trait.
1207 encode_inherent_implementations(ecx, ebml_w, def_id);
1210 // macros are encoded separately
1215 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1216 ebml_w: &mut Encoder,
1217 nitem: &ForeignItem,
1218 index: @RefCell<Vec<entry<i64>> >,
1221 index.borrow_mut().push(entry {
1222 val: nitem.id as i64,
1223 pos: ebml_w.writer.tell().unwrap(),
1226 ebml_w.start_tag(tag_items_data_item);
1227 encode_def_id(ebml_w, local_def(nitem.id));
1229 ForeignItemFn(..) => {
1230 encode_family(ebml_w, purity_fn_family(ImpureFn));
1231 encode_bounds_and_type(ebml_w, ecx,
1232 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1233 encode_name(ebml_w, nitem.ident.name);
1234 if abi == abi::RustIntrinsic {
1235 (ecx.encode_inlined_item)(ecx, ebml_w, IIForeignRef(nitem));
1237 encode_symbol(ecx, ebml_w, nitem.id);
1240 ForeignItemStatic(_, mutbl) => {
1242 encode_family(ebml_w, 'b');
1244 encode_family(ebml_w, 'c');
1246 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1247 encode_symbol(ecx, ebml_w, nitem.id);
1248 encode_name(ebml_w, nitem.ident.name);
1251 encode_path(ebml_w, path);
1255 fn my_visit_expr(_e: &Expr) { }
1257 fn my_visit_item(i: &Item,
1258 ebml_w: &mut Encoder,
1260 index: @RefCell<Vec<entry<i64>> >) {
1261 let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1263 let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1264 ecx.tcx.map.with_path(i.id, |path| {
1265 encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1269 fn my_visit_foreign_item(ni: &ForeignItem,
1270 ebml_w: &mut Encoder,
1272 index: @RefCell<Vec<entry<i64>> >) {
1274 let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1275 debug!("writing foreign item {}::{}",
1276 ecx.tcx.map.path_to_str(ni.id),
1277 token::get_ident(ni.ident));
1279 let mut ebml_w = unsafe {
1280 ebml_w.unsafe_clone()
1282 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1283 ecx.tcx.map.with_path(ni.id, |path| {
1284 encode_info_for_foreign_item(ecx, &mut ebml_w,
1290 struct EncodeVisitor<'a,'b> {
1291 ebml_w_for_visit_item: &'a mut Encoder<'b>,
1293 index: @RefCell<Vec<entry<i64>> >,
1296 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1297 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1298 visit::walk_expr(self, ex, ());
1301 fn visit_item(&mut self, i: &Item, _: ()) {
1302 visit::walk_item(self, i, ());
1304 self.ebml_w_for_visit_item,
1308 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1309 visit::walk_foreign_item(self, ni, ());
1310 my_visit_foreign_item(ni,
1311 self.ebml_w_for_visit_item,
1317 fn encode_info_for_items(ecx: &EncodeContext,
1318 ebml_w: &mut Encoder,
1320 -> Vec<entry<i64>> {
1321 let index = @RefCell::new(Vec::new());
1322 ebml_w.start_tag(tag_items_data);
1323 index.borrow_mut().push(entry {
1324 val: CRATE_NODE_ID as i64,
1325 pos: ebml_w.writer.tell().unwrap(),
1327 encode_info_for_mod(ecx,
1331 ast_map::Values([].iter()).chain(None),
1332 syntax::parse::token::special_idents::invalid,
1335 // See comment in `encode_side_tables_for_ii` in astencode
1336 let ecx_ptr: *int = unsafe { cast::transmute(ecx) };
1338 let mut visitor = EncodeVisitor {
1341 ebml_w_for_visit_item: &mut *ebml_w,
1344 visit::walk_crate(&mut visitor, krate, ());
1348 return /*bad*/index.borrow().clone();
1352 // Path and definition ID indexing
1354 fn create_index<T:Clone + Hash + 'static>(
1355 index: Vec<entry<T>> )
1356 -> Vec<@Vec<entry<T>> > {
1357 let mut buckets: Vec<@RefCell<Vec<entry<T>> >> = Vec::new();
1358 for _ in range(0u, 256u) {
1359 buckets.push(@RefCell::new(Vec::new()));
1361 for elt in index.iter() {
1362 let h = hash::hash(&elt.val) as uint;
1363 buckets.get_mut(h % 256).borrow_mut().push((*elt).clone());
1366 let mut buckets_frozen = Vec::new();
1367 for bucket in buckets.iter() {
1368 buckets_frozen.push(@/*bad*/bucket.borrow().clone());
1370 return buckets_frozen;
1373 fn encode_index<T:'static>(
1374 ebml_w: &mut Encoder,
1375 buckets: Vec<@Vec<entry<T>> > ,
1376 write_fn: |&mut MemWriter, &T|) {
1377 ebml_w.start_tag(tag_index);
1378 let mut bucket_locs = Vec::new();
1379 ebml_w.start_tag(tag_index_buckets);
1380 for bucket in buckets.iter() {
1381 bucket_locs.push(ebml_w.writer.tell().unwrap());
1382 ebml_w.start_tag(tag_index_buckets_bucket);
1383 for elt in (**bucket).iter() {
1384 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1385 assert!(elt.pos < 0xffff_ffff);
1387 let wr: &mut MemWriter = ebml_w.writer;
1388 wr.write_be_u32(elt.pos as u32);
1390 write_fn(ebml_w.writer, &elt.val);
1396 ebml_w.start_tag(tag_index_table);
1397 for pos in bucket_locs.iter() {
1398 assert!(*pos < 0xffff_ffff);
1399 let wr: &mut MemWriter = ebml_w.writer;
1400 wr.write_be_u32(*pos as u32);
1406 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1407 let wr: &mut MemWriter = writer;
1408 assert!(n < 0x7fff_ffff);
1409 wr.write_be_u32(n as u32);
1412 fn encode_meta_item(ebml_w: &mut Encoder, mi: @MetaItem) {
1414 MetaWord(ref name) => {
1415 ebml_w.start_tag(tag_meta_item_word);
1416 ebml_w.start_tag(tag_meta_item_name);
1417 ebml_w.writer.write(name.get().as_bytes());
1421 MetaNameValue(ref name, ref value) => {
1423 LitStr(ref value, _) => {
1424 ebml_w.start_tag(tag_meta_item_name_value);
1425 ebml_w.start_tag(tag_meta_item_name);
1426 ebml_w.writer.write(name.get().as_bytes());
1428 ebml_w.start_tag(tag_meta_item_value);
1429 ebml_w.writer.write(value.get().as_bytes());
1433 _ => {/* FIXME (#623): encode other variants */ }
1436 MetaList(ref name, ref items) => {
1437 ebml_w.start_tag(tag_meta_item_list);
1438 ebml_w.start_tag(tag_meta_item_name);
1439 ebml_w.writer.write(name.get().as_bytes());
1441 for inner_item in items.iter() {
1442 encode_meta_item(ebml_w, *inner_item);
1449 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1450 ebml_w.start_tag(tag_attributes);
1451 for attr in attrs.iter() {
1452 ebml_w.start_tag(tag_attribute);
1453 encode_meta_item(ebml_w, attr.node.value);
1459 // So there's a special crate attribute called 'crate_id' which defines the
1460 // metadata that Rust cares about for linking crates. If the user didn't
1461 // provide it we will throw it in anyway with a default value.
1462 fn synthesize_crate_attrs(ecx: &EncodeContext,
1463 krate: &Crate) -> Vec<Attribute> {
1465 fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute {
1466 assert!(!ecx.link_meta.crateid.name.is_empty());
1469 attr::mk_name_value_item_str(
1470 InternedString::new("crate_id"),
1471 token::intern_and_get_ident(ecx.link_meta.crateid.to_str())))
1474 let mut attrs = Vec::new();
1475 for attr in krate.attrs.iter() {
1476 if !attr.name().equiv(&("crate_id")) {
1480 attrs.push(synthesize_crateid_attr(ecx));
1485 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1486 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1487 // Pull the cnums and name,vers,hash out of cstore
1488 let mut deps = Vec::new();
1489 cstore.iter_crate_data(|key, val| {
1490 let dep = decoder::CrateDep {
1492 crate_id: decoder::get_crate_id(val.data()),
1493 hash: decoder::get_crate_hash(val.data())
1499 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1501 // Sanity-check the crate numbers
1502 let mut expected_cnum = 1;
1503 for n in deps.iter() {
1504 assert_eq!(n.cnum, expected_cnum);
1511 // We're just going to write a list of crate 'name-hash-version's, with
1512 // the assumption that they are numbered 1 to n.
1513 // FIXME (#2166): This is not nearly enough to support correct versioning
1514 // but is enough to get transitive crate dependencies working.
1515 ebml_w.start_tag(tag_crate_deps);
1516 let r = get_ordered_deps(cstore);
1517 for dep in r.iter() {
1518 encode_crate_dep(ebml_w, (*dep).clone());
1523 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1524 ebml_w.start_tag(tag_lang_items);
1526 for (i, def_id) in ecx.tcx.lang_items.items() {
1527 for id in def_id.iter() {
1528 if id.krate == LOCAL_CRATE {
1529 ebml_w.start_tag(tag_lang_items_item);
1531 ebml_w.start_tag(tag_lang_items_item_id);
1533 let wr: &mut MemWriter = ebml_w.writer;
1534 wr.write_be_u32(i as u32);
1536 ebml_w.end_tag(); // tag_lang_items_item_id
1538 ebml_w.start_tag(tag_lang_items_item_node_id);
1540 let wr: &mut MemWriter = ebml_w.writer;
1541 wr.write_be_u32(id.node as u32);
1543 ebml_w.end_tag(); // tag_lang_items_item_node_id
1545 ebml_w.end_tag(); // tag_lang_items_item
1550 ebml_w.end_tag(); // tag_lang_items
1553 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1554 ebml_w.start_tag(tag_native_libraries);
1556 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1559 cstore::NativeStatic => {} // these libraries are not propagated
1560 cstore::NativeFramework | cstore::NativeUnknown => {
1561 ebml_w.start_tag(tag_native_libraries_lib);
1563 ebml_w.start_tag(tag_native_libraries_kind);
1564 ebml_w.writer.write_be_u32(kind as u32);
1567 ebml_w.start_tag(tag_native_libraries_name);
1568 ebml_w.writer.write(lib.as_bytes());
1579 fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1580 match *ecx.tcx.sess.macro_registrar_fn.borrow() {
1582 ebml_w.start_tag(tag_macro_registrar_fn);
1583 encode_def_id(ebml_w, did);
1590 struct MacroDefVisitor<'a, 'b> {
1591 ecx: &'a EncodeContext<'a>,
1592 ebml_w: &'a mut Encoder<'b>
1595 impl<'a, 'b> Visitor<()> for MacroDefVisitor<'a, 'b> {
1596 fn visit_item(&mut self, item: &Item, _: ()) {
1599 let def = self.ecx.tcx.sess.codemap().span_to_snippet(item.span)
1600 .expect("Unable to find source for macro");
1601 self.ebml_w.start_tag(tag_macro_def);
1602 self.ebml_w.wr_str(def);
1603 self.ebml_w.end_tag();
1607 visit::walk_item(self, item, ());
1611 fn encode_macro_defs(ecx: &EncodeContext,
1613 ebml_w: &mut Encoder) {
1614 ebml_w.start_tag(tag_exported_macros);
1616 let mut visitor = MacroDefVisitor {
1620 visit::walk_crate(&mut visitor, krate, ());
1625 struct ImplVisitor<'a,'b> {
1626 ecx: &'a EncodeContext<'a>,
1627 ebml_w: &'a mut Encoder<'b>,
1630 impl<'a,'b> Visitor<()> for ImplVisitor<'a,'b> {
1631 fn visit_item(&mut self, item: &Item, _: ()) {
1633 ItemImpl(_, Some(ref trait_ref), _, _) => {
1634 let def_map = self.ecx.tcx.def_map;
1635 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1636 let def_id = ast_util::def_id_of_def(trait_def);
1638 // Load eagerly if this is an implementation of the Drop trait
1639 // or if the trait is not defined in this crate.
1640 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1641 def_id.krate != LOCAL_CRATE {
1642 self.ebml_w.start_tag(tag_impls_impl);
1643 encode_def_id(self.ebml_w, local_def(item.id));
1644 self.ebml_w.end_tag();
1649 visit::walk_item(self, item, ());
1653 /// Encodes implementations that are eagerly loaded.
1655 /// None of this is necessary in theory; we can load all implementations
1656 /// lazily. However, in two cases the optimizations to lazily load
1657 /// implementations are not yet implemented. These two cases, which require us
1658 /// to load implementations eagerly, are:
1660 /// * Destructors (implementations of the Drop trait).
1662 /// * Implementations of traits not defined in this crate.
1663 fn encode_impls(ecx: &EncodeContext,
1665 ebml_w: &mut Encoder) {
1666 ebml_w.start_tag(tag_impls);
1669 let mut visitor = ImplVisitor {
1673 visit::walk_crate(&mut visitor, krate, ());
1679 fn encode_misc_info(ecx: &EncodeContext,
1681 ebml_w: &mut Encoder) {
1682 ebml_w.start_tag(tag_misc_info);
1683 ebml_w.start_tag(tag_misc_info_crate_items);
1684 for &item in krate.module.items.iter() {
1685 ebml_w.start_tag(tag_mod_child);
1686 ebml_w.wr_str(def_to_str(local_def(item.id)));
1689 each_auxiliary_node_id(item, |auxiliary_node_id| {
1690 ebml_w.start_tag(tag_mod_child);
1691 ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
1697 // Encode reexports for the root module.
1698 encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1704 fn encode_crate_dep(ebml_w: &mut Encoder,
1705 dep: decoder::CrateDep) {
1706 ebml_w.start_tag(tag_crate_dep);
1707 ebml_w.start_tag(tag_crate_dep_crateid);
1708 ebml_w.writer.write(dep.crate_id.to_str().as_bytes());
1710 ebml_w.start_tag(tag_crate_dep_hash);
1711 ebml_w.writer.write(dep.hash.as_str().as_bytes());
1716 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1717 ebml_w.start_tag(tag_crate_hash);
1718 ebml_w.writer.write(hash.as_str().as_bytes());
1722 fn encode_crate_id(ebml_w: &mut Encoder, crate_id: &CrateId) {
1723 ebml_w.start_tag(tag_crate_crateid);
1724 ebml_w.writer.write(crate_id.to_str().as_bytes());
1728 // NB: Increment this as you change the metadata encoding version.
1729 pub static metadata_encoding_version : &'static [u8] =
1730 &[0x72, //'r' as u8,
1736 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1737 let mut wr = MemWriter::new();
1738 encode_metadata_inner(&mut wr, parms, krate);
1739 wr.unwrap().move_iter().collect()
1742 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1744 inline_bytes: Cell::new(0),
1745 attr_bytes: Cell::new(0),
1746 dep_bytes: Cell::new(0),
1747 lang_item_bytes: Cell::new(0),
1748 native_lib_bytes: Cell::new(0),
1749 macro_registrar_fn_bytes: Cell::new(0),
1750 macro_defs_bytes: Cell::new(0),
1751 impl_bytes: Cell::new(0),
1752 misc_bytes: Cell::new(0),
1753 item_bytes: Cell::new(0),
1754 index_bytes: Cell::new(0),
1755 zero_bytes: Cell::new(0),
1756 total_bytes: Cell::new(0),
1764 encode_inlined_item,
1766 non_inlineable_statics,
1769 let type_abbrevs = @RefCell::new(HashMap::new());
1771 let ecx = EncodeContext {
1775 reexports2: reexports2,
1776 item_symbols: item_symbols,
1777 non_inlineable_statics: non_inlineable_statics,
1778 link_meta: link_meta,
1780 encode_inlined_item: encode_inlined_item,
1781 type_abbrevs: type_abbrevs,
1784 let mut ebml_w = writer::Encoder(wr);
1786 encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
1787 encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1789 let mut i = ebml_w.writer.tell().unwrap();
1790 let crate_attrs = synthesize_crate_attrs(&ecx, krate);
1791 encode_attributes(&mut ebml_w, crate_attrs.as_slice());
1792 ecx.stats.attr_bytes.set(ebml_w.writer.tell().unwrap() - i);
1794 i = ebml_w.writer.tell().unwrap();
1795 encode_crate_deps(&mut ebml_w, ecx.cstore);
1796 ecx.stats.dep_bytes.set(ebml_w.writer.tell().unwrap() - i);
1798 // Encode the language items.
1799 i = ebml_w.writer.tell().unwrap();
1800 encode_lang_items(&ecx, &mut ebml_w);
1801 ecx.stats.lang_item_bytes.set(ebml_w.writer.tell().unwrap() - i);
1803 // Encode the native libraries used
1804 i = ebml_w.writer.tell().unwrap();
1805 encode_native_libraries(&ecx, &mut ebml_w);
1806 ecx.stats.native_lib_bytes.set(ebml_w.writer.tell().unwrap() - i);
1808 // Encode the macro registrar function
1809 i = ebml_w.writer.tell().unwrap();
1810 encode_macro_registrar_fn(&ecx, &mut ebml_w);
1811 ecx.stats.macro_registrar_fn_bytes.set(ebml_w.writer.tell().unwrap() - i);
1813 // Encode macro definitions
1814 i = ebml_w.writer.tell().unwrap();
1815 encode_macro_defs(&ecx, krate, &mut ebml_w);
1816 ecx.stats.macro_defs_bytes.set(ebml_w.writer.tell().unwrap() - i);
1818 // Encode the def IDs of impls, for coherence checking.
1819 i = ebml_w.writer.tell().unwrap();
1820 encode_impls(&ecx, krate, &mut ebml_w);
1821 ecx.stats.impl_bytes.set(ebml_w.writer.tell().unwrap() - i);
1823 // Encode miscellaneous info.
1824 i = ebml_w.writer.tell().unwrap();
1825 encode_misc_info(&ecx, krate, &mut ebml_w);
1826 ecx.stats.misc_bytes.set(ebml_w.writer.tell().unwrap() - i);
1828 // Encode and index the items.
1829 ebml_w.start_tag(tag_items);
1830 i = ebml_w.writer.tell().unwrap();
1831 let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1832 ecx.stats.item_bytes.set(ebml_w.writer.tell().unwrap() - i);
1834 i = ebml_w.writer.tell().unwrap();
1835 let items_buckets = create_index(items_index);
1836 encode_index(&mut ebml_w, items_buckets, write_i64);
1837 ecx.stats.index_bytes.set(ebml_w.writer.tell().unwrap() - i);
1840 ecx.stats.total_bytes.set(ebml_w.writer.tell().unwrap());
1842 if tcx.sess.meta_stats() {
1843 for e in ebml_w.writer.get_ref().iter() {
1845 ecx.stats.zero_bytes.set(ecx.stats.zero_bytes.get() + 1);
1849 println!("metadata stats:");
1850 println!(" inline bytes: {}", ecx.stats.inline_bytes.get());
1851 println!(" attribute bytes: {}", ecx.stats.attr_bytes.get());
1852 println!(" dep bytes: {}", ecx.stats.dep_bytes.get());
1853 println!(" lang item bytes: {}", ecx.stats.lang_item_bytes.get());
1854 println!(" native bytes: {}", ecx.stats.native_lib_bytes.get());
1855 println!("macro registrar bytes: {}", ecx.stats.macro_registrar_fn_bytes.get());
1856 println!(" macro def bytes: {}", ecx.stats.macro_defs_bytes.get());
1857 println!(" impl bytes: {}", ecx.stats.impl_bytes.get());
1858 println!(" misc bytes: {}", ecx.stats.misc_bytes.get());
1859 println!(" item bytes: {}", ecx.stats.item_bytes.get());
1860 println!(" index bytes: {}", ecx.stats.index_bytes.get());
1861 println!(" zero bytes: {}", ecx.stats.zero_bytes.get());
1862 println!(" total bytes: {}", ecx.stats.total_bytes.get());
1866 // Get the encoded string for a type
1867 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> ~str {
1868 let cx = &tyencode::ctxt {
1869 diag: tcx.sess.diagnostic(),
1872 abbrevs: tyencode::ac_no_abbrevs};
1873 let mut wr = MemWriter::new();
1874 tyencode::enc_ty(&mut wr, cx, t);
1875 str::from_utf8_owned(wr.get_ref().to_owned()).unwrap()