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));
697 let stab = stability::lookup(ecx.tcx, field.id);
698 encode_stability(ebml_w, stab);
705 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
706 ebml_w: &mut Encoder,
709 index: &mut Vec<entry<i64>>,
713 pos: ebml_w.writer.tell().unwrap(),
716 ebml_w.start_tag(tag_items_data_item);
717 encode_def_id(ebml_w, local_def(ctor_id));
718 encode_family(ebml_w, 'f');
719 encode_bounds_and_type(ebml_w, ecx,
720 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
721 encode_name(ebml_w, name.name);
722 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
723 ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
724 encode_parent_item(ebml_w, local_def(struct_id));
726 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
727 encode_symbol(ecx, ebml_w, ctor_id);
730 let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
731 encode_stability(ebml_w, stab);
733 // indicate that this is a tuple struct ctor, because downstream users will normally want
734 // the tuple struct definition, but without this there is no way for them to tell that
735 // they actually have a ctor rather than a normal function
736 ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
742 fn encode_method_ty_fields(ecx: &EncodeContext,
743 ebml_w: &mut Encoder,
744 method_ty: &ty::Method) {
745 encode_def_id(ebml_w, method_ty.def_id);
746 encode_name(ebml_w, method_ty.ident.name);
747 encode_ty_type_param_defs(ebml_w, ecx, &method_ty.generics.types,
748 tag_item_method_tps);
749 encode_method_fty(ecx, ebml_w, &method_ty.fty);
750 encode_visibility(ebml_w, method_ty.vis);
751 encode_explicit_self(ebml_w, method_ty.explicit_self);
752 let fn_style = method_ty.fty.fn_style;
753 match method_ty.explicit_self {
755 encode_family(ebml_w, fn_style_static_method_family(fn_style));
757 _ => encode_family(ebml_w, style_fn_family(fn_style))
759 encode_provided_source(ebml_w, method_ty.provided_source);
762 fn encode_info_for_method(ecx: &EncodeContext,
763 ebml_w: &mut Encoder,
765 impl_path: PathElems,
766 is_default_impl: bool,
768 ast_method_opt: Option<Gc<Method>>) {
770 debug!("encode_info_for_method: {:?} {}", m.def_id,
771 token::get_ident(m.ident));
772 ebml_w.start_tag(tag_items_data_item);
774 encode_method_ty_fields(ecx, ebml_w, m);
775 encode_parent_item(ebml_w, local_def(parent_id));
777 let stab = stability::lookup(ecx.tcx, m.def_id);
778 encode_stability(ebml_w, stab);
780 // The type for methods gets encoded twice, which is unfortunate.
781 let pty = lookup_item_type(ecx.tcx, m.def_id);
782 encode_bounds_and_type(ebml_w, ecx, &pty);
784 let elem = ast_map::PathName(m.ident.name);
785 encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
786 match ast_method_opt {
787 Some(ast_method) => {
788 encode_attributes(ebml_w, ast_method.attrs.as_slice())
793 for &ast_method in ast_method_opt.iter() {
794 let any_types = !pty.generics.types.is_empty();
795 if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
796 encode_inlined_item(ecx, ebml_w,
797 IIMethodRef(local_def(parent_id), false,
800 encode_symbol(ecx, ebml_w, m.def_id.node);
802 encode_method_argument_names(ebml_w, method_fn_decl(&*ast_method));
808 fn encode_method_argument_names(ebml_w: &mut Encoder,
809 decl: &ast::FnDecl) {
810 ebml_w.start_tag(tag_method_argument_names);
811 for arg in decl.inputs.iter() {
812 ebml_w.start_tag(tag_method_argument_name);
814 ast::PatIdent(_, ref path1, _) => {
815 let name = token::get_ident(path1.node);
816 ebml_w.writer.write(name.get().as_bytes());
825 fn encode_inlined_item(ecx: &EncodeContext,
826 ebml_w: &mut Encoder,
827 ii: InlinedItemRef) {
828 let mut eii = ecx.encode_inlined_item.borrow_mut();
829 let eii: &mut EncodeInlinedItem = &mut *eii;
830 (*eii)(ecx, ebml_w, ii)
833 fn style_fn_family(s: FnStyle) -> char {
840 fn fn_style_static_method_family(s: FnStyle) -> char {
848 fn should_inline(attrs: &[Attribute]) -> bool {
850 match find_inline_attr(attrs) {
851 InlineNone | InlineNever => false,
852 InlineHint | InlineAlways => true
856 // Encodes the inherent implementations of a structure, enumeration, or trait.
857 fn encode_inherent_implementations(ecx: &EncodeContext,
858 ebml_w: &mut Encoder,
860 match ecx.tcx.inherent_impls.borrow().find(&def_id) {
862 Some(implementations) => {
863 for &impl_def_id in implementations.borrow().iter() {
864 ebml_w.start_tag(tag_items_data_item_inherent_impl);
865 encode_def_id(ebml_w, impl_def_id);
872 // Encodes the implementations of a trait defined in this crate.
873 fn encode_extension_implementations(ecx: &EncodeContext,
874 ebml_w: &mut Encoder,
875 trait_def_id: DefId) {
876 match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
878 Some(implementations) => {
879 for &impl_def_id in implementations.borrow().iter() {
880 ebml_w.start_tag(tag_items_data_item_extension_impl);
881 encode_def_id(ebml_w, impl_def_id);
888 fn encode_stability(ebml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
889 stab_opt.map(|stab| {
890 ebml_w.start_tag(tag_items_data_item_stability);
891 stab.encode(ebml_w).unwrap();
896 fn encode_info_for_item(ecx: &EncodeContext,
897 ebml_w: &mut Encoder,
899 index: &mut Vec<entry<i64>>,
901 vis: ast::Visibility) {
904 fn add_to_index(item: &Item, ebml_w: &Encoder,
905 index: &mut Vec<entry<i64>>) {
908 pos: ebml_w.writer.tell().unwrap(),
912 debug!("encoding info for item at {}",
913 tcx.sess.codemap().span_to_string(item.span));
915 let def_id = local_def(item.id);
916 let stab = stability::lookup(tcx, ast_util::local_def(item.id));
919 ItemStatic(_, m, _) => {
920 add_to_index(item, ebml_w, index);
921 ebml_w.start_tag(tag_items_data_item);
922 encode_def_id(ebml_w, def_id);
923 if m == ast::MutMutable {
924 encode_family(ebml_w, 'b');
926 encode_family(ebml_w, 'c');
928 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
929 encode_symbol(ecx, ebml_w, item.id);
930 encode_name(ebml_w, item.ident.name);
931 encode_path(ebml_w, path);
933 let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
936 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
938 encode_visibility(ebml_w, vis);
939 encode_stability(ebml_w, stab);
942 ItemFn(ref decl, fn_style, _, ref generics, _) => {
943 add_to_index(item, ebml_w, index);
944 ebml_w.start_tag(tag_items_data_item);
945 encode_def_id(ebml_w, def_id);
946 encode_family(ebml_w, style_fn_family(fn_style));
947 let tps_len = generics.ty_params.len();
948 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
949 encode_name(ebml_w, item.ident.name);
950 encode_path(ebml_w, path);
951 encode_attributes(ebml_w, item.attrs.as_slice());
952 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
953 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
955 encode_symbol(ecx, ebml_w, item.id);
957 encode_visibility(ebml_w, vis);
958 encode_stability(ebml_w, stab);
959 encode_method_argument_names(ebml_w, &**decl);
963 add_to_index(item, ebml_w, index);
964 encode_info_for_mod(ecx,
967 item.attrs.as_slice(),
973 ItemForeignMod(ref fm) => {
974 add_to_index(item, ebml_w, index);
975 ebml_w.start_tag(tag_items_data_item);
976 encode_def_id(ebml_w, def_id);
977 encode_family(ebml_w, 'n');
978 encode_name(ebml_w, item.ident.name);
979 encode_path(ebml_w, path);
981 // Encode all the items in this module.
982 for foreign_item in fm.items.iter() {
983 ebml_w.start_tag(tag_mod_child);
984 ebml_w.wr_str(def_to_string(local_def(foreign_item.id)).as_slice());
987 encode_visibility(ebml_w, vis);
988 encode_stability(ebml_w, stab);
992 add_to_index(item, ebml_w, index);
993 ebml_w.start_tag(tag_items_data_item);
994 encode_def_id(ebml_w, def_id);
995 encode_family(ebml_w, 'y');
996 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
997 encode_name(ebml_w, item.ident.name);
998 encode_path(ebml_w, path);
999 encode_visibility(ebml_w, vis);
1000 encode_stability(ebml_w, stab);
1003 ItemEnum(ref enum_definition, ref generics) => {
1004 add_to_index(item, ebml_w, index);
1006 ebml_w.start_tag(tag_items_data_item);
1007 encode_def_id(ebml_w, def_id);
1008 encode_family(ebml_w, 't');
1009 encode_item_variances(ebml_w, ecx, item.id);
1010 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1011 encode_name(ebml_w, item.ident.name);
1012 encode_attributes(ebml_w, item.attrs.as_slice());
1013 for v in (*enum_definition).variants.iter() {
1014 encode_variant_id(ebml_w, local_def(v.node.id));
1016 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1017 encode_path(ebml_w, path);
1019 // Encode inherent implementations for this enumeration.
1020 encode_inherent_implementations(ecx, ebml_w, def_id);
1022 encode_visibility(ebml_w, vis);
1023 encode_stability(ebml_w, stab);
1026 encode_enum_variant_info(ecx,
1029 (*enum_definition).variants.as_slice(),
1033 ItemStruct(struct_def, _) => {
1034 let fields = ty::lookup_struct_fields(tcx, def_id);
1036 /* First, encode the fields
1037 These come first because we need to write them to make
1038 the index, and the index needs to be in the item for the
1040 let idx = encode_info_for_struct(ecx,
1045 /* Index the class*/
1046 add_to_index(item, ebml_w, index);
1048 /* Now, make an item for the class itself */
1049 ebml_w.start_tag(tag_items_data_item);
1050 encode_def_id(ebml_w, def_id);
1051 encode_family(ebml_w, 'S');
1052 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1054 encode_item_variances(ebml_w, ecx, item.id);
1055 encode_name(ebml_w, item.ident.name);
1056 encode_attributes(ebml_w, item.attrs.as_slice());
1057 encode_path(ebml_w, path.clone());
1058 encode_stability(ebml_w, stab);
1059 encode_visibility(ebml_w, vis);
1061 /* Encode def_ids for each field and method
1062 for methods, write all the stuff get_trait_method
1064 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
1066 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1068 // Encode inherent implementations for this structure.
1069 encode_inherent_implementations(ecx, ebml_w, def_id);
1071 /* Each class has its own index -- encode it */
1072 encode_index(ebml_w, idx, write_i64);
1075 // If this is a tuple-like struct, encode the type of the constructor.
1076 match struct_def.ctor_id {
1078 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1079 ctor_id, index, def_id.node);
1084 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1085 // We need to encode information about the default methods we
1086 // have inherited, so we drive this based on the impl structure.
1087 let impl_methods = tcx.impl_methods.borrow();
1088 let methods = impl_methods.get(&def_id);
1090 add_to_index(item, ebml_w, index);
1091 ebml_w.start_tag(tag_items_data_item);
1092 encode_def_id(ebml_w, def_id);
1093 encode_family(ebml_w, 'i');
1094 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1095 encode_name(ebml_w, item.ident.name);
1096 encode_attributes(ebml_w, item.attrs.as_slice());
1098 ast::TyPath(ref path, ref bounds, _) if path.segments
1100 let ident = path.segments.last().unwrap().identifier;
1101 assert!(bounds.is_none());
1102 encode_impl_type_basename(ebml_w, ident);
1106 for &method_def_id in methods.iter() {
1107 ebml_w.start_tag(tag_item_impl_method);
1108 let s = def_to_string(method_def_id);
1109 ebml_w.writer.write(s.as_bytes());
1112 for ast_trait_ref in opt_trait.iter() {
1113 let trait_ref = ty::node_id_to_trait_ref(
1114 tcx, ast_trait_ref.ref_id);
1115 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
1116 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1117 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1119 encode_path(ebml_w, path.clone());
1120 encode_stability(ebml_w, stab);
1123 // Iterate down the methods, emitting them. We rely on the
1124 // assumption that all of the actually implemented methods
1125 // appear first in the impl structure, in the same order they do
1126 // in the ast. This is a little sketchy.
1127 let num_implemented_methods = ast_methods.len();
1128 for (i, &method_def_id) in methods.iter().enumerate() {
1129 let ast_method = if i < num_implemented_methods {
1130 Some(*ast_methods.get(i))
1134 val: method_def_id.node as i64,
1135 pos: ebml_w.writer.tell().unwrap(),
1137 encode_info_for_method(ecx,
1139 &*ty::method(tcx, method_def_id),
1146 ItemTrait(_, _, ref super_traits, ref ms) => {
1147 add_to_index(item, ebml_w, index);
1148 ebml_w.start_tag(tag_items_data_item);
1149 encode_def_id(ebml_w, def_id);
1150 encode_family(ebml_w, 'I');
1151 encode_item_variances(ebml_w, ecx, item.id);
1152 let trait_def = ty::lookup_trait_def(tcx, def_id);
1153 encode_ty_type_param_defs(ebml_w, ecx,
1154 &trait_def.generics.types,
1155 tag_items_data_item_ty_param_bounds);
1156 encode_region_param_defs(ebml_w, &trait_def.generics.regions);
1157 encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1158 encode_name(ebml_w, item.ident.name);
1159 encode_attributes(ebml_w, item.attrs.as_slice());
1160 encode_visibility(ebml_w, vis);
1161 encode_stability(ebml_w, stab);
1162 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1163 ebml_w.start_tag(tag_item_trait_method);
1164 encode_def_id(ebml_w, method_def_id);
1167 ebml_w.start_tag(tag_mod_child);
1168 ebml_w.wr_str(def_to_string(method_def_id).as_slice());
1171 encode_path(ebml_w, path.clone());
1172 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1173 // reading the AST's list, because the former has already filtered out
1174 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1175 for ast_trait_ref in super_traits.iter() {
1176 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1177 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1180 // Encode the implementations of this trait.
1181 encode_extension_implementations(ecx, ebml_w, def_id);
1185 // Now output the method info for each method.
1186 let r = ty::trait_method_def_ids(tcx, def_id);
1187 for (i, &method_def_id) in r.iter().enumerate() {
1188 assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1190 let method_ty = ty::method(tcx, method_def_id);
1193 val: method_def_id.node as i64,
1194 pos: ebml_w.writer.tell().unwrap(),
1197 ebml_w.start_tag(tag_items_data_item);
1199 encode_method_ty_fields(ecx, ebml_w, &*method_ty);
1200 encode_parent_item(ebml_w, def_id);
1202 let stab = stability::lookup(tcx, method_def_id);
1203 encode_stability(ebml_w, stab);
1205 let elem = ast_map::PathName(method_ty.ident.name);
1206 encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1208 match method_ty.explicit_self {
1210 encode_family(ebml_w,
1211 fn_style_static_method_family(
1212 method_ty.fty.fn_style));
1214 let pty = ty::lookup_item_type(tcx, method_def_id);
1215 encode_bounds_and_type(ebml_w, ecx, &pty);
1219 encode_family(ebml_w,
1221 method_ty.fty.fn_style));
1226 &Required(ref tm) => {
1227 encode_attributes(ebml_w, tm.attrs.as_slice());
1228 encode_method_sort(ebml_w, 'r');
1229 encode_method_argument_names(ebml_w, &*tm.decl);
1233 encode_attributes(ebml_w, m.attrs.as_slice());
1234 // If this is a static method, we've already encoded
1236 if method_ty.explicit_self != SelfStatic {
1237 // FIXME: I feel like there is something funny going on.
1238 let pty = ty::lookup_item_type(tcx, method_def_id);
1239 encode_bounds_and_type(ebml_w, ecx, &pty);
1241 encode_method_sort(ebml_w, 'p');
1242 encode_inlined_item(ecx, ebml_w,
1243 IIMethodRef(def_id, true, &*m));
1244 encode_method_argument_names(ebml_w, method_fn_decl(m));
1251 // Encode inherent implementations for this trait.
1252 encode_inherent_implementations(ecx, ebml_w, def_id);
1255 // macros are encoded separately
1260 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1261 ebml_w: &mut Encoder,
1262 nitem: &ForeignItem,
1263 index: &mut Vec<entry<i64>>,
1267 val: nitem.id as i64,
1268 pos: ebml_w.writer.tell().unwrap(),
1271 ebml_w.start_tag(tag_items_data_item);
1272 encode_def_id(ebml_w, local_def(nitem.id));
1274 ForeignItemFn(..) => {
1275 encode_family(ebml_w, style_fn_family(NormalFn));
1276 encode_bounds_and_type(ebml_w, ecx,
1277 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1278 encode_name(ebml_w, nitem.ident.name);
1279 if abi == abi::RustIntrinsic {
1280 encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1282 encode_symbol(ecx, ebml_w, nitem.id);
1285 ForeignItemStatic(_, mutbl) => {
1287 encode_family(ebml_w, 'b');
1289 encode_family(ebml_w, 'c');
1291 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1292 encode_symbol(ecx, ebml_w, nitem.id);
1293 encode_name(ebml_w, nitem.ident.name);
1296 encode_path(ebml_w, path);
1300 fn my_visit_expr(_e: &Expr) { }
1302 fn my_visit_item(i: &Item,
1303 ebml_w: &mut Encoder,
1304 ecx_ptr: *const int,
1305 index: &mut Vec<entry<i64>>) {
1306 let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1308 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1309 ecx.tcx.map.with_path(i.id, |path| {
1310 encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1314 fn my_visit_foreign_item(ni: &ForeignItem,
1315 ebml_w: &mut Encoder,
1317 index: &mut Vec<entry<i64>>) {
1319 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1320 debug!("writing foreign item {}::{}",
1321 ecx.tcx.map.path_to_string(ni.id),
1322 token::get_ident(ni.ident));
1324 let mut ebml_w = unsafe {
1325 ebml_w.unsafe_clone()
1327 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1328 ecx.tcx.map.with_path(ni.id, |path| {
1329 encode_info_for_foreign_item(ecx, &mut ebml_w,
1335 struct EncodeVisitor<'a,'b> {
1336 ebml_w_for_visit_item: &'a mut Encoder<'b>,
1338 index: &'a mut Vec<entry<i64>>,
1341 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1342 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1343 visit::walk_expr(self, ex, ());
1346 fn visit_item(&mut self, i: &Item, _: ()) {
1347 visit::walk_item(self, i, ());
1349 self.ebml_w_for_visit_item,
1353 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1354 visit::walk_foreign_item(self, ni, ());
1355 my_visit_foreign_item(ni,
1356 self.ebml_w_for_visit_item,
1362 fn encode_info_for_items(ecx: &EncodeContext,
1363 ebml_w: &mut Encoder,
1365 -> Vec<entry<i64>> {
1366 let mut index = Vec::new();
1367 ebml_w.start_tag(tag_items_data);
1369 val: CRATE_NODE_ID as i64,
1370 pos: ebml_w.writer.tell().unwrap(),
1372 encode_info_for_mod(ecx,
1377 ast_map::Values([].iter()).chain(None),
1378 syntax::parse::token::special_idents::invalid,
1381 // See comment in `encode_side_tables_for_ii` in astencode
1382 let ecx_ptr: *const int = unsafe { mem::transmute(ecx) };
1383 visit::walk_crate(&mut EncodeVisitor {
1386 ebml_w_for_visit_item: &mut *ebml_w,
1394 // Path and definition ID indexing
1396 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1397 write_fn: |&mut MemWriter, &T|) {
1398 let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1399 for elt in index.move_iter() {
1400 let h = hash::hash(&elt.val) as uint;
1401 buckets.get_mut(h % 256).push(elt);
1404 ebml_w.start_tag(tag_index);
1405 let mut bucket_locs = Vec::new();
1406 ebml_w.start_tag(tag_index_buckets);
1407 for bucket in buckets.iter() {
1408 bucket_locs.push(ebml_w.writer.tell().unwrap());
1409 ebml_w.start_tag(tag_index_buckets_bucket);
1410 for elt in bucket.iter() {
1411 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1412 assert!(elt.pos < 0xffff_ffff);
1414 let wr: &mut MemWriter = ebml_w.writer;
1415 wr.write_be_u32(elt.pos as u32);
1417 write_fn(ebml_w.writer, &elt.val);
1423 ebml_w.start_tag(tag_index_table);
1424 for pos in bucket_locs.iter() {
1425 assert!(*pos < 0xffff_ffff);
1426 let wr: &mut MemWriter = ebml_w.writer;
1427 wr.write_be_u32(*pos as u32);
1433 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1434 let wr: &mut MemWriter = writer;
1435 assert!(n < 0x7fff_ffff);
1436 wr.write_be_u32(n as u32);
1439 fn encode_meta_item(ebml_w: &mut Encoder, mi: Gc<MetaItem>) {
1441 MetaWord(ref name) => {
1442 ebml_w.start_tag(tag_meta_item_word);
1443 ebml_w.start_tag(tag_meta_item_name);
1444 ebml_w.writer.write(name.get().as_bytes());
1448 MetaNameValue(ref name, ref value) => {
1450 LitStr(ref value, _) => {
1451 ebml_w.start_tag(tag_meta_item_name_value);
1452 ebml_w.start_tag(tag_meta_item_name);
1453 ebml_w.writer.write(name.get().as_bytes());
1455 ebml_w.start_tag(tag_meta_item_value);
1456 ebml_w.writer.write(value.get().as_bytes());
1460 _ => {/* FIXME (#623): encode other variants */ }
1463 MetaList(ref name, ref items) => {
1464 ebml_w.start_tag(tag_meta_item_list);
1465 ebml_w.start_tag(tag_meta_item_name);
1466 ebml_w.writer.write(name.get().as_bytes());
1468 for inner_item in items.iter() {
1469 encode_meta_item(ebml_w, *inner_item);
1476 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1477 ebml_w.start_tag(tag_attributes);
1478 for attr in attrs.iter() {
1479 ebml_w.start_tag(tag_attribute);
1480 encode_meta_item(ebml_w, attr.node.value);
1486 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1487 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1488 // Pull the cnums and name,vers,hash out of cstore
1489 let mut deps = Vec::new();
1490 cstore.iter_crate_data(|key, val| {
1491 let dep = decoder::CrateDep {
1493 name: decoder::get_crate_name(val.data()),
1494 hash: decoder::get_crate_hash(val.data()),
1500 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1502 // Sanity-check the crate numbers
1503 let mut expected_cnum = 1;
1504 for n in deps.iter() {
1505 assert_eq!(n.cnum, expected_cnum);
1512 // We're just going to write a list of crate 'name-hash-version's, with
1513 // the assumption that they are numbered 1 to n.
1514 // FIXME (#2166): This is not nearly enough to support correct versioning
1515 // but is enough to get transitive crate dependencies working.
1516 ebml_w.start_tag(tag_crate_deps);
1517 let r = get_ordered_deps(cstore);
1518 for dep in r.iter() {
1519 encode_crate_dep(ebml_w, (*dep).clone());
1524 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1525 ebml_w.start_tag(tag_lang_items);
1527 for (i, def_id) in ecx.tcx.lang_items.items() {
1528 for id in def_id.iter() {
1529 if id.krate == LOCAL_CRATE {
1530 ebml_w.start_tag(tag_lang_items_item);
1532 ebml_w.start_tag(tag_lang_items_item_id);
1534 let wr: &mut MemWriter = ebml_w.writer;
1535 wr.write_be_u32(i as u32);
1537 ebml_w.end_tag(); // tag_lang_items_item_id
1539 ebml_w.start_tag(tag_lang_items_item_node_id);
1541 let wr: &mut MemWriter = ebml_w.writer;
1542 wr.write_be_u32(id.node as u32);
1544 ebml_w.end_tag(); // tag_lang_items_item_node_id
1546 ebml_w.end_tag(); // tag_lang_items_item
1551 for i in ecx.tcx.lang_items.missing.iter() {
1552 ebml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1555 ebml_w.end_tag(); // tag_lang_items
1558 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1559 ebml_w.start_tag(tag_native_libraries);
1561 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1564 cstore::NativeStatic => {} // these libraries are not propagated
1565 cstore::NativeFramework | cstore::NativeUnknown => {
1566 ebml_w.start_tag(tag_native_libraries_lib);
1568 ebml_w.start_tag(tag_native_libraries_kind);
1569 ebml_w.writer.write_be_u32(kind as u32);
1572 ebml_w.start_tag(tag_native_libraries_name);
1573 ebml_w.writer.write(lib.as_bytes());
1584 fn encode_plugin_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1585 match ecx.tcx.sess.plugin_registrar_fn.get() {
1586 Some(id) => { ebml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1591 /// Given a span, write the text of that span into the output stream
1592 /// as an exported macro
1593 fn encode_macro_def(ecx: &EncodeContext,
1594 ebml_w: &mut Encoder,
1595 span: &syntax::codemap::Span) {
1596 let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
1597 .expect("Unable to find source for macro");
1598 ebml_w.start_tag(tag_macro_def);
1599 ebml_w.wr_str(def.as_slice());
1603 /// Serialize the text of the exported macros
1604 fn encode_macro_defs(ecx: &EncodeContext,
1606 ebml_w: &mut Encoder) {
1607 ebml_w.start_tag(tag_exported_macros);
1608 for span in krate.exported_macros.iter() {
1609 encode_macro_def(ecx, ebml_w, span);
1614 struct ImplVisitor<'a,'b,'c> {
1615 ecx: &'a EncodeContext<'b>,
1616 ebml_w: &'a mut Encoder<'c>,
1619 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1620 fn visit_item(&mut self, item: &Item, _: ()) {
1622 ItemImpl(_, Some(ref trait_ref), _, _) => {
1623 let def_map = &self.ecx.tcx.def_map;
1624 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1625 let def_id = trait_def.def_id();
1627 // Load eagerly if this is an implementation of the Drop trait
1628 // or if the trait is not defined in this crate.
1629 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1630 def_id.krate != LOCAL_CRATE {
1631 self.ebml_w.start_tag(tag_impls_impl);
1632 encode_def_id(self.ebml_w, local_def(item.id));
1633 self.ebml_w.end_tag();
1638 visit::walk_item(self, item, ());
1642 /// Encodes implementations that are eagerly loaded.
1644 /// None of this is necessary in theory; we can load all implementations
1645 /// lazily. However, in two cases the optimizations to lazily load
1646 /// implementations are not yet implemented. These two cases, which require us
1647 /// to load implementations eagerly, are:
1649 /// * Destructors (implementations of the Drop trait).
1651 /// * Implementations of traits not defined in this crate.
1652 fn encode_impls<'a>(ecx: &'a EncodeContext,
1654 ebml_w: &'a mut Encoder) {
1655 ebml_w.start_tag(tag_impls);
1658 let mut visitor = ImplVisitor {
1662 visit::walk_crate(&mut visitor, krate, ());
1668 fn encode_misc_info(ecx: &EncodeContext,
1670 ebml_w: &mut Encoder) {
1671 ebml_w.start_tag(tag_misc_info);
1672 ebml_w.start_tag(tag_misc_info_crate_items);
1673 for &item in krate.module.items.iter() {
1674 ebml_w.start_tag(tag_mod_child);
1675 ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
1678 each_auxiliary_node_id(item, |auxiliary_node_id| {
1679 ebml_w.start_tag(tag_mod_child);
1680 ebml_w.wr_str(def_to_string(local_def(
1681 auxiliary_node_id)).as_slice());
1687 // Encode reexports for the root module.
1688 encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1694 fn encode_reachable_extern_fns(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1695 ebml_w.start_tag(tag_reachable_extern_fns);
1697 for id in ecx.reachable.iter() {
1698 match ecx.tcx.map.find(*id) {
1699 Some(ast_map::NodeItem(i)) => {
1701 ast::ItemFn(_, _, abi, _, _) if abi != abi::Rust => {
1702 ebml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1714 fn encode_crate_dep(ebml_w: &mut Encoder,
1715 dep: decoder::CrateDep) {
1716 ebml_w.start_tag(tag_crate_dep);
1717 ebml_w.start_tag(tag_crate_dep_crate_name);
1718 ebml_w.writer.write(dep.name.as_bytes());
1720 ebml_w.start_tag(tag_crate_dep_hash);
1721 ebml_w.writer.write(dep.hash.as_str().as_bytes());
1726 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1727 ebml_w.start_tag(tag_crate_hash);
1728 ebml_w.writer.write(hash.as_str().as_bytes());
1732 fn encode_crate_name(ebml_w: &mut Encoder, crate_name: &str) {
1733 ebml_w.start_tag(tag_crate_crate_name);
1734 ebml_w.writer.write(crate_name.as_bytes());
1738 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1739 ebml_w.start_tag(tag_crate_triple);
1740 ebml_w.writer.write(triple.as_bytes());
1744 fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
1745 ebml_w.start_tag(tag_dylib_dependency_formats);
1746 match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
1748 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1749 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1750 cstore::RequireDynamic => "d",
1751 cstore::RequireStatic => "s",
1753 }).collect::<Vec<String>>();
1754 ebml_w.writer.write(s.connect(",").as_bytes());
1761 // NB: Increment this as you change the metadata encoding version.
1762 pub static metadata_encoding_version : &'static [u8] =
1763 &[0x72, //'r' as u8,
1769 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1770 let mut wr = MemWriter::new();
1771 encode_metadata_inner(&mut wr, parms, krate);
1772 wr.unwrap().move_iter().collect()
1775 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1779 lang_item_bytes: u64,
1780 native_lib_bytes: u64,
1781 plugin_registrar_fn_bytes: u64,
1782 macro_defs_bytes: u64,
1790 let mut stats = Stats {
1794 native_lib_bytes: 0,
1795 plugin_registrar_fn_bytes: 0,
1796 macro_defs_bytes: 0,
1810 encode_inlined_item,
1812 non_inlineable_statics,
1816 let ecx = EncodeContext {
1819 reexports2: reexports2,
1820 item_symbols: item_symbols,
1821 non_inlineable_statics: non_inlineable_statics,
1822 link_meta: link_meta,
1824 encode_inlined_item: RefCell::new(encode_inlined_item),
1825 type_abbrevs: RefCell::new(HashMap::new()),
1826 reachable: reachable,
1829 let mut ebml_w = writer::Encoder::new(wr);
1831 encode_crate_name(&mut ebml_w, ecx.link_meta.crate_name.as_slice());
1832 encode_crate_triple(&mut ebml_w,
1838 encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1839 encode_dylib_dependency_formats(&mut ebml_w, &ecx);
1841 let mut i = ebml_w.writer.tell().unwrap();
1842 encode_attributes(&mut ebml_w, krate.attrs.as_slice());
1843 stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1845 i = ebml_w.writer.tell().unwrap();
1846 encode_crate_deps(&mut ebml_w, ecx.cstore);
1847 stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1849 // Encode the language items.
1850 i = ebml_w.writer.tell().unwrap();
1851 encode_lang_items(&ecx, &mut ebml_w);
1852 stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1854 // Encode the native libraries used
1855 i = ebml_w.writer.tell().unwrap();
1856 encode_native_libraries(&ecx, &mut ebml_w);
1857 stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1859 // Encode the plugin registrar function
1860 i = ebml_w.writer.tell().unwrap();
1861 encode_plugin_registrar_fn(&ecx, &mut ebml_w);
1862 stats.plugin_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1864 // Encode macro definitions
1865 i = ebml_w.writer.tell().unwrap();
1866 encode_macro_defs(&ecx, krate, &mut ebml_w);
1867 stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1869 // Encode the def IDs of impls, for coherence checking.
1870 i = ebml_w.writer.tell().unwrap();
1871 encode_impls(&ecx, krate, &mut ebml_w);
1872 stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1874 // Encode miscellaneous info.
1875 i = ebml_w.writer.tell().unwrap();
1876 encode_misc_info(&ecx, krate, &mut ebml_w);
1877 encode_reachable_extern_fns(&ecx, &mut ebml_w);
1878 stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1880 // Encode and index the items.
1881 ebml_w.start_tag(tag_items);
1882 i = ebml_w.writer.tell().unwrap();
1883 let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1884 stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1886 i = ebml_w.writer.tell().unwrap();
1887 encode_index(&mut ebml_w, items_index, write_i64);
1888 stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1891 stats.total_bytes = ebml_w.writer.tell().unwrap();
1893 if tcx.sess.meta_stats() {
1894 for e in ebml_w.writer.get_ref().iter() {
1896 stats.zero_bytes += 1;
1900 println!("metadata stats:");
1901 println!(" attribute bytes: {}", stats.attr_bytes);
1902 println!(" dep bytes: {}", stats.dep_bytes);
1903 println!(" lang item bytes: {}", stats.lang_item_bytes);
1904 println!(" native bytes: {}", stats.native_lib_bytes);
1905 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
1906 println!(" macro def bytes: {}", stats.macro_defs_bytes);
1907 println!(" impl bytes: {}", stats.impl_bytes);
1908 println!(" misc bytes: {}", stats.misc_bytes);
1909 println!(" item bytes: {}", stats.item_bytes);
1910 println!(" index bytes: {}", stats.index_bytes);
1911 println!(" zero bytes: {}", stats.zero_bytes);
1912 println!(" total bytes: {}", stats.total_bytes);
1916 // Get the encoded string for a type
1917 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> String {
1918 let mut wr = MemWriter::new();
1919 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1920 diag: tcx.sess.diagnostic(),
1923 abbrevs: &RefCell::new(HashMap::new())
1925 str::from_utf8_owned(Vec::from_slice(wr.get_ref())).unwrap().to_string()