1 // Copyright 2012 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.
14 use metadata::common::*;
16 use metadata::decoder;
17 use metadata::tyencode;
18 use middle::ty::{node_id_to_type, lookup_item_type};
19 use middle::astencode;
24 use std::hashmap::{HashMap, HashSet};
25 use std::io::{Writer, Seek, Decorator};
26 use std::io::mem::MemWriter;
31 use extra::serialize::Encodable;
34 use syntax::abi::AbiSet;
38 use syntax::ast_util::*;
40 use syntax::attr::AttrMetaMethods;
41 use syntax::diagnostic::span_handler;
42 use syntax::parse::token::special_idents;
44 use syntax::visit::Visitor;
46 use syntax::parse::token;
48 use writer = extra::ebml::writer;
53 type abbrev_map = @mut HashMap<ty::t, tyencode::ty_abbrev>;
55 pub type encode_inlined_item<'self> = 'self |ecx: &EncodeContext,
56 ebml_w: &mut writer::Encoder,
57 path: &[ast_map::path_elt],
58 ii: ast::inlined_item|;
60 pub struct EncodeParams<'self> {
61 diag: @mut span_handler,
63 reexports2: middle::resolve::ExportMap2,
64 item_symbols: &'self HashMap<ast::NodeId, ~str>,
65 discrim_symbols: &'self HashMap<ast::NodeId, @str>,
66 non_inlineable_statics: &'self HashSet<ast::NodeId>,
67 link_meta: &'self LinkMeta,
68 cstore: @mut cstore::CStore,
69 encode_inlined_item: encode_inlined_item<'self>,
70 reachable: @mut HashSet<ast::NodeId>,
78 native_lib_bytes: u64,
89 pub struct EncodeContext<'self> {
90 diag: @mut span_handler,
93 reexports2: middle::resolve::ExportMap2,
94 item_symbols: &'self HashMap<ast::NodeId, ~str>,
95 discrim_symbols: &'self HashMap<ast::NodeId, @str>,
96 non_inlineable_statics: &'self HashSet<ast::NodeId>,
97 link_meta: &'self LinkMeta,
98 cstore: &'self cstore::CStore,
99 encode_inlined_item: encode_inlined_item<'self>,
100 type_abbrevs: abbrev_map,
101 reachable: @mut HashSet<ast::NodeId>,
104 pub fn reachable(ecx: &EncodeContext, id: NodeId) -> bool {
105 ecx.reachable.contains(&id)
108 fn encode_name(ecx: &EncodeContext,
109 ebml_w: &mut writer::Encoder,
111 ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name));
114 fn encode_impl_type_basename(ecx: &EncodeContext,
115 ebml_w: &mut writer::Encoder,
117 ebml_w.wr_tagged_str(tag_item_impl_type_basename,
118 ecx.tcx.sess.str_of(name));
121 pub fn encode_def_id(ebml_w: &mut writer::Encoder, id: DefId) {
122 ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
131 fn add_to_index(ebml_w: &mut writer::Encoder,
133 index: &mut ~[entry<~str>],
135 let mut full_path = ~[];
136 full_path.push_all(path);
137 full_path.push(name);
140 val: ast_util::path_name_i(full_path),
141 pos: ebml_w.writer.tell()
145 fn encode_trait_ref(ebml_w: &mut writer::Encoder,
147 trait_ref: &ty::TraitRef,
149 let ty_str_ctxt = @tyencode::ctxt {
153 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
156 ebml_w.start_tag(tag);
157 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
161 fn encode_impl_vtables(ebml_w: &mut writer::Encoder,
163 vtables: &typeck::impl_res) {
164 ebml_w.start_tag(tag_item_impl_vtables);
165 astencode::encode_vtable_res(ecx, ebml_w, vtables.trait_vtables);
166 astencode::encode_vtable_param_res(ecx, ebml_w, vtables.self_vtables);
170 // Item info table encoding
171 fn encode_family(ebml_w: &mut writer::Encoder, c: char) {
172 ebml_w.start_tag(tag_items_data_item_family);
173 ebml_w.writer.write(&[c as u8]);
177 pub fn def_to_str(did: DefId) -> ~str {
178 format!("{}:{}", did.crate, did.node)
181 fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
183 params: @~[ty::TypeParameterDef],
185 let ty_str_ctxt = @tyencode::ctxt {
189 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
191 for param in params.iter() {
192 ebml_w.start_tag(tag);
193 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
198 fn encode_region_param_defs(ebml_w: &mut writer::Encoder,
200 params: @[ty::RegionParameterDef]) {
201 for param in params.iter() {
202 ebml_w.start_tag(tag_region_param_def);
204 ebml_w.start_tag(tag_region_param_def_ident);
205 encode_name(ecx, ebml_w, param.ident);
208 ebml_w.wr_tagged_str(tag_region_param_def_def_id,
209 def_to_str(param.def_id));
215 fn encode_item_variances(ebml_w: &mut writer::Encoder,
218 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
219 ebml_w.start_tag(tag_item_variances);
224 fn encode_bounds_and_type(ebml_w: &mut writer::Encoder,
226 tpt: &ty::ty_param_bounds_and_ty) {
227 encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs,
228 tag_items_data_item_ty_param_bounds);
229 encode_region_param_defs(ebml_w, ecx, tpt.generics.region_param_defs);
230 encode_type(ecx, ebml_w, tpt.ty);
233 fn encode_variant_id(ebml_w: &mut writer::Encoder, vid: DefId) {
234 ebml_w.start_tag(tag_items_data_item_variant);
235 let s = def_to_str(vid);
236 ebml_w.writer.write(s.as_bytes());
240 pub fn write_type(ecx: &EncodeContext,
241 ebml_w: &mut writer::Encoder,
243 let ty_str_ctxt = @tyencode::ctxt {
247 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
249 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
252 pub fn write_vstore(ecx: &EncodeContext,
253 ebml_w: &mut writer::Encoder,
254 vstore: ty::vstore) {
255 let ty_str_ctxt = @tyencode::ctxt {
259 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
261 tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
264 fn encode_type(ecx: &EncodeContext,
265 ebml_w: &mut writer::Encoder,
267 ebml_w.start_tag(tag_items_data_item_type);
268 write_type(ecx, ebml_w, typ);
272 fn encode_transformed_self_ty(ecx: &EncodeContext,
273 ebml_w: &mut writer::Encoder,
274 opt_typ: Option<ty::t>) {
275 for &typ in opt_typ.iter() {
276 ebml_w.start_tag(tag_item_method_transformed_self_ty);
277 write_type(ecx, ebml_w, typ);
282 fn encode_method_fty(ecx: &EncodeContext,
283 ebml_w: &mut writer::Encoder,
284 typ: &ty::BareFnTy) {
285 ebml_w.start_tag(tag_item_method_fty);
287 let ty_str_ctxt = @tyencode::ctxt {
291 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
293 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
298 fn encode_symbol(ecx: &EncodeContext,
299 ebml_w: &mut writer::Encoder,
301 ebml_w.start_tag(tag_items_data_item_symbol);
302 match ecx.item_symbols.find(&id) {
304 debug!("encode_symbol(id={:?}, str={})", id, *x);
305 ebml_w.writer.write(x.as_bytes());
308 ecx.diag.handler().bug(
309 format!("encode_symbol: id not found {}", id));
315 fn encode_disr_val(_: &EncodeContext,
316 ebml_w: &mut writer::Encoder,
317 disr_val: ty::Disr) {
318 ebml_w.start_tag(tag_disr_val);
319 let s = disr_val.to_str();
320 ebml_w.writer.write(s.as_bytes());
324 fn encode_parent_item(ebml_w: &mut writer::Encoder, id: DefId) {
325 ebml_w.start_tag(tag_items_data_parent_item);
326 let s = def_to_str(id);
327 ebml_w.writer.write(s.as_bytes());
331 fn encode_struct_fields(ecx: &EncodeContext,
332 ebml_w: &mut writer::Encoder,
334 for f in def.fields.iter() {
336 named_field(ident, vis) => {
337 ebml_w.start_tag(tag_item_field);
338 encode_struct_field_family(ebml_w, vis);
339 encode_name(ecx, ebml_w, ident);
340 encode_def_id(ebml_w, local_def(f.node.id));
344 ebml_w.start_tag(tag_item_unnamed_field);
345 encode_def_id(ebml_w, local_def(f.node.id));
352 fn encode_enum_variant_info(ecx: &EncodeContext,
353 ebml_w: &mut writer::Encoder,
355 variants: &[variant],
356 path: &[ast_map::path_elt],
357 index: @mut ~[entry<i64>],
358 generics: &ast::Generics) {
359 debug!("encode_enum_variant_info(id={:?})", id);
361 let mut disr_val = 0;
363 let vi = ty::enum_variants(ecx.tcx,
364 ast::DefId { crate: LOCAL_CRATE, node: id });
365 for variant in variants.iter() {
366 let def_id = local_def(variant.node.id);
367 index.push(entry {val: variant.node.id as i64,
368 pos: ebml_w.writer.tell()});
369 ebml_w.start_tag(tag_items_data_item);
370 encode_def_id(ebml_w, def_id);
371 match variant.node.kind {
372 ast::tuple_variant_kind(_) => encode_family(ebml_w, 'v'),
373 ast::struct_variant_kind(_) => encode_family(ebml_w, 'V')
375 encode_name(ecx, ebml_w, variant.node.name);
376 encode_parent_item(ebml_w, local_def(id));
377 encode_visibility(ebml_w, variant.node.vis);
378 encode_attributes(ebml_w, variant.node.attrs);
379 match variant.node.kind {
380 ast::tuple_variant_kind(ref args)
381 if args.len() > 0 && generics.ty_params.len() == 0 => {
382 encode_symbol(ecx, ebml_w, variant.node.id);
384 ast::tuple_variant_kind(_) => {},
385 ast::struct_variant_kind(def) => {
386 let idx = encode_info_for_struct(ecx, ebml_w, path,
388 encode_struct_fields(ecx, ebml_w, def);
389 let bkts = create_index(idx);
390 encode_index(ebml_w, bkts, write_i64);
393 if vi[i].disr_val != disr_val {
394 encode_disr_val(ecx, ebml_w, vi[i].disr_val);
395 disr_val = vi[i].disr_val;
397 encode_bounds_and_type(ebml_w, ecx,
398 &lookup_item_type(ecx.tcx, def_id));
399 encode_path(ecx, ebml_w, path,
400 ast_map::path_name(variant.node.name));
407 fn encode_path(ecx: &EncodeContext,
408 ebml_w: &mut writer::Encoder,
409 path: &[ast_map::path_elt],
410 name: ast_map::path_elt) {
411 fn encode_path_elt(ecx: &EncodeContext,
412 ebml_w: &mut writer::Encoder,
413 elt: ast_map::path_elt) {
415 ast_map::path_mod(n) => {
416 ebml_w.wr_tagged_str(tag_path_elt_mod, ecx.tcx.sess.str_of(n));
418 ast_map::path_name(n) => {
419 ebml_w.wr_tagged_str(tag_path_elt_name, ecx.tcx.sess.str_of(n));
421 ast_map::path_pretty_name(n, extra) => {
422 ebml_w.start_tag(tag_path_elt_pretty_name);
423 ebml_w.wr_tagged_str(tag_path_elt_pretty_name_ident,
424 ecx.tcx.sess.str_of(n));
425 ebml_w.wr_tagged_u64(tag_path_elt_pretty_name_extra, extra);
431 ebml_w.start_tag(tag_path);
432 ebml_w.wr_tagged_u32(tag_path_len, (path.len() + 1) as u32);
433 for pe in path.iter() {
434 encode_path_elt(ecx, ebml_w, *pe);
436 encode_path_elt(ecx, ebml_w, name);
440 fn encode_reexported_static_method(ecx: &EncodeContext,
441 ebml_w: &mut writer::Encoder,
442 exp: &middle::resolve::Export2,
443 method_def_id: DefId,
444 method_ident: Ident) {
445 debug!("(encode reexported static method) {}::{}",
446 exp.name, ecx.tcx.sess.str_of(method_ident));
447 ebml_w.start_tag(tag_items_data_item_reexport);
448 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
449 ebml_w.wr_str(def_to_str(method_def_id));
451 ebml_w.start_tag(tag_items_data_item_reexport_name);
452 ebml_w.wr_str(format!("{}::{}", exp.name, ecx.tcx.sess.str_of(method_ident)));
457 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
458 ebml_w: &mut writer::Encoder,
459 exp: &middle::resolve::Export2)
461 match ecx.tcx.inherent_impls.find(&exp.def_id) {
462 Some(implementations) => {
463 for &base_impl in implementations.iter() {
464 for &m in base_impl.methods.iter() {
465 if m.explicit_self == ast::sty_static {
466 encode_reexported_static_method(ecx, ebml_w, exp,
478 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
479 ebml_w: &mut writer::Encoder,
480 exp: &middle::resolve::Export2)
482 match ecx.tcx.trait_methods_cache.find(&exp.def_id) {
484 for &m in methods.iter() {
485 if m.explicit_self == ast::sty_static {
486 encode_reexported_static_method(ecx, ebml_w, exp,
497 fn encode_reexported_static_methods(ecx: &EncodeContext,
498 ebml_w: &mut writer::Encoder,
499 mod_path: &[ast_map::path_elt],
500 exp: &middle::resolve::Export2) {
501 match ecx.tcx.items.find(&exp.def_id.node) {
502 Some(&ast_map::node_item(item, path)) => {
503 let original_name = ecx.tcx.sess.str_of(item.ident);
506 // We don't need to reexport static methods on items
507 // declared in the same module as our `pub use ...` since
508 // that's done when we encode the item itself.
510 // The only exception is when the reexport *changes* the
511 // name e.g. `pub use Foo = self::Bar` -- we have
512 // encoded metadata for static methods relative to Bar,
513 // but not yet for Foo.
515 if mod_path != *path || exp.name != original_name {
516 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
517 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
518 debug!("(encode reexported static methods) {} \
524 debug!("(encode reexported static methods) {} [base]",
533 /// Iterates through "auxiliary node IDs", which are node IDs that describe
534 /// top-level items that are sub-items of the given item. Specifically:
536 /// * For enums, iterates through the node IDs of the variants.
538 /// * For newtype structs, iterates through the node ID of the constructor.
539 fn each_auxiliary_node_id(item: @item, callback: |NodeId| -> bool) -> bool {
540 let mut continue_ = true;
542 item_enum(ref enum_def, _) => {
543 for variant in enum_def.variants.iter() {
544 continue_ = callback(variant.node.id);
550 item_struct(struct_def, _) => {
551 // If this is a newtype struct, return the constructor.
552 match struct_def.ctor_id {
553 Some(ctor_id) if struct_def.fields.len() > 0 &&
554 struct_def.fields[0].node.kind ==
555 ast::unnamed_field => {
556 continue_ = callback(ctor_id);
567 fn encode_reexports(ecx: &EncodeContext,
568 ebml_w: &mut writer::Encoder,
570 path: &[ast_map::path_elt]) {
571 debug!("(encoding info for module) encoding reexports for {}", id);
572 match ecx.reexports2.find(&id) {
573 Some(ref exports) => {
574 debug!("(encoding info for module) found reexports for {}", id);
575 for exp in exports.iter() {
576 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
582 ebml_w.start_tag(tag_items_data_item_reexport);
583 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
584 ebml_w.wr_str(def_to_str(exp.def_id));
586 ebml_w.start_tag(tag_items_data_item_reexport_name);
587 ebml_w.wr_str(exp.name);
590 encode_reexported_static_methods(ecx, ebml_w, path, exp);
594 debug!("(encoding info for module) found no reexports for {}",
600 fn encode_info_for_mod(ecx: &EncodeContext,
601 ebml_w: &mut writer::Encoder,
604 path: &[ast_map::path_elt],
607 ebml_w.start_tag(tag_items_data_item);
608 encode_def_id(ebml_w, local_def(id));
609 encode_family(ebml_w, 'm');
610 encode_name(ecx, ebml_w, name);
611 debug!("(encoding info for module) encoding info for module ID {}", id);
613 // Encode info about all the module children.
614 for item in md.items.iter() {
615 ebml_w.start_tag(tag_mod_child);
616 ebml_w.wr_str(def_to_str(local_def(item.id)));
619 each_auxiliary_node_id(*item, |auxiliary_node_id| {
620 ebml_w.start_tag(tag_mod_child);
621 ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
628 let (ident, did) = (item.ident, item.id);
629 debug!("(encoding info for module) ... encoding impl {} \
631 ecx.tcx.sess.str_of(ident),
633 ast_map::node_id_to_str(ecx.tcx.items, did, token::get_ident_interner()));
635 ebml_w.start_tag(tag_mod_impl);
636 ebml_w.wr_str(def_to_str(local_def(did)));
643 encode_path(ecx, ebml_w, path, ast_map::path_mod(name));
644 encode_visibility(ebml_w, vis);
646 // Encode the reexports of this module, if this module is public.
648 debug!("(encoding info for module) encoding reexports for {}", id);
649 encode_reexports(ecx, ebml_w, id, path);
655 fn encode_struct_field_family(ebml_w: &mut writer::Encoder,
656 visibility: visibility) {
657 encode_family(ebml_w, match visibility {
664 fn encode_visibility(ebml_w: &mut writer::Encoder, visibility: visibility) {
665 ebml_w.start_tag(tag_items_data_item_visibility);
666 let ch = match visibility {
671 ebml_w.wr_str(str::from_char(ch));
675 fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explicit_self_) {
676 ebml_w.start_tag(tag_item_trait_method_explicit_self);
678 // Encode the base self type.
679 match explicit_self {
681 ebml_w.writer.write(&[ 's' as u8 ]);
684 ebml_w.writer.write(&[ 'v' as u8 ]);
685 encode_mutability(ebml_w, m);
687 sty_region(_, m) => {
688 // FIXME(#4846) encode custom lifetime
689 ebml_w.writer.write(&[ '&' as u8 ]);
690 encode_mutability(ebml_w, m);
693 ebml_w.writer.write(&[ '@' as u8 ]);
694 encode_mutability(ebml_w, m);
697 ebml_w.writer.write(&[ '~' as u8 ]);
698 encode_mutability(ebml_w, m);
704 fn encode_mutability(ebml_w: &writer::Encoder,
705 m: ast::Mutability) {
707 MutImmutable => ebml_w.writer.write(&[ 'i' as u8 ]),
708 MutMutable => ebml_w.writer.write(&[ 'm' as u8 ]),
713 fn encode_method_sort(ebml_w: &mut writer::Encoder, sort: char) {
714 ebml_w.start_tag(tag_item_trait_method_sort);
715 ebml_w.writer.write(&[ sort as u8 ]);
719 fn encode_provided_source(ebml_w: &mut writer::Encoder,
720 source_opt: Option<DefId>) {
721 for source in source_opt.iter() {
722 ebml_w.start_tag(tag_item_method_provided_source);
723 let s = def_to_str(*source);
724 ebml_w.writer.write(s.as_bytes());
729 /* Returns an index of items in this class */
730 fn encode_info_for_struct(ecx: &EncodeContext,
731 ebml_w: &mut writer::Encoder,
732 path: &[ast_map::path_elt],
733 fields: &[@struct_field],
734 global_index: @mut ~[entry<i64>])
736 /* Each class has its own index, since different classes
737 may have fields with the same name */
740 /* We encode both private and public fields -- need to include
741 private fields to get the offsets right */
742 for field in fields.iter() {
743 let (nm, vis) = match field.node.kind {
744 named_field(nm, vis) => (nm, vis),
745 unnamed_field => (special_idents::unnamed_field, inherited)
748 let id = field.node.id;
749 index.push(entry {val: id as i64, pos: ebml_w.writer.tell()});
750 global_index.push(entry {val: id as i64, pos: ebml_w.writer.tell()});
751 ebml_w.start_tag(tag_items_data_item);
752 debug!("encode_info_for_struct: doing {} {}",
753 tcx.sess.str_of(nm), id);
754 encode_struct_field_family(ebml_w, vis);
755 encode_name(ecx, ebml_w, nm);
756 encode_path(ecx, ebml_w, path, ast_map::path_name(nm));
757 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
758 encode_def_id(ebml_w, local_def(id));
764 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
765 ebml_w: &mut writer::Encoder,
766 path: &[ast_map::path_elt],
769 index: @mut ~[entry<i64>],
771 index.push(entry { val: ctor_id as i64, pos: ebml_w.writer.tell() });
773 ebml_w.start_tag(tag_items_data_item);
774 encode_def_id(ebml_w, local_def(ctor_id));
775 encode_family(ebml_w, 'f');
776 encode_name(ecx, ebml_w, name);
777 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
778 encode_path(ecx, ebml_w, path, ast_map::path_name(name));
779 encode_parent_item(ebml_w, local_def(struct_id));
781 if ecx.item_symbols.contains_key(&ctor_id) {
782 encode_symbol(ecx, ebml_w, ctor_id);
788 fn encode_method_ty_fields(ecx: &EncodeContext,
789 ebml_w: &mut writer::Encoder,
790 method_ty: &ty::Method) {
791 encode_def_id(ebml_w, method_ty.def_id);
792 encode_name(ecx, ebml_w, method_ty.ident);
793 encode_ty_type_param_defs(ebml_w, ecx,
794 method_ty.generics.type_param_defs,
795 tag_item_method_tps);
796 encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty);
797 encode_method_fty(ecx, ebml_w, &method_ty.fty);
798 encode_visibility(ebml_w, method_ty.vis);
799 encode_explicit_self(ebml_w, method_ty.explicit_self);
800 let purity = method_ty.fty.purity;
801 match method_ty.explicit_self {
803 encode_family(ebml_w, purity_static_method_family(purity));
805 _ => encode_family(ebml_w, purity_fn_family(purity))
807 encode_provided_source(ebml_w, method_ty.provided_source);
810 fn encode_info_for_method(ecx: &EncodeContext,
811 ebml_w: &mut writer::Encoder,
813 impl_path: &[ast_map::path_elt],
814 is_default_impl: bool,
816 ast_method_opt: Option<@method>) {
818 debug!("encode_info_for_method: {:?} {}", m.def_id,
819 ecx.tcx.sess.str_of(m.ident));
820 ebml_w.start_tag(tag_items_data_item);
822 encode_method_ty_fields(ecx, ebml_w, m);
823 encode_parent_item(ebml_w, local_def(parent_id));
825 // The type for methods gets encoded twice, which is unfortunate.
826 let tpt = lookup_item_type(ecx.tcx, m.def_id);
827 encode_bounds_and_type(ebml_w, ecx, &tpt);
829 encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
831 for ast_method in ast_method_opt.iter() {
832 let num_params = tpt.generics.type_param_defs.len();
833 if num_params > 0u || is_default_impl
834 || should_inline(ast_method.attrs) {
835 (ecx.encode_inlined_item)(
836 ecx, ebml_w, impl_path,
837 ii_method(local_def(parent_id), false, *ast_method));
839 encode_symbol(ecx, ebml_w, m.def_id.node);
846 fn purity_fn_family(p: purity) -> char {
854 fn purity_static_method_family(p: purity) -> char {
858 _ => fail!("extern fn can't be static")
863 fn should_inline(attrs: &[Attribute]) -> bool {
865 match find_inline_attr(attrs) {
866 InlineNone | InlineNever => false,
867 InlineHint | InlineAlways => true
871 // Encodes the inherent implementations of a structure, enumeration, or trait.
872 fn encode_inherent_implementations(ecx: &EncodeContext,
873 ebml_w: &mut writer::Encoder,
875 match ecx.tcx.inherent_impls.find(&def_id) {
877 Some(&implementations) => {
878 for implementation in implementations.iter() {
879 ebml_w.start_tag(tag_items_data_item_inherent_impl);
880 encode_def_id(ebml_w, implementation.did);
887 // Encodes the implementations of a trait defined in this crate.
888 fn encode_extension_implementations(ecx: &EncodeContext,
889 ebml_w: &mut writer::Encoder,
890 trait_def_id: DefId) {
891 match ecx.tcx.trait_impls.find(&trait_def_id) {
893 Some(&implementations) => {
894 for implementation in implementations.iter() {
895 ebml_w.start_tag(tag_items_data_item_extension_impl);
896 encode_def_id(ebml_w, implementation.did);
903 fn encode_info_for_item(ecx: &EncodeContext,
904 ebml_w: &mut writer::Encoder,
906 index: @mut ~[entry<i64>],
907 path: &[ast_map::path_elt],
908 vis: ast::visibility) {
911 fn add_to_index(item: @item, ebml_w: &writer::Encoder,
912 index: @mut ~[entry<i64>]) {
913 index.push(entry { val: item.id as i64, pos: ebml_w.writer.tell() });
915 let add_to_index: || = || add_to_index(item, ebml_w, index);
917 debug!("encoding info for item at {}",
918 ecx.tcx.sess.codemap.span_to_str(item.span));
920 let def_id = local_def(item.id);
922 item_static(_, m, _) => {
924 ebml_w.start_tag(tag_items_data_item);
925 encode_def_id(ebml_w, def_id);
926 if m == ast::MutMutable {
927 encode_family(ebml_w, 'b');
929 encode_family(ebml_w, 'c');
931 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
932 encode_symbol(ecx, ebml_w, item.id);
933 encode_name(ecx, ebml_w, item.ident);
934 let elt = ast_map::path_pretty_name(item.ident, item.id as u64);
935 encode_path(ecx, ebml_w, path, elt);
936 if !ecx.non_inlineable_statics.contains(&item.id) {
937 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
939 encode_visibility(ebml_w, vis);
942 item_fn(_, purity, _, ref generics, _) => {
944 ebml_w.start_tag(tag_items_data_item);
945 encode_def_id(ebml_w, def_id);
946 encode_family(ebml_w, purity_fn_family(purity));
947 let tps_len = generics.ty_params.len();
948 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
949 encode_name(ecx, ebml_w, item.ident);
950 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
951 encode_attributes(ebml_w, item.attrs);
952 if tps_len > 0u || should_inline(item.attrs) {
953 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
955 encode_symbol(ecx, ebml_w, item.id);
957 encode_visibility(ebml_w, vis);
962 encode_info_for_mod(ecx,
970 item_foreign_mod(ref fm) => {
972 ebml_w.start_tag(tag_items_data_item);
973 encode_def_id(ebml_w, def_id);
974 encode_family(ebml_w, 'n');
975 encode_name(ecx, ebml_w, item.ident);
976 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
978 // Encode all the items in this module.
979 for foreign_item in fm.items.iter() {
980 ebml_w.start_tag(tag_mod_child);
981 ebml_w.wr_str(def_to_str(local_def(foreign_item.id)));
984 encode_visibility(ebml_w, vis);
989 ebml_w.start_tag(tag_items_data_item);
990 encode_def_id(ebml_w, def_id);
991 encode_family(ebml_w, 'y');
992 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
993 encode_name(ecx, ebml_w, item.ident);
994 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
995 encode_visibility(ebml_w, vis);
998 item_enum(ref enum_definition, ref generics) => {
1001 ebml_w.start_tag(tag_items_data_item);
1002 encode_def_id(ebml_w, def_id);
1003 encode_family(ebml_w, 't');
1004 encode_item_variances(ebml_w, ecx, item.id);
1005 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1006 encode_name(ecx, ebml_w, item.ident);
1007 encode_attributes(ebml_w, item.attrs);
1008 for v in (*enum_definition).variants.iter() {
1009 encode_variant_id(ebml_w, local_def(v.node.id));
1011 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
1012 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1014 // Encode inherent implementations for this enumeration.
1015 encode_inherent_implementations(ecx, ebml_w, def_id);
1017 encode_visibility(ebml_w, vis);
1020 encode_enum_variant_info(ecx,
1023 (*enum_definition).variants,
1028 item_struct(struct_def, _) => {
1029 /* First, encode the fields
1030 These come first because we need to write them to make
1031 the index, and the index needs to be in the item for the
1033 let idx = encode_info_for_struct(ecx, ebml_w, path,
1034 struct_def.fields, index);
1036 /* Index the class*/
1039 /* Now, make an item for the class itself */
1040 ebml_w.start_tag(tag_items_data_item);
1041 encode_def_id(ebml_w, def_id);
1042 encode_family(ebml_w, 'S');
1043 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1045 encode_item_variances(ebml_w, ecx, item.id);
1046 encode_name(ecx, ebml_w, item.ident);
1047 encode_attributes(ebml_w, item.attrs);
1048 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1049 encode_visibility(ebml_w, vis);
1051 /* Encode def_ids for each field and method
1052 for methods, write all the stuff get_trait_method
1054 encode_struct_fields(ecx, ebml_w, struct_def);
1056 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
1058 // Encode inherent implementations for this structure.
1059 encode_inherent_implementations(ecx, ebml_w, def_id);
1061 /* Each class has its own index -- encode it */
1062 let bkts = create_index(idx);
1063 encode_index(ebml_w, bkts, write_i64);
1066 // If this is a tuple- or enum-like struct, encode the type of the
1068 if struct_def.fields.len() > 0 &&
1069 struct_def.fields[0].node.kind == ast::unnamed_field {
1070 let ctor_id = match struct_def.ctor_id {
1071 Some(ctor_id) => ctor_id,
1072 None => ecx.tcx.sess.bug("struct def didn't have ctor id"),
1075 encode_info_for_struct_ctor(ecx,
1084 item_impl(_, ref opt_trait, ref ty, ref ast_methods) => {
1085 // We need to encode information about the default methods we
1086 // have inherited, so we drive this based on the impl structure.
1087 let imp = tcx.impls.get(&def_id);
1090 ebml_w.start_tag(tag_items_data_item);
1091 encode_def_id(ebml_w, def_id);
1092 encode_family(ebml_w, 'i');
1093 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1094 encode_name(ecx, ebml_w, item.ident);
1095 encode_attributes(ebml_w, item.attrs);
1097 ast::ty_path(ref path, ref bounds, _) if path.segments
1099 assert!(bounds.is_none());
1100 encode_impl_type_basename(ecx, ebml_w,
1101 ast_util::path_to_ident(path));
1105 for method in imp.methods.iter() {
1106 ebml_w.start_tag(tag_item_impl_method);
1107 let s = def_to_str(method.def_id);
1108 ebml_w.writer.write(s.as_bytes());
1111 for ast_trait_ref in opt_trait.iter() {
1112 let trait_ref = ty::node_id_to_trait_ref(
1113 tcx, ast_trait_ref.ref_id);
1114 encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
1115 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1116 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1118 let elt = ast_map::impl_pretty_name(opt_trait, ty, item.ident);
1119 encode_path(ecx, ebml_w, path, elt);
1123 let mut impl_path = vec::append(~[], path);
1124 impl_path.push(elt);
1126 // Iterate down the methods, emitting them. We rely on the
1127 // assumption that all of the actually implemented methods
1128 // appear first in the impl structure, in the same order they do
1129 // in the ast. This is a little sketchy.
1130 let num_implemented_methods = ast_methods.len();
1131 for (i, m) in imp.methods.iter().enumerate() {
1132 let ast_method = if i < num_implemented_methods {
1133 Some(ast_methods[i])
1136 index.push(entry {val: m.def_id.node as i64,
1137 pos: ebml_w.writer.tell()});
1138 encode_info_for_method(ecx,
1147 item_trait(_, ref super_traits, ref ms) => {
1149 ebml_w.start_tag(tag_items_data_item);
1150 encode_def_id(ebml_w, def_id);
1151 encode_family(ebml_w, 'I');
1152 encode_item_variances(ebml_w, ecx, item.id);
1153 let trait_def = ty::lookup_trait_def(tcx, def_id);
1154 encode_ty_type_param_defs(ebml_w, ecx,
1155 trait_def.generics.type_param_defs,
1156 tag_items_data_item_ty_param_bounds);
1157 encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
1158 encode_name(ecx, ebml_w, item.ident);
1159 encode_attributes(ebml_w, item.attrs);
1160 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1161 ebml_w.start_tag(tag_item_trait_method);
1162 encode_def_id(ebml_w, method_def_id);
1165 ebml_w.start_tag(tag_mod_child);
1166 ebml_w.wr_str(def_to_str(method_def_id));
1169 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1170 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1171 // reading the AST's list, because the former has already filtered out
1172 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1173 for ast_trait_ref in super_traits.iter() {
1174 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1175 encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
1178 // Encode the implementations of this trait.
1179 encode_extension_implementations(ecx, ebml_w, def_id);
1183 // Now output the method info for each method.
1184 let r = ty::trait_method_def_ids(tcx, def_id);
1185 for (i, &method_def_id) in r.iter().enumerate() {
1186 assert_eq!(method_def_id.crate, ast::LOCAL_CRATE);
1188 let method_ty = ty::method(tcx, method_def_id);
1190 index.push(entry {val: method_def_id.node as i64,
1191 pos: ebml_w.writer.tell()});
1193 ebml_w.start_tag(tag_items_data_item);
1195 encode_method_ty_fields(ecx, ebml_w, method_ty);
1197 encode_parent_item(ebml_w, def_id);
1199 let mut trait_path = vec::append(~[], path);
1200 trait_path.push(ast_map::path_name(item.ident));
1201 encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
1203 match method_ty.explicit_self {
1205 encode_family(ebml_w,
1206 purity_static_method_family(
1207 method_ty.fty.purity));
1209 let tpt = ty::lookup_item_type(tcx, method_def_id);
1210 encode_bounds_and_type(ebml_w, ecx, &tpt);
1214 encode_family(ebml_w,
1216 method_ty.fty.purity));
1222 encode_method_sort(ebml_w, 'r');
1226 // If this is a static method, we've already encoded
1228 if method_ty.explicit_self != sty_static {
1229 // XXX: I feel like there is something funny going on.
1230 let tpt = ty::lookup_item_type(tcx, method_def_id);
1231 encode_bounds_and_type(ebml_w, ecx, &tpt);
1233 encode_method_sort(ebml_w, 'p');
1234 (ecx.encode_inlined_item)(
1236 ii_method(def_id, true, m));
1243 // Encode inherent implementations for this trait.
1244 encode_inherent_implementations(ecx, ebml_w, def_id);
1246 item_mac(..) => fail!("item macros unimplemented")
1250 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1251 ebml_w: &mut writer::Encoder,
1252 nitem: @foreign_item,
1253 index: @mut ~[entry<i64>],
1254 path: &ast_map::path,
1256 index.push(entry { val: nitem.id as i64, pos: ebml_w.writer.tell() });
1258 ebml_w.start_tag(tag_items_data_item);
1260 foreign_item_fn(..) => {
1261 encode_def_id(ebml_w, local_def(nitem.id));
1262 encode_family(ebml_w, purity_fn_family(impure_fn));
1263 encode_bounds_and_type(ebml_w, ecx,
1264 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1265 encode_name(ecx, ebml_w, nitem.ident);
1266 if abi.is_intrinsic() {
1267 (ecx.encode_inlined_item)(ecx, ebml_w, *path, ii_foreign(nitem));
1269 encode_symbol(ecx, ebml_w, nitem.id);
1271 encode_path(ecx, ebml_w, *path, ast_map::path_name(nitem.ident));
1273 foreign_item_static(_, mutbl) => {
1274 encode_def_id(ebml_w, local_def(nitem.id));
1276 encode_family(ebml_w, 'b');
1278 encode_family(ebml_w, 'c');
1280 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1281 encode_symbol(ecx, ebml_w, nitem.id);
1282 encode_name(ecx, ebml_w, nitem.ident);
1283 encode_path(ecx, ebml_w, *path, ast_map::path_name(nitem.ident));
1289 fn my_visit_expr(_e:@Expr) { }
1291 fn my_visit_item(i:@item, items: ast_map::map, ebml_w:&writer::Encoder,
1292 ecx_ptr:*int, index: @mut ~[entry<i64>]) {
1293 match items.get_copy(&i.id) {
1294 ast_map::node_item(_, pt) => {
1295 let mut ebml_w = ebml_w.clone();
1297 let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1298 encode_info_for_item(ecx, &mut ebml_w, i, index, *pt, i.vis);
1300 _ => fail!("bad item")
1304 fn my_visit_foreign_item(ni:@foreign_item, items: ast_map::map, ebml_w:&writer::Encoder,
1305 ecx_ptr:*int, index: @mut ~[entry<i64>]) {
1306 match items.get_copy(&ni.id) {
1307 ast_map::node_foreign_item(_, abi, _, pt) => {
1308 debug!("writing foreign item {}::{}",
1309 ast_map::path_to_str(
1311 token::get_ident_interner()),
1312 token::ident_to_str(&ni.ident));
1314 let mut ebml_w = ebml_w.clone();
1316 let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1317 encode_info_for_foreign_item(ecx,
1324 // case for separate item and foreign-item tables
1325 _ => fail!("bad foreign item")
1329 struct EncodeVisitor {
1330 ebml_w_for_visit_item: writer::Encoder,
1331 ebml_w_for_visit_foreign_item: writer::Encoder,
1333 items: ast_map::map,
1334 index: @mut ~[entry<i64>],
1337 impl visit::Visitor<()> for EncodeVisitor {
1338 fn visit_expr(&mut self, ex:@Expr, _:()) {
1339 visit::walk_expr(self, ex, ());
1342 fn visit_item(&mut self, i:@item, _:()) {
1343 visit::walk_item(self, i, ());
1346 &self.ebml_w_for_visit_item,
1350 fn visit_foreign_item(&mut self, ni:@foreign_item, _:()) {
1351 visit::walk_foreign_item(self, ni, ());
1352 my_visit_foreign_item(ni,
1354 &self.ebml_w_for_visit_foreign_item,
1360 fn encode_info_for_items(ecx: &EncodeContext,
1361 ebml_w: &mut writer::Encoder,
1364 let index = @mut ~[];
1365 ebml_w.start_tag(tag_items_data);
1366 index.push(entry { val: CRATE_NODE_ID as i64, pos: ebml_w.writer.tell() });
1367 encode_info_for_mod(ecx,
1372 syntax::parse::token::special_idents::invalid,
1374 let items = ecx.tcx.items;
1376 // See comment in `encode_side_tables_for_ii` in astencode
1377 let ecx_ptr : *int = unsafe { cast::transmute(ecx) };
1378 let mut visitor = EncodeVisitor {
1382 ebml_w_for_visit_item: (*ebml_w).clone(),
1383 ebml_w_for_visit_foreign_item: (*ebml_w).clone(),
1386 visit::walk_crate(&mut visitor, crate, ());
1389 return /*bad*/(*index).clone();
1393 // Path and definition ID indexing
1395 fn create_index<T:Clone + Hash + IterBytes + 'static>(
1397 -> ~[@~[entry<T>]] {
1398 let mut buckets: ~[@mut ~[entry<T>]] = ~[];
1399 for _ in range(0u, 256u) { buckets.push(@mut ~[]); };
1400 for elt in index.iter() {
1401 let h = elt.val.hash() as uint;
1402 buckets[h % 256].push((*elt).clone());
1405 let mut buckets_frozen = ~[];
1406 for bucket in buckets.iter() {
1407 buckets_frozen.push(@/*bad*/(**bucket).clone());
1409 return buckets_frozen;
1412 fn encode_index<T:'static>(
1413 ebml_w: &mut writer::Encoder,
1414 buckets: ~[@~[entry<T>]],
1415 write_fn: |@mut MemWriter, &T|) {
1416 ebml_w.start_tag(tag_index);
1417 let mut bucket_locs = ~[];
1418 ebml_w.start_tag(tag_index_buckets);
1419 for bucket in buckets.iter() {
1420 bucket_locs.push(ebml_w.writer.tell());
1421 ebml_w.start_tag(tag_index_buckets_bucket);
1422 for elt in (**bucket).iter() {
1423 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1424 assert!(elt.pos < 0xffff_ffff);
1426 let wr: &mut MemWriter = ebml_w.writer;
1427 wr.write_be_u32(elt.pos as u32);
1429 write_fn(ebml_w.writer, &elt.val);
1435 ebml_w.start_tag(tag_index_table);
1436 for pos in bucket_locs.iter() {
1437 assert!(*pos < 0xffff_ffff);
1438 let wr: &mut MemWriter = ebml_w.writer;
1439 wr.write_be_u32(*pos as u32);
1445 fn write_str(writer: @mut MemWriter, s: ~str) {
1446 writer.write(s.as_bytes());
1449 fn write_i64(writer: @mut MemWriter, &n: &i64) {
1450 let wr: &mut MemWriter = writer;
1451 assert!(n < 0x7fff_ffff);
1452 wr.write_be_u32(n as u32);
1455 fn encode_meta_item(ebml_w: &mut writer::Encoder, mi: @MetaItem) {
1458 ebml_w.start_tag(tag_meta_item_word);
1459 ebml_w.start_tag(tag_meta_item_name);
1460 ebml_w.writer.write(name.as_bytes());
1464 MetaNameValue(name, value) => {
1466 lit_str(value, _) => {
1467 ebml_w.start_tag(tag_meta_item_name_value);
1468 ebml_w.start_tag(tag_meta_item_name);
1469 ebml_w.writer.write(name.as_bytes());
1471 ebml_w.start_tag(tag_meta_item_value);
1472 ebml_w.writer.write(value.as_bytes());
1476 _ => {/* FIXME (#623): encode other variants */ }
1479 MetaList(name, ref items) => {
1480 ebml_w.start_tag(tag_meta_item_list);
1481 ebml_w.start_tag(tag_meta_item_name);
1482 ebml_w.writer.write(name.as_bytes());
1484 for inner_item in items.iter() {
1485 encode_meta_item(ebml_w, *inner_item);
1492 fn encode_attributes(ebml_w: &mut writer::Encoder, attrs: &[Attribute]) {
1493 ebml_w.start_tag(tag_attributes);
1494 for attr in attrs.iter() {
1495 ebml_w.start_tag(tag_attribute);
1496 encode_meta_item(ebml_w, attr.node.value);
1502 // So there's a special crate attribute called 'link' which defines the
1503 // metadata that Rust cares about for linking crates. This attribute requires
1504 // 'name', 'vers' and 'package_id' items, so if the user didn't provide them we
1505 // will throw them in anyway with default values.
1506 fn synthesize_crate_attrs(ecx: &EncodeContext,
1507 crate: &Crate) -> ~[Attribute] {
1509 fn synthesize_link_attr(ecx: &EncodeContext, items: ~[@MetaItem]) ->
1512 assert!(!ecx.link_meta.name.is_empty());
1513 assert!(!ecx.link_meta.vers.is_empty());
1516 attr::mk_name_value_item_str(@"name",
1517 ecx.link_meta.name);
1519 attr::mk_name_value_item_str(@"vers",
1520 ecx.link_meta.vers);
1522 let pkgid_item = match ecx.link_meta.package_id {
1523 Some(pkg_id) => attr::mk_name_value_item_str(@"package_id",
1525 // uses package_id equal to name;
1526 // this should never happen here but package_id is an Option
1527 // FIXME (#10370): change package_id in LinkMeta to @str instead of Option<@str>
1528 _ => attr::mk_name_value_item_str(@"package_id",
1532 let mut meta_items = ~[name_item, vers_item, pkgid_item];
1534 for &mi in items.iter().filter(|mi| "name" != mi.name() && "vers" != mi.name() &&
1535 "package_id" != mi.name()) {
1536 meta_items.push(mi);
1538 let link_item = attr::mk_list_item(@"link", meta_items);
1540 return attr::mk_attr(link_item);
1543 let mut attrs = ~[];
1544 let mut found_link_attr = false;
1545 for attr in crate.attrs.iter() {
1547 if "link" != attr.name() {
1550 match attr.meta_item_list() {
1552 found_link_attr = true;;
1553 synthesize_link_attr(ecx, l.to_owned())
1560 if !found_link_attr { attrs.push(synthesize_link_attr(ecx, ~[])); }
1565 fn encode_crate_deps(ecx: &EncodeContext,
1566 ebml_w: &mut writer::Encoder,
1567 cstore: &cstore::CStore) {
1568 fn get_ordered_deps(ecx: &EncodeContext, cstore: &cstore::CStore)
1569 -> ~[decoder::CrateDep] {
1570 type numdep = decoder::CrateDep;
1572 // Pull the cnums and name,vers,hash out of cstore
1574 cstore::iter_crate_data(cstore, |key, val| {
1575 let dep = decoder::CrateDep {cnum: key,
1576 name: ecx.tcx.sess.ident_of(val.name),
1577 vers: decoder::get_crate_vers(val.data),
1578 hash: decoder::get_crate_hash(val.data)};
1583 extra::sort::quick_sort(deps, |kv1, kv2| kv1.cnum <= kv2.cnum);
1585 // Sanity-check the crate numbers
1586 let mut expected_cnum = 1;
1587 for n in deps.iter() {
1588 assert_eq!(n.cnum, expected_cnum);
1595 // We're just going to write a list of crate 'name-hash-version's, with
1596 // the assumption that they are numbered 1 to n.
1597 // FIXME (#2166): This is not nearly enough to support correct versioning
1598 // but is enough to get transitive crate dependencies working.
1599 ebml_w.start_tag(tag_crate_deps);
1600 let r = get_ordered_deps(ecx, cstore);
1601 for dep in r.iter() {
1602 encode_crate_dep(ecx, ebml_w, *dep);
1607 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1608 ebml_w.start_tag(tag_lang_items);
1610 for (i, def_id) in ecx.tcx.lang_items.items() {
1611 for id in def_id.iter() {
1612 if id.crate == LOCAL_CRATE {
1613 ebml_w.start_tag(tag_lang_items_item);
1615 ebml_w.start_tag(tag_lang_items_item_id);
1617 let wr: &mut MemWriter = ebml_w.writer;
1618 wr.write_be_u32(i as u32);
1620 ebml_w.end_tag(); // tag_lang_items_item_id
1622 ebml_w.start_tag(tag_lang_items_item_node_id);
1624 let wr: &mut MemWriter = ebml_w.writer;
1625 wr.write_be_u32(id.node as u32);
1627 ebml_w.end_tag(); // tag_lang_items_item_node_id
1629 ebml_w.end_tag(); // tag_lang_items_item
1634 ebml_w.end_tag(); // tag_lang_items
1637 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1638 ebml_w.start_tag(tag_native_libraries);
1640 for &(ref lib, kind) in cstore::get_used_libraries(ecx.cstore).iter() {
1642 cstore::NativeStatic => {} // these libraries are not propagated
1643 cstore::NativeUnknown => {
1644 ebml_w.start_tag(tag_native_libraries_lib);
1645 ebml_w.writer.write(lib.as_bytes());
1654 struct ImplVisitor<'self> {
1655 ecx: &'self EncodeContext<'self>,
1656 ebml_w: &'self mut writer::Encoder,
1659 impl<'self> Visitor<()> for ImplVisitor<'self> {
1660 fn visit_item(&mut self, item: @item, _: ()) {
1662 item_impl(_, Some(ref trait_ref), _, _) => {
1663 let def_map = self.ecx.tcx.def_map;
1664 let trait_def = def_map.get_copy(&trait_ref.ref_id);
1665 let def_id = ast_util::def_id_of_def(trait_def);
1667 // Load eagerly if this is an implementation of the Drop trait
1668 // or if the trait is not defined in this crate.
1669 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1670 def_id.crate != LOCAL_CRATE {
1671 self.ebml_w.start_tag(tag_impls_impl);
1672 encode_def_id(self.ebml_w, local_def(item.id));
1673 self.ebml_w.end_tag();
1678 visit::walk_item(self, item, ());
1682 /// Encodes implementations that are eagerly loaded.
1684 /// None of this is necessary in theory; we can load all implementations
1685 /// lazily. However, in two cases the optimizations to lazily load
1686 /// implementations are not yet implemented. These two cases, which require us
1687 /// to load implementations eagerly, are:
1689 /// * Destructors (implementations of the Drop trait).
1691 /// * Implementations of traits not defined in this crate.
1692 fn encode_impls(ecx: &EncodeContext,
1694 ebml_w: &mut writer::Encoder) {
1695 ebml_w.start_tag(tag_impls);
1698 let mut visitor = ImplVisitor {
1702 visit::walk_crate(&mut visitor, crate, ());
1708 fn encode_misc_info(ecx: &EncodeContext,
1710 ebml_w: &mut writer::Encoder) {
1711 ebml_w.start_tag(tag_misc_info);
1712 ebml_w.start_tag(tag_misc_info_crate_items);
1713 for &item in crate.module.items.iter() {
1714 ebml_w.start_tag(tag_mod_child);
1715 ebml_w.wr_str(def_to_str(local_def(item.id)));
1718 each_auxiliary_node_id(item, |auxiliary_node_id| {
1719 ebml_w.start_tag(tag_mod_child);
1720 ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
1726 // Encode reexports for the root module.
1727 encode_reexports(ecx, ebml_w, 0, []);
1733 fn encode_crate_dep(ecx: &EncodeContext,
1734 ebml_w: &mut writer::Encoder,
1735 dep: decoder::CrateDep) {
1736 ebml_w.start_tag(tag_crate_dep);
1737 ebml_w.start_tag(tag_crate_dep_name);
1738 let s = ecx.tcx.sess.str_of(dep.name);
1739 ebml_w.writer.write(s.as_bytes());
1741 ebml_w.start_tag(tag_crate_dep_vers);
1742 ebml_w.writer.write(dep.vers.as_bytes());
1744 ebml_w.start_tag(tag_crate_dep_hash);
1745 ebml_w.writer.write(dep.hash.as_bytes());
1750 fn encode_hash(ebml_w: &mut writer::Encoder, hash: &str) {
1751 ebml_w.start_tag(tag_crate_hash);
1752 ebml_w.writer.write(hash.as_bytes());
1756 // NB: Increment this as you change the metadata encoding version.
1757 pub static metadata_encoding_version : &'static [u8] =
1758 &[0x72, //'r' as u8,
1764 pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
1765 let wr = @mut MemWriter::new();
1771 native_lib_bytes: 0,
1787 encode_inlined_item,
1790 non_inlineable_statics,
1793 let type_abbrevs = @mut HashMap::new();
1794 let stats = @mut stats;
1795 let ecx = EncodeContext {
1799 reexports2: reexports2,
1800 item_symbols: item_symbols,
1801 discrim_symbols: discrim_symbols,
1802 non_inlineable_statics: non_inlineable_statics,
1803 link_meta: link_meta,
1805 encode_inlined_item: encode_inlined_item,
1806 type_abbrevs: type_abbrevs,
1807 reachable: reachable,
1810 let mut ebml_w = writer::Encoder(wr);
1812 encode_hash(&mut ebml_w, ecx.link_meta.extras_hash);
1814 let mut i = wr.tell();
1815 let crate_attrs = synthesize_crate_attrs(&ecx, crate);
1816 encode_attributes(&mut ebml_w, crate_attrs);
1817 ecx.stats.attr_bytes = wr.tell() - i;
1820 encode_crate_deps(&ecx, &mut ebml_w, ecx.cstore);
1821 ecx.stats.dep_bytes = wr.tell() - i;
1823 // Encode the language items.
1825 encode_lang_items(&ecx, &mut ebml_w);
1826 ecx.stats.lang_item_bytes = wr.tell() - i;
1828 // Encode the native libraries used
1830 encode_native_libraries(&ecx, &mut ebml_w);
1831 ecx.stats.native_lib_bytes = wr.tell() - i;
1833 // Encode the def IDs of impls, for coherence checking.
1835 encode_impls(&ecx, crate, &mut ebml_w);
1836 ecx.stats.impl_bytes = wr.tell() - i;
1838 // Encode miscellaneous info.
1840 encode_misc_info(&ecx, crate, &mut ebml_w);
1841 ecx.stats.misc_bytes = wr.tell() - i;
1843 // Encode and index the items.
1844 ebml_w.start_tag(tag_items);
1846 let items_index = encode_info_for_items(&ecx, &mut ebml_w, crate);
1847 ecx.stats.item_bytes = wr.tell() - i;
1850 let items_buckets = create_index(items_index);
1851 encode_index(&mut ebml_w, items_buckets, write_i64);
1852 ecx.stats.index_bytes = wr.tell() - i;
1855 ecx.stats.total_bytes = wr.tell();
1857 if (tcx.sess.meta_stats()) {
1858 for e in wr.inner_ref().iter() {
1860 ecx.stats.zero_bytes += 1;
1864 println("metadata stats:");
1865 println!(" inline bytes: {}", ecx.stats.inline_bytes);
1866 println!(" attribute bytes: {}", ecx.stats.attr_bytes);
1867 println!(" dep bytes: {}", ecx.stats.dep_bytes);
1868 println!(" lang item bytes: {}", ecx.stats.lang_item_bytes);
1869 println!(" native bytes: {}", ecx.stats.native_lib_bytes);
1870 println!(" impl bytes: {}", ecx.stats.impl_bytes);
1871 println!(" misc bytes: {}", ecx.stats.misc_bytes);
1872 println!(" item bytes: {}", ecx.stats.item_bytes);
1873 println!(" index bytes: {}", ecx.stats.index_bytes);
1874 println!(" zero bytes: {}", ecx.stats.zero_bytes);
1875 println!(" total bytes: {}", ecx.stats.total_bytes);
1878 // Pad this, since something (LLVM, presumably) is cutting off the
1879 // remaining % 4 bytes.
1880 wr.write(&[0u8, 0u8, 0u8, 0u8]);
1882 let writer_bytes: &mut ~[u8] = wr.inner_mut_ref();
1884 metadata_encoding_version.to_owned() +
1885 flate::deflate_bytes(*writer_bytes)
1888 // Get the encoded string for a type
1889 pub fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str {
1890 let cx = @tyencode::ctxt {
1894 abbrevs: tyencode::ac_no_abbrevs};
1895 let wr = @mut MemWriter::new();
1896 tyencode::enc_ty(wr, cx, t);
1897 str::from_utf8(*wr.inner_ref())