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)]
18 use metadata::common::*;
20 use metadata::decoder;
21 use metadata::tyencode;
22 use middle::subst::VecPerParamSpace;
23 use middle::ty::{node_id_to_type, lookup_item_type};
24 use middle::astencode;
27 use middle::stability;
29 use util::nodemap::{NodeMap, NodeSet};
31 use serialize::Encodable;
32 use std::cell::RefCell;
36 use std::io::MemWriter;
38 use std::collections::HashMap;
42 use syntax::ast_map::{PathElem, PathElems};
44 use syntax::ast_util::*;
46 use syntax::ast_util::PostExpansionMethod;
48 use syntax::attr::AttrMetaMethods;
49 use syntax::diagnostic::SpanHandler;
50 use syntax::parse::token::special_idents;
51 use syntax::parse::token;
52 use syntax::visit::Visitor;
55 use writer = serialize::ebml::writer;
57 /// A borrowed version of ast::InlinedItem.
58 pub enum InlinedItemRef<'a> {
59 IIItemRef(&'a ast::Item),
60 IIMethodRef(ast::DefId, bool, &'a ast::Method),
61 IIForeignRef(&'a ast::ForeignItem)
64 pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
66 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
68 ii: InlinedItemRef|: 'a;
70 pub struct EncodeParams<'a> {
71 pub diag: &'a SpanHandler,
72 pub tcx: &'a ty::ctxt,
73 pub reexports2: &'a middle::resolve::ExportMap2,
74 pub item_symbols: &'a RefCell<NodeMap<String>>,
75 pub non_inlineable_statics: &'a RefCell<NodeSet>,
76 pub link_meta: &'a LinkMeta,
77 pub cstore: &'a cstore::CStore,
78 pub encode_inlined_item: EncodeInlinedItem<'a>,
79 pub reachable: &'a NodeSet,
82 pub struct EncodeContext<'a> {
83 pub diag: &'a SpanHandler,
84 pub tcx: &'a ty::ctxt,
85 pub reexports2: &'a middle::resolve::ExportMap2,
86 pub item_symbols: &'a RefCell<NodeMap<String>>,
87 pub non_inlineable_statics: &'a RefCell<NodeSet>,
88 pub link_meta: &'a LinkMeta,
89 pub cstore: &'a cstore::CStore,
90 pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
91 pub type_abbrevs: tyencode::abbrev_map,
92 pub reachable: &'a NodeSet,
95 fn encode_name(ebml_w: &mut Encoder, name: Name) {
96 ebml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
99 fn encode_impl_type_basename(ebml_w: &mut Encoder, name: Ident) {
100 ebml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
103 pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
104 ebml_w.wr_tagged_str(tag_def_id, def_to_string(id).as_slice());
113 fn encode_trait_ref(ebml_w: &mut Encoder,
115 trait_ref: &ty::TraitRef,
117 let ty_str_ctxt = &tyencode::ctxt {
121 abbrevs: &ecx.type_abbrevs
124 ebml_w.start_tag(tag);
125 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
129 fn encode_impl_vtables(ebml_w: &mut Encoder,
131 vtables: &typeck::vtable_res) {
132 ebml_w.start_tag(tag_item_impl_vtables);
133 astencode::encode_vtable_res(ecx, ebml_w, vtables);
137 // Item info table encoding
138 fn encode_family(ebml_w: &mut Encoder, c: char) {
139 ebml_w.start_tag(tag_items_data_item_family);
140 ebml_w.writer.write(&[c as u8]);
144 pub fn def_to_string(did: DefId) -> String {
145 format!("{}:{}", did.krate, did.node)
148 fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
150 params: &VecPerParamSpace<ty::TypeParameterDef>,
152 let ty_str_ctxt = &tyencode::ctxt {
156 abbrevs: &ecx.type_abbrevs
158 for param in params.iter() {
159 ebml_w.start_tag(tag);
160 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
165 fn encode_region_param_defs(ebml_w: &mut Encoder,
166 params: &VecPerParamSpace<ty::RegionParameterDef>) {
167 for param in params.iter() {
168 ebml_w.start_tag(tag_region_param_def);
170 ebml_w.start_tag(tag_region_param_def_ident);
171 encode_name(ebml_w, param.name);
174 ebml_w.wr_tagged_str(tag_region_param_def_def_id,
175 def_to_string(param.def_id).as_slice());
177 ebml_w.wr_tagged_u64(tag_region_param_def_space,
178 param.space.to_uint() as u64);
180 ebml_w.wr_tagged_u64(tag_region_param_def_index,
187 fn encode_item_variances(ebml_w: &mut Encoder,
190 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
191 ebml_w.start_tag(tag_item_variances);
196 fn encode_bounds_and_type(ebml_w: &mut Encoder,
198 pty: &ty::Polytype) {
199 encode_ty_type_param_defs(ebml_w, ecx, &pty.generics.types,
200 tag_items_data_item_ty_param_bounds);
201 encode_region_param_defs(ebml_w, &pty.generics.regions);
202 encode_type(ecx, ebml_w, pty.ty);
205 fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
206 ebml_w.start_tag(tag_items_data_item_variant);
207 let s = def_to_string(vid);
208 ebml_w.writer.write(s.as_bytes());
212 pub fn write_type(ecx: &EncodeContext,
213 ebml_w: &mut Encoder,
215 let ty_str_ctxt = &tyencode::ctxt {
219 abbrevs: &ecx.type_abbrevs
221 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
224 fn encode_type(ecx: &EncodeContext,
225 ebml_w: &mut Encoder,
227 ebml_w.start_tag(tag_items_data_item_type);
228 write_type(ecx, ebml_w, typ);
232 fn encode_method_fty(ecx: &EncodeContext,
233 ebml_w: &mut Encoder,
234 typ: &ty::BareFnTy) {
235 ebml_w.start_tag(tag_item_method_fty);
237 let ty_str_ctxt = &tyencode::ctxt {
241 abbrevs: &ecx.type_abbrevs
243 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
248 fn encode_symbol(ecx: &EncodeContext,
249 ebml_w: &mut Encoder,
251 ebml_w.start_tag(tag_items_data_item_symbol);
252 match ecx.item_symbols.borrow().find(&id) {
254 debug!("encode_symbol(id={:?}, str={})", id, *x);
255 ebml_w.writer.write(x.as_bytes());
258 ecx.diag.handler().bug(
259 format!("encode_symbol: id not found {}", id).as_slice());
265 fn encode_disr_val(_: &EncodeContext,
266 ebml_w: &mut Encoder,
267 disr_val: ty::Disr) {
268 ebml_w.start_tag(tag_disr_val);
269 let s = disr_val.to_string();
270 ebml_w.writer.write(s.as_bytes());
274 fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
275 ebml_w.start_tag(tag_items_data_parent_item);
276 let s = def_to_string(id);
277 ebml_w.writer.write(s.as_bytes());
281 fn encode_struct_fields(ebml_w: &mut Encoder,
282 fields: &[ty::field_ty],
284 for f in fields.iter() {
285 if f.name == special_idents::unnamed_field.name {
286 ebml_w.start_tag(tag_item_unnamed_field);
288 ebml_w.start_tag(tag_item_field);
289 encode_name(ebml_w, f.name);
291 encode_struct_field_family(ebml_w, f.vis);
292 encode_def_id(ebml_w, f.id);
293 ebml_w.start_tag(tag_item_field_origin);
294 let s = def_to_string(origin);
295 ebml_w.writer.write(s.as_bytes());
301 fn encode_enum_variant_info(ecx: &EncodeContext,
302 ebml_w: &mut Encoder,
304 variants: &[P<Variant>],
305 index: &mut Vec<entry<i64>>,
306 generics: &ast::Generics) {
307 debug!("encode_enum_variant_info(id={:?})", id);
309 let mut disr_val = 0;
311 let vi = ty::enum_variants(ecx.tcx,
312 ast::DefId { krate: LOCAL_CRATE, node: id });
313 for variant in variants.iter() {
314 let def_id = local_def(variant.node.id);
316 val: variant.node.id as i64,
317 pos: ebml_w.writer.tell().unwrap(),
319 ebml_w.start_tag(tag_items_data_item);
320 encode_def_id(ebml_w, def_id);
321 match variant.node.kind {
322 ast::TupleVariantKind(_) => encode_family(ebml_w, 'v'),
323 ast::StructVariantKind(_) => encode_family(ebml_w, 'V')
325 encode_name(ebml_w, variant.node.name.name);
326 encode_parent_item(ebml_w, local_def(id));
327 encode_visibility(ebml_w, variant.node.vis);
328 encode_attributes(ebml_w, variant.node.attrs.as_slice());
330 let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
331 encode_stability(ebml_w, stab);
333 match variant.node.kind {
334 ast::TupleVariantKind(ref args)
335 if args.len() > 0 && generics.ty_params.len() == 0 => {
336 encode_symbol(ecx, ebml_w, variant.node.id);
338 ast::TupleVariantKind(_) => {},
339 ast::StructVariantKind(_) => {
340 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
341 let idx = encode_info_for_struct(ecx,
345 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
346 encode_index(ebml_w, idx, write_i64);
349 if vi.get(i).disr_val != disr_val {
350 encode_disr_val(ecx, ebml_w, vi.get(i).disr_val);
351 disr_val = vi.get(i).disr_val;
353 encode_bounds_and_type(ebml_w, ecx,
354 &lookup_item_type(ecx.tcx, def_id));
356 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(ebml_w, path));
363 fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
365 ebml_w.start_tag(tag_path);
366 ebml_w.wr_tagged_u32(tag_path_len, path.clone().count() as u32);
369 ast_map::PathMod(_) => tag_path_elem_mod,
370 ast_map::PathName(_) => tag_path_elem_name
372 ebml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
377 fn encode_reexported_static_method(ebml_w: &mut Encoder,
378 exp: &middle::resolve::Export2,
379 method_def_id: DefId,
380 method_ident: Ident) {
381 debug!("(encode reexported static method) {}::{}",
382 exp.name, token::get_ident(method_ident));
383 ebml_w.start_tag(tag_items_data_item_reexport);
384 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
385 ebml_w.wr_str(def_to_string(method_def_id).as_slice());
387 ebml_w.start_tag(tag_items_data_item_reexport_name);
388 ebml_w.wr_str(format!("{}::{}",
390 token::get_ident(method_ident)).as_slice());
395 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
396 ebml_w: &mut Encoder,
397 exp: &middle::resolve::Export2)
399 let impl_methods = ecx.tcx.impl_methods.borrow();
400 match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
401 Some(implementations) => {
402 for base_impl_did in implementations.borrow().iter() {
403 for &method_did in impl_methods.get(base_impl_did).iter() {
404 let m = ty::method(ecx.tcx, method_did);
405 if m.explicit_self == ty::StaticExplicitSelfCategory {
406 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
417 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
418 ebml_w: &mut Encoder,
419 exp: &middle::resolve::Export2)
421 match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
423 for m in methods.iter() {
424 if m.explicit_self == ty::StaticExplicitSelfCategory {
425 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
435 fn encode_reexported_static_methods(ecx: &EncodeContext,
436 ebml_w: &mut Encoder,
438 exp: &middle::resolve::Export2) {
439 match ecx.tcx.map.find(exp.def_id.node) {
440 Some(ast_map::NodeItem(item)) => {
441 let original_name = token::get_ident(item.ident);
443 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
444 let (mut a, mut b) = (path, mod_path.clone());
446 match (a.next(), b.next()) {
447 (None, None) => return true,
448 (None, _) | (_, None) => return false,
449 (Some(x), Some(y)) => if x != y { return false },
455 // We don't need to reexport static methods on items
456 // declared in the same module as our `pub use ...` since
457 // that's done when we encode the item itself.
459 // The only exception is when the reexport *changes* the
460 // name e.g. `pub use Foo = self::Bar` -- we have
461 // encoded metadata for static methods relative to Bar,
462 // but not yet for Foo.
464 if path_differs || original_name.get() != exp.name.as_slice() {
465 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
466 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
467 debug!("(encode reexported static methods) {} \
473 debug!("(encode reexported static methods) {} [base]",
482 /// Iterates through "auxiliary node IDs", which are node IDs that describe
483 /// top-level items that are sub-items of the given item. Specifically:
485 /// * For enums, iterates through the node IDs of the variants.
487 /// * For newtype structs, iterates through the node ID of the constructor.
488 fn each_auxiliary_node_id(item: Gc<Item>, callback: |NodeId| -> bool) -> bool {
489 let mut continue_ = true;
491 ItemEnum(ref enum_def, _) => {
492 for variant in enum_def.variants.iter() {
493 continue_ = callback(variant.node.id);
499 ItemStruct(struct_def, _) => {
500 // If this is a newtype struct, return the constructor.
501 match struct_def.ctor_id {
502 Some(ctor_id) if struct_def.fields.len() > 0 &&
503 struct_def.fields.get(0).node.kind.is_unnamed() => {
504 continue_ = callback(ctor_id);
515 fn encode_reexports(ecx: &EncodeContext,
516 ebml_w: &mut Encoder,
519 debug!("(encoding info for module) encoding reexports for {}", id);
520 match ecx.reexports2.borrow().find(&id) {
521 Some(ref exports) => {
522 debug!("(encoding info for module) found reexports for {}", id);
523 for exp in exports.iter() {
524 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
530 ebml_w.start_tag(tag_items_data_item_reexport);
531 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
532 ebml_w.wr_str(def_to_string(exp.def_id).as_slice());
534 ebml_w.start_tag(tag_items_data_item_reexport_name);
535 ebml_w.wr_str(exp.name.as_slice());
538 encode_reexported_static_methods(ecx, ebml_w, path.clone(), exp);
542 debug!("(encoding info for module) found no reexports for {}",
548 fn encode_info_for_mod(ecx: &EncodeContext,
549 ebml_w: &mut Encoder,
556 ebml_w.start_tag(tag_items_data_item);
557 encode_def_id(ebml_w, local_def(id));
558 encode_family(ebml_w, 'm');
559 encode_name(ebml_w, name.name);
560 debug!("(encoding info for module) encoding info for module ID {}", id);
562 // Encode info about all the module children.
563 for item in md.items.iter() {
564 ebml_w.start_tag(tag_mod_child);
565 ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
568 each_auxiliary_node_id(*item, |auxiliary_node_id| {
569 ebml_w.start_tag(tag_mod_child);
570 ebml_w.wr_str(def_to_string(local_def(
571 auxiliary_node_id)).as_slice());
578 let (ident, did) = (item.ident, item.id);
579 debug!("(encoding info for module) ... encoding impl {} \
581 token::get_ident(ident),
582 did, ecx.tcx.map.node_to_string(did));
584 ebml_w.start_tag(tag_mod_impl);
585 ebml_w.wr_str(def_to_string(local_def(did)).as_slice());
592 encode_path(ebml_w, path.clone());
593 encode_visibility(ebml_w, vis);
595 let stab = stability::lookup(ecx.tcx, ast_util::local_def(id));
596 encode_stability(ebml_w, stab);
598 // Encode the reexports of this module, if this module is public.
600 debug!("(encoding info for module) encoding reexports for {}", id);
601 encode_reexports(ecx, ebml_w, id, path);
603 encode_attributes(ebml_w, attrs);
608 fn encode_struct_field_family(ebml_w: &mut Encoder,
609 visibility: Visibility) {
610 encode_family(ebml_w, match visibility {
616 fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
617 ebml_w.start_tag(tag_items_data_item_visibility);
618 let ch = match visibility {
622 ebml_w.wr_str(ch.to_string().as_slice());
626 fn encode_explicit_self(ebml_w: &mut Encoder,
627 explicit_self: &ty::ExplicitSelfCategory) {
628 ebml_w.start_tag(tag_item_trait_method_explicit_self);
630 // Encode the base self type.
631 match *explicit_self {
632 ty::StaticExplicitSelfCategory => {
633 ebml_w.writer.write(&[ 's' as u8 ]);
635 ty::ByValueExplicitSelfCategory => {
636 ebml_w.writer.write(&[ 'v' as u8 ]);
638 ty::ByBoxExplicitSelfCategory => {
639 ebml_w.writer.write(&[ '~' as u8 ]);
641 ty::ByReferenceExplicitSelfCategory(_, m) => {
642 // FIXME(#4846) encode custom lifetime
643 ebml_w.writer.write(&['&' as u8]);
644 encode_mutability(ebml_w, m);
650 fn encode_mutability(ebml_w: &mut Encoder,
651 m: ast::Mutability) {
653 MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
654 MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); }
659 fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
660 ebml_w.start_tag(tag_item_trait_method_sort);
661 ebml_w.writer.write(&[ sort as u8 ]);
665 fn encode_provided_source(ebml_w: &mut Encoder,
666 source_opt: Option<DefId>) {
667 for source in source_opt.iter() {
668 ebml_w.start_tag(tag_item_method_provided_source);
669 let s = def_to_string(*source);
670 ebml_w.writer.write(s.as_bytes());
675 /* Returns an index of items in this class */
676 fn encode_info_for_struct(ecx: &EncodeContext,
677 ebml_w: &mut Encoder,
678 fields: &[ty::field_ty],
679 global_index: &mut Vec<entry<i64>>)
681 /* Each class has its own index, since different classes
682 may have fields with the same name */
683 let mut index = Vec::new();
685 /* We encode both private and public fields -- need to include
686 private fields to get the offsets right */
687 for field in fields.iter() {
689 let id = field.id.node;
691 index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
692 global_index.push(entry {
694 pos: ebml_w.writer.tell().unwrap(),
696 ebml_w.start_tag(tag_items_data_item);
697 debug!("encode_info_for_struct: doing {} {}",
698 token::get_name(nm), id);
699 encode_struct_field_family(ebml_w, field.vis);
700 encode_name(ebml_w, nm);
701 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
702 encode_def_id(ebml_w, local_def(id));
704 let stab = stability::lookup(ecx.tcx, field.id);
705 encode_stability(ebml_w, stab);
712 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
713 ebml_w: &mut Encoder,
716 index: &mut Vec<entry<i64>>,
720 pos: ebml_w.writer.tell().unwrap(),
723 ebml_w.start_tag(tag_items_data_item);
724 encode_def_id(ebml_w, local_def(ctor_id));
725 encode_family(ebml_w, 'f');
726 encode_bounds_and_type(ebml_w, ecx,
727 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
728 encode_name(ebml_w, name.name);
729 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
730 ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
731 encode_parent_item(ebml_w, local_def(struct_id));
733 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
734 encode_symbol(ecx, ebml_w, ctor_id);
737 let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
738 encode_stability(ebml_w, stab);
740 // indicate that this is a tuple struct ctor, because downstream users will normally want
741 // the tuple struct definition, but without this there is no way for them to tell that
742 // they actually have a ctor rather than a normal function
743 ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
749 fn encode_method_ty_fields(ecx: &EncodeContext,
750 ebml_w: &mut Encoder,
751 method_ty: &ty::Method) {
752 encode_def_id(ebml_w, method_ty.def_id);
753 encode_name(ebml_w, method_ty.ident.name);
754 encode_ty_type_param_defs(ebml_w, ecx, &method_ty.generics.types,
755 tag_item_method_tps);
756 encode_method_fty(ecx, ebml_w, &method_ty.fty);
757 encode_visibility(ebml_w, method_ty.vis);
758 encode_explicit_self(ebml_w, &method_ty.explicit_self);
759 let fn_style = method_ty.fty.fn_style;
760 match method_ty.explicit_self {
761 ty::StaticExplicitSelfCategory => {
762 encode_family(ebml_w, fn_style_static_method_family(fn_style));
764 _ => encode_family(ebml_w, style_fn_family(fn_style))
766 encode_provided_source(ebml_w, method_ty.provided_source);
769 fn encode_info_for_method(ecx: &EncodeContext,
770 ebml_w: &mut Encoder,
772 impl_path: PathElems,
773 is_default_impl: bool,
775 ast_method_opt: Option<Gc<Method>>) {
777 debug!("encode_info_for_method: {:?} {}", m.def_id,
778 token::get_ident(m.ident));
779 ebml_w.start_tag(tag_items_data_item);
781 encode_method_ty_fields(ecx, ebml_w, m);
782 encode_parent_item(ebml_w, local_def(parent_id));
784 let stab = stability::lookup(ecx.tcx, m.def_id);
785 encode_stability(ebml_w, stab);
787 // The type for methods gets encoded twice, which is unfortunate.
788 let pty = lookup_item_type(ecx.tcx, m.def_id);
789 encode_bounds_and_type(ebml_w, ecx, &pty);
791 let elem = ast_map::PathName(m.ident.name);
792 encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
793 match ast_method_opt {
794 Some(ast_method) => {
795 encode_attributes(ebml_w, ast_method.attrs.as_slice())
800 for &ast_method in ast_method_opt.iter() {
801 let any_types = !pty.generics.types.is_empty();
802 if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
803 encode_inlined_item(ecx, ebml_w,
804 IIMethodRef(local_def(parent_id), false,
807 encode_symbol(ecx, ebml_w, m.def_id.node);
809 encode_method_argument_names(ebml_w, &*ast_method.pe_fn_decl());
815 fn encode_method_argument_names(ebml_w: &mut Encoder,
816 decl: &ast::FnDecl) {
817 ebml_w.start_tag(tag_method_argument_names);
818 for arg in decl.inputs.iter() {
819 ebml_w.start_tag(tag_method_argument_name);
821 ast::PatIdent(_, ref path1, _) => {
822 let name = token::get_ident(path1.node);
823 ebml_w.writer.write(name.get().as_bytes());
832 fn encode_inlined_item(ecx: &EncodeContext,
833 ebml_w: &mut Encoder,
834 ii: InlinedItemRef) {
835 let mut eii = ecx.encode_inlined_item.borrow_mut();
836 let eii: &mut EncodeInlinedItem = &mut *eii;
837 (*eii)(ecx, ebml_w, ii)
840 fn style_fn_family(s: FnStyle) -> char {
847 fn fn_style_static_method_family(s: FnStyle) -> char {
855 fn should_inline(attrs: &[Attribute]) -> bool {
857 match find_inline_attr(attrs) {
858 InlineNone | InlineNever => false,
859 InlineHint | InlineAlways => true
863 // Encodes the inherent implementations of a structure, enumeration, or trait.
864 fn encode_inherent_implementations(ecx: &EncodeContext,
865 ebml_w: &mut Encoder,
867 match ecx.tcx.inherent_impls.borrow().find(&def_id) {
869 Some(implementations) => {
870 for &impl_def_id in implementations.borrow().iter() {
871 ebml_w.start_tag(tag_items_data_item_inherent_impl);
872 encode_def_id(ebml_w, impl_def_id);
879 // Encodes the implementations of a trait defined in this crate.
880 fn encode_extension_implementations(ecx: &EncodeContext,
881 ebml_w: &mut Encoder,
882 trait_def_id: DefId) {
883 match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
885 Some(implementations) => {
886 for &impl_def_id in implementations.borrow().iter() {
887 ebml_w.start_tag(tag_items_data_item_extension_impl);
888 encode_def_id(ebml_w, impl_def_id);
895 fn encode_stability(ebml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
896 stab_opt.map(|stab| {
897 ebml_w.start_tag(tag_items_data_item_stability);
898 stab.encode(ebml_w).unwrap();
903 fn encode_info_for_item(ecx: &EncodeContext,
904 ebml_w: &mut Encoder,
906 index: &mut Vec<entry<i64>>,
908 vis: ast::Visibility) {
911 fn add_to_index(item: &Item, ebml_w: &Encoder,
912 index: &mut Vec<entry<i64>>) {
915 pos: ebml_w.writer.tell().unwrap(),
919 debug!("encoding info for item at {}",
920 tcx.sess.codemap().span_to_string(item.span));
922 let def_id = local_def(item.id);
923 let stab = stability::lookup(tcx, ast_util::local_def(item.id));
926 ItemStatic(_, m, _) => {
927 add_to_index(item, ebml_w, index);
928 ebml_w.start_tag(tag_items_data_item);
929 encode_def_id(ebml_w, def_id);
930 if m == ast::MutMutable {
931 encode_family(ebml_w, 'b');
933 encode_family(ebml_w, 'c');
935 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
936 encode_symbol(ecx, ebml_w, item.id);
937 encode_name(ebml_w, item.ident.name);
938 encode_path(ebml_w, path);
940 let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
943 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
945 encode_visibility(ebml_w, vis);
946 encode_stability(ebml_w, stab);
949 ItemFn(ref decl, fn_style, _, ref generics, _) => {
950 add_to_index(item, ebml_w, index);
951 ebml_w.start_tag(tag_items_data_item);
952 encode_def_id(ebml_w, def_id);
953 encode_family(ebml_w, style_fn_family(fn_style));
954 let tps_len = generics.ty_params.len();
955 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
956 encode_name(ebml_w, item.ident.name);
957 encode_path(ebml_w, path);
958 encode_attributes(ebml_w, item.attrs.as_slice());
959 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
960 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
962 encode_symbol(ecx, ebml_w, item.id);
964 encode_visibility(ebml_w, vis);
965 encode_stability(ebml_w, stab);
966 encode_method_argument_names(ebml_w, &**decl);
970 add_to_index(item, ebml_w, index);
971 encode_info_for_mod(ecx,
974 item.attrs.as_slice(),
980 ItemForeignMod(ref fm) => {
981 add_to_index(item, ebml_w, index);
982 ebml_w.start_tag(tag_items_data_item);
983 encode_def_id(ebml_w, def_id);
984 encode_family(ebml_w, 'n');
985 encode_name(ebml_w, item.ident.name);
986 encode_path(ebml_w, path);
988 // Encode all the items in this module.
989 for foreign_item in fm.items.iter() {
990 ebml_w.start_tag(tag_mod_child);
991 ebml_w.wr_str(def_to_string(local_def(foreign_item.id)).as_slice());
994 encode_visibility(ebml_w, vis);
995 encode_stability(ebml_w, stab);
999 add_to_index(item, ebml_w, index);
1000 ebml_w.start_tag(tag_items_data_item);
1001 encode_def_id(ebml_w, def_id);
1002 encode_family(ebml_w, 'y');
1003 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1004 encode_name(ebml_w, item.ident.name);
1005 encode_path(ebml_w, path);
1006 encode_visibility(ebml_w, vis);
1007 encode_stability(ebml_w, stab);
1010 ItemEnum(ref enum_definition, ref generics) => {
1011 add_to_index(item, ebml_w, index);
1013 ebml_w.start_tag(tag_items_data_item);
1014 encode_def_id(ebml_w, def_id);
1015 encode_family(ebml_w, 't');
1016 encode_item_variances(ebml_w, ecx, item.id);
1017 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1018 encode_name(ebml_w, item.ident.name);
1019 encode_attributes(ebml_w, item.attrs.as_slice());
1020 for v in (*enum_definition).variants.iter() {
1021 encode_variant_id(ebml_w, local_def(v.node.id));
1023 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1024 encode_path(ebml_w, path);
1026 // Encode inherent implementations for this enumeration.
1027 encode_inherent_implementations(ecx, ebml_w, def_id);
1029 encode_visibility(ebml_w, vis);
1030 encode_stability(ebml_w, stab);
1033 encode_enum_variant_info(ecx,
1036 (*enum_definition).variants.as_slice(),
1040 ItemStruct(struct_def, _) => {
1041 let fields = ty::lookup_struct_fields(tcx, def_id);
1043 /* First, encode the fields
1044 These come first because we need to write them to make
1045 the index, and the index needs to be in the item for the
1047 let idx = encode_info_for_struct(ecx,
1052 /* Index the class*/
1053 add_to_index(item, ebml_w, index);
1055 /* Now, make an item for the class itself */
1056 ebml_w.start_tag(tag_items_data_item);
1057 encode_def_id(ebml_w, def_id);
1058 encode_family(ebml_w, 'S');
1059 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1061 encode_item_variances(ebml_w, ecx, item.id);
1062 encode_name(ebml_w, item.ident.name);
1063 encode_attributes(ebml_w, item.attrs.as_slice());
1064 encode_path(ebml_w, path.clone());
1065 encode_stability(ebml_w, stab);
1066 encode_visibility(ebml_w, vis);
1068 /* Encode def_ids for each field and method
1069 for methods, write all the stuff get_trait_method
1071 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
1073 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1075 // Encode inherent implementations for this structure.
1076 encode_inherent_implementations(ecx, ebml_w, def_id);
1078 /* Each class has its own index -- encode it */
1079 encode_index(ebml_w, idx, write_i64);
1082 // If this is a tuple-like struct, encode the type of the constructor.
1083 match struct_def.ctor_id {
1085 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1086 ctor_id, index, def_id.node);
1091 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1092 // We need to encode information about the default methods we
1093 // have inherited, so we drive this based on the impl structure.
1094 let impl_methods = tcx.impl_methods.borrow();
1095 let methods = impl_methods.get(&def_id);
1097 add_to_index(item, ebml_w, index);
1098 ebml_w.start_tag(tag_items_data_item);
1099 encode_def_id(ebml_w, def_id);
1100 encode_family(ebml_w, 'i');
1101 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1102 encode_name(ebml_w, item.ident.name);
1103 encode_attributes(ebml_w, item.attrs.as_slice());
1105 ast::TyPath(ref path, ref bounds, _) if path.segments
1107 let ident = path.segments.last().unwrap().identifier;
1108 assert!(bounds.is_none());
1109 encode_impl_type_basename(ebml_w, ident);
1113 for &method_def_id in methods.iter() {
1114 ebml_w.start_tag(tag_item_impl_method);
1115 let s = def_to_string(method_def_id);
1116 ebml_w.writer.write(s.as_bytes());
1119 for ast_trait_ref in opt_trait.iter() {
1120 let trait_ref = ty::node_id_to_trait_ref(
1121 tcx, ast_trait_ref.ref_id);
1122 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
1123 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1124 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1126 encode_path(ebml_w, path.clone());
1127 encode_stability(ebml_w, stab);
1130 // Iterate down the methods, emitting them. We rely on the
1131 // assumption that all of the actually implemented methods
1132 // appear first in the impl structure, in the same order they do
1133 // in the ast. This is a little sketchy.
1134 let num_implemented_methods = ast_methods.len();
1135 for (i, &method_def_id) in methods.iter().enumerate() {
1136 let ast_method = if i < num_implemented_methods {
1137 Some(*ast_methods.get(i))
1141 val: method_def_id.node as i64,
1142 pos: ebml_w.writer.tell().unwrap(),
1144 encode_info_for_method(ecx,
1146 &*ty::method(tcx, method_def_id),
1153 ItemTrait(_, _, ref super_traits, ref ms) => {
1154 add_to_index(item, ebml_w, index);
1155 ebml_w.start_tag(tag_items_data_item);
1156 encode_def_id(ebml_w, def_id);
1157 encode_family(ebml_w, 'I');
1158 encode_item_variances(ebml_w, ecx, item.id);
1159 let trait_def = ty::lookup_trait_def(tcx, def_id);
1160 encode_ty_type_param_defs(ebml_w, ecx,
1161 &trait_def.generics.types,
1162 tag_items_data_item_ty_param_bounds);
1163 encode_region_param_defs(ebml_w, &trait_def.generics.regions);
1164 encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1165 encode_name(ebml_w, item.ident.name);
1166 encode_attributes(ebml_w, item.attrs.as_slice());
1167 encode_visibility(ebml_w, vis);
1168 encode_stability(ebml_w, stab);
1169 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1170 ebml_w.start_tag(tag_item_trait_method);
1171 encode_def_id(ebml_w, method_def_id);
1174 ebml_w.start_tag(tag_mod_child);
1175 ebml_w.wr_str(def_to_string(method_def_id).as_slice());
1178 encode_path(ebml_w, path.clone());
1179 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1180 // reading the AST's list, because the former has already filtered out
1181 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1182 for ast_trait_ref in super_traits.iter() {
1183 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1184 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1187 // Encode the implementations of this trait.
1188 encode_extension_implementations(ecx, ebml_w, def_id);
1192 // Now output the method info for each method.
1193 let r = ty::trait_method_def_ids(tcx, def_id);
1194 for (i, &method_def_id) in r.iter().enumerate() {
1195 assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1197 let method_ty = ty::method(tcx, method_def_id);
1200 val: method_def_id.node as i64,
1201 pos: ebml_w.writer.tell().unwrap(),
1204 ebml_w.start_tag(tag_items_data_item);
1206 encode_method_ty_fields(ecx, ebml_w, &*method_ty);
1207 encode_parent_item(ebml_w, def_id);
1209 let stab = stability::lookup(tcx, method_def_id);
1210 encode_stability(ebml_w, stab);
1212 let elem = ast_map::PathName(method_ty.ident.name);
1213 encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1215 match method_ty.explicit_self {
1216 ty::StaticExplicitSelfCategory => {
1217 encode_family(ebml_w,
1218 fn_style_static_method_family(
1219 method_ty.fty.fn_style));
1221 let pty = ty::lookup_item_type(tcx, method_def_id);
1222 encode_bounds_and_type(ebml_w, ecx, &pty);
1226 encode_family(ebml_w,
1228 method_ty.fty.fn_style));
1233 &Required(ref tm) => {
1234 encode_attributes(ebml_w, tm.attrs.as_slice());
1235 encode_method_sort(ebml_w, 'r');
1236 encode_method_argument_names(ebml_w, &*tm.decl);
1240 encode_attributes(ebml_w, m.attrs.as_slice());
1241 // If this is a static method, we've already encoded
1243 if method_ty.explicit_self != ty::StaticExplicitSelfCategory {
1244 // FIXME: I feel like there is something funny going on.
1245 let pty = ty::lookup_item_type(tcx, method_def_id);
1246 encode_bounds_and_type(ebml_w, ecx, &pty);
1248 encode_method_sort(ebml_w, 'p');
1249 encode_inlined_item(ecx, ebml_w,
1250 IIMethodRef(def_id, true, &*m));
1251 encode_method_argument_names(ebml_w, m.pe_fn_decl());
1258 // Encode inherent implementations for this trait.
1259 encode_inherent_implementations(ecx, ebml_w, def_id);
1262 // macros are encoded separately
1267 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1268 ebml_w: &mut Encoder,
1269 nitem: &ForeignItem,
1270 index: &mut Vec<entry<i64>>,
1274 val: nitem.id as i64,
1275 pos: ebml_w.writer.tell().unwrap(),
1278 ebml_w.start_tag(tag_items_data_item);
1279 encode_def_id(ebml_w, local_def(nitem.id));
1281 ForeignItemFn(..) => {
1282 encode_family(ebml_w, style_fn_family(NormalFn));
1283 encode_bounds_and_type(ebml_w, ecx,
1284 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1285 encode_name(ebml_w, nitem.ident.name);
1286 if abi == abi::RustIntrinsic {
1287 encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1289 encode_symbol(ecx, ebml_w, nitem.id);
1292 ForeignItemStatic(_, mutbl) => {
1294 encode_family(ebml_w, 'b');
1296 encode_family(ebml_w, 'c');
1298 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1299 encode_symbol(ecx, ebml_w, nitem.id);
1300 encode_name(ebml_w, nitem.ident.name);
1303 encode_path(ebml_w, path);
1307 fn my_visit_expr(_e: &Expr) { }
1309 fn my_visit_item(i: &Item,
1310 ebml_w: &mut Encoder,
1311 ecx_ptr: *const int,
1312 index: &mut Vec<entry<i64>>) {
1313 let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1315 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1316 ecx.tcx.map.with_path(i.id, |path| {
1317 encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1321 fn my_visit_foreign_item(ni: &ForeignItem,
1322 ebml_w: &mut Encoder,
1324 index: &mut Vec<entry<i64>>) {
1326 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1327 debug!("writing foreign item {}::{}",
1328 ecx.tcx.map.path_to_string(ni.id),
1329 token::get_ident(ni.ident));
1331 let mut ebml_w = unsafe {
1332 ebml_w.unsafe_clone()
1334 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1335 ecx.tcx.map.with_path(ni.id, |path| {
1336 encode_info_for_foreign_item(ecx, &mut ebml_w,
1342 struct EncodeVisitor<'a,'b> {
1343 ebml_w_for_visit_item: &'a mut Encoder<'b>,
1345 index: &'a mut Vec<entry<i64>>,
1348 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1349 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1350 visit::walk_expr(self, ex, ());
1353 fn visit_item(&mut self, i: &Item, _: ()) {
1354 visit::walk_item(self, i, ());
1356 self.ebml_w_for_visit_item,
1360 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1361 visit::walk_foreign_item(self, ni, ());
1362 my_visit_foreign_item(ni,
1363 self.ebml_w_for_visit_item,
1369 fn encode_info_for_items(ecx: &EncodeContext,
1370 ebml_w: &mut Encoder,
1372 -> Vec<entry<i64>> {
1373 let mut index = Vec::new();
1374 ebml_w.start_tag(tag_items_data);
1376 val: CRATE_NODE_ID as i64,
1377 pos: ebml_w.writer.tell().unwrap(),
1379 encode_info_for_mod(ecx,
1384 ast_map::Values([].iter()).chain(None),
1385 syntax::parse::token::special_idents::invalid,
1388 // See comment in `encode_side_tables_for_ii` in astencode
1389 let ecx_ptr: *const int = unsafe { mem::transmute(ecx) };
1390 visit::walk_crate(&mut EncodeVisitor {
1393 ebml_w_for_visit_item: &mut *ebml_w,
1401 // Path and definition ID indexing
1403 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1404 write_fn: |&mut MemWriter, &T|) {
1405 let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1406 for elt in index.move_iter() {
1407 let h = hash::hash(&elt.val) as uint;
1408 buckets.get_mut(h % 256).push(elt);
1411 ebml_w.start_tag(tag_index);
1412 let mut bucket_locs = Vec::new();
1413 ebml_w.start_tag(tag_index_buckets);
1414 for bucket in buckets.iter() {
1415 bucket_locs.push(ebml_w.writer.tell().unwrap());
1416 ebml_w.start_tag(tag_index_buckets_bucket);
1417 for elt in bucket.iter() {
1418 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1419 assert!(elt.pos < 0xffff_ffff);
1421 let wr: &mut MemWriter = ebml_w.writer;
1422 wr.write_be_u32(elt.pos as u32);
1424 write_fn(ebml_w.writer, &elt.val);
1430 ebml_w.start_tag(tag_index_table);
1431 for pos in bucket_locs.iter() {
1432 assert!(*pos < 0xffff_ffff);
1433 let wr: &mut MemWriter = ebml_w.writer;
1434 wr.write_be_u32(*pos as u32);
1440 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1441 let wr: &mut MemWriter = writer;
1442 assert!(n < 0x7fff_ffff);
1443 wr.write_be_u32(n as u32);
1446 fn encode_meta_item(ebml_w: &mut Encoder, mi: Gc<MetaItem>) {
1448 MetaWord(ref name) => {
1449 ebml_w.start_tag(tag_meta_item_word);
1450 ebml_w.start_tag(tag_meta_item_name);
1451 ebml_w.writer.write(name.get().as_bytes());
1455 MetaNameValue(ref name, ref value) => {
1457 LitStr(ref value, _) => {
1458 ebml_w.start_tag(tag_meta_item_name_value);
1459 ebml_w.start_tag(tag_meta_item_name);
1460 ebml_w.writer.write(name.get().as_bytes());
1462 ebml_w.start_tag(tag_meta_item_value);
1463 ebml_w.writer.write(value.get().as_bytes());
1467 _ => {/* FIXME (#623): encode other variants */ }
1470 MetaList(ref name, ref items) => {
1471 ebml_w.start_tag(tag_meta_item_list);
1472 ebml_w.start_tag(tag_meta_item_name);
1473 ebml_w.writer.write(name.get().as_bytes());
1475 for inner_item in items.iter() {
1476 encode_meta_item(ebml_w, *inner_item);
1483 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1484 ebml_w.start_tag(tag_attributes);
1485 for attr in attrs.iter() {
1486 ebml_w.start_tag(tag_attribute);
1487 encode_meta_item(ebml_w, attr.node.value);
1493 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1494 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1495 // Pull the cnums and name,vers,hash out of cstore
1496 let mut deps = Vec::new();
1497 cstore.iter_crate_data(|key, val| {
1498 let dep = decoder::CrateDep {
1500 name: decoder::get_crate_name(val.data()),
1501 hash: decoder::get_crate_hash(val.data()),
1507 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1509 // Sanity-check the crate numbers
1510 let mut expected_cnum = 1;
1511 for n in deps.iter() {
1512 assert_eq!(n.cnum, expected_cnum);
1519 // We're just going to write a list of crate 'name-hash-version's, with
1520 // the assumption that they are numbered 1 to n.
1521 // FIXME (#2166): This is not nearly enough to support correct versioning
1522 // but is enough to get transitive crate dependencies working.
1523 ebml_w.start_tag(tag_crate_deps);
1524 let r = get_ordered_deps(cstore);
1525 for dep in r.iter() {
1526 encode_crate_dep(ebml_w, (*dep).clone());
1531 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1532 ebml_w.start_tag(tag_lang_items);
1534 for (i, def_id) in ecx.tcx.lang_items.items() {
1535 for id in def_id.iter() {
1536 if id.krate == LOCAL_CRATE {
1537 ebml_w.start_tag(tag_lang_items_item);
1539 ebml_w.start_tag(tag_lang_items_item_id);
1541 let wr: &mut MemWriter = ebml_w.writer;
1542 wr.write_be_u32(i as u32);
1544 ebml_w.end_tag(); // tag_lang_items_item_id
1546 ebml_w.start_tag(tag_lang_items_item_node_id);
1548 let wr: &mut MemWriter = ebml_w.writer;
1549 wr.write_be_u32(id.node as u32);
1551 ebml_w.end_tag(); // tag_lang_items_item_node_id
1553 ebml_w.end_tag(); // tag_lang_items_item
1558 for i in ecx.tcx.lang_items.missing.iter() {
1559 ebml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1562 ebml_w.end_tag(); // tag_lang_items
1565 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1566 ebml_w.start_tag(tag_native_libraries);
1568 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1571 cstore::NativeStatic => {} // these libraries are not propagated
1572 cstore::NativeFramework | cstore::NativeUnknown => {
1573 ebml_w.start_tag(tag_native_libraries_lib);
1575 ebml_w.start_tag(tag_native_libraries_kind);
1576 ebml_w.writer.write_be_u32(kind as u32);
1579 ebml_w.start_tag(tag_native_libraries_name);
1580 ebml_w.writer.write(lib.as_bytes());
1591 fn encode_plugin_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1592 match ecx.tcx.sess.plugin_registrar_fn.get() {
1593 Some(id) => { ebml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1598 /// Given a span, write the text of that span into the output stream
1599 /// as an exported macro
1600 fn encode_macro_def(ecx: &EncodeContext,
1601 ebml_w: &mut Encoder,
1602 span: &syntax::codemap::Span) {
1603 let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
1604 .expect("Unable to find source for macro");
1605 ebml_w.start_tag(tag_macro_def);
1606 ebml_w.wr_str(def.as_slice());
1610 /// Serialize the text of the exported macros
1611 fn encode_macro_defs(ecx: &EncodeContext,
1613 ebml_w: &mut Encoder) {
1614 ebml_w.start_tag(tag_exported_macros);
1615 for span in krate.exported_macros.iter() {
1616 encode_macro_def(ecx, ebml_w, span);
1621 struct ImplVisitor<'a,'b,'c> {
1622 ecx: &'a EncodeContext<'b>,
1623 ebml_w: &'a mut Encoder<'c>,
1626 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1627 fn visit_item(&mut self, item: &Item, _: ()) {
1629 ItemImpl(_, Some(ref trait_ref), _, _) => {
1630 let def_map = &self.ecx.tcx.def_map;
1631 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1632 let def_id = trait_def.def_id();
1634 // Load eagerly if this is an implementation of the Drop trait
1635 // or if the trait is not defined in this crate.
1636 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1637 def_id.krate != LOCAL_CRATE {
1638 self.ebml_w.start_tag(tag_impls_impl);
1639 encode_def_id(self.ebml_w, local_def(item.id));
1640 self.ebml_w.end_tag();
1645 visit::walk_item(self, item, ());
1649 /// Encodes implementations that are eagerly loaded.
1651 /// None of this is necessary in theory; we can load all implementations
1652 /// lazily. However, in two cases the optimizations to lazily load
1653 /// implementations are not yet implemented. These two cases, which require us
1654 /// to load implementations eagerly, are:
1656 /// * Destructors (implementations of the Drop trait).
1658 /// * Implementations of traits not defined in this crate.
1659 fn encode_impls<'a>(ecx: &'a EncodeContext,
1661 ebml_w: &'a mut Encoder) {
1662 ebml_w.start_tag(tag_impls);
1665 let mut visitor = ImplVisitor {
1669 visit::walk_crate(&mut visitor, krate, ());
1675 fn encode_misc_info(ecx: &EncodeContext,
1677 ebml_w: &mut Encoder) {
1678 ebml_w.start_tag(tag_misc_info);
1679 ebml_w.start_tag(tag_misc_info_crate_items);
1680 for &item in krate.module.items.iter() {
1681 ebml_w.start_tag(tag_mod_child);
1682 ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
1685 each_auxiliary_node_id(item, |auxiliary_node_id| {
1686 ebml_w.start_tag(tag_mod_child);
1687 ebml_w.wr_str(def_to_string(local_def(
1688 auxiliary_node_id)).as_slice());
1694 // Encode reexports for the root module.
1695 encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1701 fn encode_reachable_extern_fns(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1702 ebml_w.start_tag(tag_reachable_extern_fns);
1704 for id in ecx.reachable.iter() {
1705 match ecx.tcx.map.find(*id) {
1706 Some(ast_map::NodeItem(i)) => {
1708 ast::ItemFn(_, _, abi, _, _) if abi != abi::Rust => {
1709 ebml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1721 fn encode_crate_dep(ebml_w: &mut Encoder,
1722 dep: decoder::CrateDep) {
1723 ebml_w.start_tag(tag_crate_dep);
1724 ebml_w.start_tag(tag_crate_dep_crate_name);
1725 ebml_w.writer.write(dep.name.as_bytes());
1727 ebml_w.start_tag(tag_crate_dep_hash);
1728 ebml_w.writer.write(dep.hash.as_str().as_bytes());
1733 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1734 ebml_w.start_tag(tag_crate_hash);
1735 ebml_w.writer.write(hash.as_str().as_bytes());
1739 fn encode_crate_name(ebml_w: &mut Encoder, crate_name: &str) {
1740 ebml_w.start_tag(tag_crate_crate_name);
1741 ebml_w.writer.write(crate_name.as_bytes());
1745 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1746 ebml_w.start_tag(tag_crate_triple);
1747 ebml_w.writer.write(triple.as_bytes());
1751 fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
1752 ebml_w.start_tag(tag_dylib_dependency_formats);
1753 match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
1755 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1756 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1757 cstore::RequireDynamic => "d",
1758 cstore::RequireStatic => "s",
1760 }).collect::<Vec<String>>();
1761 ebml_w.writer.write(s.connect(",").as_bytes());
1768 // NB: Increment this as you change the metadata encoding version.
1769 pub static metadata_encoding_version : &'static [u8] =
1770 &[0x72, //'r' as u8,
1776 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1777 let mut wr = MemWriter::new();
1778 encode_metadata_inner(&mut wr, parms, krate);
1779 wr.unwrap().move_iter().collect()
1782 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1786 lang_item_bytes: u64,
1787 native_lib_bytes: u64,
1788 plugin_registrar_fn_bytes: u64,
1789 macro_defs_bytes: u64,
1797 let mut stats = Stats {
1801 native_lib_bytes: 0,
1802 plugin_registrar_fn_bytes: 0,
1803 macro_defs_bytes: 0,
1817 encode_inlined_item,
1819 non_inlineable_statics,
1823 let ecx = EncodeContext {
1826 reexports2: reexports2,
1827 item_symbols: item_symbols,
1828 non_inlineable_statics: non_inlineable_statics,
1829 link_meta: link_meta,
1831 encode_inlined_item: RefCell::new(encode_inlined_item),
1832 type_abbrevs: RefCell::new(HashMap::new()),
1833 reachable: reachable,
1836 let mut ebml_w = writer::Encoder::new(wr);
1838 encode_crate_name(&mut ebml_w, ecx.link_meta.crate_name.as_slice());
1839 encode_crate_triple(&mut ebml_w,
1845 encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1846 encode_dylib_dependency_formats(&mut ebml_w, &ecx);
1848 let mut i = ebml_w.writer.tell().unwrap();
1849 encode_attributes(&mut ebml_w, krate.attrs.as_slice());
1850 stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1852 i = ebml_w.writer.tell().unwrap();
1853 encode_crate_deps(&mut ebml_w, ecx.cstore);
1854 stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1856 // Encode the language items.
1857 i = ebml_w.writer.tell().unwrap();
1858 encode_lang_items(&ecx, &mut ebml_w);
1859 stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1861 // Encode the native libraries used
1862 i = ebml_w.writer.tell().unwrap();
1863 encode_native_libraries(&ecx, &mut ebml_w);
1864 stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1866 // Encode the plugin registrar function
1867 i = ebml_w.writer.tell().unwrap();
1868 encode_plugin_registrar_fn(&ecx, &mut ebml_w);
1869 stats.plugin_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1871 // Encode macro definitions
1872 i = ebml_w.writer.tell().unwrap();
1873 encode_macro_defs(&ecx, krate, &mut ebml_w);
1874 stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1876 // Encode the def IDs of impls, for coherence checking.
1877 i = ebml_w.writer.tell().unwrap();
1878 encode_impls(&ecx, krate, &mut ebml_w);
1879 stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1881 // Encode miscellaneous info.
1882 i = ebml_w.writer.tell().unwrap();
1883 encode_misc_info(&ecx, krate, &mut ebml_w);
1884 encode_reachable_extern_fns(&ecx, &mut ebml_w);
1885 stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1887 // Encode and index the items.
1888 ebml_w.start_tag(tag_items);
1889 i = ebml_w.writer.tell().unwrap();
1890 let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1891 stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1893 i = ebml_w.writer.tell().unwrap();
1894 encode_index(&mut ebml_w, items_index, write_i64);
1895 stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1898 stats.total_bytes = ebml_w.writer.tell().unwrap();
1900 if tcx.sess.meta_stats() {
1901 for e in ebml_w.writer.get_ref().iter() {
1903 stats.zero_bytes += 1;
1907 println!("metadata stats:");
1908 println!(" attribute bytes: {}", stats.attr_bytes);
1909 println!(" dep bytes: {}", stats.dep_bytes);
1910 println!(" lang item bytes: {}", stats.lang_item_bytes);
1911 println!(" native bytes: {}", stats.native_lib_bytes);
1912 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
1913 println!(" macro def bytes: {}", stats.macro_defs_bytes);
1914 println!(" impl bytes: {}", stats.impl_bytes);
1915 println!(" misc bytes: {}", stats.misc_bytes);
1916 println!(" item bytes: {}", stats.item_bytes);
1917 println!(" index bytes: {}", stats.index_bytes);
1918 println!(" zero bytes: {}", stats.zero_bytes);
1919 println!(" total bytes: {}", stats.total_bytes);
1923 // Get the encoded string for a type
1924 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> String {
1925 let mut wr = MemWriter::new();
1926 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1927 diag: tcx.sess.diagnostic(),
1930 abbrevs: &RefCell::new(HashMap::new())
1932 String::from_utf8(wr.unwrap()).unwrap()