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::ty::{node_id_to_type, lookup_item_type};
23 use middle::astencode;
27 use util::nodemap::{NodeMap, NodeSet};
29 use serialize::Encodable;
31 use std::cell::RefCell;
34 use std::io::MemWriter;
36 use collections::HashMap;
40 use syntax::ast_map::{PathElem, PathElems};
42 use syntax::ast_util::*;
44 use syntax::attr::AttrMetaMethods;
46 use syntax::crateid::CrateId;
47 use syntax::diagnostic::SpanHandler;
48 use syntax::parse::token::InternedString;
49 use syntax::parse::token::special_idents;
50 use syntax::parse::token;
51 use syntax::visit::Visitor;
54 use writer = serialize::ebml::writer;
56 /// A borrowed version of ast::InlinedItem.
57 pub enum InlinedItemRef<'a> {
58 IIItemRef(&'a ast::Item),
59 IIMethodRef(ast::DefId, bool, &'a ast::Method),
60 IIForeignRef(&'a ast::ForeignItem)
63 pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
65 pub type EncodeInlinedItem<'a> = |ecx: &EncodeContext,
67 ii: InlinedItemRef|: 'a;
69 pub struct EncodeParams<'a> {
70 pub diag: &'a SpanHandler,
71 pub tcx: &'a ty::ctxt,
72 pub reexports2: &'a middle::resolve::ExportMap2,
73 pub item_symbols: &'a RefCell<NodeMap<String>>,
74 pub non_inlineable_statics: &'a RefCell<NodeSet>,
75 pub link_meta: &'a LinkMeta,
76 pub cstore: &'a cstore::CStore,
77 pub encode_inlined_item: EncodeInlinedItem<'a>,
80 pub struct EncodeContext<'a> {
81 pub diag: &'a SpanHandler,
82 pub tcx: &'a ty::ctxt,
83 pub reexports2: &'a middle::resolve::ExportMap2,
84 pub item_symbols: &'a RefCell<NodeMap<String>>,
85 pub non_inlineable_statics: &'a RefCell<NodeSet>,
86 pub link_meta: &'a LinkMeta,
87 pub cstore: &'a cstore::CStore,
88 pub encode_inlined_item: RefCell<EncodeInlinedItem<'a>>,
89 pub type_abbrevs: tyencode::abbrev_map,
92 fn encode_name(ebml_w: &mut Encoder, name: Name) {
93 ebml_w.wr_tagged_str(tag_paths_data_name, token::get_name(name).get());
96 fn encode_impl_type_basename(ebml_w: &mut Encoder, name: Ident) {
97 ebml_w.wr_tagged_str(tag_item_impl_type_basename, token::get_ident(name).get());
100 pub fn encode_def_id(ebml_w: &mut Encoder, id: DefId) {
101 ebml_w.wr_tagged_str(tag_def_id, def_to_str(id).as_slice());
110 fn encode_trait_ref(ebml_w: &mut Encoder,
112 trait_ref: &ty::TraitRef,
114 let ty_str_ctxt = &tyencode::ctxt {
118 abbrevs: &ecx.type_abbrevs
121 ebml_w.start_tag(tag);
122 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
126 fn encode_impl_vtables(ebml_w: &mut Encoder,
128 vtables: &typeck::impl_res) {
129 ebml_w.start_tag(tag_item_impl_vtables);
130 astencode::encode_vtable_res(ecx, ebml_w, &vtables.trait_vtables);
131 astencode::encode_vtable_param_res(ecx, ebml_w, &vtables.self_vtables);
135 // Item info table encoding
136 fn encode_family(ebml_w: &mut Encoder, c: char) {
137 ebml_w.start_tag(tag_items_data_item_family);
138 ebml_w.writer.write(&[c as u8]);
142 pub fn def_to_str(did: DefId) -> String {
143 format!("{}:{}", did.krate, did.node)
146 fn encode_ty_type_param_defs(ebml_w: &mut Encoder,
148 params: &[ty::TypeParameterDef],
150 let ty_str_ctxt = &tyencode::ctxt {
154 abbrevs: &ecx.type_abbrevs
156 for param in params.iter() {
157 ebml_w.start_tag(tag);
158 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
163 fn encode_region_param_defs(ebml_w: &mut Encoder,
164 params: &[ty::RegionParameterDef]) {
165 for param in params.iter() {
166 ebml_w.start_tag(tag_region_param_def);
168 ebml_w.start_tag(tag_region_param_def_ident);
169 encode_name(ebml_w, param.name);
172 ebml_w.wr_tagged_str(tag_region_param_def_def_id,
173 def_to_str(param.def_id).as_slice());
179 fn encode_item_variances(ebml_w: &mut Encoder,
182 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
183 ebml_w.start_tag(tag_item_variances);
188 fn encode_bounds_and_type(ebml_w: &mut Encoder,
190 tpt: &ty::ty_param_bounds_and_ty) {
191 encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs(),
192 tag_items_data_item_ty_param_bounds);
193 encode_region_param_defs(ebml_w, tpt.generics.region_param_defs());
194 encode_type(ecx, ebml_w, tpt.ty);
197 fn encode_variant_id(ebml_w: &mut Encoder, vid: DefId) {
198 ebml_w.start_tag(tag_items_data_item_variant);
199 let s = def_to_str(vid);
200 ebml_w.writer.write(s.as_bytes());
204 pub fn write_type(ecx: &EncodeContext,
205 ebml_w: &mut Encoder,
207 let ty_str_ctxt = &tyencode::ctxt {
211 abbrevs: &ecx.type_abbrevs
213 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
216 fn encode_type(ecx: &EncodeContext,
217 ebml_w: &mut Encoder,
219 ebml_w.start_tag(tag_items_data_item_type);
220 write_type(ecx, ebml_w, typ);
224 fn encode_method_fty(ecx: &EncodeContext,
225 ebml_w: &mut Encoder,
226 typ: &ty::BareFnTy) {
227 ebml_w.start_tag(tag_item_method_fty);
229 let ty_str_ctxt = &tyencode::ctxt {
233 abbrevs: &ecx.type_abbrevs
235 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
240 fn encode_symbol(ecx: &EncodeContext,
241 ebml_w: &mut Encoder,
243 ebml_w.start_tag(tag_items_data_item_symbol);
244 match ecx.item_symbols.borrow().find(&id) {
246 debug!("encode_symbol(id={:?}, str={})", id, *x);
247 ebml_w.writer.write(x.as_bytes());
250 ecx.diag.handler().bug(
251 format!("encode_symbol: id not found {}", id).as_slice());
257 fn encode_disr_val(_: &EncodeContext,
258 ebml_w: &mut Encoder,
259 disr_val: ty::Disr) {
260 ebml_w.start_tag(tag_disr_val);
261 let s = disr_val.to_str();
262 ebml_w.writer.write(s.as_bytes());
266 fn encode_parent_item(ebml_w: &mut Encoder, id: DefId) {
267 ebml_w.start_tag(tag_items_data_parent_item);
268 let s = def_to_str(id);
269 ebml_w.writer.write(s.as_bytes());
273 fn encode_struct_fields(ebml_w: &mut Encoder,
274 fields: &[ty::field_ty],
276 for f in fields.iter() {
277 if f.name == special_idents::unnamed_field.name {
278 ebml_w.start_tag(tag_item_unnamed_field);
280 ebml_w.start_tag(tag_item_field);
281 encode_name(ebml_w, f.name);
283 encode_struct_field_family(ebml_w, f.vis);
284 encode_def_id(ebml_w, f.id);
285 ebml_w.start_tag(tag_item_field_origin);
286 let s = def_to_str(origin);
287 ebml_w.writer.write(s.as_bytes());
293 fn encode_enum_variant_info(ecx: &EncodeContext,
294 ebml_w: &mut Encoder,
296 variants: &[P<Variant>],
297 index: &mut Vec<entry<i64>>,
298 generics: &ast::Generics) {
299 debug!("encode_enum_variant_info(id={:?})", id);
301 let mut disr_val = 0;
303 let vi = ty::enum_variants(ecx.tcx,
304 ast::DefId { krate: LOCAL_CRATE, node: id });
305 for variant in variants.iter() {
306 let def_id = local_def(variant.node.id);
308 val: variant.node.id as i64,
309 pos: ebml_w.writer.tell().unwrap(),
311 ebml_w.start_tag(tag_items_data_item);
312 encode_def_id(ebml_w, def_id);
313 match variant.node.kind {
314 ast::TupleVariantKind(_) => encode_family(ebml_w, 'v'),
315 ast::StructVariantKind(_) => encode_family(ebml_w, 'V')
317 encode_name(ebml_w, variant.node.name.name);
318 encode_parent_item(ebml_w, local_def(id));
319 encode_visibility(ebml_w, variant.node.vis);
320 encode_attributes(ebml_w, variant.node.attrs.as_slice());
321 match variant.node.kind {
322 ast::TupleVariantKind(ref args)
323 if args.len() > 0 && generics.ty_params.len() == 0 => {
324 encode_symbol(ecx, ebml_w, variant.node.id);
326 ast::TupleVariantKind(_) => {},
327 ast::StructVariantKind(_) => {
328 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
329 let idx = encode_info_for_struct(ecx,
333 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
334 encode_index(ebml_w, idx, write_i64);
337 if vi.get(i).disr_val != disr_val {
338 encode_disr_val(ecx, ebml_w, vi.get(i).disr_val);
339 disr_val = vi.get(i).disr_val;
341 encode_bounds_and_type(ebml_w, ecx,
342 &lookup_item_type(ecx.tcx, def_id));
344 ecx.tcx.map.with_path(variant.node.id, |path| encode_path(ebml_w, path));
351 fn encode_path<PI: Iterator<PathElem> + Clone>(ebml_w: &mut Encoder,
353 ebml_w.start_tag(tag_path);
354 ebml_w.wr_tagged_u32(tag_path_len, path.clone().len() as u32);
357 ast_map::PathMod(_) => tag_path_elem_mod,
358 ast_map::PathName(_) => tag_path_elem_name
360 ebml_w.wr_tagged_str(tag, token::get_name(pe.name()).get());
365 fn encode_reexported_static_method(ebml_w: &mut Encoder,
366 exp: &middle::resolve::Export2,
367 method_def_id: DefId,
368 method_ident: Ident) {
369 debug!("(encode reexported static method) {}::{}",
370 exp.name, token::get_ident(method_ident));
371 ebml_w.start_tag(tag_items_data_item_reexport);
372 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
373 ebml_w.wr_str(def_to_str(method_def_id).as_slice());
375 ebml_w.start_tag(tag_items_data_item_reexport_name);
376 ebml_w.wr_str(format!("{}::{}",
378 token::get_ident(method_ident)).as_slice());
383 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
384 ebml_w: &mut Encoder,
385 exp: &middle::resolve::Export2)
387 let impl_methods = ecx.tcx.impl_methods.borrow();
388 match ecx.tcx.inherent_impls.borrow().find(&exp.def_id) {
389 Some(implementations) => {
390 for base_impl_did in implementations.borrow().iter() {
391 for &method_did in impl_methods.get(base_impl_did).iter() {
392 let m = ty::method(ecx.tcx, method_did);
393 if m.explicit_self == ast::SelfStatic {
394 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
405 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
406 ebml_w: &mut Encoder,
407 exp: &middle::resolve::Export2)
409 match ecx.tcx.trait_methods_cache.borrow().find(&exp.def_id) {
411 for m in methods.iter() {
412 if m.explicit_self == ast::SelfStatic {
413 encode_reexported_static_method(ebml_w, exp, m.def_id, m.ident);
423 fn encode_reexported_static_methods(ecx: &EncodeContext,
424 ebml_w: &mut Encoder,
426 exp: &middle::resolve::Export2) {
427 match ecx.tcx.map.find(exp.def_id.node) {
428 Some(ast_map::NodeItem(item)) => {
429 let original_name = token::get_ident(item.ident);
431 let path_differs = ecx.tcx.map.with_path(exp.def_id.node, |path| {
432 let (mut a, mut b) = (path, mod_path.clone());
434 match (a.next(), b.next()) {
435 (None, None) => return true,
436 (None, _) | (_, None) => return false,
437 (Some(x), Some(y)) => if x != y { return false },
443 // We don't need to reexport static methods on items
444 // declared in the same module as our `pub use ...` since
445 // that's done when we encode the item itself.
447 // The only exception is when the reexport *changes* the
448 // name e.g. `pub use Foo = self::Bar` -- we have
449 // encoded metadata for static methods relative to Bar,
450 // but not yet for Foo.
452 if path_differs || original_name.get() != exp.name.as_slice() {
453 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
454 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
455 debug!("(encode reexported static methods) {} \
461 debug!("(encode reexported static methods) {} [base]",
470 /// Iterates through "auxiliary node IDs", which are node IDs that describe
471 /// top-level items that are sub-items of the given item. Specifically:
473 /// * For enums, iterates through the node IDs of the variants.
475 /// * For newtype structs, iterates through the node ID of the constructor.
476 fn each_auxiliary_node_id(item: @Item, callback: |NodeId| -> bool) -> bool {
477 let mut continue_ = true;
479 ItemEnum(ref enum_def, _) => {
480 for variant in enum_def.variants.iter() {
481 continue_ = callback(variant.node.id);
487 ItemStruct(struct_def, _) => {
488 // If this is a newtype struct, return the constructor.
489 match struct_def.ctor_id {
490 Some(ctor_id) if struct_def.fields.len() > 0 &&
491 struct_def.fields.get(0).node.kind.is_unnamed() => {
492 continue_ = callback(ctor_id);
503 fn encode_reexports(ecx: &EncodeContext,
504 ebml_w: &mut Encoder,
507 debug!("(encoding info for module) encoding reexports for {}", id);
508 match ecx.reexports2.borrow().find(&id) {
509 Some(ref exports) => {
510 debug!("(encoding info for module) found reexports for {}", id);
511 for exp in exports.iter() {
512 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
518 ebml_w.start_tag(tag_items_data_item_reexport);
519 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
520 ebml_w.wr_str(def_to_str(exp.def_id).as_slice());
522 ebml_w.start_tag(tag_items_data_item_reexport_name);
523 ebml_w.wr_str(exp.name.as_slice());
526 encode_reexported_static_methods(ecx, ebml_w, path.clone(), exp);
530 debug!("(encoding info for module) found no reexports for {}",
536 fn encode_info_for_mod(ecx: &EncodeContext,
537 ebml_w: &mut Encoder,
544 ebml_w.start_tag(tag_items_data_item);
545 encode_def_id(ebml_w, local_def(id));
546 encode_family(ebml_w, 'm');
547 encode_name(ebml_w, name.name);
548 debug!("(encoding info for module) encoding info for module ID {}", id);
550 // Encode info about all the module children.
551 for item in md.items.iter() {
552 ebml_w.start_tag(tag_mod_child);
553 ebml_w.wr_str(def_to_str(local_def(item.id)).as_slice());
556 each_auxiliary_node_id(*item, |auxiliary_node_id| {
557 ebml_w.start_tag(tag_mod_child);
558 ebml_w.wr_str(def_to_str(local_def(
559 auxiliary_node_id)).as_slice());
566 let (ident, did) = (item.ident, item.id);
567 debug!("(encoding info for module) ... encoding impl {} \
569 token::get_ident(ident),
570 did, ecx.tcx.map.node_to_str(did));
572 ebml_w.start_tag(tag_mod_impl);
573 ebml_w.wr_str(def_to_str(local_def(did)).as_slice());
580 encode_path(ebml_w, path.clone());
581 encode_visibility(ebml_w, vis);
583 // Encode the reexports of this module, if this module is public.
585 debug!("(encoding info for module) encoding reexports for {}", id);
586 encode_reexports(ecx, ebml_w, id, path);
588 encode_attributes(ebml_w, attrs);
593 fn encode_struct_field_family(ebml_w: &mut Encoder,
594 visibility: Visibility) {
595 encode_family(ebml_w, match visibility {
601 fn encode_visibility(ebml_w: &mut Encoder, visibility: Visibility) {
602 ebml_w.start_tag(tag_items_data_item_visibility);
603 let ch = match visibility {
607 ebml_w.wr_str(str::from_char(ch).as_slice());
611 fn encode_explicit_self(ebml_w: &mut Encoder, explicit_self: ast::ExplicitSelf_) {
612 ebml_w.start_tag(tag_item_trait_method_explicit_self);
614 // Encode the base self type.
615 match explicit_self {
616 SelfStatic => { ebml_w.writer.write(&[ 's' as u8 ]); }
617 SelfValue => { ebml_w.writer.write(&[ 'v' as u8 ]); }
618 SelfUniq => { ebml_w.writer.write(&[ '~' as u8 ]); }
619 SelfRegion(_, m) => {
620 // FIXME(#4846) encode custom lifetime
621 ebml_w.writer.write(&['&' as u8]);
622 encode_mutability(ebml_w, m);
628 fn encode_mutability(ebml_w: &mut Encoder,
629 m: ast::Mutability) {
631 MutImmutable => { ebml_w.writer.write(&[ 'i' as u8 ]); }
632 MutMutable => { ebml_w.writer.write(&[ 'm' as u8 ]); }
637 fn encode_method_sort(ebml_w: &mut Encoder, sort: char) {
638 ebml_w.start_tag(tag_item_trait_method_sort);
639 ebml_w.writer.write(&[ sort as u8 ]);
643 fn encode_provided_source(ebml_w: &mut Encoder,
644 source_opt: Option<DefId>) {
645 for source in source_opt.iter() {
646 ebml_w.start_tag(tag_item_method_provided_source);
647 let s = def_to_str(*source);
648 ebml_w.writer.write(s.as_bytes());
653 /* Returns an index of items in this class */
654 fn encode_info_for_struct(ecx: &EncodeContext,
655 ebml_w: &mut Encoder,
656 fields: &[ty::field_ty],
657 global_index: &mut Vec<entry<i64>>)
659 /* Each class has its own index, since different classes
660 may have fields with the same name */
661 let mut index = Vec::new();
663 /* We encode both private and public fields -- need to include
664 private fields to get the offsets right */
665 for field in fields.iter() {
667 let id = field.id.node;
669 index.push(entry {val: id as i64, pos: ebml_w.writer.tell().unwrap()});
670 global_index.push(entry {
672 pos: ebml_w.writer.tell().unwrap(),
674 ebml_w.start_tag(tag_items_data_item);
675 debug!("encode_info_for_struct: doing {} {}",
676 token::get_name(nm), id);
677 encode_struct_field_family(ebml_w, field.vis);
678 encode_name(ebml_w, nm);
679 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
680 encode_def_id(ebml_w, local_def(id));
686 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
687 ebml_w: &mut Encoder,
690 index: &mut Vec<entry<i64>>,
694 pos: ebml_w.writer.tell().unwrap(),
697 ebml_w.start_tag(tag_items_data_item);
698 encode_def_id(ebml_w, local_def(ctor_id));
699 encode_family(ebml_w, 'f');
700 encode_bounds_and_type(ebml_w, ecx,
701 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
702 encode_name(ebml_w, name.name);
703 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
704 ecx.tcx.map.with_path(ctor_id, |path| encode_path(ebml_w, path));
705 encode_parent_item(ebml_w, local_def(struct_id));
707 if ecx.item_symbols.borrow().contains_key(&ctor_id) {
708 encode_symbol(ecx, ebml_w, ctor_id);
711 // indicate that this is a tuple struct ctor, because downstream users will normally want
712 // the tuple struct definition, but without this there is no way for them to tell that
713 // they actually have a ctor rather than a normal function
714 ebml_w.start_tag(tag_items_data_item_is_tuple_struct_ctor);
720 fn encode_method_ty_fields(ecx: &EncodeContext,
721 ebml_w: &mut Encoder,
722 method_ty: &ty::Method) {
723 encode_def_id(ebml_w, method_ty.def_id);
724 encode_name(ebml_w, method_ty.ident.name);
725 encode_ty_type_param_defs(ebml_w, ecx,
726 method_ty.generics.type_param_defs(),
727 tag_item_method_tps);
728 encode_method_fty(ecx, ebml_w, &method_ty.fty);
729 encode_visibility(ebml_w, method_ty.vis);
730 encode_explicit_self(ebml_w, method_ty.explicit_self);
731 let fn_style = method_ty.fty.fn_style;
732 match method_ty.explicit_self {
734 encode_family(ebml_w, fn_style_static_method_family(fn_style));
736 _ => encode_family(ebml_w, style_fn_family(fn_style))
738 encode_provided_source(ebml_w, method_ty.provided_source);
741 fn encode_info_for_method(ecx: &EncodeContext,
742 ebml_w: &mut Encoder,
744 impl_path: PathElems,
745 is_default_impl: bool,
747 ast_method_opt: Option<@Method>) {
749 debug!("encode_info_for_method: {:?} {}", m.def_id,
750 token::get_ident(m.ident));
751 ebml_w.start_tag(tag_items_data_item);
753 encode_method_ty_fields(ecx, ebml_w, m);
754 encode_parent_item(ebml_w, local_def(parent_id));
756 // The type for methods gets encoded twice, which is unfortunate.
757 let tpt = lookup_item_type(ecx.tcx, m.def_id);
758 encode_bounds_and_type(ebml_w, ecx, &tpt);
760 let elem = ast_map::PathName(m.ident.name);
761 encode_path(ebml_w, impl_path.chain(Some(elem).move_iter()));
762 match ast_method_opt {
763 Some(ast_method) => {
764 encode_attributes(ebml_w, ast_method.attrs.as_slice())
769 for &ast_method in ast_method_opt.iter() {
770 let num_params = tpt.generics.type_param_defs().len();
771 if num_params > 0u ||
773 should_inline(ast_method.attrs.as_slice()) {
774 encode_inlined_item(ecx, ebml_w,
775 IIMethodRef(local_def(parent_id), false, ast_method));
777 encode_symbol(ecx, ebml_w, m.def_id.node);
779 encode_method_argument_names(ebml_w, &*ast_method.decl);
785 fn encode_method_argument_names(ebml_w: &mut Encoder,
786 decl: &ast::FnDecl) {
787 ebml_w.start_tag(tag_method_argument_names);
788 for arg in decl.inputs.iter() {
789 ebml_w.start_tag(tag_method_argument_name);
791 ast::PatIdent(_, ref name, _) => {
792 let name = name.segments.last().unwrap().identifier;
793 let name = token::get_ident(name);
794 ebml_w.writer.write(name.get().as_bytes());
803 fn encode_inlined_item(ecx: &EncodeContext,
804 ebml_w: &mut Encoder,
805 ii: InlinedItemRef) {
806 let mut eii = ecx.encode_inlined_item.borrow_mut();
807 let eii: &mut EncodeInlinedItem = &mut *eii;
808 (*eii)(ecx, ebml_w, ii)
811 fn style_fn_family(s: FnStyle) -> char {
818 fn fn_style_static_method_family(s: FnStyle) -> char {
826 fn should_inline(attrs: &[Attribute]) -> bool {
828 match find_inline_attr(attrs) {
829 InlineNone | InlineNever => false,
830 InlineHint | InlineAlways => true
834 // Encodes the inherent implementations of a structure, enumeration, or trait.
835 fn encode_inherent_implementations(ecx: &EncodeContext,
836 ebml_w: &mut Encoder,
838 match ecx.tcx.inherent_impls.borrow().find(&def_id) {
840 Some(implementations) => {
841 for &impl_def_id in implementations.borrow().iter() {
842 ebml_w.start_tag(tag_items_data_item_inherent_impl);
843 encode_def_id(ebml_w, impl_def_id);
850 // Encodes the implementations of a trait defined in this crate.
851 fn encode_extension_implementations(ecx: &EncodeContext,
852 ebml_w: &mut Encoder,
853 trait_def_id: DefId) {
854 match ecx.tcx.trait_impls.borrow().find(&trait_def_id) {
856 Some(implementations) => {
857 for &impl_def_id in implementations.borrow().iter() {
858 ebml_w.start_tag(tag_items_data_item_extension_impl);
859 encode_def_id(ebml_w, impl_def_id);
866 fn encode_sized(ebml_w: &mut Encoder, sized: Sized) {
867 ebml_w.start_tag(tag_items_data_item_sized);
868 let ch = match sized {
872 ebml_w.wr_str(str::from_char(ch).as_slice());
876 fn encode_info_for_item(ecx: &EncodeContext,
877 ebml_w: &mut Encoder,
879 index: &mut Vec<entry<i64>>,
881 vis: ast::Visibility) {
884 fn add_to_index(item: &Item, ebml_w: &Encoder,
885 index: &mut Vec<entry<i64>>) {
888 pos: ebml_w.writer.tell().unwrap(),
892 debug!("encoding info for item at {}",
893 ecx.tcx.sess.codemap().span_to_str(item.span));
895 let def_id = local_def(item.id);
897 ItemStatic(_, m, _) => {
898 add_to_index(item, ebml_w, index);
899 ebml_w.start_tag(tag_items_data_item);
900 encode_def_id(ebml_w, def_id);
901 if m == ast::MutMutable {
902 encode_family(ebml_w, 'b');
904 encode_family(ebml_w, 'c');
906 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
907 encode_symbol(ecx, ebml_w, item.id);
908 encode_name(ebml_w, item.ident.name);
909 encode_path(ebml_w, path);
911 let inlineable = !ecx.non_inlineable_statics.borrow().contains(&item.id);
914 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
916 encode_visibility(ebml_w, vis);
919 ItemFn(ref decl, fn_style, _, ref generics, _) => {
920 add_to_index(item, ebml_w, index);
921 ebml_w.start_tag(tag_items_data_item);
922 encode_def_id(ebml_w, def_id);
923 encode_family(ebml_w, style_fn_family(fn_style));
924 let tps_len = generics.ty_params.len();
925 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
926 encode_name(ebml_w, item.ident.name);
927 encode_path(ebml_w, path);
928 encode_attributes(ebml_w, item.attrs.as_slice());
929 if tps_len > 0u || should_inline(item.attrs.as_slice()) {
930 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
932 encode_symbol(ecx, ebml_w, item.id);
934 encode_visibility(ebml_w, vis);
935 encode_method_argument_names(ebml_w, &**decl);
939 add_to_index(item, ebml_w, index);
940 encode_info_for_mod(ecx,
943 item.attrs.as_slice(),
949 ItemForeignMod(ref fm) => {
950 add_to_index(item, ebml_w, index);
951 ebml_w.start_tag(tag_items_data_item);
952 encode_def_id(ebml_w, def_id);
953 encode_family(ebml_w, 'n');
954 encode_name(ebml_w, item.ident.name);
955 encode_path(ebml_w, path);
957 // Encode all the items in this module.
958 for foreign_item in fm.items.iter() {
959 ebml_w.start_tag(tag_mod_child);
960 ebml_w.wr_str(def_to_str(local_def(foreign_item.id)).as_slice());
963 encode_visibility(ebml_w, vis);
967 add_to_index(item, ebml_w, index);
968 ebml_w.start_tag(tag_items_data_item);
969 encode_def_id(ebml_w, def_id);
970 encode_family(ebml_w, 'y');
971 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
972 encode_name(ebml_w, item.ident.name);
973 encode_path(ebml_w, path);
974 encode_visibility(ebml_w, vis);
977 ItemEnum(ref enum_definition, ref generics) => {
978 add_to_index(item, ebml_w, index);
980 ebml_w.start_tag(tag_items_data_item);
981 encode_def_id(ebml_w, def_id);
982 encode_family(ebml_w, 't');
983 encode_item_variances(ebml_w, ecx, item.id);
984 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
985 encode_name(ebml_w, item.ident.name);
986 encode_attributes(ebml_w, item.attrs.as_slice());
987 for v in (*enum_definition).variants.iter() {
988 encode_variant_id(ebml_w, local_def(v.node.id));
990 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
991 encode_path(ebml_w, path);
993 // Encode inherent implementations for this enumeration.
994 encode_inherent_implementations(ecx, ebml_w, def_id);
996 encode_visibility(ebml_w, vis);
999 encode_enum_variant_info(ecx,
1002 (*enum_definition).variants.as_slice(),
1006 ItemStruct(struct_def, _) => {
1007 let fields = ty::lookup_struct_fields(tcx, def_id);
1009 /* First, encode the fields
1010 These come first because we need to write them to make
1011 the index, and the index needs to be in the item for the
1013 let idx = encode_info_for_struct(ecx,
1018 /* Index the class*/
1019 add_to_index(item, ebml_w, index);
1021 /* Now, make an item for the class itself */
1022 ebml_w.start_tag(tag_items_data_item);
1023 encode_def_id(ebml_w, def_id);
1024 encode_family(ebml_w, 'S');
1025 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1027 encode_item_variances(ebml_w, ecx, item.id);
1028 encode_name(ebml_w, item.ident.name);
1029 encode_attributes(ebml_w, item.attrs.as_slice());
1030 encode_path(ebml_w, path.clone());
1031 encode_visibility(ebml_w, vis);
1033 /* Encode def_ids for each field and method
1034 for methods, write all the stuff get_trait_method
1036 encode_struct_fields(ebml_w, fields.as_slice(), def_id);
1038 encode_inlined_item(ecx, ebml_w, IIItemRef(item));
1040 // Encode inherent implementations for this structure.
1041 encode_inherent_implementations(ecx, ebml_w, def_id);
1043 /* Each class has its own index -- encode it */
1044 encode_index(ebml_w, idx, write_i64);
1047 // If this is a tuple-like struct, encode the type of the constructor.
1048 match struct_def.ctor_id {
1050 encode_info_for_struct_ctor(ecx, ebml_w, item.ident,
1051 ctor_id, index, def_id.node);
1056 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1057 // We need to encode information about the default methods we
1058 // have inherited, so we drive this based on the impl structure.
1059 let impl_methods = tcx.impl_methods.borrow();
1060 let methods = impl_methods.get(&def_id);
1062 add_to_index(item, ebml_w, index);
1063 ebml_w.start_tag(tag_items_data_item);
1064 encode_def_id(ebml_w, def_id);
1065 encode_family(ebml_w, 'i');
1066 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1067 encode_name(ebml_w, item.ident.name);
1068 encode_attributes(ebml_w, item.attrs.as_slice());
1070 ast::TyPath(ref path, ref bounds, _) if path.segments
1072 assert!(bounds.is_none());
1073 encode_impl_type_basename(ebml_w, ast_util::path_to_ident(path));
1077 for &method_def_id in methods.iter() {
1078 ebml_w.start_tag(tag_item_impl_method);
1079 let s = def_to_str(method_def_id);
1080 ebml_w.writer.write(s.as_bytes());
1083 for ast_trait_ref in opt_trait.iter() {
1084 let trait_ref = ty::node_id_to_trait_ref(
1085 tcx, ast_trait_ref.ref_id);
1086 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_trait_ref);
1087 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1088 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1090 encode_path(ebml_w, path.clone());
1093 // Iterate down the methods, emitting them. We rely on the
1094 // assumption that all of the actually implemented methods
1095 // appear first in the impl structure, in the same order they do
1096 // in the ast. This is a little sketchy.
1097 let num_implemented_methods = ast_methods.len();
1098 for (i, &method_def_id) in methods.iter().enumerate() {
1099 let ast_method = if i < num_implemented_methods {
1100 Some(*ast_methods.get(i))
1104 val: method_def_id.node as i64,
1105 pos: ebml_w.writer.tell().unwrap(),
1107 encode_info_for_method(ecx,
1109 &*ty::method(tcx, method_def_id),
1116 ItemTrait(_, sized, ref super_traits, ref ms) => {
1117 add_to_index(item, ebml_w, index);
1118 ebml_w.start_tag(tag_items_data_item);
1119 encode_def_id(ebml_w, def_id);
1120 encode_family(ebml_w, 'I');
1121 encode_item_variances(ebml_w, ecx, item.id);
1122 let trait_def = ty::lookup_trait_def(tcx, def_id);
1123 encode_ty_type_param_defs(ebml_w, ecx,
1124 trait_def.generics.type_param_defs(),
1125 tag_items_data_item_ty_param_bounds);
1126 encode_region_param_defs(ebml_w, trait_def.generics.region_param_defs());
1127 encode_trait_ref(ebml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
1128 encode_name(ebml_w, item.ident.name);
1129 encode_attributes(ebml_w, item.attrs.as_slice());
1130 // When we fix the rest of the supertrait nastiness (FIXME(#8559)), we
1131 // should no longer need this ugly little hack either.
1132 encode_sized(ebml_w, sized);
1133 encode_visibility(ebml_w, vis);
1134 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1135 ebml_w.start_tag(tag_item_trait_method);
1136 encode_def_id(ebml_w, method_def_id);
1139 ebml_w.start_tag(tag_mod_child);
1140 ebml_w.wr_str(def_to_str(method_def_id).as_slice());
1143 encode_path(ebml_w, path.clone());
1144 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1145 // reading the AST's list, because the former has already filtered out
1146 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1147 for ast_trait_ref in super_traits.iter() {
1148 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1149 encode_trait_ref(ebml_w, ecx, &*trait_ref, tag_item_super_trait_ref);
1152 // Encode the implementations of this trait.
1153 encode_extension_implementations(ecx, ebml_w, def_id);
1157 // Now output the method info for each method.
1158 let r = ty::trait_method_def_ids(tcx, def_id);
1159 for (i, &method_def_id) in r.iter().enumerate() {
1160 assert_eq!(method_def_id.krate, ast::LOCAL_CRATE);
1162 let method_ty = ty::method(tcx, method_def_id);
1165 val: method_def_id.node as i64,
1166 pos: ebml_w.writer.tell().unwrap(),
1169 ebml_w.start_tag(tag_items_data_item);
1171 encode_method_ty_fields(ecx, ebml_w, &*method_ty);
1173 encode_parent_item(ebml_w, def_id);
1175 let elem = ast_map::PathName(method_ty.ident.name);
1176 encode_path(ebml_w, path.clone().chain(Some(elem).move_iter()));
1178 match method_ty.explicit_self {
1180 encode_family(ebml_w,
1181 fn_style_static_method_family(
1182 method_ty.fty.fn_style));
1184 let tpt = ty::lookup_item_type(tcx, method_def_id);
1185 encode_bounds_and_type(ebml_w, ecx, &tpt);
1189 encode_family(ebml_w,
1191 method_ty.fty.fn_style));
1196 &Required(ref tm) => {
1197 encode_attributes(ebml_w, tm.attrs.as_slice());
1198 encode_method_sort(ebml_w, 'r');
1202 encode_attributes(ebml_w, m.attrs.as_slice());
1203 // If this is a static method, we've already encoded
1205 if method_ty.explicit_self != SelfStatic {
1206 // FIXME: I feel like there is something funny going on.
1207 let tpt = ty::lookup_item_type(tcx, method_def_id);
1208 encode_bounds_and_type(ebml_w, ecx, &tpt);
1210 encode_method_sort(ebml_w, 'p');
1211 encode_inlined_item(ecx, ebml_w,
1212 IIMethodRef(def_id, true, m));
1219 // Encode inherent implementations for this trait.
1220 encode_inherent_implementations(ecx, ebml_w, def_id);
1223 // macros are encoded separately
1228 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1229 ebml_w: &mut Encoder,
1230 nitem: &ForeignItem,
1231 index: &mut Vec<entry<i64>>,
1235 val: nitem.id as i64,
1236 pos: ebml_w.writer.tell().unwrap(),
1239 ebml_w.start_tag(tag_items_data_item);
1240 encode_def_id(ebml_w, local_def(nitem.id));
1242 ForeignItemFn(..) => {
1243 encode_family(ebml_w, style_fn_family(NormalFn));
1244 encode_bounds_and_type(ebml_w, ecx,
1245 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1246 encode_name(ebml_w, nitem.ident.name);
1247 if abi == abi::RustIntrinsic {
1248 encode_inlined_item(ecx, ebml_w, IIForeignRef(nitem));
1250 encode_symbol(ecx, ebml_w, nitem.id);
1253 ForeignItemStatic(_, mutbl) => {
1255 encode_family(ebml_w, 'b');
1257 encode_family(ebml_w, 'c');
1259 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1260 encode_symbol(ecx, ebml_w, nitem.id);
1261 encode_name(ebml_w, nitem.ident.name);
1264 encode_path(ebml_w, path);
1268 fn my_visit_expr(_e: &Expr) { }
1270 fn my_visit_item(i: &Item,
1271 ebml_w: &mut Encoder,
1273 index: &mut Vec<entry<i64>>) {
1274 let mut ebml_w = unsafe { ebml_w.unsafe_clone() };
1276 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1277 ecx.tcx.map.with_path(i.id, |path| {
1278 encode_info_for_item(ecx, &mut ebml_w, i, index, path, i.vis);
1282 fn my_visit_foreign_item(ni: &ForeignItem,
1283 ebml_w: &mut Encoder,
1285 index: &mut Vec<entry<i64>>) {
1287 let ecx: &EncodeContext = unsafe { mem::transmute(ecx_ptr) };
1288 debug!("writing foreign item {}::{}",
1289 ecx.tcx.map.path_to_str(ni.id),
1290 token::get_ident(ni.ident));
1292 let mut ebml_w = unsafe {
1293 ebml_w.unsafe_clone()
1295 let abi = ecx.tcx.map.get_foreign_abi(ni.id);
1296 ecx.tcx.map.with_path(ni.id, |path| {
1297 encode_info_for_foreign_item(ecx, &mut ebml_w,
1303 struct EncodeVisitor<'a,'b> {
1304 ebml_w_for_visit_item: &'a mut Encoder<'b>,
1306 index: &'a mut Vec<entry<i64>>,
1309 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1310 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1311 visit::walk_expr(self, ex, ());
1314 fn visit_item(&mut self, i: &Item, _: ()) {
1315 visit::walk_item(self, i, ());
1317 self.ebml_w_for_visit_item,
1321 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1322 visit::walk_foreign_item(self, ni, ());
1323 my_visit_foreign_item(ni,
1324 self.ebml_w_for_visit_item,
1330 fn encode_info_for_items(ecx: &EncodeContext,
1331 ebml_w: &mut Encoder,
1333 -> Vec<entry<i64>> {
1334 let mut index = Vec::new();
1335 ebml_w.start_tag(tag_items_data);
1337 val: CRATE_NODE_ID as i64,
1338 pos: ebml_w.writer.tell().unwrap(),
1340 encode_info_for_mod(ecx,
1345 ast_map::Values([].iter()).chain(None),
1346 syntax::parse::token::special_idents::invalid,
1349 // See comment in `encode_side_tables_for_ii` in astencode
1350 let ecx_ptr: *int = unsafe { mem::transmute(ecx) };
1351 visit::walk_crate(&mut EncodeVisitor {
1354 ebml_w_for_visit_item: &mut *ebml_w,
1362 // Path and definition ID indexing
1364 fn encode_index<T: Hash>(ebml_w: &mut Encoder, index: Vec<entry<T>>,
1365 write_fn: |&mut MemWriter, &T|) {
1366 let mut buckets: Vec<Vec<entry<T>>> = Vec::from_fn(256, |_| Vec::new());
1367 for elt in index.move_iter() {
1368 let h = hash::hash(&elt.val) as uint;
1369 buckets.get_mut(h % 256).push(elt);
1372 ebml_w.start_tag(tag_index);
1373 let mut bucket_locs = Vec::new();
1374 ebml_w.start_tag(tag_index_buckets);
1375 for bucket in buckets.iter() {
1376 bucket_locs.push(ebml_w.writer.tell().unwrap());
1377 ebml_w.start_tag(tag_index_buckets_bucket);
1378 for elt in bucket.iter() {
1379 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1380 assert!(elt.pos < 0xffff_ffff);
1382 let wr: &mut MemWriter = ebml_w.writer;
1383 wr.write_be_u32(elt.pos as u32);
1385 write_fn(ebml_w.writer, &elt.val);
1391 ebml_w.start_tag(tag_index_table);
1392 for pos in bucket_locs.iter() {
1393 assert!(*pos < 0xffff_ffff);
1394 let wr: &mut MemWriter = ebml_w.writer;
1395 wr.write_be_u32(*pos as u32);
1401 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1402 let wr: &mut MemWriter = writer;
1403 assert!(n < 0x7fff_ffff);
1404 wr.write_be_u32(n as u32);
1407 fn encode_meta_item(ebml_w: &mut Encoder, mi: @MetaItem) {
1409 MetaWord(ref name) => {
1410 ebml_w.start_tag(tag_meta_item_word);
1411 ebml_w.start_tag(tag_meta_item_name);
1412 ebml_w.writer.write(name.get().as_bytes());
1416 MetaNameValue(ref name, ref value) => {
1418 LitStr(ref value, _) => {
1419 ebml_w.start_tag(tag_meta_item_name_value);
1420 ebml_w.start_tag(tag_meta_item_name);
1421 ebml_w.writer.write(name.get().as_bytes());
1423 ebml_w.start_tag(tag_meta_item_value);
1424 ebml_w.writer.write(value.get().as_bytes());
1428 _ => {/* FIXME (#623): encode other variants */ }
1431 MetaList(ref name, ref items) => {
1432 ebml_w.start_tag(tag_meta_item_list);
1433 ebml_w.start_tag(tag_meta_item_name);
1434 ebml_w.writer.write(name.get().as_bytes());
1436 for inner_item in items.iter() {
1437 encode_meta_item(ebml_w, *inner_item);
1444 fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
1445 ebml_w.start_tag(tag_attributes);
1446 for attr in attrs.iter() {
1447 ebml_w.start_tag(tag_attribute);
1448 encode_meta_item(ebml_w, attr.node.value);
1454 // So there's a special crate attribute called 'crate_id' which defines the
1455 // metadata that Rust cares about for linking crates. If the user didn't
1456 // provide it we will throw it in anyway with a default value.
1457 fn synthesize_crate_attrs(ecx: &EncodeContext,
1458 krate: &Crate) -> Vec<Attribute> {
1460 fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute {
1461 assert!(!ecx.link_meta.crateid.name.is_empty());
1463 attr::mk_attr_inner(attr::mk_attr_id(),
1464 attr::mk_name_value_item_str(
1465 InternedString::new("crate_id"),
1466 token::intern_and_get_ident(ecx.link_meta
1472 let mut attrs = Vec::new();
1473 for attr in krate.attrs.iter() {
1474 if !attr.check_name("crate_id") {
1478 attrs.push(synthesize_crateid_attr(ecx));
1483 fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
1484 fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
1485 // Pull the cnums and name,vers,hash out of cstore
1486 let mut deps = Vec::new();
1487 cstore.iter_crate_data(|key, val| {
1488 let dep = decoder::CrateDep {
1490 crate_id: decoder::get_crate_id(val.data()),
1491 hash: decoder::get_crate_hash(val.data())
1497 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1499 // Sanity-check the crate numbers
1500 let mut expected_cnum = 1;
1501 for n in deps.iter() {
1502 assert_eq!(n.cnum, expected_cnum);
1509 // We're just going to write a list of crate 'name-hash-version's, with
1510 // the assumption that they are numbered 1 to n.
1511 // FIXME (#2166): This is not nearly enough to support correct versioning
1512 // but is enough to get transitive crate dependencies working.
1513 ebml_w.start_tag(tag_crate_deps);
1514 let r = get_ordered_deps(cstore);
1515 for dep in r.iter() {
1516 encode_crate_dep(ebml_w, (*dep).clone());
1521 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1522 ebml_w.start_tag(tag_lang_items);
1524 for (i, def_id) in ecx.tcx.lang_items.items() {
1525 for id in def_id.iter() {
1526 if id.krate == LOCAL_CRATE {
1527 ebml_w.start_tag(tag_lang_items_item);
1529 ebml_w.start_tag(tag_lang_items_item_id);
1531 let wr: &mut MemWriter = ebml_w.writer;
1532 wr.write_be_u32(i as u32);
1534 ebml_w.end_tag(); // tag_lang_items_item_id
1536 ebml_w.start_tag(tag_lang_items_item_node_id);
1538 let wr: &mut MemWriter = ebml_w.writer;
1539 wr.write_be_u32(id.node as u32);
1541 ebml_w.end_tag(); // tag_lang_items_item_node_id
1543 ebml_w.end_tag(); // tag_lang_items_item
1548 for i in ecx.tcx.lang_items.missing.iter() {
1549 ebml_w.wr_tagged_u32(tag_lang_items_missing, *i as u32);
1552 ebml_w.end_tag(); // tag_lang_items
1555 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1556 ebml_w.start_tag(tag_native_libraries);
1558 for &(ref lib, kind) in ecx.tcx.sess.cstore.get_used_libraries()
1561 cstore::NativeStatic => {} // these libraries are not propagated
1562 cstore::NativeFramework | cstore::NativeUnknown => {
1563 ebml_w.start_tag(tag_native_libraries_lib);
1565 ebml_w.start_tag(tag_native_libraries_kind);
1566 ebml_w.writer.write_be_u32(kind as u32);
1569 ebml_w.start_tag(tag_native_libraries_name);
1570 ebml_w.writer.write(lib.as_bytes());
1581 fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut Encoder) {
1582 match ecx.tcx.sess.macro_registrar_fn.get() {
1583 Some(id) => { ebml_w.wr_tagged_u32(tag_macro_registrar_fn, id); }
1588 struct MacroDefVisitor<'a, 'b, 'c> {
1589 ecx: &'a EncodeContext<'b>,
1590 ebml_w: &'a mut Encoder<'c>
1593 impl<'a, 'b, 'c> Visitor<()> for MacroDefVisitor<'a, 'b, 'c> {
1594 fn visit_item(&mut self, item: &Item, _: ()) {
1597 let def = self.ecx.tcx.sess.codemap().span_to_snippet(item.span)
1598 .expect("Unable to find source for macro");
1599 self.ebml_w.start_tag(tag_macro_def);
1600 self.ebml_w.wr_str(def.as_slice());
1601 self.ebml_w.end_tag();
1605 visit::walk_item(self, item, ());
1609 fn encode_macro_defs<'a>(ecx: &'a EncodeContext,
1611 ebml_w: &'a mut Encoder) {
1612 ebml_w.start_tag(tag_exported_macros);
1614 let mut visitor = MacroDefVisitor {
1618 visit::walk_crate(&mut visitor, krate, ());
1623 struct ImplVisitor<'a,'b,'c> {
1624 ecx: &'a EncodeContext<'b>,
1625 ebml_w: &'a mut Encoder<'c>,
1628 impl<'a,'b,'c> Visitor<()> for ImplVisitor<'a,'b,'c> {
1629 fn visit_item(&mut self, item: &Item, _: ()) {
1631 ItemImpl(_, Some(ref trait_ref), _, _) => {
1632 let def_map = &self.ecx.tcx.def_map;
1633 let trait_def = def_map.borrow().get_copy(&trait_ref.ref_id);
1634 let def_id = ast_util::def_id_of_def(trait_def);
1636 // Load eagerly if this is an implementation of the Drop trait
1637 // or if the trait is not defined in this crate.
1638 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1639 def_id.krate != LOCAL_CRATE {
1640 self.ebml_w.start_tag(tag_impls_impl);
1641 encode_def_id(self.ebml_w, local_def(item.id));
1642 self.ebml_w.end_tag();
1647 visit::walk_item(self, item, ());
1651 /// Encodes implementations that are eagerly loaded.
1653 /// None of this is necessary in theory; we can load all implementations
1654 /// lazily. However, in two cases the optimizations to lazily load
1655 /// implementations are not yet implemented. These two cases, which require us
1656 /// to load implementations eagerly, are:
1658 /// * Destructors (implementations of the Drop trait).
1660 /// * Implementations of traits not defined in this crate.
1661 fn encode_impls<'a>(ecx: &'a EncodeContext,
1663 ebml_w: &'a mut Encoder) {
1664 ebml_w.start_tag(tag_impls);
1667 let mut visitor = ImplVisitor {
1671 visit::walk_crate(&mut visitor, krate, ());
1677 fn encode_misc_info(ecx: &EncodeContext,
1679 ebml_w: &mut Encoder) {
1680 ebml_w.start_tag(tag_misc_info);
1681 ebml_w.start_tag(tag_misc_info_crate_items);
1682 for &item in krate.module.items.iter() {
1683 ebml_w.start_tag(tag_mod_child);
1684 ebml_w.wr_str(def_to_str(local_def(item.id)).as_slice());
1687 each_auxiliary_node_id(item, |auxiliary_node_id| {
1688 ebml_w.start_tag(tag_mod_child);
1689 ebml_w.wr_str(def_to_str(local_def(
1690 auxiliary_node_id)).as_slice());
1696 // Encode reexports for the root module.
1697 encode_reexports(ecx, ebml_w, 0, ast_map::Values([].iter()).chain(None));
1703 fn encode_crate_dep(ebml_w: &mut Encoder,
1704 dep: decoder::CrateDep) {
1705 ebml_w.start_tag(tag_crate_dep);
1706 ebml_w.start_tag(tag_crate_dep_crateid);
1707 ebml_w.writer.write(dep.crate_id.to_str().as_bytes());
1709 ebml_w.start_tag(tag_crate_dep_hash);
1710 ebml_w.writer.write(dep.hash.as_str().as_bytes());
1715 fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
1716 ebml_w.start_tag(tag_crate_hash);
1717 ebml_w.writer.write(hash.as_str().as_bytes());
1721 fn encode_crate_id(ebml_w: &mut Encoder, crate_id: &CrateId) {
1722 ebml_w.start_tag(tag_crate_crateid);
1723 ebml_w.writer.write(crate_id.to_str().as_bytes());
1727 fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
1728 ebml_w.start_tag(tag_crate_triple);
1729 ebml_w.writer.write(triple.as_bytes());
1733 fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
1734 ebml_w.start_tag(tag_dylib_dependency_formats);
1735 match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
1737 let s = arr.iter().enumerate().filter_map(|(i, slot)| {
1738 slot.map(|kind| (format!("{}:{}", i + 1, match kind {
1739 cstore::RequireDynamic => "d",
1740 cstore::RequireStatic => "s",
1742 }).collect::<Vec<String>>();
1743 ebml_w.writer.write(s.connect(",").as_bytes());
1750 // NB: Increment this as you change the metadata encoding version.
1751 pub static metadata_encoding_version : &'static [u8] =
1752 &[0x72, //'r' as u8,
1758 pub fn encode_metadata(parms: EncodeParams, krate: &Crate) -> Vec<u8> {
1759 let mut wr = MemWriter::new();
1760 encode_metadata_inner(&mut wr, parms, krate);
1761 wr.unwrap().move_iter().collect()
1764 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate) {
1768 lang_item_bytes: u64,
1769 native_lib_bytes: u64,
1770 macro_registrar_fn_bytes: u64,
1771 macro_defs_bytes: u64,
1779 let mut stats = Stats {
1783 native_lib_bytes: 0,
1784 macro_registrar_fn_bytes: 0,
1785 macro_defs_bytes: 0,
1799 encode_inlined_item,
1801 non_inlineable_statics,
1804 let ecx = EncodeContext {
1807 reexports2: reexports2,
1808 item_symbols: item_symbols,
1809 non_inlineable_statics: non_inlineable_statics,
1810 link_meta: link_meta,
1812 encode_inlined_item: RefCell::new(encode_inlined_item),
1813 type_abbrevs: RefCell::new(HashMap::new()),
1816 let mut ebml_w = writer::Encoder(wr);
1818 encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
1819 encode_crate_triple(&mut ebml_w,
1825 encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
1826 encode_dylib_dependency_formats(&mut ebml_w, &ecx);
1828 let mut i = ebml_w.writer.tell().unwrap();
1829 let crate_attrs = synthesize_crate_attrs(&ecx, krate);
1830 encode_attributes(&mut ebml_w, crate_attrs.as_slice());
1831 stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
1833 i = ebml_w.writer.tell().unwrap();
1834 encode_crate_deps(&mut ebml_w, ecx.cstore);
1835 stats.dep_bytes = ebml_w.writer.tell().unwrap() - i;
1837 // Encode the language items.
1838 i = ebml_w.writer.tell().unwrap();
1839 encode_lang_items(&ecx, &mut ebml_w);
1840 stats.lang_item_bytes = ebml_w.writer.tell().unwrap() - i;
1842 // Encode the native libraries used
1843 i = ebml_w.writer.tell().unwrap();
1844 encode_native_libraries(&ecx, &mut ebml_w);
1845 stats.native_lib_bytes = ebml_w.writer.tell().unwrap() - i;
1847 // Encode the macro registrar function
1848 i = ebml_w.writer.tell().unwrap();
1849 encode_macro_registrar_fn(&ecx, &mut ebml_w);
1850 stats.macro_registrar_fn_bytes = ebml_w.writer.tell().unwrap() - i;
1852 // Encode macro definitions
1853 i = ebml_w.writer.tell().unwrap();
1854 encode_macro_defs(&ecx, krate, &mut ebml_w);
1855 stats.macro_defs_bytes = ebml_w.writer.tell().unwrap() - i;
1857 // Encode the def IDs of impls, for coherence checking.
1858 i = ebml_w.writer.tell().unwrap();
1859 encode_impls(&ecx, krate, &mut ebml_w);
1860 stats.impl_bytes = ebml_w.writer.tell().unwrap() - i;
1862 // Encode miscellaneous info.
1863 i = ebml_w.writer.tell().unwrap();
1864 encode_misc_info(&ecx, krate, &mut ebml_w);
1865 stats.misc_bytes = ebml_w.writer.tell().unwrap() - i;
1867 // Encode and index the items.
1868 ebml_w.start_tag(tag_items);
1869 i = ebml_w.writer.tell().unwrap();
1870 let items_index = encode_info_for_items(&ecx, &mut ebml_w, krate);
1871 stats.item_bytes = ebml_w.writer.tell().unwrap() - i;
1873 i = ebml_w.writer.tell().unwrap();
1874 encode_index(&mut ebml_w, items_index, write_i64);
1875 stats.index_bytes = ebml_w.writer.tell().unwrap() - i;
1878 stats.total_bytes = ebml_w.writer.tell().unwrap();
1880 if tcx.sess.meta_stats() {
1881 for e in ebml_w.writer.get_ref().iter() {
1883 stats.zero_bytes += 1;
1887 println!("metadata stats:");
1888 println!(" attribute bytes: {}", stats.attr_bytes);
1889 println!(" dep bytes: {}", stats.dep_bytes);
1890 println!(" lang item bytes: {}", stats.lang_item_bytes);
1891 println!(" native bytes: {}", stats.native_lib_bytes);
1892 println!("macro registrar bytes: {}", stats.macro_registrar_fn_bytes);
1893 println!(" macro def bytes: {}", stats.macro_defs_bytes);
1894 println!(" impl bytes: {}", stats.impl_bytes);
1895 println!(" misc bytes: {}", stats.misc_bytes);
1896 println!(" item bytes: {}", stats.item_bytes);
1897 println!(" index bytes: {}", stats.index_bytes);
1898 println!(" zero bytes: {}", stats.zero_bytes);
1899 println!(" total bytes: {}", stats.total_bytes);
1903 // Get the encoded string for a type
1904 pub fn encoded_ty(tcx: &ty::ctxt, t: ty::t) -> String {
1905 let mut wr = MemWriter::new();
1906 tyencode::enc_ty(&mut wr, &tyencode::ctxt {
1907 diag: tcx.sess.diagnostic(),
1910 abbrevs: &RefCell::new(HashMap::new())
1912 str::from_utf8_owned(Vec::from_slice(wr.get_ref())).unwrap().to_string()