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)]
17 use metadata::common::*;
19 use metadata::decoder;
20 use metadata::tyencode;
21 use middle::ty::{node_id_to_type, lookup_item_type};
22 use middle::astencode;
26 use util::nodemap::{NodeMap, NodeSet};
28 use serialize::Encodable;
30 use std::cell::RefCell;
33 use std::io::MemWriter;
35 use collections::HashMap;
39 use syntax::ast_map::{PathElem, PathElems};
41 use syntax::ast_util::*;
43 use syntax::attr::AttrMetaMethods;
45 use syntax::crateid::CrateId;
46 use syntax::diagnostic::SpanHandler;
47 use syntax::parse::token::InternedString;
48 use syntax::parse::token::special_idents;
49 use syntax::parse::token;
50 use syntax::visit::Visitor;
53 use writer = serialize::ebml::writer;
55 /// A borrowed version of ast::InlinedItem.
56 pub enum InlinedItemRef<'a> {
57 IIItemRef(&'a ast::Item),
58 IIMethodRef(ast::DefId, bool, &'a ast::Method),
59 IIForeignRef(&'a ast::ForeignItem)
62 pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
64 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
66 ii: InlinedItemRef|: 'a;
68 pub struct EncodeParams<'a> {
69 pub diag: &'a SpanHandler,
70 pub tcx: &'a ty::ctxt,
71 pub reexports2: &'a middle::resolve::ExportMap2,
72 pub item_symbols: &'a RefCell<NodeMap<~str>>,
73 pub non_inlineable_statics: &'a RefCell<NodeSet>,
74 pub link_meta: &'a LinkMeta,
75 pub cstore: &'a cstore::CStore,
76 pub encode_inlined_item: EncodeInlinedItem<'a>,
79 pub struct EncodeContext<'a> {
80 pub diag: &'a SpanHandler,
81 pub tcx: &'a ty::ctxt,
82 pub reexports2: &'a middle::resolve::ExportMap2,
83 pub item_symbols: &'a RefCell<NodeMap<~str>>,
84 pub non_inlineable_statics: &'a RefCell<NodeSet>,
85 pub link_meta: &'a LinkMeta,
86 pub cstore: &'a cstore::CStore,
87 pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
88 pub type_abbrevs: tyencode::abbrev_map,
91 fn encode_name(ebml_w: &mut Encoder, name: Name) {
92 ebml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
95 fn encode_impl_type_basename(ebml_w: &mut Encoder, name: Ident) {
96 ebml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
99 pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
100 ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
109 fn encode_trait_ref(ebml_w: &mut Encoder,
111 trait_ref: &ty::TraitRef,
113 let ty_str_ctxt = &tyencode::ctxt {
117 abbrevs: &ecx.type_abbrevs
120 ebml_w.start_tag(tag);
121 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
125 fn encode_impl_vtables(ebml_w: &mut Encoder,
127 vtables: &typeck::impl_res) {
128 ebml_w.start_tag(tag_item_impl_vtables);
129 astencode::encode_vtable_res(ecx, ebml_w, &vtables.trait_vtables);
130 astencode::encode_vtable_param_res(ecx, ebml_w, &vtables.self_vtables);
134 // Item info table encoding
135 fn encode_family(ebml_w: &mut Encoder, c: char) {
136 ebml_w.start_tag(tag_items_data_item_family);
137 ebml_w.writer.write(&[c as u8]);
141 pub fn def_to_str(did: DefId) -> ~str {
142 format!("{}:{}", did.krate, did.node)
145 fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
147 params: &[ty::TypeParameterDef],
149 let ty_str_ctxt = &tyencode::ctxt {
153 abbrevs: &ecx.type_abbrevs
155 for param in params.iter() {
156 ebml_w.start_tag(tag);
157 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
162 fn encode_region_param_defs(ebml_w: &mut Encoder,
163 params: &[ty::RegionParameterDef]) {
164 for param in params.iter() {
165 ebml_w.start_tag(tag_region_param_def);
167 ebml_w.start_tag(tag_region_param_def_ident);
168 encode_name(ebml_w, param.name);
171 ebml_w.wr_tagged_str(tag_region_param_def_def_id,
172 def_to_str(param.def_id));
178 fn encode_item_variances(ebml_w: &mut Encoder,
181 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
182 ebml_w.start_tag(tag_item_variances);
187 fn encode_bounds_and_type(ebml_w: &mut Encoder,
189 tpt: &ty::ty_param_bounds_and_ty) {
190 encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs(),
191 tag_items_data_item_ty_param_bounds);
192 encode_region_param_defs(ebml_w, tpt.generics.region_param_defs());
193 encode_type(ecx, ebml_w, tpt.ty);
196 fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
197 ebml_w.start_tag(tag_items_data_item_variant);
198 let s = def_to_str(vid);
199 ebml_w.writer.write(s.as_bytes());
203 pub fn write_type(ecx: &EncodeContext,
204 ebml_w: &mut Encoder,
206 let ty_str_ctxt = &tyencode::ctxt {
210 abbrevs: &ecx.type_abbrevs
212 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
215 fn encode_type(ecx: &EncodeContext,
216 ebml_w: &mut Encoder,
218 ebml_w.start_tag(tag_items_data_item_type);
219 write_type(ecx, ebml_w, typ);
223 fn encode_method_fty(ecx: &EncodeContext,
224 ebml_w: &mut Encoder,
225 typ: &ty::BareFnTy) {
226 ebml_w.start_tag(tag_item_method_fty);
228 let ty_str_ctxt = &tyencode::ctxt {
232 abbrevs: &ecx.type_abbrevs
234 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
239 fn encode_symbol(ecx: &EncodeContext,
240 ebml_w: &mut Encoder,
242 ebml_w.start_tag(tag_items_data_item_symbol);
243 match ecx.item_symbols.borrow().find(&id) {
245 debug!("encode_symbol(id={:?}, str={})", id, *x);
246 ebml_w.writer.write(x.as_bytes());
249 ecx.diag.handler().bug(
250 format!("encode_symbol: id not found {}", id));
256 fn encode_disr_val(_: &EncodeContext,
257 ebml_w: &mut Encoder,
258 disr_val: ty::Disr) {
259 ebml_w.start_tag(tag_disr_val);
260 let s = disr_val.to_str();
261 ebml_w.writer.write(s.as_bytes());
265 fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
266 ebml_w.start_tag(tag_items_data_parent_item);
267 let s = def_to_str(id);
268 ebml_w.writer.write(s.as_bytes());
272 fn encode_struct_fields(ebml_w: &mut Encoder,
273 fields: &[ty::field_ty],
275 for f in fields.iter() {
276 if f.name == special_idents::unnamed_field.name {
277 ebml_w.start_tag(tag_item_unnamed_field);
279 ebml_w.start_tag(tag_item_field);
280 encode_name(ebml_w, f.name);
282 encode_struct_field_family(ebml_w, f.vis);
283 encode_def_id(ebml_w, f.id);
284 ebml_w.start_tag(tag_item_field_origin);
285 let s = def_to_str(origin);
286 ebml_w.writer.write(s.as_bytes());
292 fn encode_enum_variant_info(ecx: &EncodeContext,
293 ebml_w: &mut Encoder,
295 variants: &[P<Variant>],
296 index: &mut Vec<entry<i64>>,
297 generics: &ast::Generics) {
298 debug!("encode_enum_variant_info(id={:?})", id);
300 let mut disr_val = 0;
302 let vi = ty::enum_variants(ecx.tcx,
303 ast::DefId { krate: LOCAL_CRATE, node: id });
304 for variant in variants.iter() {
305 let def_id = local_def(variant.node.id);
307 val: variant.node.id as i64,
308 pos: ebml_w.writer.tell().unwrap(),
310 ebml_w.start_tag(tag_items_data_item);
311 encode_def_id(ebml_w, def_id);
312 match variant.node.kind {
313 ast::TupleVariantKind(_) => encode_family(ebml_w, 'v'),
314 ast::StructVariantKind(_) => encode_family(ebml_w, 'V')
316 encode_name(ebml_w, variant.node.name.name);
317 encode_parent_item(ebml_w, local_def(id));
318 encode_visibility(ebml_w, variant.node.vis);
319 encode_attributes(ebml_w, variant.node.attrs.as_slice());
320 match variant.node.kind {
321 ast::TupleVariantKind(ref args)
322 if args.len() > 0 && generics.ty_params.len() == 0 => {
323 encode_symbol(ecx, ebml_w, variant.node.id);
325 ast::TupleVariantKind(_) => {},
326 ast::StructVariantKind(_) => {
327 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
328 let idx = encode_info_for_struct(ecx,
332 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
333 encode_index(ebml_w, idx, write_i64);
336 if vi.get(i).disr_val != disr_val {
337 encode_disr_val(ecx, ebml_w, vi.get(i).disr_val);
338 disr_val = vi.get(i).disr_val;
340 encode_bounds_and_type(ebml_w, ecx,
341 &lookup_item_type(ecx.tcx, def_id));
343 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(ebml_w, path));
350 fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
352 ebml_w.start_tag(tag_path);
353 ebml_w.wr_tagged_u32(tag_path_len, path.clone().len() as u32);
356 ast_map::PathMod(_) => tag_path_elem_mod,
357 ast_map::PathName(_) => tag_path_elem_name
359 ebml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
364 fn encode_reexported_static_method(ebml_w: &mut Encoder,
365 exp: &middle::resolve::Export2,
366 method_def_id: DefId,
367 method_ident: Ident) {
368 debug!("(encode reexported static method) {}::{}",
369 exp.name, token::get_ident(method_ident));
370 ebml_w.start_tag(tag_items_data_item_reexport);
371 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
372 ebml_w.wr_str(def_to_str(method_def_id));
374 ebml_w.start_tag(tag_items_data_item_reexport_name);
375 ebml_w.wr_str(format!("{}::{}", exp.name, token::get_ident(method_ident)));
380 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
381 ebml_w: &mut Encoder,
382 exp: &middle::resolve::Export2)
384 let impl_methods = ecx.tcx.impl_methods.borrow();
385 match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
386 Some(implementations) => {
387 for base_impl_did in implementations.borrow().iter() {
388 for &method_did in impl_methods.get(base_impl_did).iter() {
389 let m = ty::method(ecx.tcx, method_did);
390 if m.explicit_self == ast::SelfStatic {
391 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
402 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
403 ebml_w: &mut Encoder,
404 exp: &middle::resolve::Export2)
406 match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
408 for m in methods.iter() {
409 if m.explicit_self == ast::SelfStatic {
410 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
420 fn encode_reexported_static_methods(ecx: &EncodeContext,
421 ebml_w: &mut Encoder,
423 exp: &middle::resolve::Export2) {
424 match ecx.tcx.map.find(exp.def_id.node) {
425 Some(ast_map::NodeItem(item)) => {
426 let original_name = token::get_ident(item.ident);
428 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
429 let (mut a, mut b) = (path, mod_path.clone());
431 match (a.next(), b.next()) {
432 (None, None) => return true,
433 (None, _) | (_, None) => return false,
434 (Some(x), Some(y)) => if x != y { return false },
440 // We don't need to reexport static methods on items
441 // declared in the same module as our `pub use ...` since
442 // that's done when we encode the item itself.
444 // The only exception is when the reexport *changes* the
445 // name e.g. `pub use Foo = self::Bar` -- we have
446 // encoded metadata for static methods relative to Bar,
447 // but not yet for Foo.
449 if path_differs || original_name.get() != exp.name {
450 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
451 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
452 debug!("(encode reexported static methods) {} \
458 debug!("(encode reexported static methods) {} [base]",
467 /// Iterates through "auxiliary node IDs", which are node IDs that describe
468 /// top-level items that are sub-items of the given item. Specifically:
470 /// * For enums, iterates through the node IDs of the variants.
472 /// * For newtype structs, iterates through the node ID of the constructor.
473 fn each_auxiliary_node_id(item: @Item, callback: |NodeId| -> bool) -> bool {
474 let mut continue_ = true;
476 ItemEnum(ref enum_def, _) => {
477 for variant in enum_def.variants.iter() {
478 continue_ = callback(variant.node.id);
484 ItemStruct(struct_def, _) => {
485 // If this is a newtype struct, return the constructor.
486 match struct_def.ctor_id {
487 Some(ctor_id) if struct_def.fields.len() > 0 &&
488 struct_def.fields.get(0).node.kind.is_unnamed() => {
489 continue_ = callback(ctor_id);
500 fn encode_reexports(ecx: &EncodeContext,
501 ebml_w: &mut Encoder,
504 debug!("(encoding info for module) encoding reexports for {}", id);
505 match ecx.reexports2.borrow().find(&id) {
506 Some(ref exports) => {
507 debug!("(encoding info for module) found reexports for {}", id);
508 for exp in exports.iter() {
509 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
515 ebml_w.start_tag(tag_items_data_item_reexport);
516 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
517 ebml_w.wr_str(def_to_str(exp.def_id));
519 ebml_w.start_tag(tag_items_data_item_reexport_name);
520 ebml_w.wr_str(exp.name);
523 encode_reexported_static_methods(ecx, ebml_w, path.clone(), exp);
527 debug!("(encoding info for module) found no reexports for {}",
533 fn encode_info_for_mod(ecx: &EncodeContext,
534 ebml_w: &mut Encoder,
540 ebml_w.start_tag(tag_items_data_item);
541 encode_def_id(ebml_w, local_def(id));
542 encode_family(ebml_w, 'm');
543 encode_name(ebml_w, name.name);
544 debug!("(encoding info for module) encoding info for module ID {}", id);
546 // Encode info about all the module children.
547 for item in md.items.iter() {
548 ebml_w.start_tag(tag_mod_child);
549 ebml_w.wr_str(def_to_str(local_def(item.id)));
552 each_auxiliary_node_id(*item, |auxiliary_node_id| {
553 ebml_w.start_tag(tag_mod_child);
554 ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
561 let (ident, did) = (item.ident, item.id);
562 debug!("(encoding info for module) ... encoding impl {} \
564 token::get_ident(ident),
565 did, ecx.tcx.map.node_to_str(did));
567 ebml_w.start_tag(tag_mod_impl);
568 ebml_w.wr_str(def_to_str(local_def(did)));
575 encode_path(ebml_w, path.clone());
576 encode_visibility(ebml_w, vis);
578 // Encode the reexports of this module, if this module is public.
580 debug!("(encoding info for module) encoding reexports for {}", id);
581 encode_reexports(ecx, ebml_w, id, path);
587 fn encode_struct_field_family(ebml_w: &mut Encoder,
588 visibility: Visibility) {
589 encode_family(ebml_w, match visibility {
595 fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
596 ebml_w.start_tag(tag_items_data_item_visibility);
597 let ch = match visibility {
601 ebml_w.wr_str(str::from_char(ch));
605 fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_) {
606 ebml_w.start_tag(tag_item_trait_method_explicit_self);
608 // Encode the base self type.
609 match explicit_self {
610 SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
611 SelfValue => { ebml_w.writer.write(&[ 'v' as u8 ]); }
612 SelfUniq => { ebml_w.writer.write(&[ '~' as u8 ]); }
613 SelfRegion(_, m) => {
614 // FIXME(#4846) encode custom lifetime
615 ebml_w.writer.write(&['&' as u8]);
616 encode_mutability(ebml_w, m);
622 fn encode_mutability(ebml_w: &mut Encoder,
623 m: ast::Mutability) {
625 MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
626 MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); }
631 fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
632 ebml_w.start_tag(tag_item_trait_method_sort);
633 ebml_w.writer.write(&[ sort as u8 ]);
637 fn encode_provided_source(ebml_w: &mut Encoder,
638 source_opt: Option<DefId>) {
639 for source in source_opt.iter() {
640 ebml_w.start_tag(tag_item_method_provided_source);
641 let s = def_to_str(*source);
642 ebml_w.writer.write(s.as_bytes());
647 /* Returns an index of items in this class */
648 fn encode_info_for_struct(ecx: &EncodeContext,
649 ebml_w: &mut Encoder,
650 fields: &[ty::field_ty],
651 global_index: &mut Vec<entry<i64>>)
653 /* Each class has its own index, since different classes
654 may have fields with the same name */
655 let mut index = Vec::new();
657 /* We encode both private and public fields -- need to include
658 private fields to get the offsets right */
659 for field in fields.iter() {
661 let id = field.id.node;
663 index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
664 global_index.push(entry {
666 pos: ebml_w.writer.tell().unwrap(),
668 ebml_w.start_tag(tag_items_data_item);
669 debug!("encode_info_for_struct: doing {} {}",
670 token::get_name(nm), id);
671 encode_struct_field_family(ebml_w, field.vis);
672 encode_name(ebml_w, nm);
673 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
674 encode_def_id(ebml_w, local_def(id));
680 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
681 ebml_w: &mut Encoder,
684 index: &mut Vec<entry<i64>>,
688 pos: ebml_w.writer.tell().unwrap(),
691 ebml_w.start_tag(tag_items_data_item);
692 encode_def_id(ebml_w, local_def(ctor_id));
693 encode_family(ebml_w, 'f');
694 encode_bounds_and_type(ebml_w, ecx,
695 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
696 encode_name(ebml_w, name.name);
697 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
698 ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
699 encode_parent_item(ebml_w, local_def(struct_id));
701 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
702 encode_symbol(ecx, ebml_w, ctor_id);
705 // indicate that this is a tuple struct ctor, because downstream users will normally want
706 // the tuple struct definition, but without this there is no way for them to tell that
707 // they actually have a ctor rather than a normal function
708 ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
714 fn encode_method_ty_fields(ecx: &EncodeContext,
715 ebml_w: &mut Encoder,
716 method_ty: &ty::Method) {
717 encode_def_id(ebml_w, method_ty.def_id);
718 encode_name(ebml_w, method_ty.ident.name);
719 encode_ty_type_param_defs(ebml_w, ecx,
720 method_ty.generics.type_param_defs(),
721 tag_item_method_tps);
722 encode_method_fty(ecx, ebml_w, &method_ty.fty);
723 encode_visibility(ebml_w, method_ty.vis);
724 encode_explicit_self(ebml_w, method_ty.explicit_self);
725 let fn_style = method_ty.fty.fn_style;
726 match method_ty.explicit_self {
728 encode_family(ebml_w, fn_style_static_method_family(fn_style));
730 _ => encode_family(ebml_w, style_fn_family(fn_style))
732 encode_provided_source(ebml_w, method_ty.provided_source);
735 fn encode_info_for_method(ecx: &EncodeContext,
736 ebml_w: &mut Encoder,
738 impl_path: PathElems,
739 is_default_impl: bool,
741 ast_method_opt: Option<@Method>) {
743 debug!("encode_info_for_method: {:?} {}", m.def_id,
744 token::get_ident(m.ident));
745 ebml_w.start_tag(tag_items_data_item);
747 encode_method_ty_fields(ecx, ebml_w, m);
748 encode_parent_item(ebml_w, local_def(parent_id));
750 // The type for methods gets encoded twice, which is unfortunate.
751 let tpt = lookup_item_type(ecx.tcx, m.def_id);
752 encode_bounds_and_type(ebml_w, ecx, &tpt);
754 let elem = ast_map::PathName(m.ident.name);
755 encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
756 match ast_method_opt {
757 Some(ast_method) => {
758 encode_attributes(ebml_w, ast_method.attrs.as_slice())
763 for &ast_method in ast_method_opt.iter() {
764 let num_params = tpt.generics.type_param_defs().len();
765 if num_params > 0u ||
767 should_inline(ast_method.attrs.as_slice()) {
768 encode_inlined_item(ecx, ebml_w,
769 IIMethodRef(local_def(parent_id), false, ast_method));
771 encode_symbol(ecx, ebml_w, m.def_id.node);
778 fn encode_inlined_item(ecx: &EncodeContext,
779 ebml_w: &mut Encoder,
780 ii: InlinedItemRef) {
781 let mut eii = ecx.encode_inlined_item.borrow_mut();
782 let eii: &mut EncodeInlinedItem = &mut *eii;
783 (*eii)(ecx, ebml_w, ii)
786 fn style_fn_family(s: FnStyle) -> char {
794 fn fn_style_static_method_family(s: FnStyle) -> char {
798 _ => fail!("extern fn can't be static")
803 fn should_inline(attrs: &[Attribute]) -> bool {
805 match find_inline_attr(attrs) {
806 InlineNone | InlineNever => false,
807 InlineHint | InlineAlways => true
811 // Encodes the inherent implementations of a structure, enumeration, or trait.
812 fn encode_inherent_implementations(ecx: &EncodeContext,
813 ebml_w: &mut Encoder,
815 match ecx.tcx.inherent_impls.borrow().find(&def_id) {
817 Some(implementations) => {
818 for &impl_def_id in implementations.borrow().iter() {
819 ebml_w.start_tag(tag_items_data_item_inherent_impl);
820 encode_def_id(ebml_w, impl_def_id);
827 // Encodes the implementations of a trait defined in this crate.
828 fn encode_extension_implementations(ecx: &EncodeContext,
829 ebml_w: &mut Encoder,
830 trait_def_id: DefId) {
831 match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
833 Some(implementations) => {
834 for &impl_def_id in implementations.borrow().iter() {
835 ebml_w.start_tag(tag_items_data_item_extension_impl);
836 encode_def_id(ebml_w, impl_def_id);
843 fn encode_sized(ebml_w: &mut Encoder, sized: Sized) {
844 ebml_w.start_tag(tag_items_data_item_sized);
845 let ch = match sized {
849 ebml_w.wr_str(str::from_char(ch));
853 fn encode_info_for_item(ecx: &EncodeContext,
854 ebml_w: &mut Encoder,
856 index: &mut Vec<entry<i64>>,
858 vis: ast::Visibility) {
861 fn add_to_index(item: &Item, ebml_w: &Encoder,
862 index: &mut Vec<entry<i64>>) {
865 pos: ebml_w.writer.tell().unwrap(),
869 debug!("encoding info for item at {}",
870 ecx.tcx.sess.codemap().span_to_str(item.span));
872 let def_id = local_def(item.id);
874 ItemStatic(_, m, _) => {
875 add_to_index(item, ebml_w, index);
876 ebml_w.start_tag(tag_items_data_item);
877 encode_def_id(ebml_w, def_id);
878 if m == ast::MutMutable {
879 encode_family(ebml_w, 'b');
881 encode_family(ebml_w, 'c');
883 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
884 encode_symbol(ecx, ebml_w, item.id);
885 encode_name(ebml_w, item.ident.name);
886 encode_path(ebml_w, path);
888 let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
891 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
893 encode_visibility(ebml_w, vis);
896 ItemFn(_, fn_style, _, ref generics, _) => {
897 add_to_index(item, ebml_w, index);
898 ebml_w.start_tag(tag_items_data_item);
899 encode_def_id(ebml_w, def_id);
900 encode_family(ebml_w, style_fn_family(fn_style));
901 let tps_len = generics.ty_params.len();
902 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
903 encode_name(ebml_w, item.ident.name);
904 encode_path(ebml_w, path);
905 encode_attributes(ebml_w, item.attrs.as_slice());
906 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
907 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
909 encode_symbol(ecx, ebml_w, item.id);
911 encode_visibility(ebml_w, vis);
915 add_to_index(item, ebml_w, index);
916 encode_info_for_mod(ecx,
924 ItemForeignMod(ref fm) => {
925 add_to_index(item, ebml_w, index);
926 ebml_w.start_tag(tag_items_data_item);
927 encode_def_id(ebml_w, def_id);
928 encode_family(ebml_w, 'n');
929 encode_name(ebml_w, item.ident.name);
930 encode_path(ebml_w, path);
932 // Encode all the items in this module.
933 for foreign_item in fm.items.iter() {
934 ebml_w.start_tag(tag_mod_child);
935 ebml_w.wr_str(def_to_str(local_def(foreign_item.id)));
938 encode_visibility(ebml_w, vis);
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, 'y');
946 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
947 encode_name(ebml_w, item.ident.name);
948 encode_path(ebml_w, path);
949 encode_visibility(ebml_w, vis);
952 ItemEnum(ref enum_definition, ref generics) => {
953 add_to_index(item, ebml_w, index);
955 ebml_w.start_tag(tag_items_data_item);
956 encode_def_id(ebml_w, def_id);
957 encode_family(ebml_w, 't');
958 encode_item_variances(ebml_w, ecx, item.id);
959 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
960 encode_name(ebml_w, item.ident.name);
961 encode_attributes(ebml_w, item.attrs.as_slice());
962 for v in (*enum_definition).variants.iter() {
963 encode_variant_id(ebml_w, local_def(v.node.id));
965 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
966 encode_path(ebml_w, path);
968 // Encode inherent implementations for this enumeration.
969 encode_inherent_implementations(ecx, ebml_w, def_id);
971 encode_visibility(ebml_w, vis);
974 encode_enum_variant_info(ecx,
977 (*enum_definition).variants.as_slice(),
981 ItemStruct(struct_def, _) => {
982 let fields = ty::lookup_struct_fields(tcx, def_id);
984 /* First, encode the fields
985 These come first because we need to write them to make
986 the index, and the index needs to be in the item for the
988 let idx = encode_info_for_struct(ecx,
994 add_to_index(item, ebml_w, index);
996 /* Now, make an item for the class itself */
997 ebml_w.start_tag(tag_items_data_item);
998 encode_def_id(ebml_w, def_id);
999 encode_family(ebml_w, 'S');
1000 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1002 encode_item_variances(ebml_w, ecx, item.id);
1003 encode_name(ebml_w, item.ident.name);
1004 encode_attributes(ebml_w, item.attrs.as_slice());
1005 encode_path(ebml_w, path.clone());
1006 encode_visibility(ebml_w, vis);
1008 /* Encode def_ids for each field and method
1009 for methods, write all the stuff get_trait_method
1011 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
1013 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1015 // Encode inherent implementations for this structure.
1016 encode_inherent_implementations(ecx, ebml_w, def_id);
1018 /* Each class has its own index -- encode it */
1019 encode_index(ebml_w, idx, write_i64);
1022 // If this is a tuple-like struct, encode the type of the constructor.
1023 match struct_def.ctor_id {
1025 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1026 ctor_id, index, def_id.node);
1031 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1032 // We need to encode information about the default methods we
1033 // have inherited, so we drive this based on the impl structure.
1034 let impl_methods = tcx.impl_methods.borrow();
1035 let methods = impl_methods.get(&def_id);
1037 add_to_index(item, ebml_w, index);
1038 ebml_w.start_tag(tag_items_data_item);
1039 encode_def_id(ebml_w, def_id);
1040 encode_family(ebml_w, 'i');
1041 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1042 encode_name(ebml_w, item.ident.name);
1043 encode_attributes(ebml_w, item.attrs.as_slice());
1045 ast::TyPath(ref path, ref bounds, _) if path.segments
1047 assert!(bounds.is_none());
1048 encode_impl_type_basename(ebml_w, ast_util::path_to_ident(path));
1052 for &method_def_id in methods.iter() {
1053 ebml_w.start_tag(tag_item_impl_method);
1054 let s = def_to_str(method_def_id);
1055 ebml_w.writer.write(s.as_bytes());
1058 for ast_trait_ref in opt_trait.iter() {
1059 let trait_ref = ty::node_id_to_trait_ref(
1060 tcx, ast_trait_ref.ref_id);
1061 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
1062 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1063 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1065 encode_path(ebml_w, path.clone());
1068 // Iterate down the methods, emitting them. We rely on the
1069 // assumption that all of the actually implemented methods
1070 // appear first in the impl structure, in the same order they do
1071 // in the ast. This is a little sketchy.
1072 let num_implemented_methods = ast_methods.len();
1073 for (i, &method_def_id) in methods.iter().enumerate() {
1074 let ast_method = if i < num_implemented_methods {
1075 Some(*ast_methods.get(i))
1079 val: method_def_id.node as i64,
1080 pos: ebml_w.writer.tell().unwrap(),
1082 encode_info_for_method(ecx,
1084 &*ty::method(tcx, method_def_id),
1091 ItemTrait(_, sized, ref super_traits, ref ms) => {
1092 add_to_index(item, ebml_w, index);
1093 ebml_w.start_tag(tag_items_data_item);
1094 encode_def_id(ebml_w, def_id);
1095 encode_family(ebml_w, 'I');
1096 encode_item_variances(ebml_w, ecx, item.id);
1097 let trait_def = ty::lookup_trait_def(tcx, def_id);
1098 encode_ty_type_param_defs(ebml_w, ecx,
1099 trait_def.generics.type_param_defs(),
1100 tag_items_data_item_ty_param_bounds);
1101 encode_region_param_defs(ebml_w, trait_def.generics.region_param_defs());
1102 encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1103 encode_name(ebml_w, item.ident.name);
1104 encode_attributes(ebml_w, item.attrs.as_slice());
1105 // When we fix the rest of the supertrait nastiness (FIXME(#8559)), we
1106 // should no longer need this ugly little hack either.
1107 encode_sized(ebml_w, sized);
1108 encode_visibility(ebml_w, vis);
1109 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1110 ebml_w.start_tag(tag_item_trait_method);
1111 encode_def_id(ebml_w, method_def_id);
1114 ebml_w.start_tag(tag_mod_child);
1115 ebml_w.wr_str(def_to_str(method_def_id));
1118 encode_path(ebml_w, path.clone());
1119 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1120 // reading the AST's list, because the former has already filtered out
1121 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1122 for ast_trait_ref in super_traits.iter() {
1123 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1124 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1127 // Encode the implementations of this trait.
1128 encode_extension_implementations(ecx, ebml_w, def_id);
1132 // Now output the method info for each method.
1133 let r = ty::trait_method_def_ids(tcx, def_id);
1134 for (i, &method_def_id) in r.iter().enumerate() {
1135 assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1137 let method_ty = ty::method(tcx, method_def_id);
1140 val: method_def_id.node as i64,
1141 pos: ebml_w.writer.tell().unwrap(),
1144 ebml_w.start_tag(tag_items_data_item);
1146 encode_method_ty_fields(ecx, ebml_w, &*method_ty);
1148 encode_parent_item(ebml_w, def_id);
1150 let elem = ast_map::PathName(method_ty.ident.name);
1151 encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1153 match method_ty.explicit_self {
1155 encode_family(ebml_w,
1156 fn_style_static_method_family(
1157 method_ty.fty.fn_style));
1159 let tpt = ty::lookup_item_type(tcx, method_def_id);
1160 encode_bounds_and_type(ebml_w, ecx, &tpt);
1164 encode_family(ebml_w,
1166 method_ty.fty.fn_style));
1171 &Required(ref tm) => {
1172 encode_attributes(ebml_w, tm.attrs.as_slice());
1173 encode_method_sort(ebml_w, 'r');
1177 encode_attributes(ebml_w, m.attrs.as_slice());
1178 // If this is a static method, we've already encoded
1180 if method_ty.explicit_self != SelfStatic {
1181 // FIXME: I feel like there is something funny going on.
1182 let tpt = ty::lookup_item_type(tcx, method_def_id);
1183 encode_bounds_and_type(ebml_w, ecx, &tpt);
1185 encode_method_sort(ebml_w, 'p');
1186 encode_inlined_item(ecx, ebml_w,
1187 IIMethodRef(def_id, true, m));
1194 // Encode inherent implementations for this trait.
1195 encode_inherent_implementations(ecx, ebml_w, def_id);
1198 // macros are encoded separately
1203 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1204 ebml_w: &mut Encoder,
1205 nitem: &ForeignItem,
1206 index: &mut Vec<entry<i64>>,
1210 val: nitem.id as i64,
1211 pos: ebml_w.writer.tell().unwrap(),
1214 ebml_w.start_tag(tag_items_data_item);
1215 encode_def_id(ebml_w, local_def(nitem.id));
1217 ForeignItemFn(..) => {
1218 encode_family(ebml_w, style_fn_family(NormalFn));
1219 encode_bounds_and_type(ebml_w, ecx,
1220 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1221 encode_name(ebml_w, nitem.ident.name);
1222 if abi == abi::RustIntrinsic {
1223 encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1225 encode_symbol(ecx, ebml_w, nitem.id);
1228 ForeignItemStatic(_, mutbl) => {
1230 encode_family(ebml_w, 'b');
1232 encode_family(ebml_w, 'c');
1234 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1235 encode_symbol(ecx, ebml_w, nitem.id);
1236 encode_name(ebml_w, nitem.ident.name);
1239 encode_path(ebml_w, path);
1243 fn my_visit_expr(_e: &Expr) { }
1245 fn my_visit_item(i: &Item,
1246 ebml_w: &mut Encoder,
1248 index: &mut Vec<entry<i64>>) {
1249 let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1251 let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1252 ecx.tcx.map.with_path(i.id, |path| {
1253 encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1257 fn my_visit_foreign_item(ni: &ForeignItem,
1258 ebml_w: &mut Encoder,
1260 index: &mut Vec<entry<i64>>) {
1262 let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1263 debug!("writing foreign item {}::{}",
1264 ecx.tcx.map.path_to_str(ni.id),
1265 token::get_ident(ni.ident));
1267 let mut ebml_w = unsafe {
1268 ebml_w.unsafe_clone()
1270 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1271 ecx.tcx.map.with_path(ni.id, |path| {
1272 encode_info_for_foreign_item(ecx, &mut ebml_w,
1278 struct EncodeVisitor<'a,'b> {
1279 ebml_w_for_visit_item: &'a mut Encoder<'b>,
1281 index: &'a mut Vec<entry<i64>>,
1284 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1285 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1286 visit::walk_expr(self, ex, ());
1289 fn visit_item(&mut self, i: &Item, _: ()) {
1290 visit::walk_item(self, i, ());
1292 self.ebml_w_for_visit_item,
1296 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1297 visit::walk_foreign_item(self, ni, ());
1298 my_visit_foreign_item(ni,
1299 self.ebml_w_for_visit_item,
1305 fn encode_info_for_items(ecx: &EncodeContext,
1306 ebml_w: &mut Encoder,
1308 -> Vec<entry<i64>> {
1309 let mut index = Vec::new();
1310 ebml_w.start_tag(tag_items_data);
1312 val: CRATE_NODE_ID as i64,
1313 pos: ebml_w.writer.tell().unwrap(),
1315 encode_info_for_mod(ecx,
1319 ast_map::Values([].iter()).chain(None),
1320 syntax::parse::token::special_idents::invalid,
1323 // See comment in `encode_side_tables_for_ii` in astencode
1324 let ecx_ptr: *int = unsafe { cast::transmute(ecx) };
1325 visit::walk_crate(&mut EncodeVisitor {
1328 ebml_w_for_visit_item: &mut *ebml_w,
1336 // Path and definition ID indexing
1338 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1339 write_fn: |&mut MemWriter, &T|) {
1340 let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1341 for elt in index.move_iter() {
1342 let h = hash::hash(&elt.val) as uint;
1343 buckets.get_mut(h % 256).push(elt);
1346 ebml_w.start_tag(tag_index);
1347 let mut bucket_locs = Vec::new();
1348 ebml_w.start_tag(tag_index_buckets);
1349 for bucket in buckets.iter() {
1350 bucket_locs.push(ebml_w.writer.tell().unwrap());
1351 ebml_w.start_tag(tag_index_buckets_bucket);
1352 for elt in bucket.iter() {
1353 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1354 assert!(elt.pos < 0xffff_ffff);
1356 let wr: &mut MemWriter = ebml_w.writer;
1357 wr.write_be_u32(elt.pos as u32);
1359 write_fn(ebml_w.writer, &elt.val);
1365 ebml_w.start_tag(tag_index_table);
1366 for pos in bucket_locs.iter() {
1367 assert!(*pos < 0xffff_ffff);
1368 let wr: &mut MemWriter = ebml_w.writer;
1369 wr.write_be_u32(*pos as u32);
1375 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1376 let wr: &mut MemWriter = writer;
1377 assert!(n < 0x7fff_ffff);
1378 wr.write_be_u32(n as u32);
1381 fn encode_meta_item(ebml_w: &mut Encoder, mi: @MetaItem) {
1383 MetaWord(ref name) => {
1384 ebml_w.start_tag(tag_meta_item_word);
1385 ebml_w.start_tag(tag_meta_item_name);
1386 ebml_w.writer.write(name.get().as_bytes());
1390 MetaNameValue(ref name, ref value) => {
1392 LitStr(ref value, _) => {
1393 ebml_w.start_tag(tag_meta_item_name_value);
1394 ebml_w.start_tag(tag_meta_item_name);
1395 ebml_w.writer.write(name.get().as_bytes());
1397 ebml_w.start_tag(tag_meta_item_value);
1398 ebml_w.writer.write(value.get().as_bytes());
1402 _ => {/* FIXME (#623): encode other variants */ }
1405 MetaList(ref name, ref items) => {
1406 ebml_w.start_tag(tag_meta_item_list);
1407 ebml_w.start_tag(tag_meta_item_name);
1408 ebml_w.writer.write(name.get().as_bytes());
1410 for inner_item in items.iter() {
1411 encode_meta_item(ebml_w, *inner_item);
1418 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1419 ebml_w.start_tag(tag_attributes);
1420 for attr in attrs.iter() {
1421 ebml_w.start_tag(tag_attribute);
1422 encode_meta_item(ebml_w, attr.node.value);
1428 // So there's a special crate attribute called 'crate_id' which defines the
1429 // metadata that Rust cares about for linking crates. If the user didn't
1430 // provide it we will throw it in anyway with a default value.
1431 fn synthesize_crate_attrs(ecx: &EncodeContext,
1432 krate: &Crate) -> Vec<Attribute> {
1434 fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute {
1435 assert!(!ecx.link_meta.crateid.name.is_empty());
1438 attr::mk_name_value_item_str(
1439 InternedString::new("crate_id"),
1440 token::intern_and_get_ident(ecx.link_meta.crateid.to_str())))
1443 let mut attrs = Vec::new();
1444 for attr in krate.attrs.iter() {
1445 if !attr.name().equiv(&("crate_id")) {
1449 attrs.push(synthesize_crateid_attr(ecx));
1454 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1455 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1456 // Pull the cnums and name,vers,hash out of cstore
1457 let mut deps = Vec::new();
1458 cstore.iter_crate_data(|key, val| {
1459 let dep = decoder::CrateDep {
1461 crate_id: decoder::get_crate_id(val.data()),
1462 hash: decoder::get_crate_hash(val.data())
1468 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1470 // Sanity-check the crate numbers
1471 let mut expected_cnum = 1;
1472 for n in deps.iter() {
1473 assert_eq!(n.cnum, expected_cnum);
1480 // We're just going to write a list of crate 'name-hash-version's, with
1481 // the assumption that they are numbered 1 to n.
1482 // FIXME (#2166): This is not nearly enough to support correct versioning
1483 // but is enough to get transitive crate dependencies working.
1484 ebml_w.start_tag(tag_crate_deps);
1485 let r = get_ordered_deps(cstore);
1486 for dep in r.iter() {
1487 encode_crate_dep(ebml_w, (*dep).clone());
1492 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1493 ebml_w.start_tag(tag_lang_items);
1495 for (i, def_id) in ecx.tcx.lang_items.items() {
1496 for id in def_id.iter() {
1497 if id.krate == LOCAL_CRATE {
1498 ebml_w.start_tag(tag_lang_items_item);
1500 ebml_w.start_tag(tag_lang_items_item_id);
1502 let wr: &mut MemWriter = ebml_w.writer;
1503 wr.write_be_u32(i as u32);
1505 ebml_w.end_tag(); // tag_lang_items_item_id
1507 ebml_w.start_tag(tag_lang_items_item_node_id);
1509 let wr: &mut MemWriter = ebml_w.writer;
1510 wr.write_be_u32(id.node as u32);
1512 ebml_w.end_tag(); // tag_lang_items_item_node_id
1514 ebml_w.end_tag(); // tag_lang_items_item
1519 ebml_w.end_tag(); // tag_lang_items
1522 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1523 ebml_w.start_tag(tag_native_libraries);
1525 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1528 cstore::NativeStatic => {} // these libraries are not propagated
1529 cstore::NativeFramework | cstore::NativeUnknown => {
1530 ebml_w.start_tag(tag_native_libraries_lib);
1532 ebml_w.start_tag(tag_native_libraries_kind);
1533 ebml_w.writer.write_be_u32(kind as u32);
1536 ebml_w.start_tag(tag_native_libraries_name);
1537 ebml_w.writer.write(lib.as_bytes());
1548 fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1549 match ecx.tcx.sess.macro_registrar_fn.get() {
1550 Some(id) => { ebml_w.wr_tagged_u32(tag_macro_registrar_fn, id); }
1555 struct MacroDefVisitor<'a, 'b, 'c> {
1556 ecx: &'a EncodeContext<'b>,
1557 ebml_w: &'a mut Encoder<'c>
1560 impl<'a, 'b, 'c> Visitor<()> for MacroDefVisitor<'a, 'b, 'c> {
1561 fn visit_item(&mut self, item: &Item, _: ()) {
1564 let def = self.ecx.tcx.sess.codemap().span_to_snippet(item.span)
1565 .expect("Unable to find source for macro");
1566 self.ebml_w.start_tag(tag_macro_def);
1567 self.ebml_w.wr_str(def);
1568 self.ebml_w.end_tag();
1572 visit::walk_item(self, item, ());
1576 fn encode_macro_defs<'a>(ecx: &'a EncodeContext,
1578 ebml_w: &'a mut Encoder) {
1579 ebml_w.start_tag(tag_exported_macros);
1581 let mut visitor = MacroDefVisitor {
1585 visit::walk_crate(&mut visitor, krate, ());
1590 struct ImplVisitor<'a,'b,'c> {
1591 ecx: &'a EncodeContext<'b>,
1592 ebml_w: &'a mut Encoder<'c>,
1595 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1596 fn visit_item(&mut self, item: &Item, _: ()) {
1598 ItemImpl(_, Some(ref trait_ref), _, _) => {
1599 let def_map = &self.ecx.tcx.def_map;
1600 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1601 let def_id = ast_util::def_id_of_def(trait_def);
1603 // Load eagerly if this is an implementation of the Drop trait
1604 // or if the trait is not defined in this crate.
1605 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1606 def_id.krate != LOCAL_CRATE {
1607 self.ebml_w.start_tag(tag_impls_impl);
1608 encode_def_id(self.ebml_w, local_def(item.id));
1609 self.ebml_w.end_tag();
1614 visit::walk_item(self, item, ());
1618 /// Encodes implementations that are eagerly loaded.
1620 /// None of this is necessary in theory; we can load all implementations
1621 /// lazily. However, in two cases the optimizations to lazily load
1622 /// implementations are not yet implemented. These two cases, which require us
1623 /// to load implementations eagerly, are:
1625 /// * Destructors (implementations of the Drop trait).
1627 /// * Implementations of traits not defined in this crate.
1628 fn encode_impls<'a>(ecx: &'a EncodeContext,
1630 ebml_w: &'a mut Encoder) {
1631 ebml_w.start_tag(tag_impls);
1634 let mut visitor = ImplVisitor {
1638 visit::walk_crate(&mut visitor, krate, ());
1644 fn encode_misc_info(ecx: &EncodeContext,
1646 ebml_w: &mut Encoder) {
1647 ebml_w.start_tag(tag_misc_info);
1648 ebml_w.start_tag(tag_misc_info_crate_items);
1649 for &item in krate.module.items.iter() {
1650 ebml_w.start_tag(tag_mod_child);
1651 ebml_w.wr_str(def_to_str(local_def(item.id)));
1654 each_auxiliary_node_id(item, |auxiliary_node_id| {
1655 ebml_w.start_tag(tag_mod_child);
1656 ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
1662 // Encode reexports for the root module.
1663 encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1669 fn encode_crate_dep(ebml_w: &mut Encoder,
1670 dep: decoder::CrateDep) {
1671 ebml_w.start_tag(tag_crate_dep);
1672 ebml_w.start_tag(tag_crate_dep_crateid);
1673 ebml_w.writer.write(dep.crate_id.to_str().as_bytes());
1675 ebml_w.start_tag(tag_crate_dep_hash);
1676 ebml_w.writer.write(dep.hash.as_str().as_bytes());
1681 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1682 ebml_w.start_tag(tag_crate_hash);
1683 ebml_w.writer.write(hash.as_str().as_bytes());
1687 fn encode_crate_id(ebml_w: &mut Encoder, crate_id: &CrateId) {
1688 ebml_w.start_tag(tag_crate_crateid);
1689 ebml_w.writer.write(crate_id.to_str().as_bytes());
1693 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1694 ebml_w.start_tag(tag_crate_triple);
1695 ebml_w.writer.write(triple.as_bytes());
1699 // NB: Increment this as you change the metadata encoding version.
1700 pub static metadata_encoding_version : &'static [u8] =
1701 &[0x72, //'r' as u8,
1707 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1708 let mut wr = MemWriter::new();
1709 encode_metadata_inner(&mut wr, parms, krate);
1710 wr.unwrap().move_iter().collect()
1713 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1717 lang_item_bytes: u64,
1718 native_lib_bytes: u64,
1719 macro_registrar_fn_bytes: u64,
1720 macro_defs_bytes: u64,
1728 let mut stats = Stats {
1732 native_lib_bytes: 0,
1733 macro_registrar_fn_bytes: 0,
1734 macro_defs_bytes: 0,
1748 encode_inlined_item,
1750 non_inlineable_statics,
1753 let ecx = EncodeContext {
1756 reexports2: reexports2,
1757 item_symbols: item_symbols,
1758 non_inlineable_statics: non_inlineable_statics,
1759 link_meta: link_meta,
1761 encode_inlined_item: RefCell::new(encode_inlined_item),
1762 type_abbrevs: RefCell::new(HashMap::new()),
1765 let mut ebml_w = writer::Encoder(wr);
1767 encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
1768 encode_crate_triple(&mut ebml_w, tcx.sess.targ_cfg.target_strs.target_triple);
1769 encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1771 let mut i = ebml_w.writer.tell().unwrap();
1772 let crate_attrs = synthesize_crate_attrs(&ecx, krate);
1773 encode_attributes(&mut ebml_w, crate_attrs.as_slice());
1774 stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1776 i = ebml_w.writer.tell().unwrap();
1777 encode_crate_deps(&mut ebml_w, ecx.cstore);
1778 stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1780 // Encode the language items.
1781 i = ebml_w.writer.tell().unwrap();
1782 encode_lang_items(&ecx, &mut ebml_w);
1783 stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1785 // Encode the native libraries used
1786 i = ebml_w.writer.tell().unwrap();
1787 encode_native_libraries(&ecx, &mut ebml_w);
1788 stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1790 // Encode the macro registrar function
1791 i = ebml_w.writer.tell().unwrap();
1792 encode_macro_registrar_fn(&ecx, &mut ebml_w);
1793 stats.macro_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1795 // Encode macro definitions
1796 i = ebml_w.writer.tell().unwrap();
1797 encode_macro_defs(&ecx, krate, &mut ebml_w);
1798 stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1800 // Encode the def IDs of impls, for coherence checking.
1801 i = ebml_w.writer.tell().unwrap();
1802 encode_impls(&ecx, krate, &mut ebml_w);
1803 stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1805 // Encode miscellaneous info.
1806 i = ebml_w.writer.tell().unwrap();
1807 encode_misc_info(&ecx, krate, &mut ebml_w);
1808 stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1810 // Encode and index the items.
1811 ebml_w.start_tag(tag_items);
1812 i = ebml_w.writer.tell().unwrap();
1813 let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1814 stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1816 i = ebml_w.writer.tell().unwrap();
1817 encode_index(&mut ebml_w, items_index, write_i64);
1818 stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1821 stats.total_bytes = ebml_w.writer.tell().unwrap();
1823 if tcx.sess.meta_stats() {
1824 for e in ebml_w.writer.get_ref().iter() {
1826 stats.zero_bytes += 1;
1830 println!("metadata stats:");
1831 println!(" attribute bytes: {}", stats.attr_bytes);
1832 println!(" dep bytes: {}", stats.dep_bytes);
1833 println!(" lang item bytes: {}", stats.lang_item_bytes);
1834 println!(" native bytes: {}", stats.native_lib_bytes);
1835 println!("macro registrar bytes: {}", stats.macro_registrar_fn_bytes);
1836 println!(" macro def bytes: {}", stats.macro_defs_bytes);
1837 println!(" impl bytes: {}", stats.impl_bytes);
1838 println!(" misc bytes: {}", stats.misc_bytes);
1839 println!(" item bytes: {}", stats.item_bytes);
1840 println!(" index bytes: {}", stats.index_bytes);
1841 println!(" zero bytes: {}", stats.zero_bytes);
1842 println!(" total bytes: {}", stats.total_bytes);
1846 // Get the encoded string for a type
1847 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> ~str {
1848 let mut wr = MemWriter::new();
1849 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1850 diag: tcx.sess.diagnostic(),
1853 abbrevs: &RefCell::new(HashMap::new())
1855 str::from_utf8_owned(wr.get_ref().to_owned()).unwrap()