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;
39 use std::collections::HashMap;
43 use syntax::ast_map::{PathElem, PathElems};
45 use syntax::ast_util::*;
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 == ast::SelfStatic {
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 == ast::SelfStatic {
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(str::from_char(ch).as_slice());
626 fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_) {
627 ebml_w.start_tag(tag_item_trait_method_explicit_self);
629 // Encode the base self type.
630 match explicit_self {
631 SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
632 SelfValue => { ebml_w.writer.write(&[ 'v' as u8 ]); }
633 SelfUniq => { ebml_w.writer.write(&[ '~' as u8 ]); }
634 SelfRegion(_, m) => {
635 // FIXME(#4846) encode custom lifetime
636 ebml_w.writer.write(&['&' as u8]);
637 encode_mutability(ebml_w, m);
643 fn encode_mutability(ebml_w: &mut Encoder,
644 m: ast::Mutability) {
646 MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
647 MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); }
652 fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
653 ebml_w.start_tag(tag_item_trait_method_sort);
654 ebml_w.writer.write(&[ sort as u8 ]);
658 fn encode_provided_source(ebml_w: &mut Encoder,
659 source_opt: Option<DefId>) {
660 for source in source_opt.iter() {
661 ebml_w.start_tag(tag_item_method_provided_source);
662 let s = def_to_string(*source);
663 ebml_w.writer.write(s.as_bytes());
668 /* Returns an index of items in this class */
669 fn encode_info_for_struct(ecx: &EncodeContext,
670 ebml_w: &mut Encoder,
671 fields: &[ty::field_ty],
672 global_index: &mut Vec<entry<i64>>)
674 /* Each class has its own index, since different classes
675 may have fields with the same name */
676 let mut index = Vec::new();
678 /* We encode both private and public fields -- need to include
679 private fields to get the offsets right */
680 for field in fields.iter() {
682 let id = field.id.node;
684 index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
685 global_index.push(entry {
687 pos: ebml_w.writer.tell().unwrap(),
689 ebml_w.start_tag(tag_items_data_item);
690 debug!("encode_info_for_struct: doing {} {}",
691 token::get_name(nm), id);
692 encode_struct_field_family(ebml_w, field.vis);
693 encode_name(ebml_w, nm);
694 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
695 encode_def_id(ebml_w, local_def(id));
701 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
702 ebml_w: &mut Encoder,
705 index: &mut Vec<entry<i64>>,
709 pos: ebml_w.writer.tell().unwrap(),
712 ebml_w.start_tag(tag_items_data_item);
713 encode_def_id(ebml_w, local_def(ctor_id));
714 encode_family(ebml_w, 'f');
715 encode_bounds_and_type(ebml_w, ecx,
716 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
717 encode_name(ebml_w, name.name);
718 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
719 ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
720 encode_parent_item(ebml_w, local_def(struct_id));
722 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
723 encode_symbol(ecx, ebml_w, ctor_id);
726 let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
727 encode_stability(ebml_w, stab);
729 // indicate that this is a tuple struct ctor, because downstream users will normally want
730 // the tuple struct definition, but without this there is no way for them to tell that
731 // they actually have a ctor rather than a normal function
732 ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
738 fn encode_method_ty_fields(ecx: &EncodeContext,
739 ebml_w: &mut Encoder,
740 method_ty: &ty::Method) {
741 encode_def_id(ebml_w, method_ty.def_id);
742 encode_name(ebml_w, method_ty.ident.name);
743 encode_ty_type_param_defs(ebml_w, ecx, &method_ty.generics.types,
744 tag_item_method_tps);
745 encode_method_fty(ecx, ebml_w, &method_ty.fty);
746 encode_visibility(ebml_w, method_ty.vis);
747 encode_explicit_self(ebml_w, method_ty.explicit_self);
748 let fn_style = method_ty.fty.fn_style;
749 match method_ty.explicit_self {
751 encode_family(ebml_w, fn_style_static_method_family(fn_style));
753 _ => encode_family(ebml_w, style_fn_family(fn_style))
755 encode_provided_source(ebml_w, method_ty.provided_source);
758 fn encode_info_for_method(ecx: &EncodeContext,
759 ebml_w: &mut Encoder,
761 impl_path: PathElems,
762 is_default_impl: bool,
764 ast_method_opt: Option<Gc<Method>>) {
766 debug!("encode_info_for_method: {:?} {}", m.def_id,
767 token::get_ident(m.ident));
768 ebml_w.start_tag(tag_items_data_item);
770 encode_method_ty_fields(ecx, ebml_w, m);
771 encode_parent_item(ebml_w, local_def(parent_id));
773 let stab = stability::lookup(ecx.tcx, m.def_id);
774 encode_stability(ebml_w, stab);
776 // The type for methods gets encoded twice, which is unfortunate.
777 let pty = lookup_item_type(ecx.tcx, m.def_id);
778 encode_bounds_and_type(ebml_w, ecx, &pty);
780 let elem = ast_map::PathName(m.ident.name);
781 encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
782 match ast_method_opt {
783 Some(ast_method) => {
784 encode_attributes(ebml_w, ast_method.attrs.as_slice())
789 for &ast_method in ast_method_opt.iter() {
790 let any_types = !pty.generics.types.is_empty();
791 if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
792 encode_inlined_item(ecx, ebml_w,
793 IIMethodRef(local_def(parent_id), false,
796 encode_symbol(ecx, ebml_w, m.def_id.node);
798 encode_method_argument_names(ebml_w, &*ast_method.decl);
804 fn encode_method_argument_names(ebml_w: &mut Encoder,
805 decl: &ast::FnDecl) {
806 ebml_w.start_tag(tag_method_argument_names);
807 for arg in decl.inputs.iter() {
808 ebml_w.start_tag(tag_method_argument_name);
810 ast::PatIdent(_, ref path1, _) => {
811 let name = token::get_ident(path1.node);
812 ebml_w.writer.write(name.get().as_bytes());
821 fn encode_inlined_item(ecx: &EncodeContext,
822 ebml_w: &mut Encoder,
823 ii: InlinedItemRef) {
824 let mut eii = ecx.encode_inlined_item.borrow_mut();
825 let eii: &mut EncodeInlinedItem = &mut *eii;
826 (*eii)(ecx, ebml_w, ii)
829 fn style_fn_family(s: FnStyle) -> char {
836 fn fn_style_static_method_family(s: FnStyle) -> char {
844 fn should_inline(attrs: &[Attribute]) -> bool {
846 match find_inline_attr(attrs) {
847 InlineNone | InlineNever => false,
848 InlineHint | InlineAlways => true
852 // Encodes the inherent implementations of a structure, enumeration, or trait.
853 fn encode_inherent_implementations(ecx: &EncodeContext,
854 ebml_w: &mut Encoder,
856 match ecx.tcx.inherent_impls.borrow().find(&def_id) {
858 Some(implementations) => {
859 for &impl_def_id in implementations.borrow().iter() {
860 ebml_w.start_tag(tag_items_data_item_inherent_impl);
861 encode_def_id(ebml_w, impl_def_id);
868 // Encodes the implementations of a trait defined in this crate.
869 fn encode_extension_implementations(ecx: &EncodeContext,
870 ebml_w: &mut Encoder,
871 trait_def_id: DefId) {
872 match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
874 Some(implementations) => {
875 for &impl_def_id in implementations.borrow().iter() {
876 ebml_w.start_tag(tag_items_data_item_extension_impl);
877 encode_def_id(ebml_w, impl_def_id);
884 fn encode_stability(ebml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
885 stab_opt.map(|stab| {
886 ebml_w.start_tag(tag_items_data_item_stability);
887 stab.encode(ebml_w).unwrap();
892 fn encode_info_for_item(ecx: &EncodeContext,
893 ebml_w: &mut Encoder,
895 index: &mut Vec<entry<i64>>,
897 vis: ast::Visibility) {
900 fn add_to_index(item: &Item, ebml_w: &Encoder,
901 index: &mut Vec<entry<i64>>) {
904 pos: ebml_w.writer.tell().unwrap(),
908 debug!("encoding info for item at {}",
909 tcx.sess.codemap().span_to_string(item.span));
911 let def_id = local_def(item.id);
912 let stab = stability::lookup(tcx, ast_util::local_def(item.id));
915 ItemStatic(_, m, _) => {
916 add_to_index(item, ebml_w, index);
917 ebml_w.start_tag(tag_items_data_item);
918 encode_def_id(ebml_w, def_id);
919 if m == ast::MutMutable {
920 encode_family(ebml_w, 'b');
922 encode_family(ebml_w, 'c');
924 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
925 encode_symbol(ecx, ebml_w, item.id);
926 encode_name(ebml_w, item.ident.name);
927 encode_path(ebml_w, path);
929 let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
932 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
934 encode_visibility(ebml_w, vis);
935 encode_stability(ebml_w, stab);
938 ItemFn(ref decl, fn_style, _, ref generics, _) => {
939 add_to_index(item, ebml_w, index);
940 ebml_w.start_tag(tag_items_data_item);
941 encode_def_id(ebml_w, def_id);
942 encode_family(ebml_w, style_fn_family(fn_style));
943 let tps_len = generics.ty_params.len();
944 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
945 encode_name(ebml_w, item.ident.name);
946 encode_path(ebml_w, path);
947 encode_attributes(ebml_w, item.attrs.as_slice());
948 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
949 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
951 encode_symbol(ecx, ebml_w, item.id);
953 encode_visibility(ebml_w, vis);
954 encode_stability(ebml_w, stab);
955 encode_method_argument_names(ebml_w, &**decl);
959 add_to_index(item, ebml_w, index);
960 encode_info_for_mod(ecx,
963 item.attrs.as_slice(),
969 ItemForeignMod(ref fm) => {
970 add_to_index(item, ebml_w, index);
971 ebml_w.start_tag(tag_items_data_item);
972 encode_def_id(ebml_w, def_id);
973 encode_family(ebml_w, 'n');
974 encode_name(ebml_w, item.ident.name);
975 encode_path(ebml_w, path);
977 // Encode all the items in this module.
978 for foreign_item in fm.items.iter() {
979 ebml_w.start_tag(tag_mod_child);
980 ebml_w.wr_str(def_to_string(local_def(foreign_item.id)).as_slice());
983 encode_visibility(ebml_w, vis);
984 encode_stability(ebml_w, stab);
988 add_to_index(item, ebml_w, index);
989 ebml_w.start_tag(tag_items_data_item);
990 encode_def_id(ebml_w, def_id);
991 encode_family(ebml_w, 'y');
992 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
993 encode_name(ebml_w, item.ident.name);
994 encode_path(ebml_w, path);
995 encode_visibility(ebml_w, vis);
996 encode_stability(ebml_w, stab);
999 ItemEnum(ref enum_definition, ref generics) => {
1000 add_to_index(item, ebml_w, index);
1002 ebml_w.start_tag(tag_items_data_item);
1003 encode_def_id(ebml_w, def_id);
1004 encode_family(ebml_w, 't');
1005 encode_item_variances(ebml_w, ecx, item.id);
1006 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1007 encode_name(ebml_w, item.ident.name);
1008 encode_attributes(ebml_w, item.attrs.as_slice());
1009 for v in (*enum_definition).variants.iter() {
1010 encode_variant_id(ebml_w, local_def(v.node.id));
1012 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1013 encode_path(ebml_w, path);
1015 // Encode inherent implementations for this enumeration.
1016 encode_inherent_implementations(ecx, ebml_w, def_id);
1018 encode_visibility(ebml_w, vis);
1019 encode_stability(ebml_w, stab);
1022 encode_enum_variant_info(ecx,
1025 (*enum_definition).variants.as_slice(),
1029 ItemStruct(struct_def, _) => {
1030 let fields = ty::lookup_struct_fields(tcx, def_id);
1032 /* First, encode the fields
1033 These come first because we need to write them to make
1034 the index, and the index needs to be in the item for the
1036 let idx = encode_info_for_struct(ecx,
1041 /* Index the class*/
1042 add_to_index(item, ebml_w, index);
1044 /* Now, make an item for the class itself */
1045 ebml_w.start_tag(tag_items_data_item);
1046 encode_def_id(ebml_w, def_id);
1047 encode_family(ebml_w, 'S');
1048 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1050 encode_item_variances(ebml_w, ecx, item.id);
1051 encode_name(ebml_w, item.ident.name);
1052 encode_attributes(ebml_w, item.attrs.as_slice());
1053 encode_path(ebml_w, path.clone());
1054 encode_stability(ebml_w, stab);
1055 encode_visibility(ebml_w, vis);
1057 /* Encode def_ids for each field and method
1058 for methods, write all the stuff get_trait_method
1060 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
1062 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1064 // Encode inherent implementations for this structure.
1065 encode_inherent_implementations(ecx, ebml_w, def_id);
1067 /* Each class has its own index -- encode it */
1068 encode_index(ebml_w, idx, write_i64);
1071 // If this is a tuple-like struct, encode the type of the constructor.
1072 match struct_def.ctor_id {
1074 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1075 ctor_id, index, def_id.node);
1080 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1081 // We need to encode information about the default methods we
1082 // have inherited, so we drive this based on the impl structure.
1083 let impl_methods = tcx.impl_methods.borrow();
1084 let methods = impl_methods.get(&def_id);
1086 add_to_index(item, ebml_w, index);
1087 ebml_w.start_tag(tag_items_data_item);
1088 encode_def_id(ebml_w, def_id);
1089 encode_family(ebml_w, 'i');
1090 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1091 encode_name(ebml_w, item.ident.name);
1092 encode_attributes(ebml_w, item.attrs.as_slice());
1094 ast::TyPath(ref path, ref bounds, _) if path.segments
1096 let ident = path.segments.last().unwrap().identifier;
1097 assert!(bounds.is_none());
1098 encode_impl_type_basename(ebml_w, ident);
1102 for &method_def_id in methods.iter() {
1103 ebml_w.start_tag(tag_item_impl_method);
1104 let s = def_to_string(method_def_id);
1105 ebml_w.writer.write(s.as_bytes());
1108 for ast_trait_ref in opt_trait.iter() {
1109 let trait_ref = ty::node_id_to_trait_ref(
1110 tcx, ast_trait_ref.ref_id);
1111 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
1112 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1113 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1115 encode_path(ebml_w, path.clone());
1116 encode_stability(ebml_w, stab);
1119 // Iterate down the methods, emitting them. We rely on the
1120 // assumption that all of the actually implemented methods
1121 // appear first in the impl structure, in the same order they do
1122 // in the ast. This is a little sketchy.
1123 let num_implemented_methods = ast_methods.len();
1124 for (i, &method_def_id) in methods.iter().enumerate() {
1125 let ast_method = if i < num_implemented_methods {
1126 Some(*ast_methods.get(i))
1130 val: method_def_id.node as i64,
1131 pos: ebml_w.writer.tell().unwrap(),
1133 encode_info_for_method(ecx,
1135 &*ty::method(tcx, method_def_id),
1142 ItemTrait(_, _, ref super_traits, ref ms) => {
1143 add_to_index(item, ebml_w, index);
1144 ebml_w.start_tag(tag_items_data_item);
1145 encode_def_id(ebml_w, def_id);
1146 encode_family(ebml_w, 'I');
1147 encode_item_variances(ebml_w, ecx, item.id);
1148 let trait_def = ty::lookup_trait_def(tcx, def_id);
1149 encode_ty_type_param_defs(ebml_w, ecx,
1150 &trait_def.generics.types,
1151 tag_items_data_item_ty_param_bounds);
1152 encode_region_param_defs(ebml_w, &trait_def.generics.regions);
1153 encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1154 encode_name(ebml_w, item.ident.name);
1155 encode_attributes(ebml_w, item.attrs.as_slice());
1156 encode_visibility(ebml_w, vis);
1157 encode_stability(ebml_w, stab);
1158 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1159 ebml_w.start_tag(tag_item_trait_method);
1160 encode_def_id(ebml_w, method_def_id);
1163 ebml_w.start_tag(tag_mod_child);
1164 ebml_w.wr_str(def_to_string(method_def_id).as_slice());
1167 encode_path(ebml_w, path.clone());
1168 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1169 // reading the AST's list, because the former has already filtered out
1170 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1171 for ast_trait_ref in super_traits.iter() {
1172 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1173 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1176 // Encode the implementations of this trait.
1177 encode_extension_implementations(ecx, ebml_w, def_id);
1181 // Now output the method info for each method.
1182 let r = ty::trait_method_def_ids(tcx, def_id);
1183 for (i, &method_def_id) in r.iter().enumerate() {
1184 assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1186 let method_ty = ty::method(tcx, method_def_id);
1189 val: method_def_id.node as i64,
1190 pos: ebml_w.writer.tell().unwrap(),
1193 ebml_w.start_tag(tag_items_data_item);
1195 encode_method_ty_fields(ecx, ebml_w, &*method_ty);
1196 encode_parent_item(ebml_w, def_id);
1198 let stab = stability::lookup(tcx, method_def_id);
1199 encode_stability(ebml_w, stab);
1201 let elem = ast_map::PathName(method_ty.ident.name);
1202 encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1204 match method_ty.explicit_self {
1206 encode_family(ebml_w,
1207 fn_style_static_method_family(
1208 method_ty.fty.fn_style));
1210 let pty = ty::lookup_item_type(tcx, method_def_id);
1211 encode_bounds_and_type(ebml_w, ecx, &pty);
1215 encode_family(ebml_w,
1217 method_ty.fty.fn_style));
1222 &Required(ref tm) => {
1223 encode_attributes(ebml_w, tm.attrs.as_slice());
1224 encode_method_sort(ebml_w, 'r');
1225 encode_method_argument_names(ebml_w, &*tm.decl);
1229 encode_attributes(ebml_w, m.attrs.as_slice());
1230 // If this is a static method, we've already encoded
1232 if method_ty.explicit_self != SelfStatic {
1233 // FIXME: I feel like there is something funny going on.
1234 let pty = ty::lookup_item_type(tcx, method_def_id);
1235 encode_bounds_and_type(ebml_w, ecx, &pty);
1237 encode_method_sort(ebml_w, 'p');
1238 encode_inlined_item(ecx, ebml_w,
1239 IIMethodRef(def_id, true, &*m));
1240 encode_method_argument_names(ebml_w, &*m.decl);
1247 // Encode inherent implementations for this trait.
1248 encode_inherent_implementations(ecx, ebml_w, def_id);
1251 // macros are encoded separately
1256 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1257 ebml_w: &mut Encoder,
1258 nitem: &ForeignItem,
1259 index: &mut Vec<entry<i64>>,
1263 val: nitem.id as i64,
1264 pos: ebml_w.writer.tell().unwrap(),
1267 ebml_w.start_tag(tag_items_data_item);
1268 encode_def_id(ebml_w, local_def(nitem.id));
1270 ForeignItemFn(..) => {
1271 encode_family(ebml_w, style_fn_family(NormalFn));
1272 encode_bounds_and_type(ebml_w, ecx,
1273 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1274 encode_name(ebml_w, nitem.ident.name);
1275 if abi == abi::RustIntrinsic {
1276 encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1278 encode_symbol(ecx, ebml_w, nitem.id);
1281 ForeignItemStatic(_, mutbl) => {
1283 encode_family(ebml_w, 'b');
1285 encode_family(ebml_w, 'c');
1287 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1288 encode_symbol(ecx, ebml_w, nitem.id);
1289 encode_name(ebml_w, nitem.ident.name);
1292 encode_path(ebml_w, path);
1296 fn my_visit_expr(_e: &Expr) { }
1298 fn my_visit_item(i: &Item,
1299 ebml_w: &mut Encoder,
1300 ecx_ptr: *const int,
1301 index: &mut Vec<entry<i64>>) {
1302 let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1304 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1305 ecx.tcx.map.with_path(i.id, |path| {
1306 encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1310 fn my_visit_foreign_item(ni: &ForeignItem,
1311 ebml_w: &mut Encoder,
1313 index: &mut Vec<entry<i64>>) {
1315 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1316 debug!("writing foreign item {}::{}",
1317 ecx.tcx.map.path_to_string(ni.id),
1318 token::get_ident(ni.ident));
1320 let mut ebml_w = unsafe {
1321 ebml_w.unsafe_clone()
1323 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1324 ecx.tcx.map.with_path(ni.id, |path| {
1325 encode_info_for_foreign_item(ecx, &mut ebml_w,
1331 struct EncodeVisitor<'a,'b> {
1332 ebml_w_for_visit_item: &'a mut Encoder<'b>,
1334 index: &'a mut Vec<entry<i64>>,
1337 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1338 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1339 visit::walk_expr(self, ex, ());
1342 fn visit_item(&mut self, i: &Item, _: ()) {
1343 visit::walk_item(self, i, ());
1345 self.ebml_w_for_visit_item,
1349 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1350 visit::walk_foreign_item(self, ni, ());
1351 my_visit_foreign_item(ni,
1352 self.ebml_w_for_visit_item,
1358 fn encode_info_for_items(ecx: &EncodeContext,
1359 ebml_w: &mut Encoder,
1361 -> Vec<entry<i64>> {
1362 let mut index = Vec::new();
1363 ebml_w.start_tag(tag_items_data);
1365 val: CRATE_NODE_ID as i64,
1366 pos: ebml_w.writer.tell().unwrap(),
1368 encode_info_for_mod(ecx,
1373 ast_map::Values([].iter()).chain(None),
1374 syntax::parse::token::special_idents::invalid,
1377 // See comment in `encode_side_tables_for_ii` in astencode
1378 let ecx_ptr: *const int = unsafe { mem::transmute(ecx) };
1379 visit::walk_crate(&mut EncodeVisitor {
1382 ebml_w_for_visit_item: &mut *ebml_w,
1390 // Path and definition ID indexing
1392 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1393 write_fn: |&mut MemWriter, &T|) {
1394 let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1395 for elt in index.move_iter() {
1396 let h = hash::hash(&elt.val) as uint;
1397 buckets.get_mut(h % 256).push(elt);
1400 ebml_w.start_tag(tag_index);
1401 let mut bucket_locs = Vec::new();
1402 ebml_w.start_tag(tag_index_buckets);
1403 for bucket in buckets.iter() {
1404 bucket_locs.push(ebml_w.writer.tell().unwrap());
1405 ebml_w.start_tag(tag_index_buckets_bucket);
1406 for elt in bucket.iter() {
1407 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1408 assert!(elt.pos < 0xffff_ffff);
1410 let wr: &mut MemWriter = ebml_w.writer;
1411 wr.write_be_u32(elt.pos as u32);
1413 write_fn(ebml_w.writer, &elt.val);
1419 ebml_w.start_tag(tag_index_table);
1420 for pos in bucket_locs.iter() {
1421 assert!(*pos < 0xffff_ffff);
1422 let wr: &mut MemWriter = ebml_w.writer;
1423 wr.write_be_u32(*pos as u32);
1429 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1430 let wr: &mut MemWriter = writer;
1431 assert!(n < 0x7fff_ffff);
1432 wr.write_be_u32(n as u32);
1435 fn encode_meta_item(ebml_w: &mut Encoder, mi: Gc<MetaItem>) {
1437 MetaWord(ref name) => {
1438 ebml_w.start_tag(tag_meta_item_word);
1439 ebml_w.start_tag(tag_meta_item_name);
1440 ebml_w.writer.write(name.get().as_bytes());
1444 MetaNameValue(ref name, ref value) => {
1446 LitStr(ref value, _) => {
1447 ebml_w.start_tag(tag_meta_item_name_value);
1448 ebml_w.start_tag(tag_meta_item_name);
1449 ebml_w.writer.write(name.get().as_bytes());
1451 ebml_w.start_tag(tag_meta_item_value);
1452 ebml_w.writer.write(value.get().as_bytes());
1456 _ => {/* FIXME (#623): encode other variants */ }
1459 MetaList(ref name, ref items) => {
1460 ebml_w.start_tag(tag_meta_item_list);
1461 ebml_w.start_tag(tag_meta_item_name);
1462 ebml_w.writer.write(name.get().as_bytes());
1464 for inner_item in items.iter() {
1465 encode_meta_item(ebml_w, *inner_item);
1472 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1473 ebml_w.start_tag(tag_attributes);
1474 for attr in attrs.iter() {
1475 ebml_w.start_tag(tag_attribute);
1476 encode_meta_item(ebml_w, attr.node.value);
1482 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1483 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1484 // Pull the cnums and name,vers,hash out of cstore
1485 let mut deps = Vec::new();
1486 cstore.iter_crate_data(|key, val| {
1487 let dep = decoder::CrateDep {
1489 name: decoder::get_crate_name(val.data()),
1490 hash: decoder::get_crate_hash(val.data()),
1496 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1498 // Sanity-check the crate numbers
1499 let mut expected_cnum = 1;
1500 for n in deps.iter() {
1501 assert_eq!(n.cnum, expected_cnum);
1508 // We're just going to write a list of crate 'name-hash-version's, with
1509 // the assumption that they are numbered 1 to n.
1510 // FIXME (#2166): This is not nearly enough to support correct versioning
1511 // but is enough to get transitive crate dependencies working.
1512 ebml_w.start_tag(tag_crate_deps);
1513 let r = get_ordered_deps(cstore);
1514 for dep in r.iter() {
1515 encode_crate_dep(ebml_w, (*dep).clone());
1520 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1521 ebml_w.start_tag(tag_lang_items);
1523 for (i, def_id) in ecx.tcx.lang_items.items() {
1524 for id in def_id.iter() {
1525 if id.krate == LOCAL_CRATE {
1526 ebml_w.start_tag(tag_lang_items_item);
1528 ebml_w.start_tag(tag_lang_items_item_id);
1530 let wr: &mut MemWriter = ebml_w.writer;
1531 wr.write_be_u32(i as u32);
1533 ebml_w.end_tag(); // tag_lang_items_item_id
1535 ebml_w.start_tag(tag_lang_items_item_node_id);
1537 let wr: &mut MemWriter = ebml_w.writer;
1538 wr.write_be_u32(id.node as u32);
1540 ebml_w.end_tag(); // tag_lang_items_item_node_id
1542 ebml_w.end_tag(); // tag_lang_items_item
1547 for i in ecx.tcx.lang_items.missing.iter() {
1548 ebml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1551 ebml_w.end_tag(); // tag_lang_items
1554 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1555 ebml_w.start_tag(tag_native_libraries);
1557 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1560 cstore::NativeStatic => {} // these libraries are not propagated
1561 cstore::NativeFramework | cstore::NativeUnknown => {
1562 ebml_w.start_tag(tag_native_libraries_lib);
1564 ebml_w.start_tag(tag_native_libraries_kind);
1565 ebml_w.writer.write_be_u32(kind as u32);
1568 ebml_w.start_tag(tag_native_libraries_name);
1569 ebml_w.writer.write(lib.as_bytes());
1580 fn encode_plugin_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1581 match ecx.tcx.sess.plugin_registrar_fn.get() {
1582 Some(id) => { ebml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1587 struct MacroDefVisitor<'a, 'b, 'c> {
1588 ecx: &'a EncodeContext<'b>,
1589 ebml_w: &'a mut Encoder<'c>
1592 impl<'a, 'b, 'c> Visitor<()> for MacroDefVisitor<'a, 'b, 'c> {
1593 fn visit_item(&mut self, item: &Item, _: ()) {
1596 let def = self.ecx.tcx.sess.codemap().span_to_snippet(item.span)
1597 .expect("Unable to find source for macro");
1598 self.ebml_w.start_tag(tag_macro_def);
1599 self.ebml_w.wr_str(def.as_slice());
1600 self.ebml_w.end_tag();
1604 visit::walk_item(self, item, ());
1608 fn encode_macro_defs<'a>(ecx: &'a EncodeContext,
1610 ebml_w: &'a mut Encoder) {
1611 ebml_w.start_tag(tag_exported_macros);
1613 let mut visitor = MacroDefVisitor {
1617 visit::walk_crate(&mut visitor, krate, ());
1622 struct ImplVisitor<'a,'b,'c> {
1623 ecx: &'a EncodeContext<'b>,
1624 ebml_w: &'a mut Encoder<'c>,
1627 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1628 fn visit_item(&mut self, item: &Item, _: ()) {
1630 ItemImpl(_, Some(ref trait_ref), _, _) => {
1631 let def_map = &self.ecx.tcx.def_map;
1632 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1633 let def_id = trait_def.def_id();
1635 // Load eagerly if this is an implementation of the Drop trait
1636 // or if the trait is not defined in this crate.
1637 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1638 def_id.krate != LOCAL_CRATE {
1639 self.ebml_w.start_tag(tag_impls_impl);
1640 encode_def_id(self.ebml_w, local_def(item.id));
1641 self.ebml_w.end_tag();
1646 visit::walk_item(self, item, ());
1650 /// Encodes implementations that are eagerly loaded.
1652 /// None of this is necessary in theory; we can load all implementations
1653 /// lazily. However, in two cases the optimizations to lazily load
1654 /// implementations are not yet implemented. These two cases, which require us
1655 /// to load implementations eagerly, are:
1657 /// * Destructors (implementations of the Drop trait).
1659 /// * Implementations of traits not defined in this crate.
1660 fn encode_impls<'a>(ecx: &'a EncodeContext,
1662 ebml_w: &'a mut Encoder) {
1663 ebml_w.start_tag(tag_impls);
1666 let mut visitor = ImplVisitor {
1670 visit::walk_crate(&mut visitor, krate, ());
1676 fn encode_misc_info(ecx: &EncodeContext,
1678 ebml_w: &mut Encoder) {
1679 ebml_w.start_tag(tag_misc_info);
1680 ebml_w.start_tag(tag_misc_info_crate_items);
1681 for &item in krate.module.items.iter() {
1682 ebml_w.start_tag(tag_mod_child);
1683 ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
1686 each_auxiliary_node_id(item, |auxiliary_node_id| {
1687 ebml_w.start_tag(tag_mod_child);
1688 ebml_w.wr_str(def_to_string(local_def(
1689 auxiliary_node_id)).as_slice());
1695 // Encode reexports for the root module.
1696 encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1702 fn encode_reachable_extern_fns(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1703 ebml_w.start_tag(tag_reachable_extern_fns);
1705 for id in ecx.reachable.iter() {
1706 match ecx.tcx.map.find(*id) {
1707 Some(ast_map::NodeItem(i)) => {
1709 ast::ItemFn(_, _, abi, _, _) if abi != abi::Rust => {
1710 ebml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1722 fn encode_crate_dep(ebml_w: &mut Encoder,
1723 dep: decoder::CrateDep) {
1724 ebml_w.start_tag(tag_crate_dep);
1725 ebml_w.start_tag(tag_crate_dep_crate_name);
1726 ebml_w.writer.write(dep.name.as_bytes());
1728 ebml_w.start_tag(tag_crate_dep_hash);
1729 ebml_w.writer.write(dep.hash.as_str().as_bytes());
1734 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1735 ebml_w.start_tag(tag_crate_hash);
1736 ebml_w.writer.write(hash.as_str().as_bytes());
1740 fn encode_crate_name(ebml_w: &mut Encoder, crate_name: &str) {
1741 ebml_w.start_tag(tag_crate_crate_name);
1742 ebml_w.writer.write(crate_name.as_bytes());
1746 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1747 ebml_w.start_tag(tag_crate_triple);
1748 ebml_w.writer.write(triple.as_bytes());
1752 fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
1753 ebml_w.start_tag(tag_dylib_dependency_formats);
1754 match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
1756 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1757 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1758 cstore::RequireDynamic => "d",
1759 cstore::RequireStatic => "s",
1761 }).collect::<Vec<String>>();
1762 ebml_w.writer.write(s.connect(",").as_bytes());
1769 // NB: Increment this as you change the metadata encoding version.
1770 pub static metadata_encoding_version : &'static [u8] =
1771 &[0x72, //'r' as u8,
1777 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1778 let mut wr = MemWriter::new();
1779 encode_metadata_inner(&mut wr, parms, krate);
1780 wr.unwrap().move_iter().collect()
1783 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1787 lang_item_bytes: u64,
1788 native_lib_bytes: u64,
1789 plugin_registrar_fn_bytes: u64,
1790 macro_defs_bytes: u64,
1798 let mut stats = Stats {
1802 native_lib_bytes: 0,
1803 plugin_registrar_fn_bytes: 0,
1804 macro_defs_bytes: 0,
1818 encode_inlined_item,
1820 non_inlineable_statics,
1824 let ecx = EncodeContext {
1827 reexports2: reexports2,
1828 item_symbols: item_symbols,
1829 non_inlineable_statics: non_inlineable_statics,
1830 link_meta: link_meta,
1832 encode_inlined_item: RefCell::new(encode_inlined_item),
1833 type_abbrevs: RefCell::new(HashMap::new()),
1834 reachable: reachable,
1837 let mut ebml_w = writer::Encoder::new(wr);
1839 encode_crate_name(&mut ebml_w, ecx.link_meta.crate_name.as_slice());
1840 encode_crate_triple(&mut ebml_w,
1846 encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1847 encode_dylib_dependency_formats(&mut ebml_w, &ecx);
1849 let mut i = ebml_w.writer.tell().unwrap();
1850 encode_attributes(&mut ebml_w, krate.attrs.as_slice());
1851 stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1853 i = ebml_w.writer.tell().unwrap();
1854 encode_crate_deps(&mut ebml_w, ecx.cstore);
1855 stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1857 // Encode the language items.
1858 i = ebml_w.writer.tell().unwrap();
1859 encode_lang_items(&ecx, &mut ebml_w);
1860 stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1862 // Encode the native libraries used
1863 i = ebml_w.writer.tell().unwrap();
1864 encode_native_libraries(&ecx, &mut ebml_w);
1865 stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1867 // Encode the plugin registrar function
1868 i = ebml_w.writer.tell().unwrap();
1869 encode_plugin_registrar_fn(&ecx, &mut ebml_w);
1870 stats.plugin_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1872 // Encode macro definitions
1873 i = ebml_w.writer.tell().unwrap();
1874 encode_macro_defs(&ecx, krate, &mut ebml_w);
1875 stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1877 // Encode the def IDs of impls, for coherence checking.
1878 i = ebml_w.writer.tell().unwrap();
1879 encode_impls(&ecx, krate, &mut ebml_w);
1880 stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1882 // Encode miscellaneous info.
1883 i = ebml_w.writer.tell().unwrap();
1884 encode_misc_info(&ecx, krate, &mut ebml_w);
1885 encode_reachable_extern_fns(&ecx, &mut ebml_w);
1886 stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1888 // Encode and index the items.
1889 ebml_w.start_tag(tag_items);
1890 i = ebml_w.writer.tell().unwrap();
1891 let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1892 stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1894 i = ebml_w.writer.tell().unwrap();
1895 encode_index(&mut ebml_w, items_index, write_i64);
1896 stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1899 stats.total_bytes = ebml_w.writer.tell().unwrap();
1901 if tcx.sess.meta_stats() {
1902 for e in ebml_w.writer.get_ref().iter() {
1904 stats.zero_bytes += 1;
1908 println!("metadata stats:");
1909 println!(" attribute bytes: {}", stats.attr_bytes);
1910 println!(" dep bytes: {}", stats.dep_bytes);
1911 println!(" lang item bytes: {}", stats.lang_item_bytes);
1912 println!(" native bytes: {}", stats.native_lib_bytes);
1913 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
1914 println!(" macro def bytes: {}", stats.macro_defs_bytes);
1915 println!(" impl bytes: {}", stats.impl_bytes);
1916 println!(" misc bytes: {}", stats.misc_bytes);
1917 println!(" item bytes: {}", stats.item_bytes);
1918 println!(" index bytes: {}", stats.index_bytes);
1919 println!(" zero bytes: {}", stats.zero_bytes);
1920 println!(" total bytes: {}", stats.total_bytes);
1924 // Get the encoded string for a type
1925 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> String {
1926 let mut wr = MemWriter::new();
1927 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1928 diag: tcx.sess.diagnostic(),
1931 abbrevs: &RefCell::new(HashMap::new())
1933 str::from_utf8_owned(Vec::from_slice(wr.get_ref())).unwrap().to_string()