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 extra::serialize::Encodable;
26 use std::cell::{Cell, RefCell};
27 use std::hashmap::{HashMap, HashSet};
28 use std::io::MemWriter;
31 use syntax::abi::AbiSet;
35 use syntax::ast_util::*;
37 use syntax::attr::AttrMetaMethods;
40 use syntax::diagnostic::SpanHandler;
41 use syntax::parse::token::InternedString;
42 use syntax::parse::token::special_idents;
43 use syntax::parse::token;
44 use syntax::visit::Visitor;
47 use writer = extra::ebml::writer;
50 type abbrev_map = @RefCell<HashMap<ty::t, tyencode::ty_abbrev>>;
52 /// A borrowed version of ast::InlinedItem.
53 pub enum InlinedItemRef<'a> {
54 IIItemRef(&'a ast::Item),
55 IIMethodRef(ast::DefId, bool, &'a ast::Method),
56 IIForeignRef(&'a ast::ForeignItem)
59 pub type encode_inlined_item<'a> = 'a |ecx: &EncodeContext,
60 ebml_w: &mut writer::Encoder,
61 path: &[ast_map::PathElem],
64 pub struct EncodeParams<'a> {
67 reexports2: middle::resolve::ExportMap2,
68 item_symbols: &'a RefCell<HashMap<ast::NodeId, ~str>>,
69 non_inlineable_statics: &'a RefCell<HashSet<ast::NodeId>>,
70 link_meta: &'a LinkMeta,
71 cstore: @cstore::CStore,
72 encode_inlined_item: encode_inlined_item<'a>,
73 reachable: @RefCell<HashSet<ast::NodeId>>,
74 codemap: @codemap::CodeMap,
78 inline_bytes: Cell<u64>,
79 attr_bytes: Cell<u64>,
81 lang_item_bytes: Cell<u64>,
82 native_lib_bytes: Cell<u64>,
83 macro_registrar_fn_bytes: Cell<u64>,
84 macro_defs_bytes: Cell<u64>,
85 impl_bytes: Cell<u64>,
86 misc_bytes: Cell<u64>,
87 item_bytes: Cell<u64>,
88 index_bytes: Cell<u64>,
89 zero_bytes: Cell<u64>,
90 total_bytes: Cell<u64>,
93 pub struct EncodeContext<'a> {
97 reexports2: middle::resolve::ExportMap2,
98 item_symbols: &'a RefCell<HashMap<ast::NodeId, ~str>>,
99 non_inlineable_statics: &'a RefCell<HashSet<ast::NodeId>>,
100 link_meta: &'a LinkMeta,
101 cstore: &'a cstore::CStore,
102 encode_inlined_item: encode_inlined_item<'a>,
103 type_abbrevs: abbrev_map,
104 reachable: @RefCell<HashSet<ast::NodeId>>,
105 codemap: @codemap::CodeMap,
108 pub fn reachable(ecx: &EncodeContext, id: NodeId) -> bool {
109 let reachable = ecx.reachable.borrow();
110 reachable.get().contains(&id)
113 fn encode_name(ecx: &EncodeContext,
114 ebml_w: &mut writer::Encoder,
116 ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name));
119 fn encode_impl_type_basename(ecx: &EncodeContext,
120 ebml_w: &mut writer::Encoder,
122 ebml_w.wr_tagged_str(tag_item_impl_type_basename,
123 ecx.tcx.sess.str_of(name));
126 pub fn encode_def_id(ebml_w: &mut writer::Encoder, id: DefId) {
127 ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
136 fn encode_trait_ref(ebml_w: &mut writer::Encoder,
138 trait_ref: &ty::TraitRef,
140 let ty_str_ctxt = @tyencode::ctxt {
144 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
147 ebml_w.start_tag(tag);
148 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
152 fn encode_impl_vtables(ebml_w: &mut writer::Encoder,
154 vtables: &typeck::impl_res) {
155 ebml_w.start_tag(tag_item_impl_vtables);
156 astencode::encode_vtable_res(ecx, ebml_w, vtables.trait_vtables);
157 astencode::encode_vtable_param_res(ecx, ebml_w, vtables.self_vtables);
161 // Item info table encoding
162 fn encode_family(ebml_w: &mut writer::Encoder, c: char) {
163 ebml_w.start_tag(tag_items_data_item_family);
164 ebml_w.writer.write(&[c as u8]);
168 pub fn def_to_str(did: DefId) -> ~str {
169 format!("{}:{}", did.crate, did.node)
172 fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
174 params: @~[ty::TypeParameterDef],
176 let ty_str_ctxt = @tyencode::ctxt {
180 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
182 for param in params.iter() {
183 ebml_w.start_tag(tag);
184 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
189 fn encode_region_param_defs(ebml_w: &mut writer::Encoder,
191 params: @[ty::RegionParameterDef]) {
192 for param in params.iter() {
193 ebml_w.start_tag(tag_region_param_def);
195 ebml_w.start_tag(tag_region_param_def_ident);
196 encode_name(ecx, ebml_w, param.ident);
199 ebml_w.wr_tagged_str(tag_region_param_def_def_id,
200 def_to_str(param.def_id));
206 fn encode_item_variances(ebml_w: &mut writer::Encoder,
209 let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
210 ebml_w.start_tag(tag_item_variances);
215 fn encode_bounds_and_type(ebml_w: &mut writer::Encoder,
217 tpt: &ty::ty_param_bounds_and_ty) {
218 encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs,
219 tag_items_data_item_ty_param_bounds);
220 encode_region_param_defs(ebml_w, ecx, tpt.generics.region_param_defs);
221 encode_type(ecx, ebml_w, tpt.ty);
224 fn encode_variant_id(ebml_w: &mut writer::Encoder, vid: DefId) {
225 ebml_w.start_tag(tag_items_data_item_variant);
226 let s = def_to_str(vid);
227 ebml_w.writer.write(s.as_bytes());
231 pub fn write_type(ecx: &EncodeContext,
232 ebml_w: &mut writer::Encoder,
234 let ty_str_ctxt = @tyencode::ctxt {
238 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
240 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
243 pub fn write_vstore(ecx: &EncodeContext,
244 ebml_w: &mut writer::Encoder,
245 vstore: ty::vstore) {
246 let ty_str_ctxt = @tyencode::ctxt {
250 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
252 tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
255 fn encode_type(ecx: &EncodeContext,
256 ebml_w: &mut writer::Encoder,
258 ebml_w.start_tag(tag_items_data_item_type);
259 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 let item_symbols = ecx.item_symbols.borrow();
284 match item_symbols.get().find(&id) {
286 debug!("encode_symbol(id={:?}, str={})", id, *x);
287 ebml_w.writer.write(x.as_bytes());
290 ecx.diag.handler().bug(
291 format!("encode_symbol: id not found {}", id));
297 fn encode_disr_val(_: &EncodeContext,
298 ebml_w: &mut writer::Encoder,
299 disr_val: ty::Disr) {
300 ebml_w.start_tag(tag_disr_val);
301 let s = disr_val.to_str();
302 ebml_w.writer.write(s.as_bytes());
306 fn encode_parent_item(ebml_w: &mut writer::Encoder, id: DefId) {
307 ebml_w.start_tag(tag_items_data_parent_item);
308 let s = def_to_str(id);
309 ebml_w.writer.write(s.as_bytes());
313 fn encode_struct_fields(ecx: &EncodeContext,
314 ebml_w: &mut writer::Encoder,
316 for f in def.fields.iter() {
318 NamedField(ident, vis) => {
319 ebml_w.start_tag(tag_item_field);
320 encode_struct_field_family(ebml_w, vis);
321 encode_name(ecx, ebml_w, ident);
322 encode_def_id(ebml_w, local_def(f.node.id));
326 ebml_w.start_tag(tag_item_unnamed_field);
327 encode_def_id(ebml_w, local_def(f.node.id));
334 fn encode_enum_variant_info(ecx: &EncodeContext,
335 ebml_w: &mut writer::Encoder,
337 variants: &[P<Variant>],
338 path: &[ast_map::PathElem],
339 index: @RefCell<~[entry<i64>]>,
340 generics: &ast::Generics) {
341 debug!("encode_enum_variant_info(id={:?})", id);
343 let mut disr_val = 0;
345 let vi = ty::enum_variants(ecx.tcx,
346 ast::DefId { crate: LOCAL_CRATE, node: id });
347 for variant in variants.iter() {
348 let def_id = local_def(variant.node.id);
350 let mut index = index.borrow_mut();
351 index.get().push(entry {
352 val: variant.node.id as i64,
353 pos: ebml_w.writer.tell(),
356 ebml_w.start_tag(tag_items_data_item);
357 encode_def_id(ebml_w, def_id);
358 match variant.node.kind {
359 ast::TupleVariantKind(_) => encode_family(ebml_w, 'v'),
360 ast::StructVariantKind(_) => encode_family(ebml_w, 'V')
362 encode_name(ecx, ebml_w, variant.node.name);
363 encode_parent_item(ebml_w, local_def(id));
364 encode_visibility(ebml_w, variant.node.vis);
365 encode_attributes(ebml_w, variant.node.attrs);
366 match variant.node.kind {
367 ast::TupleVariantKind(ref args)
368 if args.len() > 0 && generics.ty_params.len() == 0 => {
369 encode_symbol(ecx, ebml_w, variant.node.id);
371 ast::TupleVariantKind(_) => {},
372 ast::StructVariantKind(def) => {
373 let idx = encode_info_for_struct(ecx, ebml_w, path,
375 encode_struct_fields(ecx, ebml_w, def);
376 let bkts = create_index(idx);
377 encode_index(ebml_w, bkts, write_i64);
380 if vi[i].disr_val != disr_val {
381 encode_disr_val(ecx, ebml_w, vi[i].disr_val);
382 disr_val = vi[i].disr_val;
384 encode_bounds_and_type(ebml_w, ecx,
385 &lookup_item_type(ecx.tcx, def_id));
386 encode_path(ecx, ebml_w, path,
387 ast_map::PathName(variant.node.name));
394 fn encode_path(ecx: &EncodeContext,
395 ebml_w: &mut writer::Encoder,
396 path: &[ast_map::PathElem],
397 name: ast_map::PathElem) {
398 fn encode_path_elem(ecx: &EncodeContext,
399 ebml_w: &mut writer::Encoder,
400 elt: ast_map::PathElem) {
402 ast_map::PathMod(n) => {
403 ebml_w.wr_tagged_str(tag_path_elem_mod, ecx.tcx.sess.str_of(n));
405 ast_map::PathName(n) => {
406 ebml_w.wr_tagged_str(tag_path_elem_name, ecx.tcx.sess.str_of(n));
408 ast_map::PathPrettyName(n, extra) => {
409 ebml_w.start_tag(tag_path_elem_pretty_name);
410 ebml_w.wr_tagged_str(tag_path_elem_pretty_name_ident,
411 ecx.tcx.sess.str_of(n));
412 ebml_w.wr_tagged_u64(tag_path_elem_pretty_name_extra, extra);
418 ebml_w.start_tag(tag_path);
419 ebml_w.wr_tagged_u32(tag_path_len, (path.len() + 1) as u32);
420 for pe in path.iter() {
421 encode_path_elem(ecx, ebml_w, *pe);
423 encode_path_elem(ecx, ebml_w, name);
427 fn encode_reexported_static_method(ecx: &EncodeContext,
428 ebml_w: &mut writer::Encoder,
429 exp: &middle::resolve::Export2,
430 method_def_id: DefId,
431 method_ident: Ident) {
432 debug!("(encode reexported static method) {}::{}",
433 exp.name, ecx.tcx.sess.str_of(method_ident));
434 ebml_w.start_tag(tag_items_data_item_reexport);
435 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
436 ebml_w.wr_str(def_to_str(method_def_id));
438 ebml_w.start_tag(tag_items_data_item_reexport_name);
439 ebml_w.wr_str(format!("{}::{}", exp.name, ecx.tcx.sess.str_of(method_ident)));
444 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
445 ebml_w: &mut writer::Encoder,
446 exp: &middle::resolve::Export2)
448 let inherent_impls = ecx.tcx.inherent_impls.borrow();
449 match inherent_impls.get().find(&exp.def_id) {
450 Some(implementations) => {
451 let implementations = implementations.borrow();
452 for &base_impl in implementations.get().iter() {
453 for &m in base_impl.methods.iter() {
454 if m.explicit_self == ast::SelfStatic {
455 encode_reexported_static_method(ecx, ebml_w, exp,
467 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
468 ebml_w: &mut writer::Encoder,
469 exp: &middle::resolve::Export2)
471 let trait_methods_cache = ecx.tcx.trait_methods_cache.borrow();
472 match trait_methods_cache.get().find(&exp.def_id) {
474 for &m in methods.iter() {
475 if m.explicit_self == ast::SelfStatic {
476 encode_reexported_static_method(ecx, ebml_w, exp,
487 fn encode_reexported_static_methods(ecx: &EncodeContext,
488 ebml_w: &mut writer::Encoder,
489 mod_path: &[ast_map::PathElem],
490 exp: &middle::resolve::Export2) {
491 match ecx.tcx.items.find(exp.def_id.node) {
492 Some(ast_map::NodeItem(item, path)) => {
493 let original_name = token::get_ident(item.ident.name);
496 // We don't need to reexport static methods on items
497 // declared in the same module as our `pub use ...` since
498 // that's done when we encode the item itself.
500 // The only exception is when the reexport *changes* the
501 // name e.g. `pub use Foo = self::Bar` -- we have
502 // encoded metadata for static methods relative to Bar,
503 // but not yet for Foo.
505 if mod_path != *path || original_name.get() != exp.name {
506 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
507 if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
508 debug!("(encode reexported static methods) {} \
514 debug!("(encode reexported static methods) {} [base]",
523 /// Iterates through "auxiliary node IDs", which are node IDs that describe
524 /// top-level items that are sub-items of the given item. Specifically:
526 /// * For enums, iterates through the node IDs of the variants.
528 /// * For newtype structs, iterates through the node ID of the constructor.
529 fn each_auxiliary_node_id(item: @Item, callback: |NodeId| -> bool) -> bool {
530 let mut continue_ = true;
532 ItemEnum(ref enum_def, _) => {
533 for variant in enum_def.variants.iter() {
534 continue_ = callback(variant.node.id);
540 ItemStruct(struct_def, _) => {
541 // If this is a newtype struct, return the constructor.
542 match struct_def.ctor_id {
543 Some(ctor_id) if struct_def.fields.len() > 0 &&
544 struct_def.fields[0].node.kind ==
545 ast::UnnamedField => {
546 continue_ = callback(ctor_id);
557 fn encode_reexports(ecx: &EncodeContext,
558 ebml_w: &mut writer::Encoder,
560 path: &[ast_map::PathElem]) {
561 debug!("(encoding info for module) encoding reexports for {}", id);
562 let reexports2 = ecx.reexports2.borrow();
563 match reexports2.get().find(&id) {
564 Some(ref exports) => {
565 debug!("(encoding info for module) found reexports for {}", id);
566 for exp in exports.iter() {
567 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
573 ebml_w.start_tag(tag_items_data_item_reexport);
574 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
575 ebml_w.wr_str(def_to_str(exp.def_id));
577 ebml_w.start_tag(tag_items_data_item_reexport_name);
578 ebml_w.wr_str(exp.name);
581 encode_reexported_static_methods(ecx, ebml_w, path, exp);
585 debug!("(encoding info for module) found no reexports for {}",
591 fn encode_info_for_mod(ecx: &EncodeContext,
592 ebml_w: &mut writer::Encoder,
595 path: &[ast_map::PathElem],
598 ebml_w.start_tag(tag_items_data_item);
599 encode_def_id(ebml_w, local_def(id));
600 encode_family(ebml_w, 'm');
601 encode_name(ecx, ebml_w, name);
602 debug!("(encoding info for module) encoding info for module ID {}", id);
604 // Encode info about all the module children.
605 for item in md.items.iter() {
606 ebml_w.start_tag(tag_mod_child);
607 ebml_w.wr_str(def_to_str(local_def(item.id)));
610 each_auxiliary_node_id(*item, |auxiliary_node_id| {
611 ebml_w.start_tag(tag_mod_child);
612 ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
619 let (ident, did) = (item.ident, item.id);
620 debug!("(encoding info for module) ... encoding impl {} \
622 ecx.tcx.sess.str_of(ident),
624 ast_map::node_id_to_str(ecx.tcx.items, did, token::get_ident_interner()));
626 ebml_w.start_tag(tag_mod_impl);
627 ebml_w.wr_str(def_to_str(local_def(did)));
634 encode_path(ecx, ebml_w, path, ast_map::PathMod(name));
635 encode_visibility(ebml_w, vis);
637 // Encode the reexports of this module, if this module is public.
639 debug!("(encoding info for module) encoding reexports for {}", id);
640 encode_reexports(ecx, ebml_w, id, path);
646 fn encode_struct_field_family(ebml_w: &mut writer::Encoder,
647 visibility: Visibility) {
648 encode_family(ebml_w, match visibility {
655 fn encode_visibility(ebml_w: &mut writer::Encoder, visibility: Visibility) {
656 ebml_w.start_tag(tag_items_data_item_visibility);
657 let ch = match visibility {
662 ebml_w.wr_str(str::from_char(ch));
666 fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::ExplicitSelf_) {
667 ebml_w.start_tag(tag_item_trait_method_explicit_self);
669 // Encode the base self type.
670 match explicit_self {
671 SelfStatic => ebml_w.writer.write(&[ 's' as u8 ]),
672 SelfValue => ebml_w.writer.write(&[ 'v' as u8 ]),
673 SelfBox => ebml_w.writer.write(&[ '@' as u8 ]),
674 SelfUniq => ebml_w.writer.write(&[ '~' as u8 ]),
675 SelfRegion(_, m) => {
676 // FIXME(#4846) encode custom lifetime
677 ebml_w.writer.write(&['&' as u8]);
678 encode_mutability(ebml_w, m);
684 fn encode_mutability(ebml_w: &writer::Encoder,
685 m: ast::Mutability) {
687 MutImmutable => ebml_w.writer.write(&[ 'i' as u8 ]),
688 MutMutable => ebml_w.writer.write(&[ 'm' as u8 ]),
693 fn encode_method_sort(ebml_w: &mut writer::Encoder, sort: char) {
694 ebml_w.start_tag(tag_item_trait_method_sort);
695 ebml_w.writer.write(&[ sort as u8 ]);
699 fn encode_provided_source(ebml_w: &mut writer::Encoder,
700 source_opt: Option<DefId>) {
701 for source in source_opt.iter() {
702 ebml_w.start_tag(tag_item_method_provided_source);
703 let s = def_to_str(*source);
704 ebml_w.writer.write(s.as_bytes());
709 /* Returns an index of items in this class */
710 fn encode_info_for_struct(ecx: &EncodeContext,
711 ebml_w: &mut writer::Encoder,
712 path: &[ast_map::PathElem],
713 fields: &[StructField],
714 global_index: @RefCell<~[entry<i64>]>)
716 /* Each class has its own index, since different classes
717 may have fields with the same name */
720 /* We encode both private and public fields -- need to include
721 private fields to get the offsets right */
722 for field in fields.iter() {
723 let (nm, vis) = match field.node.kind {
724 NamedField(nm, vis) => (nm, vis),
725 UnnamedField => (special_idents::unnamed_field, Inherited)
728 let id = field.node.id;
729 index.push(entry {val: id as i64, pos: ebml_w.writer.tell()});
731 let mut global_index = global_index.borrow_mut();
732 global_index.get().push(entry {
734 pos: ebml_w.writer.tell(),
737 ebml_w.start_tag(tag_items_data_item);
738 debug!("encode_info_for_struct: doing {} {}",
739 tcx.sess.str_of(nm), id);
740 encode_struct_field_family(ebml_w, vis);
741 encode_name(ecx, ebml_w, nm);
742 encode_path(ecx, ebml_w, path, ast_map::PathName(nm));
743 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
744 encode_def_id(ebml_w, local_def(id));
750 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
751 ebml_w: &mut writer::Encoder,
752 path: &[ast_map::PathElem],
755 index: @RefCell<~[entry<i64>]>,
758 let mut index = index.borrow_mut();
759 index.get().push(entry {
761 pos: ebml_w.writer.tell(),
765 ebml_w.start_tag(tag_items_data_item);
766 encode_def_id(ebml_w, local_def(ctor_id));
767 encode_family(ebml_w, 'f');
768 encode_bounds_and_type(ebml_w, ecx,
769 &lookup_item_type(ecx.tcx, local_def(ctor_id)));
770 encode_name(ecx, ebml_w, name);
771 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
772 encode_path(ecx, ebml_w, path, ast_map::PathName(name));
773 encode_parent_item(ebml_w, local_def(struct_id));
775 let item_symbols = ecx.item_symbols.borrow();
776 if item_symbols.get().contains_key(&ctor_id) {
777 encode_symbol(ecx, ebml_w, ctor_id);
783 fn encode_method_ty_fields(ecx: &EncodeContext,
784 ebml_w: &mut writer::Encoder,
785 method_ty: &ty::Method) {
786 encode_def_id(ebml_w, method_ty.def_id);
787 encode_name(ecx, ebml_w, method_ty.ident);
788 encode_ty_type_param_defs(ebml_w, ecx,
789 method_ty.generics.type_param_defs,
790 tag_item_method_tps);
791 encode_method_fty(ecx, ebml_w, &method_ty.fty);
792 encode_visibility(ebml_w, method_ty.vis);
793 encode_explicit_self(ebml_w, method_ty.explicit_self);
794 let purity = method_ty.fty.purity;
795 match method_ty.explicit_self {
797 encode_family(ebml_w, purity_static_method_family(purity));
799 _ => encode_family(ebml_w, purity_fn_family(purity))
801 encode_provided_source(ebml_w, method_ty.provided_source);
804 fn encode_info_for_method(ecx: &EncodeContext,
805 ebml_w: &mut writer::Encoder,
807 impl_path: &[ast_map::PathElem],
808 is_default_impl: bool,
810 ast_method_opt: Option<@Method>) {
812 debug!("encode_info_for_method: {:?} {}", m.def_id,
813 ecx.tcx.sess.str_of(m.ident));
814 ebml_w.start_tag(tag_items_data_item);
816 encode_method_ty_fields(ecx, ebml_w, m);
817 encode_parent_item(ebml_w, local_def(parent_id));
819 // The type for methods gets encoded twice, which is unfortunate.
820 let tpt = lookup_item_type(ecx.tcx, m.def_id);
821 encode_bounds_and_type(ebml_w, ecx, &tpt);
823 encode_path(ecx, ebml_w, impl_path, ast_map::PathName(m.ident));
824 match ast_method_opt {
825 Some(ast_method) => encode_attributes(ebml_w, ast_method.attrs),
829 for &ast_method in ast_method_opt.iter() {
830 let num_params = tpt.generics.type_param_defs.len();
831 if num_params > 0u || is_default_impl
832 || should_inline(ast_method.attrs) {
833 (ecx.encode_inlined_item)(
834 ecx, ebml_w, impl_path,
835 IIMethodRef(local_def(parent_id), false, ast_method));
837 encode_symbol(ecx, ebml_w, m.def_id.node);
844 fn purity_fn_family(p: Purity) -> char {
852 fn purity_static_method_family(p: Purity) -> char {
856 _ => fail!("extern fn can't be static")
861 fn should_inline(attrs: &[Attribute]) -> bool {
863 match find_inline_attr(attrs) {
864 InlineNone | InlineNever => false,
865 InlineHint | InlineAlways => true
869 // Encodes the inherent implementations of a structure, enumeration, or trait.
870 fn encode_inherent_implementations(ecx: &EncodeContext,
871 ebml_w: &mut writer::Encoder,
873 let inherent_impls = ecx.tcx.inherent_impls.borrow();
874 match inherent_impls.get().find(&def_id) {
876 Some(&implementations) => {
877 let implementations = implementations.borrow();
878 for implementation in implementations.get().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 let trait_impls = ecx.tcx.trait_impls.borrow();
892 match trait_impls.get().find(&trait_def_id) {
894 Some(&implementations) => {
895 let implementations = implementations.borrow();
896 for implementation in implementations.get().iter() {
897 ebml_w.start_tag(tag_items_data_item_extension_impl);
898 encode_def_id(ebml_w, implementation.did);
905 fn encode_info_for_item(ecx: &EncodeContext,
906 ebml_w: &mut writer::Encoder,
908 index: @RefCell<~[entry<i64>]>,
909 path: &[ast_map::PathElem],
910 vis: ast::Visibility) {
913 fn add_to_index(item: &Item, ebml_w: &writer::Encoder,
914 index: @RefCell<~[entry<i64>]>) {
915 let mut index = index.borrow_mut();
916 index.get().push(entry {
918 pos: ebml_w.writer.tell(),
921 let add_to_index: || = || add_to_index(item, ebml_w, index);
923 debug!("encoding info for item at {}",
924 ecx.tcx.sess.codemap.span_to_str(item.span));
926 let def_id = local_def(item.id);
928 ItemStatic(_, m, _) => {
930 ebml_w.start_tag(tag_items_data_item);
931 encode_def_id(ebml_w, def_id);
932 if m == ast::MutMutable {
933 encode_family(ebml_w, 'b');
935 encode_family(ebml_w, 'c');
937 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
938 encode_symbol(ecx, ebml_w, item.id);
939 encode_name(ecx, ebml_w, item.ident);
940 let elt = ast_map::PathPrettyName(item.ident, item.id as u64);
941 encode_path(ecx, ebml_w, path, elt);
945 let non_inlineable_statics = ecx.non_inlineable_statics.borrow();
946 non_inlineable = non_inlineable_statics.get().contains(&item.id);
950 (ecx.encode_inlined_item)(ecx, ebml_w, path, IIItemRef(item));
952 encode_visibility(ebml_w, vis);
955 ItemFn(_, purity, _, ref generics, _) => {
957 ebml_w.start_tag(tag_items_data_item);
958 encode_def_id(ebml_w, def_id);
959 encode_family(ebml_w, purity_fn_family(purity));
960 let tps_len = generics.ty_params.len();
961 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
962 encode_name(ecx, ebml_w, item.ident);
963 encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
964 encode_attributes(ebml_w, item.attrs);
965 if tps_len > 0u || should_inline(item.attrs) {
966 (ecx.encode_inlined_item)(ecx, ebml_w, path, IIItemRef(item));
968 encode_symbol(ecx, ebml_w, item.id);
970 encode_visibility(ebml_w, vis);
975 encode_info_for_mod(ecx,
983 ItemForeignMod(ref fm) => {
985 ebml_w.start_tag(tag_items_data_item);
986 encode_def_id(ebml_w, def_id);
987 encode_family(ebml_w, 'n');
988 encode_name(ecx, ebml_w, item.ident);
989 encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
991 // Encode all the items in this module.
992 for foreign_item in fm.items.iter() {
993 ebml_w.start_tag(tag_mod_child);
994 ebml_w.wr_str(def_to_str(local_def(foreign_item.id)));
997 encode_visibility(ebml_w, vis);
1002 ebml_w.start_tag(tag_items_data_item);
1003 encode_def_id(ebml_w, def_id);
1004 encode_family(ebml_w, 'y');
1005 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1006 encode_name(ecx, ebml_w, item.ident);
1007 encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
1008 encode_visibility(ebml_w, vis);
1011 ItemEnum(ref enum_definition, ref generics) => {
1014 ebml_w.start_tag(tag_items_data_item);
1015 encode_def_id(ebml_w, def_id);
1016 encode_family(ebml_w, 't');
1017 encode_item_variances(ebml_w, ecx, item.id);
1018 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1019 encode_name(ecx, ebml_w, item.ident);
1020 encode_attributes(ebml_w, item.attrs);
1021 for v in (*enum_definition).variants.iter() {
1022 encode_variant_id(ebml_w, local_def(v.node.id));
1024 (ecx.encode_inlined_item)(ecx, ebml_w, path, IIItemRef(item));
1025 encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
1027 // Encode inherent implementations for this enumeration.
1028 encode_inherent_implementations(ecx, ebml_w, def_id);
1030 encode_visibility(ebml_w, vis);
1033 encode_enum_variant_info(ecx,
1036 (*enum_definition).variants,
1041 ItemStruct(struct_def, _) => {
1042 /* First, encode the fields
1043 These come first because we need to write them to make
1044 the index, and the index needs to be in the item for the
1046 let idx = encode_info_for_struct(ecx, ebml_w, path,
1047 struct_def.fields, index);
1049 /* Index the class*/
1052 /* Now, make an item for the class itself */
1053 ebml_w.start_tag(tag_items_data_item);
1054 encode_def_id(ebml_w, def_id);
1055 encode_family(ebml_w, 'S');
1056 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1058 encode_item_variances(ebml_w, ecx, item.id);
1059 encode_name(ecx, ebml_w, item.ident);
1060 encode_attributes(ebml_w, item.attrs);
1061 encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
1062 encode_visibility(ebml_w, vis);
1064 /* Encode def_ids for each field and method
1065 for methods, write all the stuff get_trait_method
1067 encode_struct_fields(ecx, ebml_w, struct_def);
1069 (ecx.encode_inlined_item)(ecx, ebml_w, path, IIItemRef(item));
1071 // Encode inherent implementations for this structure.
1072 encode_inherent_implementations(ecx, ebml_w, def_id);
1074 /* Each class has its own index -- encode it */
1075 let bkts = create_index(idx);
1076 encode_index(ebml_w, bkts, write_i64);
1079 // If this is a tuple- or enum-like struct, encode the type of the
1081 if struct_def.fields.len() > 0 &&
1082 struct_def.fields[0].node.kind == ast::UnnamedField {
1083 let ctor_id = match struct_def.ctor_id {
1084 Some(ctor_id) => ctor_id,
1085 None => ecx.tcx.sess.bug("struct def didn't have ctor id"),
1088 encode_info_for_struct_ctor(ecx,
1097 ItemImpl(_, ref opt_trait, ty, ref ast_methods) => {
1098 // We need to encode information about the default methods we
1099 // have inherited, so we drive this based on the impl structure.
1100 let impls = tcx.impls.borrow();
1101 let imp = impls.get().get(&def_id);
1104 ebml_w.start_tag(tag_items_data_item);
1105 encode_def_id(ebml_w, def_id);
1106 encode_family(ebml_w, 'i');
1107 encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1108 encode_name(ecx, ebml_w, item.ident);
1109 encode_attributes(ebml_w, item.attrs);
1111 ast::TyPath(ref path, ref bounds, _) if path.segments
1113 assert!(bounds.is_none());
1114 encode_impl_type_basename(ecx, ebml_w,
1115 ast_util::path_to_ident(path));
1119 for method in imp.methods.iter() {
1120 ebml_w.start_tag(tag_item_impl_method);
1121 let s = def_to_str(method.def_id);
1122 ebml_w.writer.write(s.as_bytes());
1125 for ast_trait_ref in opt_trait.iter() {
1126 let trait_ref = ty::node_id_to_trait_ref(
1127 tcx, ast_trait_ref.ref_id);
1128 encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
1129 let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1130 encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1132 let elt = ast_map::impl_pretty_name(opt_trait, ty);
1133 encode_path(ecx, ebml_w, path, elt);
1137 let mut impl_path = vec::append(~[], path);
1138 impl_path.push(elt);
1140 // Iterate down the methods, emitting them. We rely on the
1141 // assumption that all of the actually implemented methods
1142 // appear first in the impl structure, in the same order they do
1143 // in the ast. This is a little sketchy.
1144 let num_implemented_methods = ast_methods.len();
1145 for (i, m) in imp.methods.iter().enumerate() {
1146 let ast_method = if i < num_implemented_methods {
1147 Some(ast_methods[i])
1151 let mut index = index.borrow_mut();
1152 index.get().push(entry {
1153 val: m.def_id.node as i64,
1154 pos: ebml_w.writer.tell(),
1157 encode_info_for_method(ecx,
1166 ItemTrait(_, ref super_traits, ref ms) => {
1168 ebml_w.start_tag(tag_items_data_item);
1169 encode_def_id(ebml_w, def_id);
1170 encode_family(ebml_w, 'I');
1171 encode_item_variances(ebml_w, ecx, item.id);
1172 let trait_def = ty::lookup_trait_def(tcx, def_id);
1173 encode_ty_type_param_defs(ebml_w, ecx,
1174 trait_def.generics.type_param_defs,
1175 tag_items_data_item_ty_param_bounds);
1176 encode_region_param_defs(ebml_w, ecx,
1177 trait_def.generics.region_param_defs);
1178 encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
1179 encode_name(ecx, ebml_w, item.ident);
1180 encode_attributes(ebml_w, item.attrs);
1181 encode_visibility(ebml_w, vis);
1182 for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1183 ebml_w.start_tag(tag_item_trait_method);
1184 encode_def_id(ebml_w, method_def_id);
1187 ebml_w.start_tag(tag_mod_child);
1188 ebml_w.wr_str(def_to_str(method_def_id));
1191 encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
1192 // FIXME(#8559): This should use the tcx's supertrait cache instead of
1193 // reading the AST's list, because the former has already filtered out
1194 // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1195 for ast_trait_ref in super_traits.iter() {
1196 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1197 encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
1200 // Encode the implementations of this trait.
1201 encode_extension_implementations(ecx, ebml_w, def_id);
1205 // Now output the method info for each method.
1206 let r = ty::trait_method_def_ids(tcx, def_id);
1207 for (i, &method_def_id) in r.iter().enumerate() {
1208 assert_eq!(method_def_id.crate, ast::LOCAL_CRATE);
1210 let method_ty = ty::method(tcx, method_def_id);
1213 let mut index = index.borrow_mut();
1214 index.get().push(entry {
1215 val: method_def_id.node as i64,
1216 pos: ebml_w.writer.tell(),
1220 ebml_w.start_tag(tag_items_data_item);
1222 encode_method_ty_fields(ecx, ebml_w, method_ty);
1224 encode_parent_item(ebml_w, def_id);
1226 let mut trait_path = vec::append(~[], path);
1227 trait_path.push(ast_map::PathName(item.ident));
1228 encode_path(ecx, ebml_w, trait_path, ast_map::PathName(method_ty.ident));
1230 match method_ty.explicit_self {
1232 encode_family(ebml_w,
1233 purity_static_method_family(
1234 method_ty.fty.purity));
1236 let tpt = ty::lookup_item_type(tcx, method_def_id);
1237 encode_bounds_and_type(ebml_w, ecx, &tpt);
1241 encode_family(ebml_w,
1243 method_ty.fty.purity));
1248 Required(ref tm) => {
1249 encode_attributes(ebml_w, tm.attrs);
1250 encode_method_sort(ebml_w, 'r');
1254 encode_attributes(ebml_w, m.attrs);
1255 // If this is a static method, we've already encoded
1257 if method_ty.explicit_self != SelfStatic {
1258 // FIXME: I feel like there is something funny going on.
1259 let tpt = ty::lookup_item_type(tcx, method_def_id);
1260 encode_bounds_and_type(ebml_w, ecx, &tpt);
1262 encode_method_sort(ebml_w, 'p');
1263 (ecx.encode_inlined_item)(
1265 IIMethodRef(def_id, true, m));
1272 // Encode inherent implementations for this trait.
1273 encode_inherent_implementations(ecx, ebml_w, def_id);
1276 // macros are encoded separately
1281 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1282 ebml_w: &mut writer::Encoder,
1283 nitem: &ForeignItem,
1284 index: @RefCell<~[entry<i64>]>,
1285 path: &ast_map::Path,
1288 let mut index = index.borrow_mut();
1289 index.get().push(entry {
1290 val: nitem.id as i64,
1291 pos: ebml_w.writer.tell(),
1295 ebml_w.start_tag(tag_items_data_item);
1297 ForeignItemFn(..) => {
1298 encode_def_id(ebml_w, local_def(nitem.id));
1299 encode_family(ebml_w, purity_fn_family(ImpureFn));
1300 encode_bounds_and_type(ebml_w, ecx,
1301 &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1302 encode_name(ecx, ebml_w, nitem.ident);
1303 if abi.is_intrinsic() {
1304 (ecx.encode_inlined_item)(ecx, ebml_w, *path, IIForeignRef(nitem));
1306 encode_symbol(ecx, ebml_w, nitem.id);
1308 encode_path(ecx, ebml_w, *path, ast_map::PathName(nitem.ident));
1310 ForeignItemStatic(_, mutbl) => {
1311 encode_def_id(ebml_w, local_def(nitem.id));
1313 encode_family(ebml_w, 'b');
1315 encode_family(ebml_w, 'c');
1317 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1318 encode_symbol(ecx, ebml_w, nitem.id);
1319 encode_name(ecx, ebml_w, nitem.ident);
1320 encode_path(ecx, ebml_w, *path, ast_map::PathName(nitem.ident));
1326 fn my_visit_expr(_e: &Expr) { }
1328 fn my_visit_item(i: &Item,
1329 items: ast_map::Map,
1330 ebml_w: &mut writer::Encoder,
1332 index: @RefCell<~[entry<i64>]>) {
1333 match items.get(i.id) {
1334 ast_map::NodeItem(_, pt) => {
1335 let mut ebml_w = unsafe {
1336 ebml_w.unsafe_clone()
1339 let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1340 encode_info_for_item(ecx, &mut ebml_w, i, index, *pt, i.vis);
1342 _ => fail!("bad item")
1346 fn my_visit_foreign_item(ni: &ForeignItem,
1347 items: ast_map::Map,
1348 ebml_w: &mut writer::Encoder,
1350 index: @RefCell<~[entry<i64>]>) {
1351 match items.get(ni.id) {
1352 ast_map::NodeForeignItem(_, abi, _, pt) => {
1353 let string = token::get_ident(ni.ident.name);
1354 debug!("writing foreign item {}::{}",
1355 ast_map::path_to_str(*pt, token::get_ident_interner()),
1358 let mut ebml_w = unsafe {
1359 ebml_w.unsafe_clone()
1362 let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1363 encode_info_for_foreign_item(ecx,
1370 // case for separate item and foreign-item tables
1371 _ => fail!("bad foreign item")
1375 struct EncodeVisitor<'a,'b> {
1376 ebml_w_for_visit_item: &'a mut writer::Encoder<'b>,
1378 items: ast_map::Map,
1379 index: @RefCell<~[entry<i64>]>,
1382 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1383 fn visit_expr(&mut self, ex: &Expr, _: ()) {
1384 visit::walk_expr(self, ex, ());
1387 fn visit_item(&mut self, i: &Item, _: ()) {
1388 visit::walk_item(self, i, ());
1391 self.ebml_w_for_visit_item,
1395 fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1396 visit::walk_foreign_item(self, ni, ());
1397 my_visit_foreign_item(ni,
1399 self.ebml_w_for_visit_item,
1405 fn encode_info_for_items(ecx: &EncodeContext,
1406 ebml_w: &mut writer::Encoder,
1409 let index = @RefCell::new(~[]);
1410 ebml_w.start_tag(tag_items_data);
1412 let mut index = index.borrow_mut();
1413 index.get().push(entry {
1414 val: CRATE_NODE_ID as i64,
1415 pos: ebml_w.writer.tell(),
1418 encode_info_for_mod(ecx,
1423 syntax::parse::token::special_idents::invalid,
1425 let items = ecx.tcx.items;
1427 // See comment in `encode_side_tables_for_ii` in astencode
1428 let ecx_ptr : *int = unsafe { cast::transmute(ecx) };
1430 let mut visitor = EncodeVisitor {
1434 ebml_w_for_visit_item: &mut *ebml_w,
1437 visit::walk_crate(&mut visitor, crate, ());
1441 return /*bad*/(*index).get();
1445 // Path and definition ID indexing
1447 fn create_index<T:Clone + Hash + IterBytes + 'static>(
1449 -> ~[@~[entry<T>]] {
1450 let mut buckets: ~[@RefCell<~[entry<T>]>] = ~[];
1451 for _ in range(0u, 256u) {
1452 buckets.push(@RefCell::new(~[]));
1454 for elt in index.iter() {
1455 let h = elt.val.hash() as uint;
1456 let mut bucket = buckets[h % 256].borrow_mut();
1457 bucket.get().push((*elt).clone());
1460 let mut buckets_frozen = ~[];
1461 for bucket in buckets.iter() {
1462 buckets_frozen.push(@/*bad*/(**bucket).get());
1464 return buckets_frozen;
1467 fn encode_index<T:'static>(
1468 ebml_w: &mut writer::Encoder,
1469 buckets: ~[@~[entry<T>]],
1470 write_fn: |&mut MemWriter, &T|) {
1471 ebml_w.start_tag(tag_index);
1472 let mut bucket_locs = ~[];
1473 ebml_w.start_tag(tag_index_buckets);
1474 for bucket in buckets.iter() {
1475 bucket_locs.push(ebml_w.writer.tell());
1476 ebml_w.start_tag(tag_index_buckets_bucket);
1477 for elt in (**bucket).iter() {
1478 ebml_w.start_tag(tag_index_buckets_bucket_elt);
1479 assert!(elt.pos < 0xffff_ffff);
1481 let wr: &mut MemWriter = ebml_w.writer;
1482 wr.write_be_u32(elt.pos as u32);
1484 write_fn(ebml_w.writer, &elt.val);
1490 ebml_w.start_tag(tag_index_table);
1491 for pos in bucket_locs.iter() {
1492 assert!(*pos < 0xffff_ffff);
1493 let wr: &mut MemWriter = ebml_w.writer;
1494 wr.write_be_u32(*pos as u32);
1500 fn write_i64(writer: &mut MemWriter, &n: &i64) {
1501 let wr: &mut MemWriter = writer;
1502 assert!(n < 0x7fff_ffff);
1503 wr.write_be_u32(n as u32);
1506 fn encode_meta_item(ebml_w: &mut writer::Encoder, mi: @MetaItem) {
1508 MetaWord(ref name) => {
1509 ebml_w.start_tag(tag_meta_item_word);
1510 ebml_w.start_tag(tag_meta_item_name);
1511 ebml_w.writer.write(name.get().as_bytes());
1515 MetaNameValue(ref name, ref value) => {
1517 LitStr(ref value, _) => {
1518 ebml_w.start_tag(tag_meta_item_name_value);
1519 ebml_w.start_tag(tag_meta_item_name);
1520 ebml_w.writer.write(name.get().as_bytes());
1522 ebml_w.start_tag(tag_meta_item_value);
1523 ebml_w.writer.write(value.get().as_bytes());
1527 _ => {/* FIXME (#623): encode other variants */ }
1530 MetaList(ref name, ref items) => {
1531 ebml_w.start_tag(tag_meta_item_list);
1532 ebml_w.start_tag(tag_meta_item_name);
1533 ebml_w.writer.write(name.get().as_bytes());
1535 for inner_item in items.iter() {
1536 encode_meta_item(ebml_w, *inner_item);
1543 fn encode_attributes(ebml_w: &mut writer::Encoder, attrs: &[Attribute]) {
1544 ebml_w.start_tag(tag_attributes);
1545 for attr in attrs.iter() {
1546 ebml_w.start_tag(tag_attribute);
1547 encode_meta_item(ebml_w, attr.node.value);
1553 // So there's a special crate attribute called 'crate_id' which defines the
1554 // metadata that Rust cares about for linking crates. If the user didn't
1555 // provide it we will throw it in anyway with a default value.
1556 fn synthesize_crate_attrs(ecx: &EncodeContext,
1557 crate: &Crate) -> ~[Attribute] {
1559 fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute {
1560 assert!(!ecx.link_meta.crateid.name.is_empty());
1563 attr::mk_name_value_item_str(
1564 InternedString::new("crate_id"),
1565 token::intern_and_get_ident(ecx.link_meta.crateid.to_str())))
1568 let mut attrs = ~[];
1569 for attr in crate.attrs.iter() {
1570 if !attr.name().equiv(&("crate_id")) {
1574 attrs.push(synthesize_crateid_attr(ecx));
1579 fn encode_crate_deps(ecx: &EncodeContext,
1580 ebml_w: &mut writer::Encoder,
1581 cstore: &cstore::CStore) {
1582 fn get_ordered_deps(ecx: &EncodeContext, cstore: &cstore::CStore)
1583 -> ~[decoder::CrateDep] {
1584 type numdep = decoder::CrateDep;
1586 // Pull the cnums and name,vers,hash out of cstore
1588 cstore.iter_crate_data(|key, val| {
1589 let dep = decoder::CrateDep {cnum: key,
1590 name: ecx.tcx.sess.ident_of(val.name),
1591 vers: decoder::get_crate_vers(val.data()),
1592 hash: decoder::get_crate_hash(val.data())};
1597 deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1599 // Sanity-check the crate numbers
1600 let mut expected_cnum = 1;
1601 for n in deps.iter() {
1602 assert_eq!(n.cnum, expected_cnum);
1609 // We're just going to write a list of crate 'name-hash-version's, with
1610 // the assumption that they are numbered 1 to n.
1611 // FIXME (#2166): This is not nearly enough to support correct versioning
1612 // but is enough to get transitive crate dependencies working.
1613 ebml_w.start_tag(tag_crate_deps);
1614 let r = get_ordered_deps(ecx, cstore);
1615 for dep in r.iter() {
1616 encode_crate_dep(ecx, ebml_w, (*dep).clone());
1621 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1622 ebml_w.start_tag(tag_lang_items);
1624 for (i, def_id) in ecx.tcx.lang_items.items() {
1625 for id in def_id.iter() {
1626 if id.crate == LOCAL_CRATE {
1627 ebml_w.start_tag(tag_lang_items_item);
1629 ebml_w.start_tag(tag_lang_items_item_id);
1631 let wr: &mut MemWriter = ebml_w.writer;
1632 wr.write_be_u32(i as u32);
1634 ebml_w.end_tag(); // tag_lang_items_item_id
1636 ebml_w.start_tag(tag_lang_items_item_node_id);
1638 let wr: &mut MemWriter = ebml_w.writer;
1639 wr.write_be_u32(id.node as u32);
1641 ebml_w.end_tag(); // tag_lang_items_item_node_id
1643 ebml_w.end_tag(); // tag_lang_items_item
1648 ebml_w.end_tag(); // tag_lang_items
1651 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1652 ebml_w.start_tag(tag_native_libraries);
1654 let used_libraries = ecx.tcx.sess.cstore.get_used_libraries();
1655 let used_libraries = used_libraries.borrow();
1656 for &(ref lib, kind) in used_libraries.get().iter() {
1658 cstore::NativeStatic => {} // these libraries are not propagated
1659 cstore::NativeFramework | cstore::NativeUnknown => {
1660 ebml_w.start_tag(tag_native_libraries_lib);
1662 ebml_w.start_tag(tag_native_libraries_kind);
1663 ebml_w.writer.write_be_u32(kind as u32);
1666 ebml_w.start_tag(tag_native_libraries_name);
1667 ebml_w.writer.write(lib.as_bytes());
1678 fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1679 let ptr = ecx.tcx.sess.macro_registrar_fn.borrow();
1682 ebml_w.start_tag(tag_macro_registrar_fn);
1683 encode_def_id(ebml_w, did);
1690 struct MacroDefVisitor<'a, 'b> {
1691 ecx: &'a EncodeContext<'a>,
1692 ebml_w: &'a mut writer::Encoder<'b>
1695 impl<'a, 'b> Visitor<()> for MacroDefVisitor<'a, 'b> {
1696 fn visit_item(&mut self, item: &Item, _: ()) {
1699 let def = self.ecx.codemap.span_to_snippet(item.span)
1700 .expect("Unable to find source for macro");
1701 self.ebml_w.start_tag(tag_macro_def);
1702 self.ebml_w.wr_str(def);
1703 self.ebml_w.end_tag();
1707 visit::walk_item(self, item, ());
1711 fn encode_macro_defs(ecx: &EncodeContext,
1713 ebml_w: &mut writer::Encoder) {
1714 ebml_w.start_tag(tag_exported_macros);
1716 let mut visitor = MacroDefVisitor {
1720 visit::walk_crate(&mut visitor, crate, ());
1725 struct ImplVisitor<'a,'b> {
1726 ecx: &'a EncodeContext<'a>,
1727 ebml_w: &'a mut writer::Encoder<'b>,
1730 impl<'a,'b> Visitor<()> for ImplVisitor<'a,'b> {
1731 fn visit_item(&mut self, item: &Item, _: ()) {
1733 ItemImpl(_, Some(ref trait_ref), _, _) => {
1734 let def_map = self.ecx.tcx.def_map;
1735 let def_map = def_map.borrow();
1736 let trait_def = def_map.get().get_copy(&trait_ref.ref_id);
1737 let def_id = ast_util::def_id_of_def(trait_def);
1739 // Load eagerly if this is an implementation of the Drop trait
1740 // or if the trait is not defined in this crate.
1741 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1742 def_id.crate != LOCAL_CRATE {
1743 self.ebml_w.start_tag(tag_impls_impl);
1744 encode_def_id(self.ebml_w, local_def(item.id));
1745 self.ebml_w.end_tag();
1750 visit::walk_item(self, item, ());
1754 /// Encodes implementations that are eagerly loaded.
1756 /// None of this is necessary in theory; we can load all implementations
1757 /// lazily. However, in two cases the optimizations to lazily load
1758 /// implementations are not yet implemented. These two cases, which require us
1759 /// to load implementations eagerly, are:
1761 /// * Destructors (implementations of the Drop trait).
1763 /// * Implementations of traits not defined in this crate.
1764 fn encode_impls(ecx: &EncodeContext,
1766 ebml_w: &mut writer::Encoder) {
1767 ebml_w.start_tag(tag_impls);
1770 let mut visitor = ImplVisitor {
1774 visit::walk_crate(&mut visitor, crate, ());
1780 fn encode_misc_info(ecx: &EncodeContext,
1782 ebml_w: &mut writer::Encoder) {
1783 ebml_w.start_tag(tag_misc_info);
1784 ebml_w.start_tag(tag_misc_info_crate_items);
1785 for &item in crate.module.items.iter() {
1786 ebml_w.start_tag(tag_mod_child);
1787 ebml_w.wr_str(def_to_str(local_def(item.id)));
1790 each_auxiliary_node_id(item, |auxiliary_node_id| {
1791 ebml_w.start_tag(tag_mod_child);
1792 ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
1798 // Encode reexports for the root module.
1799 encode_reexports(ecx, ebml_w, 0, []);
1805 fn encode_crate_dep(ecx: &EncodeContext,
1806 ebml_w: &mut writer::Encoder,
1807 dep: decoder::CrateDep) {
1808 ebml_w.start_tag(tag_crate_dep);
1809 ebml_w.start_tag(tag_crate_dep_name);
1810 let s = ecx.tcx.sess.str_of(dep.name);
1811 ebml_w.writer.write(s.as_bytes());
1813 ebml_w.start_tag(tag_crate_dep_vers);
1814 ebml_w.writer.write(dep.vers.as_bytes());
1816 ebml_w.start_tag(tag_crate_dep_hash);
1817 ebml_w.writer.write(dep.hash.as_bytes());
1822 fn encode_hash(ebml_w: &mut writer::Encoder, hash: &str) {
1823 ebml_w.start_tag(tag_crate_hash);
1824 ebml_w.writer.write(hash.as_bytes());
1828 // NB: Increment this as you change the metadata encoding version.
1829 pub static metadata_encoding_version : &'static [u8] =
1830 &[0x72, //'r' as u8,
1836 pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
1837 let mut wr = MemWriter::new();
1838 encode_metadata_inner(&mut wr, parms, crate);
1842 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate) {
1844 inline_bytes: Cell::new(0),
1845 attr_bytes: Cell::new(0),
1846 dep_bytes: Cell::new(0),
1847 lang_item_bytes: Cell::new(0),
1848 native_lib_bytes: Cell::new(0),
1849 macro_registrar_fn_bytes: Cell::new(0),
1850 macro_defs_bytes: Cell::new(0),
1851 impl_bytes: Cell::new(0),
1852 misc_bytes: Cell::new(0),
1853 item_bytes: Cell::new(0),
1854 index_bytes: Cell::new(0),
1855 zero_bytes: Cell::new(0),
1856 total_bytes: Cell::new(0),
1864 encode_inlined_item,
1867 non_inlineable_statics,
1871 let type_abbrevs = @RefCell::new(HashMap::new());
1873 let ecx = EncodeContext {
1877 reexports2: reexports2,
1878 item_symbols: item_symbols,
1879 non_inlineable_statics: non_inlineable_statics,
1880 link_meta: link_meta,
1882 encode_inlined_item: encode_inlined_item,
1883 type_abbrevs: type_abbrevs,
1884 reachable: reachable,
1888 let mut ebml_w = writer::Encoder(wr);
1890 encode_hash(&mut ebml_w, ecx.link_meta.crate_hash);
1892 let mut i = ebml_w.writer.tell();
1893 let crate_attrs = synthesize_crate_attrs(&ecx, crate);
1894 encode_attributes(&mut ebml_w, crate_attrs);
1895 ecx.stats.attr_bytes.set(ebml_w.writer.tell() - i);
1897 i = ebml_w.writer.tell();
1898 encode_crate_deps(&ecx, &mut ebml_w, ecx.cstore);
1899 ecx.stats.dep_bytes.set(ebml_w.writer.tell() - i);
1901 // Encode the language items.
1902 i = ebml_w.writer.tell();
1903 encode_lang_items(&ecx, &mut ebml_w);
1904 ecx.stats.lang_item_bytes.set(ebml_w.writer.tell() - i);
1906 // Encode the native libraries used
1907 i = ebml_w.writer.tell();
1908 encode_native_libraries(&ecx, &mut ebml_w);
1909 ecx.stats.native_lib_bytes.set(ebml_w.writer.tell() - i);
1911 // Encode the macro registrar function
1912 i = ebml_w.writer.tell();
1913 encode_macro_registrar_fn(&ecx, &mut ebml_w);
1914 ecx.stats.macro_registrar_fn_bytes.set(ebml_w.writer.tell() - i);
1916 // Encode macro definitions
1917 i = ebml_w.writer.tell();
1918 encode_macro_defs(&ecx, crate, &mut ebml_w);
1919 ecx.stats.macro_defs_bytes.set(ebml_w.writer.tell() - i);
1921 // Encode the def IDs of impls, for coherence checking.
1922 i = ebml_w.writer.tell();
1923 encode_impls(&ecx, crate, &mut ebml_w);
1924 ecx.stats.impl_bytes.set(ebml_w.writer.tell() - i);
1926 // Encode miscellaneous info.
1927 i = ebml_w.writer.tell();
1928 encode_misc_info(&ecx, crate, &mut ebml_w);
1929 ecx.stats.misc_bytes.set(ebml_w.writer.tell() - i);
1931 // Encode and index the items.
1932 ebml_w.start_tag(tag_items);
1933 i = ebml_w.writer.tell();
1934 let items_index = encode_info_for_items(&ecx, &mut ebml_w, crate);
1935 ecx.stats.item_bytes.set(ebml_w.writer.tell() - i);
1937 i = ebml_w.writer.tell();
1938 let items_buckets = create_index(items_index);
1939 encode_index(&mut ebml_w, items_buckets, write_i64);
1940 ecx.stats.index_bytes.set(ebml_w.writer.tell() - i);
1943 ecx.stats.total_bytes.set(ebml_w.writer.tell());
1945 if tcx.sess.meta_stats() {
1946 for e in ebml_w.writer.get_ref().iter() {
1948 ecx.stats.zero_bytes.set(ecx.stats.zero_bytes.get() + 1);
1952 println!("metadata stats:");
1953 println!(" inline bytes: {}", ecx.stats.inline_bytes.get());
1954 println!(" attribute bytes: {}", ecx.stats.attr_bytes.get());
1955 println!(" dep bytes: {}", ecx.stats.dep_bytes.get());
1956 println!(" lang item bytes: {}", ecx.stats.lang_item_bytes.get());
1957 println!(" native bytes: {}", ecx.stats.native_lib_bytes.get());
1958 println!("macro registrar bytes: {}", ecx.stats.macro_registrar_fn_bytes.get());
1959 println!(" macro def bytes: {}", ecx.stats.macro_defs_bytes.get());
1960 println!(" impl bytes: {}", ecx.stats.impl_bytes.get());
1961 println!(" misc bytes: {}", ecx.stats.misc_bytes.get());
1962 println!(" item bytes: {}", ecx.stats.item_bytes.get());
1963 println!(" index bytes: {}", ecx.stats.index_bytes.get());
1964 println!(" zero bytes: {}", ecx.stats.zero_bytes.get());
1965 println!(" total bytes: {}", ecx.stats.total_bytes.get());
1969 // Get the encoded string for a type
1970 pub fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str {
1971 let cx = @tyencode::ctxt {
1975 abbrevs: tyencode::ac_no_abbrevs};
1976 let mut wr = MemWriter::new();
1977 tyencode::enc_ty(&mut wr, cx, t);
1978 str::from_utf8_owned(wr.get_ref().to_owned()).unwrap()