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};
29 use extra::serialize::Encodable;
31 use syntax::abi::AbiSet;
35 use syntax::ast_util::*;
37 use syntax::attr::AttrMetaMethods;
38 use syntax::diagnostic::span_handler;
39 use syntax::parse::token::special_idents;
41 use syntax::visit::Visitor;
43 use syntax::parse::token;
45 use writer = extra::ebml::writer;
50 type abbrev_map = @mut HashMap<ty::t, tyencode::ty_abbrev>;
52 pub type encode_inlined_item<'self> = &'self fn(ecx: &EncodeContext,
53 ebml_w: &mut writer::Encoder,
54 path: &[ast_map::path_elt],
55 ii: ast::inlined_item);
57 pub struct EncodeParams<'self> {
58 diag: @mut span_handler,
60 reexports2: middle::resolve::ExportMap2,
61 item_symbols: &'self HashMap<ast::NodeId, ~str>,
62 discrim_symbols: &'self HashMap<ast::NodeId, @str>,
63 non_inlineable_statics: &'self HashSet<ast::NodeId>,
64 link_meta: &'self LinkMeta,
65 cstore: @mut cstore::CStore,
66 encode_inlined_item: encode_inlined_item<'self>,
67 reachable: @mut HashSet<ast::NodeId>,
74 lang_item_bytes: uint,
75 link_args_bytes: uint,
86 pub struct EncodeContext<'self> {
87 diag: @mut span_handler,
90 reexports2: middle::resolve::ExportMap2,
91 item_symbols: &'self HashMap<ast::NodeId, ~str>,
92 discrim_symbols: &'self HashMap<ast::NodeId, @str>,
93 non_inlineable_statics: &'self HashSet<ast::NodeId>,
94 link_meta: &'self LinkMeta,
95 cstore: &'self cstore::CStore,
96 encode_inlined_item: encode_inlined_item<'self>,
97 type_abbrevs: abbrev_map,
98 reachable: @mut HashSet<ast::NodeId>,
101 pub fn reachable(ecx: &EncodeContext, id: NodeId) -> bool {
102 ecx.reachable.contains(&id)
105 fn encode_name(ecx: &EncodeContext,
106 ebml_w: &mut writer::Encoder,
108 ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name));
111 fn encode_impl_type_basename(ecx: &EncodeContext,
112 ebml_w: &mut writer::Encoder,
114 ebml_w.wr_tagged_str(tag_item_impl_type_basename,
115 ecx.tcx.sess.str_of(name));
118 pub fn encode_def_id(ebml_w: &mut writer::Encoder, id: DefId) {
119 ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
122 fn encode_region_param(ecx: &EncodeContext,
123 ebml_w: &mut writer::Encoder,
125 let opt_rp = ecx.tcx.region_paramd_items.find(&it.id);
126 for rp in opt_rp.iter() {
127 ebml_w.start_tag(tag_region_param);
139 fn add_to_index(ebml_w: &mut writer::Encoder,
141 index: &mut ~[entry<~str>],
143 let mut full_path = ~[];
144 full_path.push_all(path);
145 full_path.push(name);
148 val: ast_util::path_name_i(full_path),
149 pos: ebml_w.writer.tell()
153 fn encode_trait_ref(ebml_w: &mut writer::Encoder,
155 trait_ref: &ty::TraitRef,
157 let ty_str_ctxt = @tyencode::ctxt {
161 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
164 ebml_w.start_tag(tag);
165 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
169 fn encode_impl_vtables(ebml_w: &mut writer::Encoder,
171 vtables: &typeck::impl_res) {
172 ebml_w.start_tag(tag_item_impl_vtables);
173 astencode::encode_vtable_res(ecx, ebml_w, vtables.trait_vtables);
174 astencode::encode_vtable_param_res(ecx, ebml_w, vtables.self_vtables);
178 // Item info table encoding
179 fn encode_family(ebml_w: &mut writer::Encoder, c: char) {
180 ebml_w.start_tag(tag_items_data_item_family);
181 ebml_w.writer.write(&[c as u8]);
185 pub fn def_to_str(did: DefId) -> ~str {
186 format!("{}:{}", did.crate, did.node)
189 fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
191 params: @~[ty::TypeParameterDef],
193 let ty_str_ctxt = @tyencode::ctxt {
197 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
199 for param in params.iter() {
200 ebml_w.start_tag(tag);
201 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
206 fn encode_bounds_and_type(ebml_w: &mut writer::Encoder,
208 tpt: &ty::ty_param_bounds_and_ty) {
209 encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs,
210 tag_items_data_item_ty_param_bounds);
211 encode_type(ecx, ebml_w, tpt.ty);
214 fn encode_variant_id(ebml_w: &mut writer::Encoder, vid: DefId) {
215 ebml_w.start_tag(tag_items_data_item_variant);
216 let s = def_to_str(vid);
217 ebml_w.writer.write(s.as_bytes());
221 pub fn write_type(ecx: &EncodeContext,
222 ebml_w: &mut writer::Encoder,
224 let ty_str_ctxt = @tyencode::ctxt {
228 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
230 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
233 pub fn write_vstore(ecx: &EncodeContext,
234 ebml_w: &mut writer::Encoder,
235 vstore: ty::vstore) {
236 let ty_str_ctxt = @tyencode::ctxt {
240 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
242 tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
245 fn encode_type(ecx: &EncodeContext,
246 ebml_w: &mut writer::Encoder,
248 ebml_w.start_tag(tag_items_data_item_type);
249 write_type(ecx, ebml_w, typ);
253 fn encode_transformed_self_ty(ecx: &EncodeContext,
254 ebml_w: &mut writer::Encoder,
255 opt_typ: Option<ty::t>) {
256 for &typ in opt_typ.iter() {
257 ebml_w.start_tag(tag_item_method_transformed_self_ty);
258 write_type(ecx, ebml_w, typ);
263 fn encode_method_fty(ecx: &EncodeContext,
264 ebml_w: &mut writer::Encoder,
265 typ: &ty::BareFnTy) {
266 ebml_w.start_tag(tag_item_method_fty);
268 let ty_str_ctxt = @tyencode::ctxt {
272 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
274 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
279 fn encode_symbol(ecx: &EncodeContext,
280 ebml_w: &mut writer::Encoder,
282 ebml_w.start_tag(tag_items_data_item_symbol);
283 match ecx.item_symbols.find(&id) {
285 debug!("encode_symbol(id={:?}, str={})", id, *x);
286 ebml_w.writer.write(x.as_bytes());
289 ecx.diag.handler().bug(
290 format!("encode_symbol: id not found {}", id));
296 fn encode_disr_val(_: &EncodeContext,
297 ebml_w: &mut writer::Encoder,
298 disr_val: ty::Disr) {
299 ebml_w.start_tag(tag_disr_val);
300 let s = disr_val.to_str();
301 ebml_w.writer.write(s.as_bytes());
305 fn encode_parent_item(ebml_w: &mut writer::Encoder, id: DefId) {
306 ebml_w.start_tag(tag_items_data_parent_item);
307 let s = def_to_str(id);
308 ebml_w.writer.write(s.as_bytes());
312 fn encode_struct_fields(ecx: &EncodeContext,
313 ebml_w: &mut writer::Encoder,
315 for f in def.fields.iter() {
317 named_field(ident, vis) => {
318 ebml_w.start_tag(tag_item_field);
319 encode_struct_field_family(ebml_w, vis);
320 encode_name(ecx, ebml_w, ident);
321 encode_def_id(ebml_w, local_def(f.node.id));
325 ebml_w.start_tag(tag_item_unnamed_field);
326 encode_def_id(ebml_w, local_def(f.node.id));
333 fn encode_enum_variant_info(ecx: &EncodeContext,
334 ebml_w: &mut writer::Encoder,
336 variants: &[variant],
337 path: &[ast_map::path_elt],
338 index: @mut ~[entry<i64>],
339 generics: &ast::Generics) {
340 debug!("encode_enum_variant_info(id={:?})", id);
342 let mut disr_val = 0;
344 let vi = ty::enum_variants(ecx.tcx,
345 ast::DefId { crate: LOCAL_CRATE, node: id });
346 for variant in variants.iter() {
347 let def_id = local_def(variant.node.id);
348 index.push(entry {val: variant.node.id as i64,
349 pos: ebml_w.writer.tell()});
350 ebml_w.start_tag(tag_items_data_item);
351 encode_def_id(ebml_w, def_id);
352 match variant.node.kind {
353 ast::tuple_variant_kind(_) => encode_family(ebml_w, 'v'),
354 ast::struct_variant_kind(_) => encode_family(ebml_w, 'V')
356 encode_name(ecx, ebml_w, variant.node.name);
357 encode_parent_item(ebml_w, local_def(id));
358 encode_visibility(ebml_w, variant.node.vis);
359 encode_attributes(ebml_w, variant.node.attrs);
360 match variant.node.kind {
361 ast::tuple_variant_kind(ref args)
362 if args.len() > 0 && generics.ty_params.len() == 0 => {
363 encode_symbol(ecx, ebml_w, variant.node.id);
365 ast::tuple_variant_kind(_) => {},
366 ast::struct_variant_kind(def) => {
367 let idx = encode_info_for_struct(ecx, ebml_w, path,
369 encode_struct_fields(ecx, ebml_w, def);
370 let bkts = create_index(idx);
371 encode_index(ebml_w, bkts, write_i64);
374 if vi[i].disr_val != disr_val {
375 encode_disr_val(ecx, ebml_w, vi[i].disr_val);
376 disr_val = vi[i].disr_val;
378 encode_bounds_and_type(ebml_w, ecx,
379 &lookup_item_type(ecx.tcx, def_id));
380 encode_path(ecx, ebml_w, path,
381 ast_map::path_name(variant.node.name));
388 fn encode_path(ecx: &EncodeContext,
389 ebml_w: &mut writer::Encoder,
390 path: &[ast_map::path_elt],
391 name: ast_map::path_elt) {
392 fn encode_path_elt(ecx: &EncodeContext,
393 ebml_w: &mut writer::Encoder,
394 elt: ast_map::path_elt) {
396 ast_map::path_mod(n) => {
397 ebml_w.wr_tagged_str(tag_path_elt_mod, ecx.tcx.sess.str_of(n));
399 ast_map::path_name(n) => {
400 ebml_w.wr_tagged_str(tag_path_elt_name, ecx.tcx.sess.str_of(n));
402 ast_map::path_pretty_name(n, extra) => {
403 ebml_w.start_tag(tag_path_elt_pretty_name);
404 ebml_w.wr_tagged_str(tag_path_elt_pretty_name_ident,
405 ecx.tcx.sess.str_of(n));
406 ebml_w.wr_tagged_u64(tag_path_elt_pretty_name_extra, extra);
412 ebml_w.start_tag(tag_path);
413 ebml_w.wr_tagged_u32(tag_path_len, (path.len() + 1) as u32);
414 for pe in path.iter() {
415 encode_path_elt(ecx, ebml_w, *pe);
417 encode_path_elt(ecx, ebml_w, name);
421 fn encode_reexported_static_method(ecx: &EncodeContext,
422 ebml_w: &mut writer::Encoder,
423 exp: &middle::resolve::Export2,
424 method_def_id: DefId,
425 method_ident: Ident) {
426 debug!("(encode reexported static method) {}::{}",
427 exp.name, ecx.tcx.sess.str_of(method_ident));
428 ebml_w.start_tag(tag_items_data_item_reexport);
429 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
430 ebml_w.wr_str(def_to_str(method_def_id));
432 ebml_w.start_tag(tag_items_data_item_reexport_name);
433 ebml_w.wr_str(format!("{}::{}", exp.name, ecx.tcx.sess.str_of(method_ident)));
438 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
439 ebml_w: &mut writer::Encoder,
440 exp: &middle::resolve::Export2)
442 match ecx.tcx.inherent_impls.find(&exp.def_id) {
443 Some(implementations) => {
444 for &base_impl in implementations.iter() {
445 for &m in base_impl.methods.iter() {
446 if m.explicit_self == ast::sty_static {
447 encode_reexported_static_method(ecx, ebml_w, exp,
459 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
460 ebml_w: &mut writer::Encoder,
461 exp: &middle::resolve::Export2)
463 match ecx.tcx.trait_methods_cache.find(&exp.def_id) {
465 for &m in methods.iter() {
466 if m.explicit_self == ast::sty_static {
467 encode_reexported_static_method(ecx, ebml_w, exp,
478 fn encode_reexported_static_methods(ecx: &EncodeContext,
479 ebml_w: &mut writer::Encoder,
480 mod_path: &[ast_map::path_elt],
481 exp: &middle::resolve::Export2) {
482 match ecx.tcx.items.find(&exp.def_id.node) {
483 Some(&ast_map::node_item(item, path)) => {
484 let original_name = ecx.tcx.sess.str_of(item.ident);
487 // We don't need to reexport static methods on items
488 // declared in the same module as our `pub use ...` since
489 // that's done when we encode the item itself.
491 // The only exception is when the reexport *changes* the
492 // name e.g. `pub use Foo = self::Bar` -- we have
493 // encoded metadata for static methods relative to Bar,
494 // but not yet for Foo.
496 if mod_path != *path || exp.name != original_name {
497 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
498 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
499 debug!("(encode reexported static methods) {} \
505 debug!("(encode reexported static methods) {} [base]",
514 /// Iterates through "auxiliary node IDs", which are node IDs that describe
515 /// top-level items that are sub-items of the given item. Specifically:
517 /// * For enums, iterates through the node IDs of the variants.
519 /// * For newtype structs, iterates through the node ID of the constructor.
520 fn each_auxiliary_node_id(item: @item, callback: &fn(NodeId) -> bool)
522 let mut continue_ = true;
524 item_enum(ref enum_def, _) => {
525 for variant in enum_def.variants.iter() {
526 continue_ = callback(variant.node.id);
532 item_struct(struct_def, _) => {
533 // If this is a newtype struct, return the constructor.
534 match struct_def.ctor_id {
535 Some(ctor_id) if struct_def.fields.len() > 0 &&
536 struct_def.fields[0].node.kind ==
537 ast::unnamed_field => {
538 continue_ = callback(ctor_id);
549 fn encode_reexports(ecx: &EncodeContext,
550 ebml_w: &mut writer::Encoder,
552 path: &[ast_map::path_elt]) {
553 debug!("(encoding info for module) encoding reexports for {}", id);
554 match ecx.reexports2.find(&id) {
555 Some(ref exports) => {
556 debug!("(encoding info for module) found reexports for {}", id);
557 for exp in exports.iter() {
558 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
564 ebml_w.start_tag(tag_items_data_item_reexport);
565 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
566 ebml_w.wr_str(def_to_str(exp.def_id));
568 ebml_w.start_tag(tag_items_data_item_reexport_name);
569 ebml_w.wr_str(exp.name);
572 encode_reexported_static_methods(ecx, ebml_w, path, exp);
576 debug!("(encoding info for module) found no reexports for {}",
582 fn encode_info_for_mod(ecx: &EncodeContext,
583 ebml_w: &mut writer::Encoder,
586 path: &[ast_map::path_elt],
589 ebml_w.start_tag(tag_items_data_item);
590 encode_def_id(ebml_w, local_def(id));
591 encode_family(ebml_w, 'm');
592 encode_name(ecx, ebml_w, name);
593 debug!("(encoding info for module) encoding info for module ID {}", id);
595 // Encode info about all the module children.
596 for item in md.items.iter() {
597 ebml_w.start_tag(tag_mod_child);
598 ebml_w.wr_str(def_to_str(local_def(item.id)));
601 do each_auxiliary_node_id(*item) |auxiliary_node_id| {
602 ebml_w.start_tag(tag_mod_child);
603 ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
610 let (ident, did) = (item.ident, item.id);
611 debug!("(encoding info for module) ... encoding impl {} \
613 ecx.tcx.sess.str_of(ident),
615 ast_map::node_id_to_str(ecx.tcx.items, did, token::get_ident_interner()));
617 ebml_w.start_tag(tag_mod_impl);
618 ebml_w.wr_str(def_to_str(local_def(did)));
625 encode_path(ecx, ebml_w, path, ast_map::path_mod(name));
626 encode_visibility(ebml_w, vis);
628 // Encode the reexports of this module, if this module is public.
630 debug!("(encoding info for module) encoding reexports for {}", id);
631 encode_reexports(ecx, ebml_w, id, path);
637 fn encode_struct_field_family(ebml_w: &mut writer::Encoder,
638 visibility: visibility) {
639 encode_family(ebml_w, match visibility {
646 fn encode_visibility(ebml_w: &mut writer::Encoder, visibility: visibility) {
647 ebml_w.start_tag(tag_items_data_item_visibility);
648 let ch = match visibility {
653 ebml_w.wr_str(str::from_char(ch));
657 fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explicit_self_) {
658 ebml_w.start_tag(tag_item_trait_method_explicit_self);
660 // Encode the base self type.
661 match explicit_self {
663 ebml_w.writer.write(&[ 's' as u8 ]);
666 ebml_w.writer.write(&[ 'v' as u8 ]);
667 encode_mutability(ebml_w, m);
669 sty_region(_, m) => {
670 // FIXME(#4846) encode custom lifetime
671 ebml_w.writer.write(&[ '&' as u8 ]);
672 encode_mutability(ebml_w, m);
675 ebml_w.writer.write(&[ '@' as u8 ]);
676 encode_mutability(ebml_w, m);
679 ebml_w.writer.write(&[ '~' as u8 ]);
685 fn encode_mutability(ebml_w: &writer::Encoder,
686 m: ast::Mutability) {
688 MutImmutable => ebml_w.writer.write(&[ 'i' as u8 ]),
689 MutMutable => ebml_w.writer.write(&[ 'm' as u8 ]),
694 fn encode_method_sort(ebml_w: &mut writer::Encoder, sort: char) {
695 ebml_w.start_tag(tag_item_trait_method_sort);
696 ebml_w.writer.write(&[ sort as u8 ]);
700 fn encode_provided_source(ebml_w: &mut writer::Encoder,
701 source_opt: Option<DefId>) {
702 for source in source_opt.iter() {
703 ebml_w.start_tag(tag_item_method_provided_source);
704 let s = def_to_str(*source);
705 ebml_w.writer.write(s.as_bytes());
710 /* Returns an index of items in this class */
711 fn encode_info_for_struct(ecx: &EncodeContext,
712 ebml_w: &mut writer::Encoder,
713 path: &[ast_map::path_elt],
714 fields: &[@struct_field],
715 global_index: @mut ~[entry<i64>])
717 /* Each class has its own index, since different classes
718 may have fields with the same name */
721 /* We encode both private and public fields -- need to include
722 private fields to get the offsets right */
723 for field in fields.iter() {
724 let (nm, vis) = match field.node.kind {
725 named_field(nm, vis) => (nm, vis),
726 unnamed_field => (special_idents::unnamed_field, inherited)
729 let id = field.node.id;
730 index.push(entry {val: id as i64, pos: ebml_w.writer.tell()});
731 global_index.push(entry {val: id as i64, pos: ebml_w.writer.tell()});
732 ebml_w.start_tag(tag_items_data_item);
733 debug!("encode_info_for_struct: doing {} {}",
734 tcx.sess.str_of(nm), id);
735 encode_struct_field_family(ebml_w, vis);
736 encode_name(ecx, ebml_w, nm);
737 encode_path(ecx, ebml_w, path, ast_map::path_name(nm));
738 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
739 encode_def_id(ebml_w, local_def(id));
745 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
746 ebml_w: &mut writer::Encoder,
747 path: &[ast_map::path_elt],
750 index: @mut ~[entry<i64>],
752 index.push(entry { val: ctor_id as i64, pos: ebml_w.writer.tell() });
754 ebml_w.start_tag(tag_items_data_item);
755 encode_def_id(ebml_w, local_def(ctor_id));
756 encode_family(ebml_w, 'f');
757 encode_name(ecx, ebml_w, name);
758 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
759 encode_path(ecx, ebml_w, path, ast_map::path_name(name));
760 encode_parent_item(ebml_w, local_def(struct_id));
762 if ecx.item_symbols.contains_key(&ctor_id) {
763 encode_symbol(ecx, ebml_w, ctor_id);
769 fn encode_method_ty_fields(ecx: &EncodeContext,
770 ebml_w: &mut writer::Encoder,
771 method_ty: &ty::Method) {
772 encode_def_id(ebml_w, method_ty.def_id);
773 encode_name(ecx, ebml_w, method_ty.ident);
774 encode_ty_type_param_defs(ebml_w, ecx,
775 method_ty.generics.type_param_defs,
776 tag_item_method_tps);
777 encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty);
778 encode_method_fty(ecx, ebml_w, &method_ty.fty);
779 encode_visibility(ebml_w, method_ty.vis);
780 encode_explicit_self(ebml_w, method_ty.explicit_self);
781 let purity = method_ty.fty.purity;
782 match method_ty.explicit_self {
784 encode_family(ebml_w, purity_static_method_family(purity));
786 _ => encode_family(ebml_w, purity_fn_family(purity))
788 encode_provided_source(ebml_w, method_ty.provided_source);
791 fn encode_info_for_method(ecx: &EncodeContext,
792 ebml_w: &mut writer::Encoder,
794 impl_path: &[ast_map::path_elt],
795 is_default_impl: bool,
797 ast_method_opt: Option<@method>) {
799 debug!("encode_info_for_method: {:?} {}", m.def_id,
800 ecx.tcx.sess.str_of(m.ident));
801 ebml_w.start_tag(tag_items_data_item);
803 encode_method_ty_fields(ecx, ebml_w, m);
804 encode_parent_item(ebml_w, local_def(parent_id));
806 // The type for methods gets encoded twice, which is unfortunate.
807 let tpt = lookup_item_type(ecx.tcx, m.def_id);
808 encode_bounds_and_type(ebml_w, ecx, &tpt);
810 encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
812 for ast_method in ast_method_opt.iter() {
813 let num_params = tpt.generics.type_param_defs.len();
814 if num_params > 0u || is_default_impl
815 || should_inline(ast_method.attrs) {
816 (ecx.encode_inlined_item)(
817 ecx, ebml_w, impl_path,
818 ii_method(local_def(parent_id), false, *ast_method));
820 encode_symbol(ecx, ebml_w, m.def_id.node);
827 fn purity_fn_family(p: purity) -> char {
835 fn purity_static_method_family(p: purity) -> char {
839 _ => fail!("extern fn can't be static")
844 fn should_inline(attrs: &[Attribute]) -> bool {
846 match find_inline_attr(attrs) {
847 InlineNone | InlineNever => false,
848 InlineHint | InlineAlways => true
852 // Encodes the inherent implementations of a structure, enumeration, or trait.
853 fn encode_inherent_implementations(ecx: &EncodeContext,
854 ebml_w: &mut writer::Encoder,
856 match ecx.tcx.inherent_impls.find(&def_id) {
858 Some(&implementations) => {
859 for implementation in implementations.iter() {
860 ebml_w.start_tag(tag_items_data_item_inherent_impl);
861 encode_def_id(ebml_w, implementation.did);
868 // Encodes the implementations of a trait defined in this crate.
869 fn encode_extension_implementations(ecx: &EncodeContext,
870 ebml_w: &mut writer::Encoder,
871 trait_def_id: DefId) {
872 match ecx.tcx.trait_impls.find(&trait_def_id) {
874 Some(&implementations) => {
875 for implementation in implementations.iter() {
876 ebml_w.start_tag(tag_items_data_item_extension_impl);
877 encode_def_id(ebml_w, implementation.did);
884 fn encode_info_for_item(ecx: &EncodeContext,
885 ebml_w: &mut writer::Encoder,
887 index: @mut ~[entry<i64>],
888 path: &[ast_map::path_elt],
889 vis: ast::visibility) {
892 fn add_to_index_(item: @item, ebml_w: &writer::Encoder,
893 index: @mut ~[entry<i64>]) {
894 index.push(entry { val: item.id as i64, pos: ebml_w.writer.tell() });
896 let add_to_index: &fn() = || add_to_index_(item, ebml_w, index);
898 debug!("encoding info for item at {}",
899 ecx.tcx.sess.codemap.span_to_str(item.span));
901 let def_id = local_def(item.id);
903 item_static(_, m, _) => {
905 ebml_w.start_tag(tag_items_data_item);
906 encode_def_id(ebml_w, def_id);
907 if m == ast::MutMutable {
908 encode_family(ebml_w, 'b');
910 encode_family(ebml_w, 'c');
912 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
913 encode_symbol(ecx, ebml_w, item.id);
914 encode_name(ecx, ebml_w, item.ident);
915 let elt = ast_map::path_pretty_name(item.ident, item.id as u64);
916 encode_path(ecx, ebml_w, path, elt);
917 if !ecx.non_inlineable_statics.contains(&item.id) {
918 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
920 encode_visibility(ebml_w, vis);
923 item_fn(_, purity, _, ref generics, _) => {
925 ebml_w.start_tag(tag_items_data_item);
926 encode_def_id(ebml_w, def_id);
927 encode_family(ebml_w, purity_fn_family(purity));
928 let tps_len = generics.ty_params.len();
929 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
930 encode_name(ecx, ebml_w, item.ident);
931 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
932 encode_attributes(ebml_w, item.attrs);
933 if tps_len > 0u || should_inline(item.attrs) {
934 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
936 encode_symbol(ecx, ebml_w, item.id);
938 encode_visibility(ebml_w, vis);
943 encode_info_for_mod(ecx,
951 item_foreign_mod(ref fm) => {
953 ebml_w.start_tag(tag_items_data_item);
954 encode_def_id(ebml_w, def_id);
955 encode_family(ebml_w, 'n');
956 encode_name(ecx, ebml_w, item.ident);
957 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
959 // Encode all the items in this module.
960 for foreign_item in fm.items.iter() {
961 ebml_w.start_tag(tag_mod_child);
962 ebml_w.wr_str(def_to_str(local_def(foreign_item.id)));
965 encode_visibility(ebml_w, vis);
970 ebml_w.start_tag(tag_items_data_item);
971 encode_def_id(ebml_w, def_id);
972 encode_family(ebml_w, 'y');
973 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
974 encode_name(ecx, ebml_w, item.ident);
975 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
976 encode_region_param(ecx, ebml_w, item);
977 encode_visibility(ebml_w, vis);
980 item_enum(ref enum_definition, ref generics) => {
983 ebml_w.start_tag(tag_items_data_item);
984 encode_def_id(ebml_w, def_id);
985 encode_family(ebml_w, 't');
986 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
987 encode_name(ecx, ebml_w, item.ident);
988 for v in (*enum_definition).variants.iter() {
989 encode_variant_id(ebml_w, local_def(v.node.id));
991 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
992 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
993 encode_region_param(ecx, ebml_w, item);
995 // Encode inherent implementations for this enumeration.
996 encode_inherent_implementations(ecx, ebml_w, def_id);
998 encode_visibility(ebml_w, vis);
1001 encode_enum_variant_info(ecx,
1004 (*enum_definition).variants,
1009 item_struct(struct_def, _) => {
1010 /* First, encode the fields
1011 These come first because we need to write them to make
1012 the index, and the index needs to be in the item for the
1014 let idx = encode_info_for_struct(ecx, ebml_w, path,
1015 struct_def.fields, index);
1017 /* Index the class*/
1020 /* Now, make an item for the class itself */
1021 ebml_w.start_tag(tag_items_data_item);
1022 encode_def_id(ebml_w, def_id);
1023 encode_family(ebml_w, 'S');
1024 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1026 encode_name(ecx, ebml_w, item.ident);
1027 encode_attributes(ebml_w, item.attrs);
1028 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1029 encode_region_param(ecx, ebml_w, item);
1030 encode_visibility(ebml_w, vis);
1032 /* Encode def_ids for each field and method
1033 for methods, write all the stuff get_trait_method
1035 encode_struct_fields(ecx, ebml_w, struct_def);
1037 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
1039 // Encode inherent implementations for this structure.
1040 encode_inherent_implementations(ecx, ebml_w, def_id);
1042 /* Each class has its own index -- encode it */
1043 let bkts = create_index(idx);
1044 encode_index(ebml_w, bkts, write_i64);
1047 // If this is a tuple- or enum-like struct, encode the type of the
1049 if struct_def.fields.len() > 0 &&
1050 struct_def.fields[0].node.kind == ast::unnamed_field {
1051 let ctor_id = match struct_def.ctor_id {
1052 Some(ctor_id) => ctor_id,
1053 None => ecx.tcx.sess.bug("struct def didn't have ctor id"),
1056 encode_info_for_struct_ctor(ecx,
1065 item_impl(_, ref opt_trait, ref ty, ref ast_methods) => {
1066 // We need to encode information about the default methods we
1067 // have inherited, so we drive this based on the impl structure.
1068 let imp = tcx.impls.get(&def_id);
1071 ebml_w.start_tag(tag_items_data_item);
1072 encode_def_id(ebml_w, def_id);
1073 encode_family(ebml_w, 'i');
1074 encode_region_param(ecx, ebml_w, item);
1075 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1076 encode_name(ecx, ebml_w, item.ident);
1077 encode_attributes(ebml_w, item.attrs);
1079 ast::ty_path(ref path, ref bounds, _) if path.segments
1081 assert!(bounds.is_none());
1082 encode_impl_type_basename(ecx, ebml_w,
1083 ast_util::path_to_ident(path));
1087 for method in imp.methods.iter() {
1088 ebml_w.start_tag(tag_item_impl_method);
1089 let s = def_to_str(method.def_id);
1090 ebml_w.writer.write(s.as_bytes());
1093 for ast_trait_ref in opt_trait.iter() {
1094 let trait_ref = ty::node_id_to_trait_ref(
1095 tcx, ast_trait_ref.ref_id);
1096 encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
1097 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1098 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1100 let elt = ast_map::impl_pretty_name(opt_trait, ty, item.ident);
1101 encode_path(ecx, ebml_w, path, elt);
1105 let mut impl_path = vec::append(~[], path);
1106 impl_path.push(elt);
1108 // Iterate down the methods, emitting them. We rely on the
1109 // assumption that all of the actually implemented methods
1110 // appear first in the impl structure, in the same order they do
1111 // in the ast. This is a little sketchy.
1112 let num_implemented_methods = ast_methods.len();
1113 for (i, m) in imp.methods.iter().enumerate() {
1114 let ast_method = if i < num_implemented_methods {
1115 Some(ast_methods[i])
1118 index.push(entry {val: m.def_id.node as i64,
1119 pos: ebml_w.writer.tell()});
1120 encode_info_for_method(ecx,
1129 item_trait(_, ref super_traits, ref ms) => {
1131 ebml_w.start_tag(tag_items_data_item);
1132 encode_def_id(ebml_w, def_id);
1133 encode_family(ebml_w, 'I');
1134 encode_region_param(ecx, ebml_w, item);
1135 let trait_def = ty::lookup_trait_def(tcx, def_id);
1136 encode_ty_type_param_defs(ebml_w, ecx,
1137 trait_def.generics.type_param_defs,
1138 tag_items_data_item_ty_param_bounds);
1139 encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
1140 encode_name(ecx, ebml_w, item.ident);
1141 encode_attributes(ebml_w, item.attrs);
1142 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1143 ebml_w.start_tag(tag_item_trait_method);
1144 encode_def_id(ebml_w, method_def_id);
1147 ebml_w.start_tag(tag_mod_child);
1148 ebml_w.wr_str(def_to_str(method_def_id));
1151 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1152 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1153 // reading the AST's list, because the former has already filtered out
1154 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1155 for ast_trait_ref in super_traits.iter() {
1156 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1157 encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
1160 // Encode the implementations of this trait.
1161 encode_extension_implementations(ecx, ebml_w, def_id);
1165 // Now output the method info for each method.
1166 let r = ty::trait_method_def_ids(tcx, def_id);
1167 for (i, &method_def_id) in r.iter().enumerate() {
1168 assert_eq!(method_def_id.crate, ast::LOCAL_CRATE);
1170 let method_ty = ty::method(tcx, method_def_id);
1172 index.push(entry {val: method_def_id.node as i64,
1173 pos: ebml_w.writer.tell()});
1175 ebml_w.start_tag(tag_items_data_item);
1177 encode_method_ty_fields(ecx, ebml_w, method_ty);
1179 encode_parent_item(ebml_w, def_id);
1181 let mut trait_path = vec::append(~[], path);
1182 trait_path.push(ast_map::path_name(item.ident));
1183 encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
1185 match method_ty.explicit_self {
1187 encode_family(ebml_w,
1188 purity_static_method_family(
1189 method_ty.fty.purity));
1191 let tpt = ty::lookup_item_type(tcx, method_def_id);
1192 encode_bounds_and_type(ebml_w, ecx, &tpt);
1196 encode_family(ebml_w,
1198 method_ty.fty.purity));
1204 encode_method_sort(ebml_w, 'r');
1208 // If this is a static method, we've already encoded
1210 if method_ty.explicit_self != sty_static {
1211 // XXX: I feel like there is something funny going on.
1212 let tpt = ty::lookup_item_type(tcx, method_def_id);
1213 encode_bounds_and_type(ebml_w, ecx, &tpt);
1215 encode_method_sort(ebml_w, 'p');
1216 (ecx.encode_inlined_item)(
1218 ii_method(def_id, true, m));
1225 // Encode inherent implementations for this trait.
1226 encode_inherent_implementations(ecx, ebml_w, def_id);
1228 item_mac(*) => fail!("item macros unimplemented")
1232 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1233 ebml_w: &mut writer::Encoder,
1234 nitem: @foreign_item,
1235 index: @mut ~[entry<i64>],
1236 path: &ast_map::path,
1238 index.push(entry { val: nitem.id as i64, pos: ebml_w.writer.tell() });
1240 ebml_w.start_tag(tag_items_data_item);
1242 foreign_item_fn(*) => {
1243 encode_def_id(ebml_w, local_def(nitem.id));
1244 encode_family(ebml_w, purity_fn_family(impure_fn));
1245 encode_bounds_and_type(ebml_w, ecx,
1246 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1247 encode_name(ecx, ebml_w, nitem.ident);
1248 if abi.is_intrinsic() {
1249 (ecx.encode_inlined_item)(ecx, ebml_w, *path, ii_foreign(nitem));
1251 encode_symbol(ecx, ebml_w, nitem.id);
1253 encode_path(ecx, ebml_w, *path, ast_map::path_name(nitem.ident));
1255 foreign_item_static(_, mutbl) => {
1256 encode_def_id(ebml_w, local_def(nitem.id));
1258 encode_family(ebml_w, 'b');
1260 encode_family(ebml_w, 'c');
1262 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1263 encode_symbol(ecx, ebml_w, nitem.id);
1264 encode_name(ecx, ebml_w, nitem.ident);
1265 encode_path(ecx, ebml_w, *path, ast_map::path_name(nitem.ident));
1271 fn my_visit_expr(_e:@Expr) { }
1273 fn my_visit_item(i:@item, items: ast_map::map, ebml_w:&writer::Encoder,
1274 ecx_ptr:*int, index: @mut ~[entry<i64>]) {
1275 match items.get_copy(&i.id) {
1276 ast_map::node_item(_, pt) => {
1277 let mut ebml_w = ebml_w.clone();
1279 let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1280 encode_info_for_item(ecx, &mut ebml_w, i, index, *pt, i.vis);
1282 _ => fail!("bad item")
1286 fn my_visit_foreign_item(ni:@foreign_item, items: ast_map::map, ebml_w:&writer::Encoder,
1287 ecx_ptr:*int, index: @mut ~[entry<i64>]) {
1288 match items.get_copy(&ni.id) {
1289 ast_map::node_foreign_item(_, abi, _, pt) => {
1290 debug!("writing foreign item {}::{}",
1291 ast_map::path_to_str(
1293 token::get_ident_interner()),
1294 token::ident_to_str(&ni.ident));
1296 let mut ebml_w = ebml_w.clone();
1298 let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1299 encode_info_for_foreign_item(ecx,
1306 // case for separate item and foreign-item tables
1307 _ => fail!("bad foreign item")
1311 struct EncodeVisitor {
1312 ebml_w_for_visit_item: writer::Encoder,
1313 ebml_w_for_visit_foreign_item: writer::Encoder,
1315 items: ast_map::map,
1316 index: @mut ~[entry<i64>],
1319 impl visit::Visitor<()> for EncodeVisitor {
1320 fn visit_expr(&mut self, ex:@Expr, _:()) {
1321 visit::walk_expr(self, ex, ());
1324 fn visit_item(&mut self, i:@item, _:()) {
1325 visit::walk_item(self, i, ());
1328 &self.ebml_w_for_visit_item,
1332 fn visit_foreign_item(&mut self, ni:@foreign_item, _:()) {
1333 visit::walk_foreign_item(self, ni, ());
1334 my_visit_foreign_item(ni,
1336 &self.ebml_w_for_visit_foreign_item,
1342 fn encode_info_for_items(ecx: &EncodeContext,
1343 ebml_w: &mut writer::Encoder,
1346 let index = @mut ~[];
1347 ebml_w.start_tag(tag_items_data);
1348 index.push(entry { val: CRATE_NODE_ID as i64, pos: ebml_w.writer.tell() });
1349 encode_info_for_mod(ecx,
1354 syntax::parse::token::special_idents::invalid,
1356 let items = ecx.tcx.items;
1358 // See comment in `encode_side_tables_for_ii` in astencode
1359 let ecx_ptr : *int = unsafe { cast::transmute(ecx) };
1360 let mut visitor = EncodeVisitor {
1364 ebml_w_for_visit_item: (*ebml_w).clone(),
1365 ebml_w_for_visit_foreign_item: (*ebml_w).clone(),
1368 visit::walk_crate(&mut visitor, crate, ());
1371 return /*bad*/(*index).clone();
1375 // Path and definition ID indexing
1377 fn create_index<T:Clone + Hash + IterBytes + 'static>(
1379 -> ~[@~[entry<T>]] {
1380 let mut buckets: ~[@mut ~[entry<T>]] = ~[];
1381 for _ in range(0u, 256u) { buckets.push(@mut ~[]); };
1382 for elt in index.iter() {
1383 let h = elt.val.hash() as uint;
1384 buckets[h % 256].push((*elt).clone());
1387 let mut buckets_frozen = ~[];
1388 for bucket in buckets.iter() {
1389 buckets_frozen.push(@/*bad*/(**bucket).clone());
1391 return buckets_frozen;
1394 fn encode_index<T:'static>(
1395 ebml_w: &mut writer::Encoder,
1396 buckets: ~[@~[entry<T>]],
1397 write_fn: &fn(@io::Writer, &T)) {
1398 let writer = ebml_w.writer;
1399 ebml_w.start_tag(tag_index);
1400 let mut bucket_locs: ~[uint] = ~[];
1401 ebml_w.start_tag(tag_index_buckets);
1402 for bucket in buckets.iter() {
1403 bucket_locs.push(ebml_w.writer.tell());
1404 ebml_w.start_tag(tag_index_buckets_bucket);
1405 for elt in (**bucket).iter() {
1406 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1407 assert!(elt.pos < 0xffff_ffff);
1408 writer.write_be_u32(elt.pos as u32);
1409 write_fn(writer, &elt.val);
1415 ebml_w.start_tag(tag_index_table);
1416 for pos in bucket_locs.iter() {
1417 assert!(*pos < 0xffff_ffff);
1418 writer.write_be_u32(*pos as u32);
1424 fn write_str(writer: @io::Writer, s: ~str) {
1425 writer.write_str(s);
1428 fn write_i64(writer: @io::Writer, &n: &i64) {
1429 assert!(n < 0x7fff_ffff);
1430 writer.write_be_u32(n as u32);
1433 fn encode_meta_item(ebml_w: &mut writer::Encoder, mi: @MetaItem) {
1436 ebml_w.start_tag(tag_meta_item_word);
1437 ebml_w.start_tag(tag_meta_item_name);
1438 ebml_w.writer.write(name.as_bytes());
1442 MetaNameValue(name, value) => {
1444 lit_str(value, _) => {
1445 ebml_w.start_tag(tag_meta_item_name_value);
1446 ebml_w.start_tag(tag_meta_item_name);
1447 ebml_w.writer.write(name.as_bytes());
1449 ebml_w.start_tag(tag_meta_item_value);
1450 ebml_w.writer.write(value.as_bytes());
1454 _ => {/* FIXME (#623): encode other variants */ }
1457 MetaList(name, ref items) => {
1458 ebml_w.start_tag(tag_meta_item_list);
1459 ebml_w.start_tag(tag_meta_item_name);
1460 ebml_w.writer.write(name.as_bytes());
1462 for inner_item in items.iter() {
1463 encode_meta_item(ebml_w, *inner_item);
1470 fn encode_attributes(ebml_w: &mut writer::Encoder, attrs: &[Attribute]) {
1471 ebml_w.start_tag(tag_attributes);
1472 for attr in attrs.iter() {
1473 ebml_w.start_tag(tag_attribute);
1474 encode_meta_item(ebml_w, attr.node.value);
1480 // So there's a special crate attribute called 'link' which defines the
1481 // metadata that Rust cares about for linking crates. This attribute requires
1482 // 'name' and 'vers' items, so if the user didn't provide them we will throw
1483 // them in anyway with default values.
1484 fn synthesize_crate_attrs(ecx: &EncodeContext,
1485 crate: &Crate) -> ~[Attribute] {
1487 fn synthesize_link_attr(ecx: &EncodeContext, items: ~[@MetaItem]) ->
1490 assert!(!ecx.link_meta.name.is_empty());
1491 assert!(!ecx.link_meta.vers.is_empty());
1494 attr::mk_name_value_item_str(@"name",
1495 ecx.link_meta.name);
1497 attr::mk_name_value_item_str(@"vers",
1498 ecx.link_meta.vers);
1500 let mut meta_items = ~[name_item, vers_item];
1502 for &mi in items.iter().filter(|mi| "name" != mi.name() && "vers" != mi.name()) {
1503 meta_items.push(mi);
1505 let link_item = attr::mk_list_item(@"link", meta_items);
1507 return attr::mk_attr(link_item);
1510 let mut attrs = ~[];
1511 let mut found_link_attr = false;
1512 for attr in crate.attrs.iter() {
1514 if "link" != attr.name() {
1517 match attr.meta_item_list() {
1519 found_link_attr = true;;
1520 synthesize_link_attr(ecx, l.to_owned())
1527 if !found_link_attr { attrs.push(synthesize_link_attr(ecx, ~[])); }
1532 fn encode_crate_deps(ecx: &EncodeContext,
1533 ebml_w: &mut writer::Encoder,
1534 cstore: &cstore::CStore) {
1535 fn get_ordered_deps(ecx: &EncodeContext, cstore: &cstore::CStore)
1536 -> ~[decoder::CrateDep] {
1537 type numdep = decoder::CrateDep;
1539 // Pull the cnums and name,vers,hash out of cstore
1541 do cstore::iter_crate_data(cstore) |key, val| {
1542 let dep = decoder::CrateDep {cnum: key,
1543 name: ecx.tcx.sess.ident_of(val.name),
1544 vers: decoder::get_crate_vers(val.data),
1545 hash: decoder::get_crate_hash(val.data)};
1550 extra::sort::quick_sort(deps, |kv1, kv2| kv1.cnum <= kv2.cnum);
1552 // Sanity-check the crate numbers
1553 let mut expected_cnum = 1;
1554 for n in deps.iter() {
1555 assert_eq!(n.cnum, expected_cnum);
1562 // We're just going to write a list of crate 'name-hash-version's, with
1563 // the assumption that they are numbered 1 to n.
1564 // FIXME (#2166): This is not nearly enough to support correct versioning
1565 // but is enough to get transitive crate dependencies working.
1566 ebml_w.start_tag(tag_crate_deps);
1567 let r = get_ordered_deps(ecx, cstore);
1568 for dep in r.iter() {
1569 encode_crate_dep(ecx, ebml_w, *dep);
1574 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1575 ebml_w.start_tag(tag_lang_items);
1577 for (i, def_id) in ecx.tcx.lang_items.items() {
1578 for id in def_id.iter() {
1579 if id.crate == LOCAL_CRATE {
1580 ebml_w.start_tag(tag_lang_items_item);
1582 ebml_w.start_tag(tag_lang_items_item_id);
1583 ebml_w.writer.write_be_u32(i as u32);
1584 ebml_w.end_tag(); // tag_lang_items_item_id
1586 ebml_w.start_tag(tag_lang_items_item_node_id);
1587 ebml_w.writer.write_be_u32(id.node as u32);
1588 ebml_w.end_tag(); // tag_lang_items_item_node_id
1590 ebml_w.end_tag(); // tag_lang_items_item
1595 ebml_w.end_tag(); // tag_lang_items
1598 fn encode_link_args(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1599 ebml_w.start_tag(tag_link_args);
1601 let link_args = cstore::get_used_link_args(ecx.cstore);
1602 for link_arg in link_args.iter() {
1603 ebml_w.start_tag(tag_link_args_arg);
1604 ebml_w.writer.write_str(link_arg.to_str());
1611 struct ImplVisitor<'self> {
1612 ecx: &'self EncodeContext<'self>,
1613 ebml_w: &'self mut writer::Encoder,
1616 impl<'self> Visitor<()> for ImplVisitor<'self> {
1617 fn visit_item(&mut self, item: @item, _: ()) {
1619 item_impl(_, Some(ref trait_ref), _, _) => {
1620 let def_map = self.ecx.tcx.def_map;
1621 let trait_def = def_map.get_copy(&trait_ref.ref_id);
1622 let def_id = ast_util::def_id_of_def(trait_def);
1624 // Load eagerly if this is an implementation of the Drop trait
1625 // or if the trait is not defined in this crate.
1626 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1627 def_id.crate != LOCAL_CRATE {
1628 self.ebml_w.start_tag(tag_impls_impl);
1629 encode_def_id(self.ebml_w, local_def(item.id));
1630 self.ebml_w.end_tag();
1635 visit::walk_item(self, item, ());
1639 /// Encodes implementations that are eagerly loaded.
1641 /// None of this is necessary in theory; we can load all implementations
1642 /// lazily. However, in two cases the optimizations to lazily load
1643 /// implementations are not yet implemented. These two cases, which require us
1644 /// to load implementations eagerly, are:
1646 /// * Destructors (implementations of the Drop trait).
1648 /// * Implementations of traits not defined in this crate.
1649 fn encode_impls(ecx: &EncodeContext,
1651 ebml_w: &mut writer::Encoder) {
1652 ebml_w.start_tag(tag_impls);
1655 let mut visitor = ImplVisitor {
1659 visit::walk_crate(&mut visitor, crate, ());
1665 fn encode_misc_info(ecx: &EncodeContext,
1667 ebml_w: &mut writer::Encoder) {
1668 ebml_w.start_tag(tag_misc_info);
1669 ebml_w.start_tag(tag_misc_info_crate_items);
1670 for &item in crate.module.items.iter() {
1671 ebml_w.start_tag(tag_mod_child);
1672 ebml_w.wr_str(def_to_str(local_def(item.id)));
1675 do each_auxiliary_node_id(item) |auxiliary_node_id| {
1676 ebml_w.start_tag(tag_mod_child);
1677 ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
1683 // Encode reexports for the root module.
1684 encode_reexports(ecx, ebml_w, 0, []);
1690 fn encode_crate_dep(ecx: &EncodeContext,
1691 ebml_w: &mut writer::Encoder,
1692 dep: decoder::CrateDep) {
1693 ebml_w.start_tag(tag_crate_dep);
1694 ebml_w.start_tag(tag_crate_dep_name);
1695 let s = ecx.tcx.sess.str_of(dep.name);
1696 ebml_w.writer.write(s.as_bytes());
1698 ebml_w.start_tag(tag_crate_dep_vers);
1699 ebml_w.writer.write(dep.vers.as_bytes());
1701 ebml_w.start_tag(tag_crate_dep_hash);
1702 ebml_w.writer.write(dep.hash.as_bytes());
1707 fn encode_hash(ebml_w: &mut writer::Encoder, hash: &str) {
1708 ebml_w.start_tag(tag_crate_hash);
1709 ebml_w.writer.write(hash.as_bytes());
1713 // NB: Increment this as you change the metadata encoding version.
1714 pub static metadata_encoding_version : &'static [u8] =
1715 &[0x72, //'r' as u8,
1721 pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
1722 let wr = @io::BytesWriter::new();
1744 encode_inlined_item,
1747 non_inlineable_statics,
1750 let type_abbrevs = @mut HashMap::new();
1751 let stats = @mut stats;
1752 let ecx = EncodeContext {
1756 reexports2: reexports2,
1757 item_symbols: item_symbols,
1758 discrim_symbols: discrim_symbols,
1759 non_inlineable_statics: non_inlineable_statics,
1760 link_meta: link_meta,
1762 encode_inlined_item: encode_inlined_item,
1763 type_abbrevs: type_abbrevs,
1764 reachable: reachable,
1767 let mut ebml_w = writer::Encoder(wr as @io::Writer);
1769 encode_hash(&mut ebml_w, ecx.link_meta.extras_hash);
1771 let mut i = *wr.pos;
1772 let crate_attrs = synthesize_crate_attrs(&ecx, crate);
1773 encode_attributes(&mut ebml_w, crate_attrs);
1774 ecx.stats.attr_bytes = *wr.pos - i;
1777 encode_crate_deps(&ecx, &mut ebml_w, ecx.cstore);
1778 ecx.stats.dep_bytes = *wr.pos - i;
1780 // Encode the language items.
1782 encode_lang_items(&ecx, &mut ebml_w);
1783 ecx.stats.lang_item_bytes = *wr.pos - i;
1785 // Encode the link args.
1787 encode_link_args(&ecx, &mut ebml_w);
1788 ecx.stats.link_args_bytes = *wr.pos - i;
1790 // Encode the def IDs of impls, for coherence checking.
1792 encode_impls(&ecx, crate, &mut ebml_w);
1793 ecx.stats.impl_bytes = *wr.pos - i;
1795 // Encode miscellaneous info.
1797 encode_misc_info(&ecx, crate, &mut ebml_w);
1798 ecx.stats.misc_bytes = *wr.pos - i;
1800 // Encode and index the items.
1801 ebml_w.start_tag(tag_items);
1803 let items_index = encode_info_for_items(&ecx, &mut ebml_w, crate);
1804 ecx.stats.item_bytes = *wr.pos - i;
1807 let items_buckets = create_index(items_index);
1808 encode_index(&mut ebml_w, items_buckets, write_i64);
1809 ecx.stats.index_bytes = *wr.pos - i;
1812 ecx.stats.total_bytes = *wr.pos;
1814 if (tcx.sess.meta_stats()) {
1815 for e in wr.bytes.iter() {
1817 ecx.stats.zero_bytes += 1;
1821 io::println("metadata stats:");
1822 println!(" inline bytes: {}", ecx.stats.inline_bytes);
1823 println!(" attribute bytes: {}", ecx.stats.attr_bytes);
1824 println!(" dep bytes: {}", ecx.stats.dep_bytes);
1825 println!(" lang item bytes: {}", ecx.stats.lang_item_bytes);
1826 println!(" link args bytes: {}", ecx.stats.link_args_bytes);
1827 println!(" impl bytes: {}", ecx.stats.impl_bytes);
1828 println!(" misc bytes: {}", ecx.stats.misc_bytes);
1829 println!(" item bytes: {}", ecx.stats.item_bytes);
1830 println!(" index bytes: {}", ecx.stats.index_bytes);
1831 println!(" zero bytes: {}", ecx.stats.zero_bytes);
1832 println!(" total bytes: {}", ecx.stats.total_bytes);
1835 // Pad this, since something (LLVM, presumably) is cutting off the
1836 // remaining % 4 bytes.
1837 wr.write(&[0u8, 0u8, 0u8, 0u8]);
1839 let writer_bytes: &mut ~[u8] = wr.bytes;
1841 metadata_encoding_version.to_owned() +
1842 flate::deflate_bytes(*writer_bytes)
1845 // Get the encoded string for a type
1846 pub fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str {
1847 let cx = @tyencode::ctxt {
1851 abbrevs: tyencode::ac_no_abbrevs};
1852 do io::with_str_writer |wr| {
1853 tyencode::enc_ty(wr, cx, t);