1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
13 #![allow(unused_must_use)] // everything is just a MemWriter, can't fail
14 #![allow(non_camel_case_types)]
18 use metadata::common::*;
20 use metadata::decoder;
21 use metadata::tyencode;
22 use middle::subst::VecPerParamSpace;
23 use middle::ty::{node_id_to_type, lookup_item_type};
24 use middle::astencode;
27 use middle::stability;
29 use util::nodemap::{NodeMap, NodeSet};
31 use serialize::Encodable;
32 use std::cell::RefCell;
36 use std::io::MemWriter;
38 use std::collections::HashMap;
42 use syntax::ast_map::{PathElem, PathElems};
44 use syntax::ast_util::*;
47 use syntax::attr::AttrMetaMethods;
48 use syntax::diagnostic::SpanHandler;
49 use syntax::parse::token::special_idents;
50 use syntax::parse::token;
51 use syntax::visit::Visitor;
54 use writer = serialize::ebml::writer;
56 /// A borrowed version of ast::InlinedItem.
57 pub enum InlinedItemRef<'a> {
58 IIItemRef(&'a ast::Item),
59 IIMethodRef(ast::DefId, bool, &'a ast::Method),
60 IIForeignRef(&'a ast::ForeignItem)
63 pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
65 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
67 ii: InlinedItemRef|: 'a;
69 pub struct EncodeParams<'a> {
70 pub diag: &'a SpanHandler,
71 pub tcx: &'a ty::ctxt,
72 pub reexports2: &'a middle::resolve::ExportMap2,
73 pub item_symbols: &'a RefCell<NodeMap<String>>,
74 pub non_inlineable_statics: &'a RefCell<NodeSet>,
75 pub link_meta: &'a LinkMeta,
76 pub cstore: &'a cstore::CStore,
77 pub encode_inlined_item: EncodeInlinedItem<'a>,
78 pub reachable: &'a NodeSet,
81 pub struct EncodeContext<'a> {
82 pub diag: &'a SpanHandler,
83 pub tcx: &'a ty::ctxt,
84 pub reexports2: &'a middle::resolve::ExportMap2,
85 pub item_symbols: &'a RefCell<NodeMap<String>>,
86 pub non_inlineable_statics: &'a RefCell<NodeSet>,
87 pub link_meta: &'a LinkMeta,
88 pub cstore: &'a cstore::CStore,
89 pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
90 pub type_abbrevs: tyencode::abbrev_map,
91 pub reachable: &'a NodeSet,
94 fn encode_name(ebml_w: &mut Encoder, name: Name) {
95 ebml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
98 fn encode_impl_type_basename(ebml_w: &mut Encoder, name: Ident) {
99 ebml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
102 pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
103 ebml_w.wr_tagged_str(tag_def_id, def_to_string(id).as_slice());
112 fn encode_trait_ref(ebml_w: &mut Encoder,
114 trait_ref: &ty::TraitRef,
116 let ty_str_ctxt = &tyencode::ctxt {
120 abbrevs: &ecx.type_abbrevs
123 ebml_w.start_tag(tag);
124 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
128 fn encode_impl_vtables(ebml_w: &mut Encoder,
130 vtables: &typeck::vtable_res) {
131 ebml_w.start_tag(tag_item_impl_vtables);
132 astencode::encode_vtable_res(ecx, ebml_w, vtables);
136 // Item info table encoding
137 fn encode_family(ebml_w: &mut Encoder, c: char) {
138 ebml_w.start_tag(tag_items_data_item_family);
139 ebml_w.writer.write(&[c as u8]);
143 pub fn def_to_string(did: DefId) -> String {
144 format!("{}:{}", did.krate, did.node)
147 fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
149 params: &VecPerParamSpace<ty::TypeParameterDef>,
151 let ty_str_ctxt = &tyencode::ctxt {
155 abbrevs: &ecx.type_abbrevs
157 for param in params.iter() {
158 ebml_w.start_tag(tag);
159 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
164 fn encode_region_param_defs(ebml_w: &mut Encoder,
165 params: &VecPerParamSpace<ty::RegionParameterDef>) {
166 for param in params.iter() {
167 ebml_w.start_tag(tag_region_param_def);
169 ebml_w.start_tag(tag_region_param_def_ident);
170 encode_name(ebml_w, param.name);
173 ebml_w.wr_tagged_str(tag_region_param_def_def_id,
174 def_to_string(param.def_id).as_slice());
176 ebml_w.wr_tagged_u64(tag_region_param_def_space,
177 param.space.to_uint() as u64);
179 ebml_w.wr_tagged_u64(tag_region_param_def_index,
186 fn encode_item_variances(ebml_w: &mut Encoder,
189 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
190 ebml_w.start_tag(tag_item_variances);
195 fn encode_bounds_and_type(ebml_w: &mut Encoder,
197 pty: &ty::Polytype) {
198 encode_ty_type_param_defs(ebml_w, ecx, &pty.generics.types,
199 tag_items_data_item_ty_param_bounds);
200 encode_region_param_defs(ebml_w, &pty.generics.regions);
201 encode_type(ecx, ebml_w, pty.ty);
204 fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
205 ebml_w.start_tag(tag_items_data_item_variant);
206 let s = def_to_string(vid);
207 ebml_w.writer.write(s.as_bytes());
211 pub fn write_type(ecx: &EncodeContext,
212 ebml_w: &mut Encoder,
214 let ty_str_ctxt = &tyencode::ctxt {
218 abbrevs: &ecx.type_abbrevs
220 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
223 fn encode_type(ecx: &EncodeContext,
224 ebml_w: &mut Encoder,
226 ebml_w.start_tag(tag_items_data_item_type);
227 write_type(ecx, ebml_w, typ);
231 fn encode_method_fty(ecx: &EncodeContext,
232 ebml_w: &mut Encoder,
233 typ: &ty::BareFnTy) {
234 ebml_w.start_tag(tag_item_method_fty);
236 let ty_str_ctxt = &tyencode::ctxt {
240 abbrevs: &ecx.type_abbrevs
242 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
247 fn encode_symbol(ecx: &EncodeContext,
248 ebml_w: &mut Encoder,
250 ebml_w.start_tag(tag_items_data_item_symbol);
251 match ecx.item_symbols.borrow().find(&id) {
253 debug!("encode_symbol(id={:?}, str={})", id, *x);
254 ebml_w.writer.write(x.as_bytes());
257 ecx.diag.handler().bug(
258 format!("encode_symbol: id not found {}", id).as_slice());
264 fn encode_disr_val(_: &EncodeContext,
265 ebml_w: &mut Encoder,
266 disr_val: ty::Disr) {
267 ebml_w.start_tag(tag_disr_val);
268 let s = disr_val.to_string();
269 ebml_w.writer.write(s.as_bytes());
273 fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
274 ebml_w.start_tag(tag_items_data_parent_item);
275 let s = def_to_string(id);
276 ebml_w.writer.write(s.as_bytes());
280 fn encode_struct_fields(ebml_w: &mut Encoder,
281 fields: &[ty::field_ty],
283 for f in fields.iter() {
284 if f.name == special_idents::unnamed_field.name {
285 ebml_w.start_tag(tag_item_unnamed_field);
287 ebml_w.start_tag(tag_item_field);
288 encode_name(ebml_w, f.name);
290 encode_struct_field_family(ebml_w, f.vis);
291 encode_def_id(ebml_w, f.id);
292 ebml_w.start_tag(tag_item_field_origin);
293 let s = def_to_string(origin);
294 ebml_w.writer.write(s.as_bytes());
300 fn encode_enum_variant_info(ecx: &EncodeContext,
301 ebml_w: &mut Encoder,
303 variants: &[P<Variant>],
304 index: &mut Vec<entry<i64>>,
305 generics: &ast::Generics) {
306 debug!("encode_enum_variant_info(id={:?})", id);
308 let mut disr_val = 0;
310 let vi = ty::enum_variants(ecx.tcx,
311 ast::DefId { krate: LOCAL_CRATE, node: id });
312 for variant in variants.iter() {
313 let def_id = local_def(variant.node.id);
315 val: variant.node.id as i64,
316 pos: ebml_w.writer.tell().unwrap(),
318 ebml_w.start_tag(tag_items_data_item);
319 encode_def_id(ebml_w, def_id);
320 match variant.node.kind {
321 ast::TupleVariantKind(_) => encode_family(ebml_w, 'v'),
322 ast::StructVariantKind(_) => encode_family(ebml_w, 'V')
324 encode_name(ebml_w, variant.node.name.name);
325 encode_parent_item(ebml_w, local_def(id));
326 encode_visibility(ebml_w, variant.node.vis);
327 encode_attributes(ebml_w, variant.node.attrs.as_slice());
329 let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
330 encode_stability(ebml_w, stab);
332 match variant.node.kind {
333 ast::TupleVariantKind(ref args)
334 if args.len() > 0 && generics.ty_params.len() == 0 => {
335 encode_symbol(ecx, ebml_w, variant.node.id);
337 ast::TupleVariantKind(_) => {},
338 ast::StructVariantKind(_) => {
339 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
340 let idx = encode_info_for_struct(ecx,
344 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
345 encode_index(ebml_w, idx, write_i64);
348 if vi.get(i).disr_val != disr_val {
349 encode_disr_val(ecx, ebml_w, vi.get(i).disr_val);
350 disr_val = vi.get(i).disr_val;
352 encode_bounds_and_type(ebml_w, ecx,
353 &lookup_item_type(ecx.tcx, def_id));
355 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(ebml_w, path));
362 fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
364 ebml_w.start_tag(tag_path);
365 ebml_w.wr_tagged_u32(tag_path_len, path.clone().count() as u32);
368 ast_map::PathMod(_) => tag_path_elem_mod,
369 ast_map::PathName(_) => tag_path_elem_name
371 ebml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
376 fn encode_reexported_static_method(ebml_w: &mut Encoder,
377 exp: &middle::resolve::Export2,
378 method_def_id: DefId,
379 method_ident: Ident) {
380 debug!("(encode reexported static method) {}::{}",
381 exp.name, token::get_ident(method_ident));
382 ebml_w.start_tag(tag_items_data_item_reexport);
383 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
384 ebml_w.wr_str(def_to_string(method_def_id).as_slice());
386 ebml_w.start_tag(tag_items_data_item_reexport_name);
387 ebml_w.wr_str(format!("{}::{}",
389 token::get_ident(method_ident)).as_slice());
394 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
395 ebml_w: &mut Encoder,
396 exp: &middle::resolve::Export2)
398 let impl_methods = ecx.tcx.impl_methods.borrow();
399 match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
400 Some(implementations) => {
401 for base_impl_did in implementations.borrow().iter() {
402 for &method_did in impl_methods.get(base_impl_did).iter() {
403 let m = ty::method(ecx.tcx, method_did);
404 if m.explicit_self == ast::SelfStatic {
405 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
416 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
417 ebml_w: &mut Encoder,
418 exp: &middle::resolve::Export2)
420 match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
422 for m in methods.iter() {
423 if m.explicit_self == ast::SelfStatic {
424 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
434 fn encode_reexported_static_methods(ecx: &EncodeContext,
435 ebml_w: &mut Encoder,
437 exp: &middle::resolve::Export2) {
438 match ecx.tcx.map.find(exp.def_id.node) {
439 Some(ast_map::NodeItem(item)) => {
440 let original_name = token::get_ident(item.ident);
442 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
443 let (mut a, mut b) = (path, mod_path.clone());
445 match (a.next(), b.next()) {
446 (None, None) => return true,
447 (None, _) | (_, None) => return false,
448 (Some(x), Some(y)) => if x != y { return false },
454 // We don't need to reexport static methods on items
455 // declared in the same module as our `pub use ...` since
456 // that's done when we encode the item itself.
458 // The only exception is when the reexport *changes* the
459 // name e.g. `pub use Foo = self::Bar` -- we have
460 // encoded metadata for static methods relative to Bar,
461 // but not yet for Foo.
463 if path_differs || original_name.get() != exp.name.as_slice() {
464 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
465 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
466 debug!("(encode reexported static methods) {} \
472 debug!("(encode reexported static methods) {} [base]",
481 /// Iterates through "auxiliary node IDs", which are node IDs that describe
482 /// top-level items that are sub-items of the given item. Specifically:
484 /// * For enums, iterates through the node IDs of the variants.
486 /// * For newtype structs, iterates through the node ID of the constructor.
487 fn each_auxiliary_node_id(item: Gc<Item>, callback: |NodeId| -> bool) -> bool {
488 let mut continue_ = true;
490 ItemEnum(ref enum_def, _) => {
491 for variant in enum_def.variants.iter() {
492 continue_ = callback(variant.node.id);
498 ItemStruct(struct_def, _) => {
499 // If this is a newtype struct, return the constructor.
500 match struct_def.ctor_id {
501 Some(ctor_id) if struct_def.fields.len() > 0 &&
502 struct_def.fields.get(0).node.kind.is_unnamed() => {
503 continue_ = callback(ctor_id);
514 fn encode_reexports(ecx: &EncodeContext,
515 ebml_w: &mut Encoder,
518 debug!("(encoding info for module) encoding reexports for {}", id);
519 match ecx.reexports2.borrow().find(&id) {
520 Some(ref exports) => {
521 debug!("(encoding info for module) found reexports for {}", id);
522 for exp in exports.iter() {
523 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
529 ebml_w.start_tag(tag_items_data_item_reexport);
530 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
531 ebml_w.wr_str(def_to_string(exp.def_id).as_slice());
533 ebml_w.start_tag(tag_items_data_item_reexport_name);
534 ebml_w.wr_str(exp.name.as_slice());
537 encode_reexported_static_methods(ecx, ebml_w, path.clone(), exp);
541 debug!("(encoding info for module) found no reexports for {}",
547 fn encode_info_for_mod(ecx: &EncodeContext,
548 ebml_w: &mut Encoder,
555 ebml_w.start_tag(tag_items_data_item);
556 encode_def_id(ebml_w, local_def(id));
557 encode_family(ebml_w, 'm');
558 encode_name(ebml_w, name.name);
559 debug!("(encoding info for module) encoding info for module ID {}", id);
561 // Encode info about all the module children.
562 for item in md.items.iter() {
563 ebml_w.start_tag(tag_mod_child);
564 ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
567 each_auxiliary_node_id(*item, |auxiliary_node_id| {
568 ebml_w.start_tag(tag_mod_child);
569 ebml_w.wr_str(def_to_string(local_def(
570 auxiliary_node_id)).as_slice());
577 let (ident, did) = (item.ident, item.id);
578 debug!("(encoding info for module) ... encoding impl {} \
580 token::get_ident(ident),
581 did, ecx.tcx.map.node_to_string(did));
583 ebml_w.start_tag(tag_mod_impl);
584 ebml_w.wr_str(def_to_string(local_def(did)).as_slice());
591 encode_path(ebml_w, path.clone());
592 encode_visibility(ebml_w, vis);
594 let stab = stability::lookup(ecx.tcx, ast_util::local_def(id));
595 encode_stability(ebml_w, stab);
597 // Encode the reexports of this module, if this module is public.
599 debug!("(encoding info for module) encoding reexports for {}", id);
600 encode_reexports(ecx, ebml_w, id, path);
602 encode_attributes(ebml_w, attrs);
607 fn encode_struct_field_family(ebml_w: &mut Encoder,
608 visibility: Visibility) {
609 encode_family(ebml_w, match visibility {
615 fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
616 ebml_w.start_tag(tag_items_data_item_visibility);
617 let ch = match visibility {
621 ebml_w.wr_str(ch.to_string().as_slice());
625 fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_) {
626 ebml_w.start_tag(tag_item_trait_method_explicit_self);
628 // Encode the base self type.
629 match explicit_self {
630 SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
631 SelfValue(_) => { ebml_w.writer.write(&[ 'v' as u8 ]); }
632 SelfUniq(_) => { ebml_w.writer.write(&[ '~' as u8 ]); }
633 SelfRegion(_, m, _) => {
634 // FIXME(#4846) encode custom lifetime
635 ebml_w.writer.write(&['&' as u8]);
636 encode_mutability(ebml_w, m);
642 fn encode_mutability(ebml_w: &mut Encoder,
643 m: ast::Mutability) {
645 MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
646 MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); }
651 fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
652 ebml_w.start_tag(tag_item_trait_method_sort);
653 ebml_w.writer.write(&[ sort as u8 ]);
657 fn encode_provided_source(ebml_w: &mut Encoder,
658 source_opt: Option<DefId>) {
659 for source in source_opt.iter() {
660 ebml_w.start_tag(tag_item_method_provided_source);
661 let s = def_to_string(*source);
662 ebml_w.writer.write(s.as_bytes());
667 /* Returns an index of items in this class */
668 fn encode_info_for_struct(ecx: &EncodeContext,
669 ebml_w: &mut Encoder,
670 fields: &[ty::field_ty],
671 global_index: &mut Vec<entry<i64>>)
673 /* Each class has its own index, since different classes
674 may have fields with the same name */
675 let mut index = Vec::new();
677 /* We encode both private and public fields -- need to include
678 private fields to get the offsets right */
679 for field in fields.iter() {
681 let id = field.id.node;
683 index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
684 global_index.push(entry {
686 pos: ebml_w.writer.tell().unwrap(),
688 ebml_w.start_tag(tag_items_data_item);
689 debug!("encode_info_for_struct: doing {} {}",
690 token::get_name(nm), id);
691 encode_struct_field_family(ebml_w, field.vis);
692 encode_name(ebml_w, nm);
693 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
694 encode_def_id(ebml_w, local_def(id));
696 let stab = stability::lookup(ecx.tcx, field.id);
697 encode_stability(ebml_w, stab);
704 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
705 ebml_w: &mut Encoder,
708 index: &mut Vec<entry<i64>>,
712 pos: ebml_w.writer.tell().unwrap(),
715 ebml_w.start_tag(tag_items_data_item);
716 encode_def_id(ebml_w, local_def(ctor_id));
717 encode_family(ebml_w, 'f');
718 encode_bounds_and_type(ebml_w, ecx,
719 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
720 encode_name(ebml_w, name.name);
721 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
722 ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
723 encode_parent_item(ebml_w, local_def(struct_id));
725 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
726 encode_symbol(ecx, ebml_w, ctor_id);
729 let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
730 encode_stability(ebml_w, stab);
732 // indicate that this is a tuple struct ctor, because downstream users will normally want
733 // the tuple struct definition, but without this there is no way for them to tell that
734 // they actually have a ctor rather than a normal function
735 ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
741 fn encode_method_ty_fields(ecx: &EncodeContext,
742 ebml_w: &mut Encoder,
743 method_ty: &ty::Method) {
744 encode_def_id(ebml_w, method_ty.def_id);
745 encode_name(ebml_w, method_ty.ident.name);
746 encode_ty_type_param_defs(ebml_w, ecx, &method_ty.generics.types,
747 tag_item_method_tps);
748 encode_method_fty(ecx, ebml_w, &method_ty.fty);
749 encode_visibility(ebml_w, method_ty.vis);
750 encode_explicit_self(ebml_w, method_ty.explicit_self);
751 let fn_style = method_ty.fty.fn_style;
752 match method_ty.explicit_self {
754 encode_family(ebml_w, fn_style_static_method_family(fn_style));
756 _ => encode_family(ebml_w, style_fn_family(fn_style))
758 encode_provided_source(ebml_w, method_ty.provided_source);
761 fn encode_info_for_method(ecx: &EncodeContext,
762 ebml_w: &mut Encoder,
764 impl_path: PathElems,
765 is_default_impl: bool,
767 ast_method_opt: Option<Gc<Method>>) {
769 debug!("encode_info_for_method: {:?} {}", m.def_id,
770 token::get_ident(m.ident));
771 ebml_w.start_tag(tag_items_data_item);
773 encode_method_ty_fields(ecx, ebml_w, m);
774 encode_parent_item(ebml_w, local_def(parent_id));
776 let stab = stability::lookup(ecx.tcx, m.def_id);
777 encode_stability(ebml_w, stab);
779 // The type for methods gets encoded twice, which is unfortunate.
780 let pty = lookup_item_type(ecx.tcx, m.def_id);
781 encode_bounds_and_type(ebml_w, ecx, &pty);
783 let elem = ast_map::PathName(m.ident.name);
784 encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
785 match ast_method_opt {
786 Some(ast_method) => {
787 encode_attributes(ebml_w, ast_method.attrs.as_slice())
792 for &ast_method in ast_method_opt.iter() {
793 let any_types = !pty.generics.types.is_empty();
794 if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
795 encode_inlined_item(ecx, ebml_w,
796 IIMethodRef(local_def(parent_id), false,
799 encode_symbol(ecx, ebml_w, m.def_id.node);
801 encode_method_argument_names(ebml_w, method_fn_decl(&*ast_method));
807 fn encode_method_argument_names(ebml_w: &mut Encoder,
808 decl: &ast::FnDecl) {
809 ebml_w.start_tag(tag_method_argument_names);
810 for arg in decl.inputs.iter() {
811 ebml_w.start_tag(tag_method_argument_name);
813 ast::PatIdent(_, ref path1, _) => {
814 let name = token::get_ident(path1.node);
815 ebml_w.writer.write(name.get().as_bytes());
824 fn encode_inlined_item(ecx: &EncodeContext,
825 ebml_w: &mut Encoder,
826 ii: InlinedItemRef) {
827 let mut eii = ecx.encode_inlined_item.borrow_mut();
828 let eii: &mut EncodeInlinedItem = &mut *eii;
829 (*eii)(ecx, ebml_w, ii)
832 fn style_fn_family(s: FnStyle) -> char {
839 fn fn_style_static_method_family(s: FnStyle) -> char {
847 fn should_inline(attrs: &[Attribute]) -> bool {
849 match find_inline_attr(attrs) {
850 InlineNone | InlineNever => false,
851 InlineHint | InlineAlways => true
855 // Encodes the inherent implementations of a structure, enumeration, or trait.
856 fn encode_inherent_implementations(ecx: &EncodeContext,
857 ebml_w: &mut Encoder,
859 match ecx.tcx.inherent_impls.borrow().find(&def_id) {
861 Some(implementations) => {
862 for &impl_def_id in implementations.borrow().iter() {
863 ebml_w.start_tag(tag_items_data_item_inherent_impl);
864 encode_def_id(ebml_w, impl_def_id);
871 // Encodes the implementations of a trait defined in this crate.
872 fn encode_extension_implementations(ecx: &EncodeContext,
873 ebml_w: &mut Encoder,
874 trait_def_id: DefId) {
875 match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
877 Some(implementations) => {
878 for &impl_def_id in implementations.borrow().iter() {
879 ebml_w.start_tag(tag_items_data_item_extension_impl);
880 encode_def_id(ebml_w, impl_def_id);
887 fn encode_stability(ebml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
888 stab_opt.map(|stab| {
889 ebml_w.start_tag(tag_items_data_item_stability);
890 stab.encode(ebml_w).unwrap();
895 fn encode_info_for_item(ecx: &EncodeContext,
896 ebml_w: &mut Encoder,
898 index: &mut Vec<entry<i64>>,
900 vis: ast::Visibility) {
903 fn add_to_index(item: &Item, ebml_w: &Encoder,
904 index: &mut Vec<entry<i64>>) {
907 pos: ebml_w.writer.tell().unwrap(),
911 debug!("encoding info for item at {}",
912 tcx.sess.codemap().span_to_string(item.span));
914 let def_id = local_def(item.id);
915 let stab = stability::lookup(tcx, ast_util::local_def(item.id));
918 ItemStatic(_, m, _) => {
919 add_to_index(item, ebml_w, index);
920 ebml_w.start_tag(tag_items_data_item);
921 encode_def_id(ebml_w, def_id);
922 if m == ast::MutMutable {
923 encode_family(ebml_w, 'b');
925 encode_family(ebml_w, 'c');
927 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
928 encode_symbol(ecx, ebml_w, item.id);
929 encode_name(ebml_w, item.ident.name);
930 encode_path(ebml_w, path);
932 let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
935 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
937 encode_visibility(ebml_w, vis);
938 encode_stability(ebml_w, stab);
941 ItemFn(ref decl, fn_style, _, ref generics, _) => {
942 add_to_index(item, ebml_w, index);
943 ebml_w.start_tag(tag_items_data_item);
944 encode_def_id(ebml_w, def_id);
945 encode_family(ebml_w, style_fn_family(fn_style));
946 let tps_len = generics.ty_params.len();
947 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
948 encode_name(ebml_w, item.ident.name);
949 encode_path(ebml_w, path);
950 encode_attributes(ebml_w, item.attrs.as_slice());
951 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
952 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
954 encode_symbol(ecx, ebml_w, item.id);
956 encode_visibility(ebml_w, vis);
957 encode_stability(ebml_w, stab);
958 encode_method_argument_names(ebml_w, &**decl);
962 add_to_index(item, ebml_w, index);
963 encode_info_for_mod(ecx,
966 item.attrs.as_slice(),
972 ItemForeignMod(ref fm) => {
973 add_to_index(item, ebml_w, index);
974 ebml_w.start_tag(tag_items_data_item);
975 encode_def_id(ebml_w, def_id);
976 encode_family(ebml_w, 'n');
977 encode_name(ebml_w, item.ident.name);
978 encode_path(ebml_w, path);
980 // Encode all the items in this module.
981 for foreign_item in fm.items.iter() {
982 ebml_w.start_tag(tag_mod_child);
983 ebml_w.wr_str(def_to_string(local_def(foreign_item.id)).as_slice());
986 encode_visibility(ebml_w, vis);
987 encode_stability(ebml_w, stab);
991 add_to_index(item, ebml_w, index);
992 ebml_w.start_tag(tag_items_data_item);
993 encode_def_id(ebml_w, def_id);
994 encode_family(ebml_w, 'y');
995 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
996 encode_name(ebml_w, item.ident.name);
997 encode_path(ebml_w, path);
998 encode_visibility(ebml_w, vis);
999 encode_stability(ebml_w, stab);
1002 ItemEnum(ref enum_definition, ref generics) => {
1003 add_to_index(item, ebml_w, index);
1005 ebml_w.start_tag(tag_items_data_item);
1006 encode_def_id(ebml_w, def_id);
1007 encode_family(ebml_w, 't');
1008 encode_item_variances(ebml_w, ecx, item.id);
1009 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1010 encode_name(ebml_w, item.ident.name);
1011 encode_attributes(ebml_w, item.attrs.as_slice());
1012 for v in (*enum_definition).variants.iter() {
1013 encode_variant_id(ebml_w, local_def(v.node.id));
1015 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1016 encode_path(ebml_w, path);
1018 // Encode inherent implementations for this enumeration.
1019 encode_inherent_implementations(ecx, ebml_w, def_id);
1021 encode_visibility(ebml_w, vis);
1022 encode_stability(ebml_w, stab);
1025 encode_enum_variant_info(ecx,
1028 (*enum_definition).variants.as_slice(),
1032 ItemStruct(struct_def, _) => {
1033 let fields = ty::lookup_struct_fields(tcx, def_id);
1035 /* First, encode the fields
1036 These come first because we need to write them to make
1037 the index, and the index needs to be in the item for the
1039 let idx = encode_info_for_struct(ecx,
1044 /* Index the class*/
1045 add_to_index(item, ebml_w, index);
1047 /* Now, make an item for the class itself */
1048 ebml_w.start_tag(tag_items_data_item);
1049 encode_def_id(ebml_w, def_id);
1050 encode_family(ebml_w, 'S');
1051 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1053 encode_item_variances(ebml_w, ecx, item.id);
1054 encode_name(ebml_w, item.ident.name);
1055 encode_attributes(ebml_w, item.attrs.as_slice());
1056 encode_path(ebml_w, path.clone());
1057 encode_stability(ebml_w, stab);
1058 encode_visibility(ebml_w, vis);
1060 /* Encode def_ids for each field and method
1061 for methods, write all the stuff get_trait_method
1063 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
1065 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1067 // Encode inherent implementations for this structure.
1068 encode_inherent_implementations(ecx, ebml_w, def_id);
1070 /* Each class has its own index -- encode it */
1071 encode_index(ebml_w, idx, write_i64);
1074 // If this is a tuple-like struct, encode the type of the constructor.
1075 match struct_def.ctor_id {
1077 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1078 ctor_id, index, def_id.node);
1083 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1084 // We need to encode information about the default methods we
1085 // have inherited, so we drive this based on the impl structure.
1086 let impl_methods = tcx.impl_methods.borrow();
1087 let methods = impl_methods.get(&def_id);
1089 add_to_index(item, ebml_w, index);
1090 ebml_w.start_tag(tag_items_data_item);
1091 encode_def_id(ebml_w, def_id);
1092 encode_family(ebml_w, 'i');
1093 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1094 encode_name(ebml_w, item.ident.name);
1095 encode_attributes(ebml_w, item.attrs.as_slice());
1097 ast::TyPath(ref path, ref bounds, _) if path.segments
1099 let ident = path.segments.last().unwrap().identifier;
1100 assert!(bounds.is_none());
1101 encode_impl_type_basename(ebml_w, ident);
1105 for &method_def_id in methods.iter() {
1106 ebml_w.start_tag(tag_item_impl_method);
1107 let s = def_to_string(method_def_id);
1108 ebml_w.writer.write(s.as_bytes());
1111 for ast_trait_ref in opt_trait.iter() {
1112 let trait_ref = ty::node_id_to_trait_ref(
1113 tcx, ast_trait_ref.ref_id);
1114 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
1115 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1116 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1118 encode_path(ebml_w, path.clone());
1119 encode_stability(ebml_w, stab);
1122 // Iterate down the methods, emitting them. We rely on the
1123 // assumption that all of the actually implemented methods
1124 // appear first in the impl structure, in the same order they do
1125 // in the ast. This is a little sketchy.
1126 let num_implemented_methods = ast_methods.len();
1127 for (i, &method_def_id) in methods.iter().enumerate() {
1128 let ast_method = if i < num_implemented_methods {
1129 Some(*ast_methods.get(i))
1133 val: method_def_id.node as i64,
1134 pos: ebml_w.writer.tell().unwrap(),
1136 encode_info_for_method(ecx,
1138 &*ty::method(tcx, method_def_id),
1145 ItemTrait(_, _, ref super_traits, ref ms) => {
1146 add_to_index(item, ebml_w, index);
1147 ebml_w.start_tag(tag_items_data_item);
1148 encode_def_id(ebml_w, def_id);
1149 encode_family(ebml_w, 'I');
1150 encode_item_variances(ebml_w, ecx, item.id);
1151 let trait_def = ty::lookup_trait_def(tcx, def_id);
1152 encode_ty_type_param_defs(ebml_w, ecx,
1153 &trait_def.generics.types,
1154 tag_items_data_item_ty_param_bounds);
1155 encode_region_param_defs(ebml_w, &trait_def.generics.regions);
1156 encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1157 encode_name(ebml_w, item.ident.name);
1158 encode_attributes(ebml_w, item.attrs.as_slice());
1159 encode_visibility(ebml_w, vis);
1160 encode_stability(ebml_w, stab);
1161 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1162 ebml_w.start_tag(tag_item_trait_method);
1163 encode_def_id(ebml_w, method_def_id);
1166 ebml_w.start_tag(tag_mod_child);
1167 ebml_w.wr_str(def_to_string(method_def_id).as_slice());
1170 encode_path(ebml_w, path.clone());
1171 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1172 // reading the AST's list, because the former has already filtered out
1173 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1174 for ast_trait_ref in super_traits.iter() {
1175 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1176 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1179 // Encode the implementations of this trait.
1180 encode_extension_implementations(ecx, ebml_w, def_id);
1184 // Now output the method info for each method.
1185 let r = ty::trait_method_def_ids(tcx, def_id);
1186 for (i, &method_def_id) in r.iter().enumerate() {
1187 assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1189 let method_ty = ty::method(tcx, method_def_id);
1192 val: method_def_id.node as i64,
1193 pos: ebml_w.writer.tell().unwrap(),
1196 ebml_w.start_tag(tag_items_data_item);
1198 encode_method_ty_fields(ecx, ebml_w, &*method_ty);
1199 encode_parent_item(ebml_w, def_id);
1201 let stab = stability::lookup(tcx, method_def_id);
1202 encode_stability(ebml_w, stab);
1204 let elem = ast_map::PathName(method_ty.ident.name);
1205 encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1207 match method_ty.explicit_self {
1209 encode_family(ebml_w,
1210 fn_style_static_method_family(
1211 method_ty.fty.fn_style));
1213 let pty = ty::lookup_item_type(tcx, method_def_id);
1214 encode_bounds_and_type(ebml_w, ecx, &pty);
1218 encode_family(ebml_w,
1220 method_ty.fty.fn_style));
1225 &Required(ref tm) => {
1226 encode_attributes(ebml_w, tm.attrs.as_slice());
1227 encode_method_sort(ebml_w, 'r');
1228 encode_method_argument_names(ebml_w, &*tm.decl);
1232 encode_attributes(ebml_w, m.attrs.as_slice());
1233 // If this is a static method, we've already encoded
1235 if method_ty.explicit_self != SelfStatic {
1236 // FIXME: I feel like there is something funny going on.
1237 let pty = ty::lookup_item_type(tcx, method_def_id);
1238 encode_bounds_and_type(ebml_w, ecx, &pty);
1240 encode_method_sort(ebml_w, 'p');
1241 encode_inlined_item(ecx, ebml_w,
1242 IIMethodRef(def_id, true, &*m));
1243 encode_method_argument_names(ebml_w, method_fn_decl(m));
1250 // Encode inherent implementations for this trait.
1251 encode_inherent_implementations(ecx, ebml_w, def_id);
1254 // macros are encoded separately
1259 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1260 ebml_w: &mut Encoder,
1261 nitem: &ForeignItem,
1262 index: &mut Vec<entry<i64>>,
1266 val: nitem.id as i64,
1267 pos: ebml_w.writer.tell().unwrap(),
1270 ebml_w.start_tag(tag_items_data_item);
1271 encode_def_id(ebml_w, local_def(nitem.id));
1273 ForeignItemFn(..) => {
1274 encode_family(ebml_w, style_fn_family(NormalFn));
1275 encode_bounds_and_type(ebml_w, ecx,
1276 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1277 encode_name(ebml_w, nitem.ident.name);
1278 if abi == abi::RustIntrinsic {
1279 encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1281 encode_symbol(ecx, ebml_w, nitem.id);
1284 ForeignItemStatic(_, mutbl) => {
1286 encode_family(ebml_w, 'b');
1288 encode_family(ebml_w, 'c');
1290 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1291 encode_symbol(ecx, ebml_w, nitem.id);
1292 encode_name(ebml_w, nitem.ident.name);
1295 encode_path(ebml_w, path);
1299 fn my_visit_expr(_e: &Expr) { }
1301 fn my_visit_item(i: &Item,
1302 ebml_w: &mut Encoder,
1303 ecx_ptr: *const int,
1304 index: &mut Vec<entry<i64>>) {
1305 let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1307 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1308 ecx.tcx.map.with_path(i.id, |path| {
1309 encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1313 fn my_visit_foreign_item(ni: &ForeignItem,
1314 ebml_w: &mut Encoder,
1316 index: &mut Vec<entry<i64>>) {
1318 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1319 debug!("writing foreign item {}::{}",
1320 ecx.tcx.map.path_to_string(ni.id),
1321 token::get_ident(ni.ident));
1323 let mut ebml_w = unsafe {
1324 ebml_w.unsafe_clone()
1326 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1327 ecx.tcx.map.with_path(ni.id, |path| {
1328 encode_info_for_foreign_item(ecx, &mut ebml_w,
1334 struct EncodeVisitor<'a,'b> {
1335 ebml_w_for_visit_item: &'a mut Encoder<'b>,
1337 index: &'a mut Vec<entry<i64>>,
1340 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1341 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1342 visit::walk_expr(self, ex, ());
1345 fn visit_item(&mut self, i: &Item, _: ()) {
1346 visit::walk_item(self, i, ());
1348 self.ebml_w_for_visit_item,
1352 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1353 visit::walk_foreign_item(self, ni, ());
1354 my_visit_foreign_item(ni,
1355 self.ebml_w_for_visit_item,
1361 fn encode_info_for_items(ecx: &EncodeContext,
1362 ebml_w: &mut Encoder,
1364 -> Vec<entry<i64>> {
1365 let mut index = Vec::new();
1366 ebml_w.start_tag(tag_items_data);
1368 val: CRATE_NODE_ID as i64,
1369 pos: ebml_w.writer.tell().unwrap(),
1371 encode_info_for_mod(ecx,
1376 ast_map::Values([].iter()).chain(None),
1377 syntax::parse::token::special_idents::invalid,
1380 // See comment in `encode_side_tables_for_ii` in astencode
1381 let ecx_ptr: *const int = unsafe { mem::transmute(ecx) };
1382 visit::walk_crate(&mut EncodeVisitor {
1385 ebml_w_for_visit_item: &mut *ebml_w,
1393 // Path and definition ID indexing
1395 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1396 write_fn: |&mut MemWriter, &T|) {
1397 let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1398 for elt in index.move_iter() {
1399 let h = hash::hash(&elt.val) as uint;
1400 buckets.get_mut(h % 256).push(elt);
1403 ebml_w.start_tag(tag_index);
1404 let mut bucket_locs = Vec::new();
1405 ebml_w.start_tag(tag_index_buckets);
1406 for bucket in buckets.iter() {
1407 bucket_locs.push(ebml_w.writer.tell().unwrap());
1408 ebml_w.start_tag(tag_index_buckets_bucket);
1409 for elt in bucket.iter() {
1410 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1411 assert!(elt.pos < 0xffff_ffff);
1413 let wr: &mut MemWriter = ebml_w.writer;
1414 wr.write_be_u32(elt.pos as u32);
1416 write_fn(ebml_w.writer, &elt.val);
1422 ebml_w.start_tag(tag_index_table);
1423 for pos in bucket_locs.iter() {
1424 assert!(*pos < 0xffff_ffff);
1425 let wr: &mut MemWriter = ebml_w.writer;
1426 wr.write_be_u32(*pos as u32);
1432 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1433 let wr: &mut MemWriter = writer;
1434 assert!(n < 0x7fff_ffff);
1435 wr.write_be_u32(n as u32);
1438 fn encode_meta_item(ebml_w: &mut Encoder, mi: Gc<MetaItem>) {
1440 MetaWord(ref name) => {
1441 ebml_w.start_tag(tag_meta_item_word);
1442 ebml_w.start_tag(tag_meta_item_name);
1443 ebml_w.writer.write(name.get().as_bytes());
1447 MetaNameValue(ref name, ref value) => {
1449 LitStr(ref value, _) => {
1450 ebml_w.start_tag(tag_meta_item_name_value);
1451 ebml_w.start_tag(tag_meta_item_name);
1452 ebml_w.writer.write(name.get().as_bytes());
1454 ebml_w.start_tag(tag_meta_item_value);
1455 ebml_w.writer.write(value.get().as_bytes());
1459 _ => {/* FIXME (#623): encode other variants */ }
1462 MetaList(ref name, ref items) => {
1463 ebml_w.start_tag(tag_meta_item_list);
1464 ebml_w.start_tag(tag_meta_item_name);
1465 ebml_w.writer.write(name.get().as_bytes());
1467 for inner_item in items.iter() {
1468 encode_meta_item(ebml_w, *inner_item);
1475 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1476 ebml_w.start_tag(tag_attributes);
1477 for attr in attrs.iter() {
1478 ebml_w.start_tag(tag_attribute);
1479 encode_meta_item(ebml_w, attr.node.value);
1485 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1486 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1487 // Pull the cnums and name,vers,hash out of cstore
1488 let mut deps = Vec::new();
1489 cstore.iter_crate_data(|key, val| {
1490 let dep = decoder::CrateDep {
1492 name: decoder::get_crate_name(val.data()),
1493 hash: decoder::get_crate_hash(val.data()),
1499 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1501 // Sanity-check the crate numbers
1502 let mut expected_cnum = 1;
1503 for n in deps.iter() {
1504 assert_eq!(n.cnum, expected_cnum);
1511 // We're just going to write a list of crate 'name-hash-version's, with
1512 // the assumption that they are numbered 1 to n.
1513 // FIXME (#2166): This is not nearly enough to support correct versioning
1514 // but is enough to get transitive crate dependencies working.
1515 ebml_w.start_tag(tag_crate_deps);
1516 let r = get_ordered_deps(cstore);
1517 for dep in r.iter() {
1518 encode_crate_dep(ebml_w, (*dep).clone());
1523 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1524 ebml_w.start_tag(tag_lang_items);
1526 for (i, def_id) in ecx.tcx.lang_items.items() {
1527 for id in def_id.iter() {
1528 if id.krate == LOCAL_CRATE {
1529 ebml_w.start_tag(tag_lang_items_item);
1531 ebml_w.start_tag(tag_lang_items_item_id);
1533 let wr: &mut MemWriter = ebml_w.writer;
1534 wr.write_be_u32(i as u32);
1536 ebml_w.end_tag(); // tag_lang_items_item_id
1538 ebml_w.start_tag(tag_lang_items_item_node_id);
1540 let wr: &mut MemWriter = ebml_w.writer;
1541 wr.write_be_u32(id.node as u32);
1543 ebml_w.end_tag(); // tag_lang_items_item_node_id
1545 ebml_w.end_tag(); // tag_lang_items_item
1550 for i in ecx.tcx.lang_items.missing.iter() {
1551 ebml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1554 ebml_w.end_tag(); // tag_lang_items
1557 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1558 ebml_w.start_tag(tag_native_libraries);
1560 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1563 cstore::NativeStatic => {} // these libraries are not propagated
1564 cstore::NativeFramework | cstore::NativeUnknown => {
1565 ebml_w.start_tag(tag_native_libraries_lib);
1567 ebml_w.start_tag(tag_native_libraries_kind);
1568 ebml_w.writer.write_be_u32(kind as u32);
1571 ebml_w.start_tag(tag_native_libraries_name);
1572 ebml_w.writer.write(lib.as_bytes());
1583 fn encode_plugin_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1584 match ecx.tcx.sess.plugin_registrar_fn.get() {
1585 Some(id) => { ebml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1590 /// Given a span, write the text of that span into the output stream
1591 /// as an exported macro
1592 fn encode_macro_def(ecx: &EncodeContext,
1593 ebml_w: &mut Encoder,
1594 span: &syntax::codemap::Span) {
1595 let def = ecx.tcx.sess.codemap().span_to_snippet(*span)
1596 .expect("Unable to find source for macro");
1597 ebml_w.start_tag(tag_macro_def);
1598 ebml_w.wr_str(def.as_slice());
1602 /// Serialize the text of the exported macros
1603 fn encode_macro_defs(ecx: &EncodeContext,
1605 ebml_w: &mut Encoder) {
1606 ebml_w.start_tag(tag_exported_macros);
1607 for span in krate.exported_macros.iter() {
1608 encode_macro_def(ecx, ebml_w, span);
1613 struct ImplVisitor<'a,'b,'c> {
1614 ecx: &'a EncodeContext<'b>,
1615 ebml_w: &'a mut Encoder<'c>,
1618 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1619 fn visit_item(&mut self, item: &Item, _: ()) {
1621 ItemImpl(_, Some(ref trait_ref), _, _) => {
1622 let def_map = &self.ecx.tcx.def_map;
1623 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1624 let def_id = trait_def.def_id();
1626 // Load eagerly if this is an implementation of the Drop trait
1627 // or if the trait is not defined in this crate.
1628 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1629 def_id.krate != LOCAL_CRATE {
1630 self.ebml_w.start_tag(tag_impls_impl);
1631 encode_def_id(self.ebml_w, local_def(item.id));
1632 self.ebml_w.end_tag();
1637 visit::walk_item(self, item, ());
1641 /// Encodes implementations that are eagerly loaded.
1643 /// None of this is necessary in theory; we can load all implementations
1644 /// lazily. However, in two cases the optimizations to lazily load
1645 /// implementations are not yet implemented. These two cases, which require us
1646 /// to load implementations eagerly, are:
1648 /// * Destructors (implementations of the Drop trait).
1650 /// * Implementations of traits not defined in this crate.
1651 fn encode_impls<'a>(ecx: &'a EncodeContext,
1653 ebml_w: &'a mut Encoder) {
1654 ebml_w.start_tag(tag_impls);
1657 let mut visitor = ImplVisitor {
1661 visit::walk_crate(&mut visitor, krate, ());
1667 fn encode_misc_info(ecx: &EncodeContext,
1669 ebml_w: &mut Encoder) {
1670 ebml_w.start_tag(tag_misc_info);
1671 ebml_w.start_tag(tag_misc_info_crate_items);
1672 for &item in krate.module.items.iter() {
1673 ebml_w.start_tag(tag_mod_child);
1674 ebml_w.wr_str(def_to_string(local_def(item.id)).as_slice());
1677 each_auxiliary_node_id(item, |auxiliary_node_id| {
1678 ebml_w.start_tag(tag_mod_child);
1679 ebml_w.wr_str(def_to_string(local_def(
1680 auxiliary_node_id)).as_slice());
1686 // Encode reexports for the root module.
1687 encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1693 fn encode_reachable_extern_fns(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1694 ebml_w.start_tag(tag_reachable_extern_fns);
1696 for id in ecx.reachable.iter() {
1697 match ecx.tcx.map.find(*id) {
1698 Some(ast_map::NodeItem(i)) => {
1700 ast::ItemFn(_, _, abi, _, _) if abi != abi::Rust => {
1701 ebml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1713 fn encode_crate_dep(ebml_w: &mut Encoder,
1714 dep: decoder::CrateDep) {
1715 ebml_w.start_tag(tag_crate_dep);
1716 ebml_w.start_tag(tag_crate_dep_crate_name);
1717 ebml_w.writer.write(dep.name.as_bytes());
1719 ebml_w.start_tag(tag_crate_dep_hash);
1720 ebml_w.writer.write(dep.hash.as_str().as_bytes());
1725 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1726 ebml_w.start_tag(tag_crate_hash);
1727 ebml_w.writer.write(hash.as_str().as_bytes());
1731 fn encode_crate_name(ebml_w: &mut Encoder, crate_name: &str) {
1732 ebml_w.start_tag(tag_crate_crate_name);
1733 ebml_w.writer.write(crate_name.as_bytes());
1737 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1738 ebml_w.start_tag(tag_crate_triple);
1739 ebml_w.writer.write(triple.as_bytes());
1743 fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
1744 ebml_w.start_tag(tag_dylib_dependency_formats);
1745 match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
1747 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1748 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1749 cstore::RequireDynamic => "d",
1750 cstore::RequireStatic => "s",
1752 }).collect::<Vec<String>>();
1753 ebml_w.writer.write(s.connect(",").as_bytes());
1760 // NB: Increment this as you change the metadata encoding version.
1761 pub static metadata_encoding_version : &'static [u8] =
1762 &[0x72, //'r' as u8,
1768 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1769 let mut wr = MemWriter::new();
1770 encode_metadata_inner(&mut wr, parms, krate);
1771 wr.unwrap().move_iter().collect()
1774 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1778 lang_item_bytes: u64,
1779 native_lib_bytes: u64,
1780 plugin_registrar_fn_bytes: u64,
1781 macro_defs_bytes: u64,
1789 let mut stats = Stats {
1793 native_lib_bytes: 0,
1794 plugin_registrar_fn_bytes: 0,
1795 macro_defs_bytes: 0,
1809 encode_inlined_item,
1811 non_inlineable_statics,
1815 let ecx = EncodeContext {
1818 reexports2: reexports2,
1819 item_symbols: item_symbols,
1820 non_inlineable_statics: non_inlineable_statics,
1821 link_meta: link_meta,
1823 encode_inlined_item: RefCell::new(encode_inlined_item),
1824 type_abbrevs: RefCell::new(HashMap::new()),
1825 reachable: reachable,
1828 let mut ebml_w = writer::Encoder::new(wr);
1830 encode_crate_name(&mut ebml_w, ecx.link_meta.crate_name.as_slice());
1831 encode_crate_triple(&mut ebml_w,
1837 encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1838 encode_dylib_dependency_formats(&mut ebml_w, &ecx);
1840 let mut i = ebml_w.writer.tell().unwrap();
1841 encode_attributes(&mut ebml_w, krate.attrs.as_slice());
1842 stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1844 i = ebml_w.writer.tell().unwrap();
1845 encode_crate_deps(&mut ebml_w, ecx.cstore);
1846 stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1848 // Encode the language items.
1849 i = ebml_w.writer.tell().unwrap();
1850 encode_lang_items(&ecx, &mut ebml_w);
1851 stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1853 // Encode the native libraries used
1854 i = ebml_w.writer.tell().unwrap();
1855 encode_native_libraries(&ecx, &mut ebml_w);
1856 stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1858 // Encode the plugin registrar function
1859 i = ebml_w.writer.tell().unwrap();
1860 encode_plugin_registrar_fn(&ecx, &mut ebml_w);
1861 stats.plugin_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1863 // Encode macro definitions
1864 i = ebml_w.writer.tell().unwrap();
1865 encode_macro_defs(&ecx, krate, &mut ebml_w);
1866 stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1868 // Encode the def IDs of impls, for coherence checking.
1869 i = ebml_w.writer.tell().unwrap();
1870 encode_impls(&ecx, krate, &mut ebml_w);
1871 stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1873 // Encode miscellaneous info.
1874 i = ebml_w.writer.tell().unwrap();
1875 encode_misc_info(&ecx, krate, &mut ebml_w);
1876 encode_reachable_extern_fns(&ecx, &mut ebml_w);
1877 stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1879 // Encode and index the items.
1880 ebml_w.start_tag(tag_items);
1881 i = ebml_w.writer.tell().unwrap();
1882 let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1883 stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1885 i = ebml_w.writer.tell().unwrap();
1886 encode_index(&mut ebml_w, items_index, write_i64);
1887 stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1890 stats.total_bytes = ebml_w.writer.tell().unwrap();
1892 if tcx.sess.meta_stats() {
1893 for e in ebml_w.writer.get_ref().iter() {
1895 stats.zero_bytes += 1;
1899 println!("metadata stats:");
1900 println!(" attribute bytes: {}", stats.attr_bytes);
1901 println!(" dep bytes: {}", stats.dep_bytes);
1902 println!(" lang item bytes: {}", stats.lang_item_bytes);
1903 println!(" native bytes: {}", stats.native_lib_bytes);
1904 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
1905 println!(" macro def bytes: {}", stats.macro_defs_bytes);
1906 println!(" impl bytes: {}", stats.impl_bytes);
1907 println!(" misc bytes: {}", stats.misc_bytes);
1908 println!(" item bytes: {}", stats.item_bytes);
1909 println!(" index bytes: {}", stats.index_bytes);
1910 println!(" zero bytes: {}", stats.zero_bytes);
1911 println!(" total bytes: {}", stats.total_bytes);
1915 // Get the encoded string for a type
1916 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> String {
1917 let mut wr = MemWriter::new();
1918 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1919 diag: tcx.sess.diagnostic(),
1922 abbrevs: &RefCell::new(HashMap::new())
1924 String::from_utf8(wr.unwrap()).unwrap()