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::*;
47 use syntax::attr::AttrMetaMethods;
49 use syntax::crateid::CrateId;
50 use syntax::diagnostic::SpanHandler;
51 use syntax::parse::token::InternedString;
52 use syntax::parse::token::special_idents;
53 use syntax::parse::token;
54 use syntax::visit::Visitor;
57 use writer = serialize::ebml::writer;
59 /// A borrowed version of ast::InlinedItem.
60 pub enum InlinedItemRef<'a> {
61 IIItemRef(&'a ast::Item),
62 IIMethodRef(ast::DefId, bool, &'a ast::Method),
63 IIForeignRef(&'a ast::ForeignItem)
66 pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
68 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
70 ii: InlinedItemRef|: 'a;
72 pub struct EncodeParams<'a> {
73 pub diag: &'a SpanHandler,
74 pub tcx: &'a ty::ctxt,
75 pub reexports2: &'a middle::resolve::ExportMap2,
76 pub item_symbols: &'a RefCell<NodeMap<String>>,
77 pub non_inlineable_statics: &'a RefCell<NodeSet>,
78 pub link_meta: &'a LinkMeta,
79 pub cstore: &'a cstore::CStore,
80 pub encode_inlined_item: EncodeInlinedItem<'a>,
81 pub reachable: &'a NodeSet,
84 pub struct EncodeContext<'a> {
85 pub diag: &'a SpanHandler,
86 pub tcx: &'a ty::ctxt,
87 pub reexports2: &'a middle::resolve::ExportMap2,
88 pub item_symbols: &'a RefCell<NodeMap<String>>,
89 pub non_inlineable_statics: &'a RefCell<NodeSet>,
90 pub link_meta: &'a LinkMeta,
91 pub cstore: &'a cstore::CStore,
92 pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
93 pub type_abbrevs: tyencode::abbrev_map,
94 pub reachable: &'a NodeSet,
97 fn encode_name(ebml_w: &mut Encoder, name: Name) {
98 ebml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
101 fn encode_impl_type_basename(ebml_w: &mut Encoder, name: Ident) {
102 ebml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
105 pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
106 ebml_w.wr_tagged_str(tag_def_id, def_to_str(id).as_slice());
115 fn encode_trait_ref(ebml_w: &mut Encoder,
117 trait_ref: &ty::TraitRef,
119 let ty_str_ctxt = &tyencode::ctxt {
123 abbrevs: &ecx.type_abbrevs
126 ebml_w.start_tag(tag);
127 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
131 fn encode_impl_vtables(ebml_w: &mut Encoder,
133 vtables: &typeck::vtable_res) {
134 ebml_w.start_tag(tag_item_impl_vtables);
135 astencode::encode_vtable_res(ecx, ebml_w, vtables);
139 // Item info table encoding
140 fn encode_family(ebml_w: &mut Encoder, c: char) {
141 ebml_w.start_tag(tag_items_data_item_family);
142 ebml_w.writer.write(&[c as u8]);
146 pub fn def_to_str(did: DefId) -> String {
147 format!("{}:{}", did.krate, did.node)
150 fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
152 params: &VecPerParamSpace<ty::TypeParameterDef>,
154 let ty_str_ctxt = &tyencode::ctxt {
158 abbrevs: &ecx.type_abbrevs
160 for param in params.iter() {
161 ebml_w.start_tag(tag);
162 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
167 fn encode_region_param_defs(ebml_w: &mut Encoder,
168 params: &VecPerParamSpace<ty::RegionParameterDef>) {
169 for param in params.iter() {
170 ebml_w.start_tag(tag_region_param_def);
172 ebml_w.start_tag(tag_region_param_def_ident);
173 encode_name(ebml_w, param.name);
176 ebml_w.wr_tagged_str(tag_region_param_def_def_id,
177 def_to_str(param.def_id).as_slice());
179 ebml_w.wr_tagged_u64(tag_region_param_def_space,
180 param.space.to_uint() as u64);
182 ebml_w.wr_tagged_u64(tag_region_param_def_index,
189 fn encode_item_variances(ebml_w: &mut Encoder,
192 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
193 ebml_w.start_tag(tag_item_variances);
198 fn encode_bounds_and_type(ebml_w: &mut Encoder,
200 pty: &ty::Polytype) {
201 encode_ty_type_param_defs(ebml_w, ecx, &pty.generics.types,
202 tag_items_data_item_ty_param_bounds);
203 encode_region_param_defs(ebml_w, &pty.generics.regions);
204 encode_type(ecx, ebml_w, pty.ty);
207 fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
208 ebml_w.start_tag(tag_items_data_item_variant);
209 let s = def_to_str(vid);
210 ebml_w.writer.write(s.as_bytes());
214 pub fn write_type(ecx: &EncodeContext,
215 ebml_w: &mut Encoder,
217 let ty_str_ctxt = &tyencode::ctxt {
221 abbrevs: &ecx.type_abbrevs
223 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
226 fn encode_type(ecx: &EncodeContext,
227 ebml_w: &mut Encoder,
229 ebml_w.start_tag(tag_items_data_item_type);
230 write_type(ecx, ebml_w, typ);
234 fn encode_method_fty(ecx: &EncodeContext,
235 ebml_w: &mut Encoder,
236 typ: &ty::BareFnTy) {
237 ebml_w.start_tag(tag_item_method_fty);
239 let ty_str_ctxt = &tyencode::ctxt {
243 abbrevs: &ecx.type_abbrevs
245 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
250 fn encode_symbol(ecx: &EncodeContext,
251 ebml_w: &mut Encoder,
253 ebml_w.start_tag(tag_items_data_item_symbol);
254 match ecx.item_symbols.borrow().find(&id) {
256 debug!("encode_symbol(id={:?}, str={})", id, *x);
257 ebml_w.writer.write(x.as_bytes());
260 ecx.diag.handler().bug(
261 format!("encode_symbol: id not found {}", id).as_slice());
267 fn encode_disr_val(_: &EncodeContext,
268 ebml_w: &mut Encoder,
269 disr_val: ty::Disr) {
270 ebml_w.start_tag(tag_disr_val);
271 let s = disr_val.to_str();
272 ebml_w.writer.write(s.as_bytes());
276 fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
277 ebml_w.start_tag(tag_items_data_parent_item);
278 let s = def_to_str(id);
279 ebml_w.writer.write(s.as_bytes());
283 fn encode_struct_fields(ebml_w: &mut Encoder,
284 fields: &[ty::field_ty],
286 for f in fields.iter() {
287 if f.name == special_idents::unnamed_field.name {
288 ebml_w.start_tag(tag_item_unnamed_field);
290 ebml_w.start_tag(tag_item_field);
291 encode_name(ebml_w, f.name);
293 encode_struct_field_family(ebml_w, f.vis);
294 encode_def_id(ebml_w, f.id);
295 ebml_w.start_tag(tag_item_field_origin);
296 let s = def_to_str(origin);
297 ebml_w.writer.write(s.as_bytes());
303 fn encode_enum_variant_info(ecx: &EncodeContext,
304 ebml_w: &mut Encoder,
306 variants: &[P<Variant>],
307 index: &mut Vec<entry<i64>>,
308 generics: &ast::Generics) {
309 debug!("encode_enum_variant_info(id={:?})", id);
311 let mut disr_val = 0;
313 let vi = ty::enum_variants(ecx.tcx,
314 ast::DefId { krate: LOCAL_CRATE, node: id });
315 for variant in variants.iter() {
316 let def_id = local_def(variant.node.id);
318 val: variant.node.id as i64,
319 pos: ebml_w.writer.tell().unwrap(),
321 ebml_w.start_tag(tag_items_data_item);
322 encode_def_id(ebml_w, def_id);
323 match variant.node.kind {
324 ast::TupleVariantKind(_) => encode_family(ebml_w, 'v'),
325 ast::StructVariantKind(_) => encode_family(ebml_w, 'V')
327 encode_name(ebml_w, variant.node.name.name);
328 encode_parent_item(ebml_w, local_def(id));
329 encode_visibility(ebml_w, variant.node.vis);
330 encode_attributes(ebml_w, variant.node.attrs.as_slice());
332 let stab = stability::lookup(ecx.tcx, ast_util::local_def(variant.node.id));
333 encode_stability(ebml_w, stab);
335 match variant.node.kind {
336 ast::TupleVariantKind(ref args)
337 if args.len() > 0 && generics.ty_params.len() == 0 => {
338 encode_symbol(ecx, ebml_w, variant.node.id);
340 ast::TupleVariantKind(_) => {},
341 ast::StructVariantKind(_) => {
342 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
343 let idx = encode_info_for_struct(ecx,
347 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
348 encode_index(ebml_w, idx, write_i64);
351 if vi.get(i).disr_val != disr_val {
352 encode_disr_val(ecx, ebml_w, vi.get(i).disr_val);
353 disr_val = vi.get(i).disr_val;
355 encode_bounds_and_type(ebml_w, ecx,
356 &lookup_item_type(ecx.tcx, def_id));
358 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(ebml_w, path));
365 fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
367 ebml_w.start_tag(tag_path);
368 ebml_w.wr_tagged_u32(tag_path_len, path.clone().count() as u32);
371 ast_map::PathMod(_) => tag_path_elem_mod,
372 ast_map::PathName(_) => tag_path_elem_name
374 ebml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
379 fn encode_reexported_static_method(ebml_w: &mut Encoder,
380 exp: &middle::resolve::Export2,
381 method_def_id: DefId,
382 method_ident: Ident) {
383 debug!("(encode reexported static method) {}::{}",
384 exp.name, token::get_ident(method_ident));
385 ebml_w.start_tag(tag_items_data_item_reexport);
386 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
387 ebml_w.wr_str(def_to_str(method_def_id).as_slice());
389 ebml_w.start_tag(tag_items_data_item_reexport_name);
390 ebml_w.wr_str(format!("{}::{}",
392 token::get_ident(method_ident)).as_slice());
397 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
398 ebml_w: &mut Encoder,
399 exp: &middle::resolve::Export2)
401 let impl_methods = ecx.tcx.impl_methods.borrow();
402 match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
403 Some(implementations) => {
404 for base_impl_did in implementations.borrow().iter() {
405 for &method_did in impl_methods.get(base_impl_did).iter() {
406 let m = ty::method(ecx.tcx, method_did);
407 if m.explicit_self == ast::SelfStatic {
408 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
419 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
420 ebml_w: &mut Encoder,
421 exp: &middle::resolve::Export2)
423 match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
425 for m in methods.iter() {
426 if m.explicit_self == ast::SelfStatic {
427 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
437 fn encode_reexported_static_methods(ecx: &EncodeContext,
438 ebml_w: &mut Encoder,
440 exp: &middle::resolve::Export2) {
441 match ecx.tcx.map.find(exp.def_id.node) {
442 Some(ast_map::NodeItem(item)) => {
443 let original_name = token::get_ident(item.ident);
445 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
446 let (mut a, mut b) = (path, mod_path.clone());
448 match (a.next(), b.next()) {
449 (None, None) => return true,
450 (None, _) | (_, None) => return false,
451 (Some(x), Some(y)) => if x != y { return false },
457 // We don't need to reexport static methods on items
458 // declared in the same module as our `pub use ...` since
459 // that's done when we encode the item itself.
461 // The only exception is when the reexport *changes* the
462 // name e.g. `pub use Foo = self::Bar` -- we have
463 // encoded metadata for static methods relative to Bar,
464 // but not yet for Foo.
466 if path_differs || original_name.get() != exp.name.as_slice() {
467 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
468 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
469 debug!("(encode reexported static methods) {} \
475 debug!("(encode reexported static methods) {} [base]",
484 /// Iterates through "auxiliary node IDs", which are node IDs that describe
485 /// top-level items that are sub-items of the given item. Specifically:
487 /// * For enums, iterates through the node IDs of the variants.
489 /// * For newtype structs, iterates through the node ID of the constructor.
490 fn each_auxiliary_node_id(item: Gc<Item>, callback: |NodeId| -> bool) -> bool {
491 let mut continue_ = true;
493 ItemEnum(ref enum_def, _) => {
494 for variant in enum_def.variants.iter() {
495 continue_ = callback(variant.node.id);
501 ItemStruct(struct_def, _) => {
502 // If this is a newtype struct, return the constructor.
503 match struct_def.ctor_id {
504 Some(ctor_id) if struct_def.fields.len() > 0 &&
505 struct_def.fields.get(0).node.kind.is_unnamed() => {
506 continue_ = callback(ctor_id);
517 fn encode_reexports(ecx: &EncodeContext,
518 ebml_w: &mut Encoder,
521 debug!("(encoding info for module) encoding reexports for {}", id);
522 match ecx.reexports2.borrow().find(&id) {
523 Some(ref exports) => {
524 debug!("(encoding info for module) found reexports for {}", id);
525 for exp in exports.iter() {
526 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
532 ebml_w.start_tag(tag_items_data_item_reexport);
533 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
534 ebml_w.wr_str(def_to_str(exp.def_id).as_slice());
536 ebml_w.start_tag(tag_items_data_item_reexport_name);
537 ebml_w.wr_str(exp.name.as_slice());
540 encode_reexported_static_methods(ecx, ebml_w, path.clone(), exp);
544 debug!("(encoding info for module) found no reexports for {}",
550 fn encode_info_for_mod(ecx: &EncodeContext,
551 ebml_w: &mut Encoder,
558 ebml_w.start_tag(tag_items_data_item);
559 encode_def_id(ebml_w, local_def(id));
560 encode_family(ebml_w, 'm');
561 encode_name(ebml_w, name.name);
562 debug!("(encoding info for module) encoding info for module ID {}", id);
564 // Encode info about all the module children.
565 for item in md.items.iter() {
566 ebml_w.start_tag(tag_mod_child);
567 ebml_w.wr_str(def_to_str(local_def(item.id)).as_slice());
570 each_auxiliary_node_id(*item, |auxiliary_node_id| {
571 ebml_w.start_tag(tag_mod_child);
572 ebml_w.wr_str(def_to_str(local_def(
573 auxiliary_node_id)).as_slice());
580 let (ident, did) = (item.ident, item.id);
581 debug!("(encoding info for module) ... encoding impl {} \
583 token::get_ident(ident),
584 did, ecx.tcx.map.node_to_str(did));
586 ebml_w.start_tag(tag_mod_impl);
587 ebml_w.wr_str(def_to_str(local_def(did)).as_slice());
594 encode_path(ebml_w, path.clone());
595 encode_visibility(ebml_w, vis);
597 let stab = stability::lookup(ecx.tcx, ast_util::local_def(id));
598 encode_stability(ebml_w, stab);
600 // Encode the reexports of this module, if this module is public.
602 debug!("(encoding info for module) encoding reexports for {}", id);
603 encode_reexports(ecx, ebml_w, id, path);
605 encode_attributes(ebml_w, attrs);
610 fn encode_struct_field_family(ebml_w: &mut Encoder,
611 visibility: Visibility) {
612 encode_family(ebml_w, match visibility {
618 fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
619 ebml_w.start_tag(tag_items_data_item_visibility);
620 let ch = match visibility {
624 ebml_w.wr_str(str::from_char(ch).as_slice());
628 fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_) {
629 ebml_w.start_tag(tag_item_trait_method_explicit_self);
631 // Encode the base self type.
632 match explicit_self {
633 SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
634 SelfValue => { ebml_w.writer.write(&[ 'v' as u8 ]); }
635 SelfUniq => { ebml_w.writer.write(&[ '~' as u8 ]); }
636 SelfRegion(_, m) => {
637 // FIXME(#4846) encode custom lifetime
638 ebml_w.writer.write(&['&' as u8]);
639 encode_mutability(ebml_w, m);
645 fn encode_mutability(ebml_w: &mut Encoder,
646 m: ast::Mutability) {
648 MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
649 MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); }
654 fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
655 ebml_w.start_tag(tag_item_trait_method_sort);
656 ebml_w.writer.write(&[ sort as u8 ]);
660 fn encode_provided_source(ebml_w: &mut Encoder,
661 source_opt: Option<DefId>) {
662 for source in source_opt.iter() {
663 ebml_w.start_tag(tag_item_method_provided_source);
664 let s = def_to_str(*source);
665 ebml_w.writer.write(s.as_bytes());
670 /* Returns an index of items in this class */
671 fn encode_info_for_struct(ecx: &EncodeContext,
672 ebml_w: &mut Encoder,
673 fields: &[ty::field_ty],
674 global_index: &mut Vec<entry<i64>>)
676 /* Each class has its own index, since different classes
677 may have fields with the same name */
678 let mut index = Vec::new();
680 /* We encode both private and public fields -- need to include
681 private fields to get the offsets right */
682 for field in fields.iter() {
684 let id = field.id.node;
686 index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
687 global_index.push(entry {
689 pos: ebml_w.writer.tell().unwrap(),
691 ebml_w.start_tag(tag_items_data_item);
692 debug!("encode_info_for_struct: doing {} {}",
693 token::get_name(nm), id);
694 encode_struct_field_family(ebml_w, field.vis);
695 encode_name(ebml_w, nm);
696 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
697 encode_def_id(ebml_w, local_def(id));
703 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
704 ebml_w: &mut Encoder,
707 index: &mut Vec<entry<i64>>,
711 pos: ebml_w.writer.tell().unwrap(),
714 ebml_w.start_tag(tag_items_data_item);
715 encode_def_id(ebml_w, local_def(ctor_id));
716 encode_family(ebml_w, 'f');
717 encode_bounds_and_type(ebml_w, ecx,
718 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
719 encode_name(ebml_w, name.name);
720 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
721 ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
722 encode_parent_item(ebml_w, local_def(struct_id));
724 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
725 encode_symbol(ecx, ebml_w, ctor_id);
728 let stab = stability::lookup(ecx.tcx, ast_util::local_def(ctor_id));
729 encode_stability(ebml_w, stab);
731 // indicate that this is a tuple struct ctor, because downstream users will normally want
732 // the tuple struct definition, but without this there is no way for them to tell that
733 // they actually have a ctor rather than a normal function
734 ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
740 fn encode_method_ty_fields(ecx: &EncodeContext,
741 ebml_w: &mut Encoder,
742 method_ty: &ty::Method) {
743 encode_def_id(ebml_w, method_ty.def_id);
744 encode_name(ebml_w, method_ty.ident.name);
745 encode_ty_type_param_defs(ebml_w, ecx, &method_ty.generics.types,
746 tag_item_method_tps);
747 encode_method_fty(ecx, ebml_w, &method_ty.fty);
748 encode_visibility(ebml_w, method_ty.vis);
749 encode_explicit_self(ebml_w, method_ty.explicit_self);
750 let fn_style = method_ty.fty.fn_style;
751 match method_ty.explicit_self {
753 encode_family(ebml_w, fn_style_static_method_family(fn_style));
755 _ => encode_family(ebml_w, style_fn_family(fn_style))
757 encode_provided_source(ebml_w, method_ty.provided_source);
760 fn encode_info_for_method(ecx: &EncodeContext,
761 ebml_w: &mut Encoder,
763 impl_path: PathElems,
764 is_default_impl: bool,
766 ast_method_opt: Option<Gc<Method>>) {
768 debug!("encode_info_for_method: {:?} {}", m.def_id,
769 token::get_ident(m.ident));
770 ebml_w.start_tag(tag_items_data_item);
772 encode_method_ty_fields(ecx, ebml_w, m);
773 encode_parent_item(ebml_w, local_def(parent_id));
775 let stab = stability::lookup(ecx.tcx, m.def_id);
776 encode_stability(ebml_w, stab);
778 // The type for methods gets encoded twice, which is unfortunate.
779 let pty = lookup_item_type(ecx.tcx, m.def_id);
780 encode_bounds_and_type(ebml_w, ecx, &pty);
782 let elem = ast_map::PathName(m.ident.name);
783 encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
784 match ast_method_opt {
785 Some(ast_method) => {
786 encode_attributes(ebml_w, ast_method.attrs.as_slice())
791 for &ast_method in ast_method_opt.iter() {
792 let any_types = !pty.generics.types.is_empty();
793 if any_types || is_default_impl || should_inline(ast_method.attrs.as_slice()) {
794 encode_inlined_item(ecx, ebml_w,
795 IIMethodRef(local_def(parent_id), false,
798 encode_symbol(ecx, ebml_w, m.def_id.node);
800 encode_method_argument_names(ebml_w, &*ast_method.decl);
806 fn encode_method_argument_names(ebml_w: &mut Encoder,
807 decl: &ast::FnDecl) {
808 ebml_w.start_tag(tag_method_argument_names);
809 for arg in decl.inputs.iter() {
810 ebml_w.start_tag(tag_method_argument_name);
812 ast::PatIdent(_, ref path1, _) => {
813 let name = token::get_ident(path1.node);
814 ebml_w.writer.write(name.get().as_bytes());
823 fn encode_inlined_item(ecx: &EncodeContext,
824 ebml_w: &mut Encoder,
825 ii: InlinedItemRef) {
826 let mut eii = ecx.encode_inlined_item.borrow_mut();
827 let eii: &mut EncodeInlinedItem = &mut *eii;
828 (*eii)(ecx, ebml_w, ii)
831 fn style_fn_family(s: FnStyle) -> char {
838 fn fn_style_static_method_family(s: FnStyle) -> char {
846 fn should_inline(attrs: &[Attribute]) -> bool {
848 match find_inline_attr(attrs) {
849 InlineNone | InlineNever => false,
850 InlineHint | InlineAlways => true
854 // Encodes the inherent implementations of a structure, enumeration, or trait.
855 fn encode_inherent_implementations(ecx: &EncodeContext,
856 ebml_w: &mut Encoder,
858 match ecx.tcx.inherent_impls.borrow().find(&def_id) {
860 Some(implementations) => {
861 for &impl_def_id in implementations.borrow().iter() {
862 ebml_w.start_tag(tag_items_data_item_inherent_impl);
863 encode_def_id(ebml_w, impl_def_id);
870 // Encodes the implementations of a trait defined in this crate.
871 fn encode_extension_implementations(ecx: &EncodeContext,
872 ebml_w: &mut Encoder,
873 trait_def_id: DefId) {
874 match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
876 Some(implementations) => {
877 for &impl_def_id in implementations.borrow().iter() {
878 ebml_w.start_tag(tag_items_data_item_extension_impl);
879 encode_def_id(ebml_w, impl_def_id);
886 fn encode_sized(ebml_w: &mut Encoder, sized: Sized) {
887 ebml_w.start_tag(tag_items_data_item_sized);
888 let ch = match sized {
892 ebml_w.wr_str(str::from_char(ch).as_slice());
896 fn encode_stability(ebml_w: &mut Encoder, stab_opt: Option<attr::Stability>) {
897 stab_opt.map(|stab| {
898 ebml_w.start_tag(tag_items_data_item_stability);
899 stab.encode(ebml_w).unwrap();
904 fn encode_info_for_item(ecx: &EncodeContext,
905 ebml_w: &mut Encoder,
907 index: &mut Vec<entry<i64>>,
909 vis: ast::Visibility) {
912 fn add_to_index(item: &Item, ebml_w: &Encoder,
913 index: &mut Vec<entry<i64>>) {
916 pos: ebml_w.writer.tell().unwrap(),
920 debug!("encoding info for item at {}",
921 tcx.sess.codemap().span_to_str(item.span));
923 let def_id = local_def(item.id);
924 let stab = stability::lookup(tcx, ast_util::local_def(item.id));
927 ItemStatic(_, m, _) => {
928 add_to_index(item, ebml_w, index);
929 ebml_w.start_tag(tag_items_data_item);
930 encode_def_id(ebml_w, def_id);
931 if m == ast::MutMutable {
932 encode_family(ebml_w, 'b');
934 encode_family(ebml_w, 'c');
936 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
937 encode_symbol(ecx, ebml_w, item.id);
938 encode_name(ebml_w, item.ident.name);
939 encode_path(ebml_w, path);
941 let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
944 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
946 encode_visibility(ebml_w, vis);
947 encode_stability(ebml_w, stab);
950 ItemFn(ref decl, fn_style, _, ref generics, _) => {
951 add_to_index(item, ebml_w, index);
952 ebml_w.start_tag(tag_items_data_item);
953 encode_def_id(ebml_w, def_id);
954 encode_family(ebml_w, style_fn_family(fn_style));
955 let tps_len = generics.ty_params.len();
956 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
957 encode_name(ebml_w, item.ident.name);
958 encode_path(ebml_w, path);
959 encode_attributes(ebml_w, item.attrs.as_slice());
960 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
961 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
963 encode_symbol(ecx, ebml_w, item.id);
965 encode_visibility(ebml_w, vis);
966 encode_stability(ebml_w, stab);
967 encode_method_argument_names(ebml_w, &**decl);
971 add_to_index(item, ebml_w, index);
972 encode_info_for_mod(ecx,
975 item.attrs.as_slice(),
981 ItemForeignMod(ref fm) => {
982 add_to_index(item, ebml_w, index);
983 ebml_w.start_tag(tag_items_data_item);
984 encode_def_id(ebml_w, def_id);
985 encode_family(ebml_w, 'n');
986 encode_name(ebml_w, item.ident.name);
987 encode_path(ebml_w, path);
989 // Encode all the items in this module.
990 for foreign_item in fm.items.iter() {
991 ebml_w.start_tag(tag_mod_child);
992 ebml_w.wr_str(def_to_str(local_def(foreign_item.id)).as_slice());
995 encode_visibility(ebml_w, vis);
996 encode_stability(ebml_w, stab);
1000 add_to_index(item, ebml_w, index);
1001 ebml_w.start_tag(tag_items_data_item);
1002 encode_def_id(ebml_w, def_id);
1003 encode_family(ebml_w, 'y');
1004 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1005 encode_name(ebml_w, item.ident.name);
1006 encode_path(ebml_w, path);
1007 encode_visibility(ebml_w, vis);
1008 encode_stability(ebml_w, stab);
1011 ItemEnum(ref enum_definition, ref generics) => {
1012 add_to_index(item, ebml_w, index);
1014 ebml_w.start_tag(tag_items_data_item);
1015 encode_def_id(ebml_w, def_id);
1016 encode_family(ebml_w, 't');
1017 encode_item_variances(ebml_w, ecx, item.id);
1018 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1019 encode_name(ebml_w, item.ident.name);
1020 encode_attributes(ebml_w, item.attrs.as_slice());
1021 for v in (*enum_definition).variants.iter() {
1022 encode_variant_id(ebml_w, local_def(v.node.id));
1024 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1025 encode_path(ebml_w, path);
1027 // Encode inherent implementations for this enumeration.
1028 encode_inherent_implementations(ecx, ebml_w, def_id);
1030 encode_visibility(ebml_w, vis);
1031 encode_stability(ebml_w, stab);
1034 encode_enum_variant_info(ecx,
1037 (*enum_definition).variants.as_slice(),
1041 ItemStruct(struct_def, _) => {
1042 let fields = ty::lookup_struct_fields(tcx, def_id);
1044 /* First, encode the fields
1045 These come first because we need to write them to make
1046 the index, and the index needs to be in the item for the
1048 let idx = encode_info_for_struct(ecx,
1053 /* Index the class*/
1054 add_to_index(item, ebml_w, index);
1056 /* Now, make an item for the class itself */
1057 ebml_w.start_tag(tag_items_data_item);
1058 encode_def_id(ebml_w, def_id);
1059 encode_family(ebml_w, 'S');
1060 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1062 encode_item_variances(ebml_w, ecx, item.id);
1063 encode_name(ebml_w, item.ident.name);
1064 encode_attributes(ebml_w, item.attrs.as_slice());
1065 encode_path(ebml_w, path.clone());
1066 encode_stability(ebml_w, stab);
1067 encode_visibility(ebml_w, vis);
1069 /* Encode def_ids for each field and method
1070 for methods, write all the stuff get_trait_method
1072 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
1074 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1076 // Encode inherent implementations for this structure.
1077 encode_inherent_implementations(ecx, ebml_w, def_id);
1079 /* Each class has its own index -- encode it */
1080 encode_index(ebml_w, idx, write_i64);
1083 // If this is a tuple-like struct, encode the type of the constructor.
1084 match struct_def.ctor_id {
1086 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1087 ctor_id, index, def_id.node);
1092 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1093 // We need to encode information about the default methods we
1094 // have inherited, so we drive this based on the impl structure.
1095 let impl_methods = tcx.impl_methods.borrow();
1096 let methods = impl_methods.get(&def_id);
1098 add_to_index(item, ebml_w, index);
1099 ebml_w.start_tag(tag_items_data_item);
1100 encode_def_id(ebml_w, def_id);
1101 encode_family(ebml_w, 'i');
1102 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1103 encode_name(ebml_w, item.ident.name);
1104 encode_attributes(ebml_w, item.attrs.as_slice());
1106 ast::TyPath(ref path, ref bounds, _) if path.segments
1108 let ident = path.segments.last().unwrap().identifier;
1109 assert!(bounds.is_none());
1110 encode_impl_type_basename(ebml_w, ident);
1114 for &method_def_id in methods.iter() {
1115 ebml_w.start_tag(tag_item_impl_method);
1116 let s = def_to_str(method_def_id);
1117 ebml_w.writer.write(s.as_bytes());
1120 for ast_trait_ref in opt_trait.iter() {
1121 let trait_ref = ty::node_id_to_trait_ref(
1122 tcx, ast_trait_ref.ref_id);
1123 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
1124 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1125 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1127 encode_path(ebml_w, path.clone());
1128 encode_stability(ebml_w, stab);
1131 // Iterate down the methods, emitting them. We rely on the
1132 // assumption that all of the actually implemented methods
1133 // appear first in the impl structure, in the same order they do
1134 // in the ast. This is a little sketchy.
1135 let num_implemented_methods = ast_methods.len();
1136 for (i, &method_def_id) in methods.iter().enumerate() {
1137 let ast_method = if i < num_implemented_methods {
1138 Some(*ast_methods.get(i))
1142 val: method_def_id.node as i64,
1143 pos: ebml_w.writer.tell().unwrap(),
1145 encode_info_for_method(ecx,
1147 &*ty::method(tcx, method_def_id),
1154 ItemTrait(_, sized, ref super_traits, ref ms) => {
1155 add_to_index(item, ebml_w, index);
1156 ebml_w.start_tag(tag_items_data_item);
1157 encode_def_id(ebml_w, def_id);
1158 encode_family(ebml_w, 'I');
1159 encode_item_variances(ebml_w, ecx, item.id);
1160 let trait_def = ty::lookup_trait_def(tcx, def_id);
1161 encode_ty_type_param_defs(ebml_w, ecx,
1162 &trait_def.generics.types,
1163 tag_items_data_item_ty_param_bounds);
1164 encode_region_param_defs(ebml_w, &trait_def.generics.regions);
1165 encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1166 encode_name(ebml_w, item.ident.name);
1167 encode_attributes(ebml_w, item.attrs.as_slice());
1168 // When we fix the rest of the supertrait nastiness (FIXME(#8559)), we
1169 // should no longer need this ugly little hack either.
1170 encode_sized(ebml_w, sized);
1171 encode_visibility(ebml_w, vis);
1172 encode_stability(ebml_w, stab);
1173 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1174 ebml_w.start_tag(tag_item_trait_method);
1175 encode_def_id(ebml_w, method_def_id);
1178 ebml_w.start_tag(tag_mod_child);
1179 ebml_w.wr_str(def_to_str(method_def_id).as_slice());
1182 encode_path(ebml_w, path.clone());
1183 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1184 // reading the AST's list, because the former has already filtered out
1185 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1186 for ast_trait_ref in super_traits.iter() {
1187 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1188 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1191 // Encode the implementations of this trait.
1192 encode_extension_implementations(ecx, ebml_w, def_id);
1196 // Now output the method info for each method.
1197 let r = ty::trait_method_def_ids(tcx, def_id);
1198 for (i, &method_def_id) in r.iter().enumerate() {
1199 assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1201 let method_ty = ty::method(tcx, method_def_id);
1204 val: method_def_id.node as i64,
1205 pos: ebml_w.writer.tell().unwrap(),
1208 ebml_w.start_tag(tag_items_data_item);
1210 encode_method_ty_fields(ecx, ebml_w, &*method_ty);
1211 encode_parent_item(ebml_w, def_id);
1213 let stab = stability::lookup(tcx, method_def_id);
1214 encode_stability(ebml_w, stab);
1216 let elem = ast_map::PathName(method_ty.ident.name);
1217 encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1219 match method_ty.explicit_self {
1221 encode_family(ebml_w,
1222 fn_style_static_method_family(
1223 method_ty.fty.fn_style));
1225 let pty = ty::lookup_item_type(tcx, method_def_id);
1226 encode_bounds_and_type(ebml_w, ecx, &pty);
1230 encode_family(ebml_w,
1232 method_ty.fty.fn_style));
1237 &Required(ref tm) => {
1238 encode_attributes(ebml_w, tm.attrs.as_slice());
1239 encode_method_sort(ebml_w, 'r');
1240 encode_method_argument_names(ebml_w, &*tm.decl);
1244 encode_attributes(ebml_w, m.attrs.as_slice());
1245 // If this is a static method, we've already encoded
1247 if method_ty.explicit_self != SelfStatic {
1248 // FIXME: I feel like there is something funny going on.
1249 let pty = ty::lookup_item_type(tcx, method_def_id);
1250 encode_bounds_and_type(ebml_w, ecx, &pty);
1252 encode_method_sort(ebml_w, 'p');
1253 encode_inlined_item(ecx, ebml_w,
1254 IIMethodRef(def_id, true, &*m));
1255 encode_method_argument_names(ebml_w, &*m.decl);
1262 // Encode inherent implementations for this trait.
1263 encode_inherent_implementations(ecx, ebml_w, def_id);
1266 // macros are encoded separately
1271 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1272 ebml_w: &mut Encoder,
1273 nitem: &ForeignItem,
1274 index: &mut Vec<entry<i64>>,
1278 val: nitem.id as i64,
1279 pos: ebml_w.writer.tell().unwrap(),
1282 ebml_w.start_tag(tag_items_data_item);
1283 encode_def_id(ebml_w, local_def(nitem.id));
1285 ForeignItemFn(..) => {
1286 encode_family(ebml_w, style_fn_family(NormalFn));
1287 encode_bounds_and_type(ebml_w, ecx,
1288 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1289 encode_name(ebml_w, nitem.ident.name);
1290 if abi == abi::RustIntrinsic {
1291 encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1293 encode_symbol(ecx, ebml_w, nitem.id);
1296 ForeignItemStatic(_, mutbl) => {
1298 encode_family(ebml_w, 'b');
1300 encode_family(ebml_w, 'c');
1302 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1303 encode_symbol(ecx, ebml_w, nitem.id);
1304 encode_name(ebml_w, nitem.ident.name);
1307 encode_path(ebml_w, path);
1311 fn my_visit_expr(_e: &Expr) { }
1313 fn my_visit_item(i: &Item,
1314 ebml_w: &mut Encoder,
1315 ecx_ptr: *const int,
1316 index: &mut Vec<entry<i64>>) {
1317 let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1319 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1320 ecx.tcx.map.with_path(i.id, |path| {
1321 encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1325 fn my_visit_foreign_item(ni: &ForeignItem,
1326 ebml_w: &mut Encoder,
1328 index: &mut Vec<entry<i64>>) {
1330 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1331 debug!("writing foreign item {}::{}",
1332 ecx.tcx.map.path_to_str(ni.id),
1333 token::get_ident(ni.ident));
1335 let mut ebml_w = unsafe {
1336 ebml_w.unsafe_clone()
1338 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1339 ecx.tcx.map.with_path(ni.id, |path| {
1340 encode_info_for_foreign_item(ecx, &mut ebml_w,
1346 struct EncodeVisitor<'a,'b> {
1347 ebml_w_for_visit_item: &'a mut Encoder<'b>,
1349 index: &'a mut Vec<entry<i64>>,
1352 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1353 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1354 visit::walk_expr(self, ex, ());
1357 fn visit_item(&mut self, i: &Item, _: ()) {
1358 visit::walk_item(self, i, ());
1360 self.ebml_w_for_visit_item,
1364 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1365 visit::walk_foreign_item(self, ni, ());
1366 my_visit_foreign_item(ni,
1367 self.ebml_w_for_visit_item,
1373 fn encode_info_for_items(ecx: &EncodeContext,
1374 ebml_w: &mut Encoder,
1376 -> Vec<entry<i64>> {
1377 let mut index = Vec::new();
1378 ebml_w.start_tag(tag_items_data);
1380 val: CRATE_NODE_ID as i64,
1381 pos: ebml_w.writer.tell().unwrap(),
1383 encode_info_for_mod(ecx,
1388 ast_map::Values([].iter()).chain(None),
1389 syntax::parse::token::special_idents::invalid,
1392 // See comment in `encode_side_tables_for_ii` in astencode
1393 let ecx_ptr: *const int = unsafe { mem::transmute(ecx) };
1394 visit::walk_crate(&mut EncodeVisitor {
1397 ebml_w_for_visit_item: &mut *ebml_w,
1405 // Path and definition ID indexing
1407 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1408 write_fn: |&mut MemWriter, &T|) {
1409 let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1410 for elt in index.move_iter() {
1411 let h = hash::hash(&elt.val) as uint;
1412 buckets.get_mut(h % 256).push(elt);
1415 ebml_w.start_tag(tag_index);
1416 let mut bucket_locs = Vec::new();
1417 ebml_w.start_tag(tag_index_buckets);
1418 for bucket in buckets.iter() {
1419 bucket_locs.push(ebml_w.writer.tell().unwrap());
1420 ebml_w.start_tag(tag_index_buckets_bucket);
1421 for elt in bucket.iter() {
1422 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1423 assert!(elt.pos < 0xffff_ffff);
1425 let wr: &mut MemWriter = ebml_w.writer;
1426 wr.write_be_u32(elt.pos as u32);
1428 write_fn(ebml_w.writer, &elt.val);
1434 ebml_w.start_tag(tag_index_table);
1435 for pos in bucket_locs.iter() {
1436 assert!(*pos < 0xffff_ffff);
1437 let wr: &mut MemWriter = ebml_w.writer;
1438 wr.write_be_u32(*pos as u32);
1444 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1445 let wr: &mut MemWriter = writer;
1446 assert!(n < 0x7fff_ffff);
1447 wr.write_be_u32(n as u32);
1450 fn encode_meta_item(ebml_w: &mut Encoder, mi: Gc<MetaItem>) {
1452 MetaWord(ref name) => {
1453 ebml_w.start_tag(tag_meta_item_word);
1454 ebml_w.start_tag(tag_meta_item_name);
1455 ebml_w.writer.write(name.get().as_bytes());
1459 MetaNameValue(ref name, ref value) => {
1461 LitStr(ref value, _) => {
1462 ebml_w.start_tag(tag_meta_item_name_value);
1463 ebml_w.start_tag(tag_meta_item_name);
1464 ebml_w.writer.write(name.get().as_bytes());
1466 ebml_w.start_tag(tag_meta_item_value);
1467 ebml_w.writer.write(value.get().as_bytes());
1471 _ => {/* FIXME (#623): encode other variants */ }
1474 MetaList(ref name, ref items) => {
1475 ebml_w.start_tag(tag_meta_item_list);
1476 ebml_w.start_tag(tag_meta_item_name);
1477 ebml_w.writer.write(name.get().as_bytes());
1479 for inner_item in items.iter() {
1480 encode_meta_item(ebml_w, *inner_item);
1487 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1488 ebml_w.start_tag(tag_attributes);
1489 for attr in attrs.iter() {
1490 ebml_w.start_tag(tag_attribute);
1491 encode_meta_item(ebml_w, attr.node.value);
1497 // So there's a special crate attribute called 'crate_id' which defines the
1498 // metadata that Rust cares about for linking crates. If the user didn't
1499 // provide it we will throw it in anyway with a default value.
1500 fn synthesize_crate_attrs(ecx: &EncodeContext,
1501 krate: &Crate) -> Vec<Attribute> {
1503 fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute {
1504 assert!(!ecx.link_meta.crateid.name.is_empty());
1506 attr::mk_attr_inner(attr::mk_attr_id(),
1507 attr::mk_name_value_item_str(
1508 InternedString::new("crate_id"),
1509 token::intern_and_get_ident(ecx.link_meta
1515 let mut attrs = Vec::new();
1516 for attr in krate.attrs.iter() {
1517 if !attr.check_name("crate_id") {
1521 attrs.push(synthesize_crateid_attr(ecx));
1526 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1527 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1528 // Pull the cnums and name,vers,hash out of cstore
1529 let mut deps = Vec::new();
1530 cstore.iter_crate_data(|key, val| {
1531 let dep = decoder::CrateDep {
1533 crate_id: decoder::get_crate_id(val.data()),
1534 hash: decoder::get_crate_hash(val.data())
1540 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1542 // Sanity-check the crate numbers
1543 let mut expected_cnum = 1;
1544 for n in deps.iter() {
1545 assert_eq!(n.cnum, expected_cnum);
1552 // We're just going to write a list of crate 'name-hash-version's, with
1553 // the assumption that they are numbered 1 to n.
1554 // FIXME (#2166): This is not nearly enough to support correct versioning
1555 // but is enough to get transitive crate dependencies working.
1556 ebml_w.start_tag(tag_crate_deps);
1557 let r = get_ordered_deps(cstore);
1558 for dep in r.iter() {
1559 encode_crate_dep(ebml_w, (*dep).clone());
1564 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1565 ebml_w.start_tag(tag_lang_items);
1567 for (i, def_id) in ecx.tcx.lang_items.items() {
1568 for id in def_id.iter() {
1569 if id.krate == LOCAL_CRATE {
1570 ebml_w.start_tag(tag_lang_items_item);
1572 ebml_w.start_tag(tag_lang_items_item_id);
1574 let wr: &mut MemWriter = ebml_w.writer;
1575 wr.write_be_u32(i as u32);
1577 ebml_w.end_tag(); // tag_lang_items_item_id
1579 ebml_w.start_tag(tag_lang_items_item_node_id);
1581 let wr: &mut MemWriter = ebml_w.writer;
1582 wr.write_be_u32(id.node as u32);
1584 ebml_w.end_tag(); // tag_lang_items_item_node_id
1586 ebml_w.end_tag(); // tag_lang_items_item
1591 for i in ecx.tcx.lang_items.missing.iter() {
1592 ebml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1595 ebml_w.end_tag(); // tag_lang_items
1598 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1599 ebml_w.start_tag(tag_native_libraries);
1601 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1604 cstore::NativeStatic => {} // these libraries are not propagated
1605 cstore::NativeFramework | cstore::NativeUnknown => {
1606 ebml_w.start_tag(tag_native_libraries_lib);
1608 ebml_w.start_tag(tag_native_libraries_kind);
1609 ebml_w.writer.write_be_u32(kind as u32);
1612 ebml_w.start_tag(tag_native_libraries_name);
1613 ebml_w.writer.write(lib.as_bytes());
1624 fn encode_plugin_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1625 match ecx.tcx.sess.plugin_registrar_fn.get() {
1626 Some(id) => { ebml_w.wr_tagged_u32(tag_plugin_registrar_fn, id); }
1631 struct MacroDefVisitor<'a, 'b, 'c> {
1632 ecx: &'a EncodeContext<'b>,
1633 ebml_w: &'a mut Encoder<'c>
1636 impl<'a, 'b, 'c> Visitor<()> for MacroDefVisitor<'a, 'b, 'c> {
1637 fn visit_item(&mut self, item: &Item, _: ()) {
1640 let def = self.ecx.tcx.sess.codemap().span_to_snippet(item.span)
1641 .expect("Unable to find source for macro");
1642 self.ebml_w.start_tag(tag_macro_def);
1643 self.ebml_w.wr_str(def.as_slice());
1644 self.ebml_w.end_tag();
1648 visit::walk_item(self, item, ());
1652 fn encode_macro_defs<'a>(ecx: &'a EncodeContext,
1654 ebml_w: &'a mut Encoder) {
1655 ebml_w.start_tag(tag_exported_macros);
1657 let mut visitor = MacroDefVisitor {
1661 visit::walk_crate(&mut visitor, krate, ());
1666 struct ImplVisitor<'a,'b,'c> {
1667 ecx: &'a EncodeContext<'b>,
1668 ebml_w: &'a mut Encoder<'c>,
1671 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1672 fn visit_item(&mut self, item: &Item, _: ()) {
1674 ItemImpl(_, Some(ref trait_ref), _, _) => {
1675 let def_map = &self.ecx.tcx.def_map;
1676 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1677 let def_id = trait_def.def_id();
1679 // Load eagerly if this is an implementation of the Drop trait
1680 // or if the trait is not defined in this crate.
1681 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1682 def_id.krate != LOCAL_CRATE {
1683 self.ebml_w.start_tag(tag_impls_impl);
1684 encode_def_id(self.ebml_w, local_def(item.id));
1685 self.ebml_w.end_tag();
1690 visit::walk_item(self, item, ());
1694 /// Encodes implementations that are eagerly loaded.
1696 /// None of this is necessary in theory; we can load all implementations
1697 /// lazily. However, in two cases the optimizations to lazily load
1698 /// implementations are not yet implemented. These two cases, which require us
1699 /// to load implementations eagerly, are:
1701 /// * Destructors (implementations of the Drop trait).
1703 /// * Implementations of traits not defined in this crate.
1704 fn encode_impls<'a>(ecx: &'a EncodeContext,
1706 ebml_w: &'a mut Encoder) {
1707 ebml_w.start_tag(tag_impls);
1710 let mut visitor = ImplVisitor {
1714 visit::walk_crate(&mut visitor, krate, ());
1720 fn encode_misc_info(ecx: &EncodeContext,
1722 ebml_w: &mut Encoder) {
1723 ebml_w.start_tag(tag_misc_info);
1724 ebml_w.start_tag(tag_misc_info_crate_items);
1725 for &item in krate.module.items.iter() {
1726 ebml_w.start_tag(tag_mod_child);
1727 ebml_w.wr_str(def_to_str(local_def(item.id)).as_slice());
1730 each_auxiliary_node_id(item, |auxiliary_node_id| {
1731 ebml_w.start_tag(tag_mod_child);
1732 ebml_w.wr_str(def_to_str(local_def(
1733 auxiliary_node_id)).as_slice());
1739 // Encode reexports for the root module.
1740 encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1746 fn encode_reachable_extern_fns(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1747 ebml_w.start_tag(tag_reachable_extern_fns);
1749 for id in ecx.reachable.iter() {
1750 match ecx.tcx.map.find(*id) {
1751 Some(ast_map::NodeItem(i)) => {
1753 ast::ItemFn(_, _, abi, _, _) if abi != abi::Rust => {
1754 ebml_w.wr_tagged_u32(tag_reachable_extern_fn_id, *id);
1766 fn encode_crate_dep(ebml_w: &mut Encoder,
1767 dep: decoder::CrateDep) {
1768 ebml_w.start_tag(tag_crate_dep);
1769 ebml_w.start_tag(tag_crate_dep_crateid);
1770 ebml_w.writer.write(dep.crate_id.to_str().as_bytes());
1772 ebml_w.start_tag(tag_crate_dep_hash);
1773 ebml_w.writer.write(dep.hash.as_str().as_bytes());
1778 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1779 ebml_w.start_tag(tag_crate_hash);
1780 ebml_w.writer.write(hash.as_str().as_bytes());
1784 fn encode_crate_id(ebml_w: &mut Encoder, crate_id: &CrateId) {
1785 ebml_w.start_tag(tag_crate_crateid);
1786 ebml_w.writer.write(crate_id.to_str().as_bytes());
1790 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1791 ebml_w.start_tag(tag_crate_triple);
1792 ebml_w.writer.write(triple.as_bytes());
1796 fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
1797 ebml_w.start_tag(tag_dylib_dependency_formats);
1798 match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
1800 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1801 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1802 cstore::RequireDynamic => "d",
1803 cstore::RequireStatic => "s",
1805 }).collect::<Vec<String>>();
1806 ebml_w.writer.write(s.connect(",").as_bytes());
1813 // NB: Increment this as you change the metadata encoding version.
1814 pub static metadata_encoding_version : &'static [u8] =
1815 &[0x72, //'r' as u8,
1821 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1822 let mut wr = MemWriter::new();
1823 encode_metadata_inner(&mut wr, parms, krate);
1824 wr.unwrap().move_iter().collect()
1827 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1831 lang_item_bytes: u64,
1832 native_lib_bytes: u64,
1833 plugin_registrar_fn_bytes: u64,
1834 macro_defs_bytes: u64,
1842 let mut stats = Stats {
1846 native_lib_bytes: 0,
1847 plugin_registrar_fn_bytes: 0,
1848 macro_defs_bytes: 0,
1862 encode_inlined_item,
1864 non_inlineable_statics,
1868 let ecx = EncodeContext {
1871 reexports2: reexports2,
1872 item_symbols: item_symbols,
1873 non_inlineable_statics: non_inlineable_statics,
1874 link_meta: link_meta,
1876 encode_inlined_item: RefCell::new(encode_inlined_item),
1877 type_abbrevs: RefCell::new(HashMap::new()),
1878 reachable: reachable,
1881 let mut ebml_w = writer::Encoder::new(wr);
1883 encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
1884 encode_crate_triple(&mut ebml_w,
1890 encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1891 encode_dylib_dependency_formats(&mut ebml_w, &ecx);
1893 let mut i = ebml_w.writer.tell().unwrap();
1894 let crate_attrs = synthesize_crate_attrs(&ecx, krate);
1895 encode_attributes(&mut ebml_w, crate_attrs.as_slice());
1896 stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1898 i = ebml_w.writer.tell().unwrap();
1899 encode_crate_deps(&mut ebml_w, ecx.cstore);
1900 stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1902 // Encode the language items.
1903 i = ebml_w.writer.tell().unwrap();
1904 encode_lang_items(&ecx, &mut ebml_w);
1905 stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1907 // Encode the native libraries used
1908 i = ebml_w.writer.tell().unwrap();
1909 encode_native_libraries(&ecx, &mut ebml_w);
1910 stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1912 // Encode the plugin registrar function
1913 i = ebml_w.writer.tell().unwrap();
1914 encode_plugin_registrar_fn(&ecx, &mut ebml_w);
1915 stats.plugin_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1917 // Encode macro definitions
1918 i = ebml_w.writer.tell().unwrap();
1919 encode_macro_defs(&ecx, krate, &mut ebml_w);
1920 stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1922 // Encode the def IDs of impls, for coherence checking.
1923 i = ebml_w.writer.tell().unwrap();
1924 encode_impls(&ecx, krate, &mut ebml_w);
1925 stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1927 // Encode miscellaneous info.
1928 i = ebml_w.writer.tell().unwrap();
1929 encode_misc_info(&ecx, krate, &mut ebml_w);
1930 encode_reachable_extern_fns(&ecx, &mut ebml_w);
1931 stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1933 // Encode and index the items.
1934 ebml_w.start_tag(tag_items);
1935 i = ebml_w.writer.tell().unwrap();
1936 let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1937 stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1939 i = ebml_w.writer.tell().unwrap();
1940 encode_index(&mut ebml_w, items_index, write_i64);
1941 stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1944 stats.total_bytes = ebml_w.writer.tell().unwrap();
1946 if tcx.sess.meta_stats() {
1947 for e in ebml_w.writer.get_ref().iter() {
1949 stats.zero_bytes += 1;
1953 println!("metadata stats:");
1954 println!(" attribute bytes: {}", stats.attr_bytes);
1955 println!(" dep bytes: {}", stats.dep_bytes);
1956 println!(" lang item bytes: {}", stats.lang_item_bytes);
1957 println!(" native bytes: {}", stats.native_lib_bytes);
1958 println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
1959 println!(" macro def bytes: {}", stats.macro_defs_bytes);
1960 println!(" impl bytes: {}", stats.impl_bytes);
1961 println!(" misc bytes: {}", stats.misc_bytes);
1962 println!(" item bytes: {}", stats.item_bytes);
1963 println!(" index bytes: {}", stats.index_bytes);
1964 println!(" zero bytes: {}", stats.zero_bytes);
1965 println!(" total bytes: {}", stats.total_bytes);
1969 // Get the encoded string for a type
1970 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> String {
1971 let mut wr = MemWriter::new();
1972 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1973 diag: tcx.sess.diagnostic(),
1976 abbrevs: &RefCell::new(HashMap::new())
1978 str::from_utf8_owned(Vec::from_slice(wr.get_ref())).unwrap().to_string()