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.
13 use metadata::common::*;
15 use metadata::decoder;
16 use metadata::tyencode;
17 use middle::trans::reachable;
18 use middle::ty::node_id_to_type;
21 use util::ppaux::ty_to_str;
24 use core::hash::HashUtil;
25 use core::hashmap::HashMap;
26 use std::serialize::Encodable;
28 use syntax::abi::AbiSet;
32 use syntax::ast_util::*;
34 use syntax::diagnostic::span_handler;
35 use syntax::parse::token::special_idents;
36 use syntax::{ast_util, visit};
37 use syntax::opt_vec::OptVec;
40 use writer = std::ebml::writer;
43 type abbrev_map = @mut HashMap<ty::t, tyencode::ty_abbrev>;
46 pub type encode_inlined_item = @fn(ecx: @EncodeContext,
47 ebml_w: &writer::Encoder,
48 path: &[ast_map::path_elt],
49 ii: ast::inlined_item);
52 pub type encode_inlined_item = @fn(ecx: @EncodeContext,
53 ebml_w: &mut writer::Encoder,
54 path: &[ast_map::path_elt],
55 ii: ast::inlined_item);
57 pub struct EncodeParams {
60 reachable: reachable::map,
61 reexports2: middle::resolve::ExportMap2,
62 item_symbols: @mut HashMap<ast::node_id, ~str>,
63 discrim_symbols: @mut HashMap<ast::node_id, @~str>,
65 cstore: @mut cstore::CStore,
66 encode_inlined_item: encode_inlined_item
73 lang_item_bytes: uint,
74 link_args_bytes: uint,
83 pub struct EncodeContext {
87 reachable: reachable::map,
88 reexports2: middle::resolve::ExportMap2,
89 item_symbols: @mut HashMap<ast::node_id, ~str>,
90 discrim_symbols: @mut HashMap<ast::node_id, @~str>,
92 cstore: @mut cstore::CStore,
93 encode_inlined_item: encode_inlined_item,
94 type_abbrevs: abbrev_map
97 pub fn reachable(ecx: @EncodeContext, id: node_id) -> bool {
98 ecx.reachable.contains(&id)
102 fn encode_name(ecx: @EncodeContext, ebml_w: &writer::Encoder, name: ident) {
103 ebml_w.wr_tagged_str(tag_paths_data_name, *ecx.tcx.sess.str_of(name));
107 fn encode_name(ecx: @EncodeContext,
108 ebml_w: &mut writer::Encoder,
110 ebml_w.wr_tagged_str(tag_paths_data_name, *ecx.tcx.sess.str_of(name));
114 fn encode_impl_type_basename(ecx: @EncodeContext,
115 ebml_w: &writer::Encoder,
117 ebml_w.wr_tagged_str(tag_item_impl_type_basename,
118 *ecx.tcx.sess.str_of(name));
122 fn encode_impl_type_basename(ecx: @EncodeContext,
123 ebml_w: &mut writer::Encoder,
125 ebml_w.wr_tagged_str(tag_item_impl_type_basename,
126 *ecx.tcx.sess.str_of(name));
130 pub fn encode_def_id(ebml_w: &writer::Encoder, id: def_id) {
131 ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
135 pub fn encode_def_id(ebml_w: &mut writer::Encoder, id: def_id) {
136 ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
140 fn encode_region_param(ecx: @EncodeContext,
141 ebml_w: &writer::Encoder,
143 let opt_rp = ecx.tcx.region_paramd_items.find(&it.id);
144 for opt_rp.each |rp| {
145 do ebml_w.wr_tag(tag_region_param) {
152 fn encode_region_param(ecx: @EncodeContext,
153 ebml_w: &mut writer::Encoder,
155 let opt_rp = ecx.tcx.region_paramd_items.find(&it.id);
156 for opt_rp.each |rp| {
157 ebml_w.start_tag(tag_region_param);
164 fn encode_mutability(ebml_w: &writer::Encoder, mt: struct_mutability) {
165 do ebml_w.wr_tag(tag_struct_mut) {
167 struct_immutable => 'a',
168 struct_mutable => 'm'
170 ebml_w.writer.write(&[val as u8]);
175 fn encode_mutability(ebml_w: &mut writer::Encoder, mt: struct_mutability) {
176 ebml_w.start_tag(tag_struct_mut);
178 struct_immutable => 'a',
179 struct_mutable => 'm'
181 ebml_w.writer.write(&[val as u8]);
191 fn add_to_index(ecx: @EncodeContext,
192 ebml_w: &writer::Encoder,
194 index: &mut ~[entry<~str>],
196 let mut full_path = ~[];
197 full_path.push_all(path);
198 full_path.push(name);
201 val: ast_util::path_name_i(full_path,
202 ecx.tcx.sess.parse_sess.interner),
203 pos: ebml_w.writer.tell()
208 fn add_to_index(ecx: @EncodeContext,
209 ebml_w: &mut writer::Encoder,
211 index: &mut ~[entry<~str>],
213 let mut full_path = ~[];
214 full_path.push_all(path);
215 full_path.push(name);
218 val: ast_util::path_name_i(full_path,
219 ecx.tcx.sess.parse_sess.interner),
220 pos: ebml_w.writer.tell()
225 fn encode_trait_ref(ebml_w: &writer::Encoder,
227 trait_ref: &ty::TraitRef,
229 let ty_str_ctxt = @tyencode::ctxt {
233 reachable: |a| reachable(ecx, a),
234 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
236 ebml_w.start_tag(tag);
237 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
242 fn encode_trait_ref(ebml_w: &mut writer::Encoder,
244 trait_ref: &ty::TraitRef,
246 let ty_str_ctxt = @tyencode::ctxt {
250 reachable: |a| reachable(ecx, a),
251 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
253 ebml_w.start_tag(tag);
254 tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
258 // Item info table encoding
260 fn encode_family(ebml_w: &writer::Encoder, c: char) {
261 ebml_w.start_tag(tag_items_data_item_family);
262 ebml_w.writer.write(&[c as u8]);
266 // Item info table encoding
268 fn encode_family(ebml_w: &mut writer::Encoder, c: char) {
269 ebml_w.start_tag(tag_items_data_item_family);
270 ebml_w.writer.write(&[c as u8]);
274 pub fn def_to_str(did: def_id) -> ~str {
275 fmt!("%d:%d", did.crate, did.node)
279 fn encode_ty_type_param_defs(ebml_w: &writer::Encoder,
281 params: @~[ty::TypeParameterDef],
283 let ty_str_ctxt = @tyencode::ctxt {
287 reachable: |a| reachable(ecx, a),
288 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
289 for params.each |param| {
290 ebml_w.start_tag(tag);
291 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
297 fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
299 params: @~[ty::TypeParameterDef],
301 let ty_str_ctxt = @tyencode::ctxt {
305 reachable: |a| reachable(ecx, a),
306 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
307 for params.each |param| {
308 ebml_w.start_tag(tag);
309 tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
315 fn encode_type_param_bounds(ebml_w: &writer::Encoder,
317 params: &OptVec<TyParam>) {
319 @params.map_to_vec(|param| *ecx.tcx.ty_param_defs.get(¶m.id));
320 encode_ty_type_param_defs(ebml_w, ecx, ty_param_defs,
321 tag_items_data_item_ty_param_bounds);
325 fn encode_type_param_bounds(ebml_w: &mut writer::Encoder,
327 params: &OptVec<TyParam>) {
329 @params.map_to_vec(|param| *ecx.tcx.ty_param_defs.get(¶m.id));
330 encode_ty_type_param_defs(ebml_w, ecx, ty_param_defs,
331 tag_items_data_item_ty_param_bounds);
335 fn encode_variant_id(ebml_w: &writer::Encoder, vid: def_id) {
336 ebml_w.start_tag(tag_items_data_item_variant);
337 ebml_w.writer.write(str::to_bytes(def_to_str(vid)));
342 fn encode_variant_id(ebml_w: &mut writer::Encoder, vid: def_id) {
343 ebml_w.start_tag(tag_items_data_item_variant);
344 ebml_w.writer.write(str::to_bytes(def_to_str(vid)));
349 pub fn write_type(ecx: @EncodeContext, ebml_w: &writer::Encoder, typ: ty::t) {
350 let ty_str_ctxt = @tyencode::ctxt {
354 reachable: |a| reachable(ecx, a),
355 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
356 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
360 pub fn write_type(ecx: @EncodeContext,
361 ebml_w: &mut writer::Encoder,
363 let ty_str_ctxt = @tyencode::ctxt {
367 reachable: |a| reachable(ecx, a),
368 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
369 tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
373 pub fn write_vstore(ecx: @EncodeContext,
374 ebml_w: &writer::Encoder,
375 vstore: ty::vstore) {
376 let ty_str_ctxt = @tyencode::ctxt {
380 reachable: |a| reachable(ecx, a),
381 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
382 tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
386 pub fn write_vstore(ecx: @EncodeContext,
387 ebml_w: &mut writer::Encoder,
388 vstore: ty::vstore) {
389 let ty_str_ctxt = @tyencode::ctxt {
393 reachable: |a| reachable(ecx, a),
394 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
395 tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
399 fn encode_type(ecx: @EncodeContext, ebml_w: &writer::Encoder, typ: ty::t) {
400 ebml_w.start_tag(tag_items_data_item_type);
401 write_type(ecx, ebml_w, typ);
406 fn encode_type(ecx: @EncodeContext,
407 ebml_w: &mut writer::Encoder,
409 ebml_w.start_tag(tag_items_data_item_type);
410 write_type(ecx, ebml_w, typ);
415 fn encode_transformed_self_ty(ecx: @EncodeContext,
416 ebml_w: &writer::Encoder,
417 opt_typ: Option<ty::t>) {
418 for opt_typ.each |&typ| {
419 ebml_w.start_tag(tag_item_method_transformed_self_ty);
420 write_type(ecx, ebml_w, typ);
426 fn encode_transformed_self_ty(ecx: @EncodeContext,
427 ebml_w: &mut writer::Encoder,
428 opt_typ: Option<ty::t>) {
429 for opt_typ.each |&typ| {
430 ebml_w.start_tag(tag_item_method_transformed_self_ty);
431 write_type(ecx, ebml_w, typ);
437 fn encode_method_fty(ecx: @EncodeContext,
438 ebml_w: &writer::Encoder,
439 typ: &ty::BareFnTy) {
440 ebml_w.start_tag(tag_item_method_fty);
442 let ty_str_ctxt = @tyencode::ctxt {
446 reachable: |a| reachable(ecx, a),
447 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
448 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
454 fn encode_method_fty(ecx: @EncodeContext,
455 ebml_w: &mut writer::Encoder,
456 typ: &ty::BareFnTy) {
457 ebml_w.start_tag(tag_item_method_fty);
459 let ty_str_ctxt = @tyencode::ctxt {
463 reachable: |a| reachable(ecx, a),
464 abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)};
465 tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
471 fn encode_symbol(ecx: @EncodeContext, ebml_w: &writer::Encoder, id: node_id) {
472 ebml_w.start_tag(tag_items_data_item_symbol);
473 match ecx.item_symbols.find(&id) {
475 debug!("encode_symbol(id=%?, str=%s)", id, *x);
476 ebml_w.writer.write(str::to_bytes(*x));
479 ecx.diag.handler().bug(
480 fmt!("encode_symbol: id not found %d", id));
487 fn encode_symbol(ecx: @EncodeContext,
488 ebml_w: &mut writer::Encoder,
490 ebml_w.start_tag(tag_items_data_item_symbol);
491 match ecx.item_symbols.find(&id) {
493 debug!("encode_symbol(id=%?, str=%s)", id, *x);
494 ebml_w.writer.write(str::to_bytes(*x));
497 ecx.diag.handler().bug(
498 fmt!("encode_symbol: id not found %d", id));
505 fn encode_discriminant(ecx: @EncodeContext,
506 ebml_w: &writer::Encoder,
508 ebml_w.start_tag(tag_items_data_item_symbol);
509 ebml_w.writer.write(str::to_bytes(**ecx.discrim_symbols.get(&id)));
514 fn encode_discriminant(ecx: @EncodeContext,
515 ebml_w: &mut writer::Encoder,
517 ebml_w.start_tag(tag_items_data_item_symbol);
518 ebml_w.writer.write(str::to_bytes(**ecx.discrim_symbols.get(&id)));
523 fn encode_disr_val(_: @EncodeContext,
524 ebml_w: &writer::Encoder,
526 ebml_w.start_tag(tag_disr_val);
527 ebml_w.writer.write(str::to_bytes(int::to_str(disr_val)));
532 fn encode_disr_val(_: @EncodeContext,
533 ebml_w: &mut writer::Encoder,
535 ebml_w.start_tag(tag_disr_val);
536 ebml_w.writer.write(str::to_bytes(int::to_str(disr_val)));
541 fn encode_parent_item(ebml_w: &writer::Encoder, id: def_id) {
542 ebml_w.start_tag(tag_items_data_parent_item);
543 ebml_w.writer.write(str::to_bytes(def_to_str(id)));
548 fn encode_parent_item(ebml_w: &mut writer::Encoder, id: def_id) {
549 ebml_w.start_tag(tag_items_data_parent_item);
550 ebml_w.writer.write(str::to_bytes(def_to_str(id)));
555 fn encode_enum_variant_info(ecx: @EncodeContext,
556 ebml_w: &writer::Encoder,
558 variants: &[variant],
559 path: &[ast_map::path_elt],
560 index: @mut ~[entry<int>],
561 generics: &ast::Generics) {
562 debug!("encode_enum_variant_info(id=%?)", id);
564 let mut disr_val = 0;
566 let vi = ty::enum_variants(ecx.tcx,
567 ast::def_id { crate: local_crate, node: id });
568 for variants.each |variant| {
569 index.push(entry {val: variant.node.id, pos: ebml_w.writer.tell()});
570 ebml_w.start_tag(tag_items_data_item);
571 encode_def_id(ebml_w, local_def(variant.node.id));
572 encode_family(ebml_w, 'v');
573 encode_name(ecx, ebml_w, variant.node.name);
574 encode_parent_item(ebml_w, local_def(id));
575 encode_type(ecx, ebml_w,
576 node_id_to_type(ecx.tcx, variant.node.id));
577 match variant.node.kind {
578 ast::tuple_variant_kind(ref args)
579 if args.len() > 0 && generics.ty_params.len() == 0 => {
580 encode_symbol(ecx, ebml_w, variant.node.id);
582 ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) => {}
584 encode_discriminant(ecx, ebml_w, variant.node.id);
585 if vi[i].disr_val != disr_val {
586 encode_disr_val(ecx, ebml_w, vi[i].disr_val);
587 disr_val = vi[i].disr_val;
589 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
590 encode_path(ecx, ebml_w, path,
591 ast_map::path_name(variant.node.name));
599 fn encode_enum_variant_info(ecx: @EncodeContext,
600 ebml_w: &mut writer::Encoder,
602 variants: &[variant],
603 path: &[ast_map::path_elt],
604 index: @mut ~[entry<int>],
605 generics: &ast::Generics) {
606 debug!("encode_enum_variant_info(id=%?)", id);
608 let mut disr_val = 0;
610 let vi = ty::enum_variants(ecx.tcx,
611 ast::def_id { crate: local_crate, node: id });
612 for variants.each |variant| {
613 index.push(entry {val: variant.node.id, pos: ebml_w.writer.tell()});
614 ebml_w.start_tag(tag_items_data_item);
615 encode_def_id(ebml_w, local_def(variant.node.id));
616 encode_family(ebml_w, 'v');
617 encode_name(ecx, ebml_w, variant.node.name);
618 encode_parent_item(ebml_w, local_def(id));
619 encode_type(ecx, ebml_w,
620 node_id_to_type(ecx.tcx, variant.node.id));
621 match variant.node.kind {
622 ast::tuple_variant_kind(ref args)
623 if args.len() > 0 && generics.ty_params.len() == 0 => {
624 encode_symbol(ecx, ebml_w, variant.node.id);
626 ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) => {}
628 encode_discriminant(ecx, ebml_w, variant.node.id);
629 if vi[i].disr_val != disr_val {
630 encode_disr_val(ecx, ebml_w, vi[i].disr_val);
631 disr_val = vi[i].disr_val;
633 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
634 encode_path(ecx, ebml_w, path,
635 ast_map::path_name(variant.node.name));
643 fn encode_path(ecx: @EncodeContext,
644 ebml_w: &writer::Encoder,
645 path: &[ast_map::path_elt],
646 name: ast_map::path_elt) {
647 fn encode_path_elt(ecx: @EncodeContext, ebml_w: &writer::Encoder,
648 elt: ast_map::path_elt) {
649 let (tag, name) = match elt {
650 ast_map::path_mod(name) => (tag_path_elt_mod, name),
651 ast_map::path_name(name) => (tag_path_elt_name, name)
654 ebml_w.wr_tagged_str(tag, *ecx.tcx.sess.str_of(name));
657 do ebml_w.wr_tag(tag_path) {
658 ebml_w.wr_tagged_u32(tag_path_len, (path.len() + 1) as u32);
660 encode_path_elt(ecx, ebml_w, *pe);
662 encode_path_elt(ecx, ebml_w, name);
667 fn encode_path(ecx: @EncodeContext,
668 ebml_w: &mut writer::Encoder,
669 path: &[ast_map::path_elt],
670 name: ast_map::path_elt) {
671 fn encode_path_elt(ecx: @EncodeContext,
672 ebml_w: &mut writer::Encoder,
673 elt: ast_map::path_elt) {
674 let (tag, name) = match elt {
675 ast_map::path_mod(name) => (tag_path_elt_mod, name),
676 ast_map::path_name(name) => (tag_path_elt_name, name)
679 ebml_w.wr_tagged_str(tag, *ecx.tcx.sess.str_of(name));
682 ebml_w.start_tag(tag_path);
683 ebml_w.wr_tagged_u32(tag_path_len, (path.len() + 1) as u32);
685 encode_path_elt(ecx, ebml_w, *pe);
687 encode_path_elt(ecx, ebml_w, name);
692 fn encode_info_for_mod(ecx: @EncodeContext,
693 ebml_w: &writer::Encoder,
696 path: &[ast_map::path_elt],
698 ebml_w.start_tag(tag_items_data_item);
699 encode_def_id(ebml_w, local_def(id));
700 encode_family(ebml_w, 'm');
701 encode_name(ecx, ebml_w, name);
702 debug!("(encoding info for module) encoding info for module ID %d", id);
704 // Encode info about all the module children.
705 for md.items.each |item| {
708 let (ident, did) = (item.ident, item.id);
709 debug!("(encoding info for module) ... encoding impl %s \
711 *ecx.tcx.sess.str_of(ident),
713 ast_map::node_id_to_str(ecx.tcx.items, did, ecx.tcx
714 .sess.parse_sess.interner));
716 ebml_w.start_tag(tag_mod_impl);
717 ebml_w.wr_str(def_to_str(local_def(did)));
720 _ => {} // FIXME #4573: Encode these too.
724 encode_path(ecx, ebml_w, path, ast_map::path_mod(name));
726 // Encode the reexports of this module.
727 debug!("(encoding info for module) encoding reexports for %d", id);
728 match ecx.reexports2.find(&id) {
729 Some(ref exports) => {
730 debug!("(encoding info for module) found reexports for %d", id);
731 for exports.each |exp| {
732 debug!("(encoding info for module) reexport '%s' for %d",
734 ebml_w.start_tag(tag_items_data_item_reexport);
735 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
736 ebml_w.wr_str(def_to_str(exp.def_id));
738 ebml_w.start_tag(tag_items_data_item_reexport_name);
739 ebml_w.wr_str(*exp.name);
745 debug!("(encoding info for module) found no reexports for %d",
754 fn encode_info_for_mod(ecx: @EncodeContext,
755 ebml_w: &mut writer::Encoder,
758 path: &[ast_map::path_elt],
760 ebml_w.start_tag(tag_items_data_item);
761 encode_def_id(ebml_w, local_def(id));
762 encode_family(ebml_w, 'm');
763 encode_name(ecx, ebml_w, name);
764 debug!("(encoding info for module) encoding info for module ID %d", id);
766 // Encode info about all the module children.
767 for md.items.each |item| {
770 let (ident, did) = (item.ident, item.id);
771 debug!("(encoding info for module) ... encoding impl %s \
773 *ecx.tcx.sess.str_of(ident),
775 ast_map::node_id_to_str(ecx.tcx.items, did, ecx.tcx
776 .sess.parse_sess.interner));
778 ebml_w.start_tag(tag_mod_impl);
779 ebml_w.wr_str(def_to_str(local_def(did)));
782 _ => {} // FIXME #4573: Encode these too.
786 encode_path(ecx, ebml_w, path, ast_map::path_mod(name));
788 // Encode the reexports of this module.
789 debug!("(encoding info for module) encoding reexports for %d", id);
790 match ecx.reexports2.find(&id) {
791 Some(ref exports) => {
792 debug!("(encoding info for module) found reexports for %d", id);
793 for exports.each |exp| {
794 debug!("(encoding info for module) reexport '%s' for %d",
796 ebml_w.start_tag(tag_items_data_item_reexport);
797 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
798 ebml_w.wr_str(def_to_str(exp.def_id));
800 ebml_w.start_tag(tag_items_data_item_reexport_name);
801 ebml_w.wr_str(*exp.name);
807 debug!("(encoding info for module) found no reexports for %d",
816 fn encode_struct_field_family(ebml_w: &writer::Encoder,
817 visibility: visibility) {
818 encode_family(ebml_w, match visibility {
826 fn encode_struct_field_family(ebml_w: &mut writer::Encoder,
827 visibility: visibility) {
828 encode_family(ebml_w, match visibility {
836 fn encode_visibility(ebml_w: &writer::Encoder, visibility: visibility) {
837 ebml_w.start_tag(tag_items_data_item_visibility);
838 let ch = match visibility {
843 ebml_w.wr_str(str::from_char(ch));
848 fn encode_visibility(ebml_w: &mut writer::Encoder, visibility: visibility) {
849 ebml_w.start_tag(tag_items_data_item_visibility);
850 let ch = match visibility {
855 ebml_w.wr_str(str::from_char(ch));
860 fn encode_self_type(ebml_w: &writer::Encoder, self_type: ast::self_ty_) {
861 ebml_w.start_tag(tag_item_trait_method_self_ty);
863 // Encode the base self type.
866 ebml_w.writer.write(&[ 's' as u8 ]);
869 ebml_w.writer.write(&[ 'v' as u8 ]);
871 sty_region(_, m) => {
872 // FIXME(#4846) encode custom lifetime
873 ebml_w.writer.write(&[ '&' as u8 ]);
874 encode_mutability(ebml_w, m);
877 ebml_w.writer.write(&[ '@' as u8 ]);
878 encode_mutability(ebml_w, m);
881 ebml_w.writer.write(&[ '~' as u8 ]);
882 encode_mutability(ebml_w, m);
888 fn encode_mutability(ebml_w: &writer::Encoder,
889 m: ast::mutability) {
892 ebml_w.writer.write(&[ 'i' as u8 ]);
895 ebml_w.writer.write(&[ 'm' as u8 ]);
898 ebml_w.writer.write(&[ 'c' as u8 ]);
905 fn encode_self_type(ebml_w: &mut writer::Encoder, self_type: ast::self_ty_) {
906 ebml_w.start_tag(tag_item_trait_method_self_ty);
908 // Encode the base self type.
911 ebml_w.writer.write(&[ 's' as u8 ]);
914 ebml_w.writer.write(&[ 'v' as u8 ]);
916 sty_region(_, m) => {
917 // FIXME(#4846) encode custom lifetime
918 ebml_w.writer.write(&[ '&' as u8 ]);
919 encode_mutability(ebml_w, m);
922 ebml_w.writer.write(&[ '@' as u8 ]);
923 encode_mutability(ebml_w, m);
926 ebml_w.writer.write(&[ '~' as u8 ]);
927 encode_mutability(ebml_w, m);
933 fn encode_mutability(ebml_w: &writer::Encoder,
934 m: ast::mutability) {
937 ebml_w.writer.write(&[ 'i' as u8 ]);
940 ebml_w.writer.write(&[ 'm' as u8 ]);
943 ebml_w.writer.write(&[ 'c' as u8 ]);
950 fn encode_method_sort(ebml_w: &writer::Encoder, sort: char) {
951 ebml_w.start_tag(tag_item_trait_method_sort);
952 ebml_w.writer.write(&[ sort as u8 ]);
957 fn encode_method_sort(ebml_w: &mut writer::Encoder, sort: char) {
958 ebml_w.start_tag(tag_item_trait_method_sort);
959 ebml_w.writer.write(&[ sort as u8 ]);
963 /* Returns an index of items in this class */
965 fn encode_info_for_struct(ecx: @EncodeContext,
966 ebml_w: &writer::Encoder,
967 path: &[ast_map::path_elt],
968 fields: &[@struct_field],
969 global_index: @mut~[entry<int>])
971 /* Each class has its own index, since different classes
972 may have fields with the same name */
973 let index = @mut ~[];
975 /* We encode both private and public fields -- need to include
976 private fields to get the offsets right */
977 for fields.each |field| {
978 let (nm, mt, vis) = match field.node.kind {
979 named_field(nm, mt, vis) => (nm, mt, vis),
981 special_idents::unnamed_field,
987 let id = field.node.id;
988 index.push(entry {val: id, pos: ebml_w.writer.tell()});
989 global_index.push(entry {val: id, pos: ebml_w.writer.tell()});
990 ebml_w.start_tag(tag_items_data_item);
991 debug!("encode_info_for_struct: doing %s %d",
992 *tcx.sess.str_of(nm), id);
993 encode_struct_field_family(ebml_w, vis);
994 encode_name(ecx, ebml_w, nm);
995 encode_path(ecx, ebml_w, path, ast_map::path_name(nm));
996 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
997 encode_mutability(ebml_w, mt);
998 encode_def_id(ebml_w, local_def(id));
1005 fn encode_info_for_struct(ecx: @EncodeContext,
1006 ebml_w: &mut writer::Encoder,
1007 path: &[ast_map::path_elt],
1008 fields: &[@struct_field],
1009 global_index: @mut ~[entry<int>])
1011 /* Each class has its own index, since different classes
1012 may have fields with the same name */
1013 let index = @mut ~[];
1015 /* We encode both private and public fields -- need to include
1016 private fields to get the offsets right */
1017 for fields.each |field| {
1018 let (nm, mt, vis) = match field.node.kind {
1019 named_field(nm, mt, vis) => (nm, mt, vis),
1021 special_idents::unnamed_field,
1027 let id = field.node.id;
1028 index.push(entry {val: id, pos: ebml_w.writer.tell()});
1029 global_index.push(entry {val: id, pos: ebml_w.writer.tell()});
1030 ebml_w.start_tag(tag_items_data_item);
1031 debug!("encode_info_for_struct: doing %s %d",
1032 *tcx.sess.str_of(nm), id);
1033 encode_struct_field_family(ebml_w, vis);
1034 encode_name(ecx, ebml_w, nm);
1035 encode_path(ecx, ebml_w, path, ast_map::path_name(nm));
1036 encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
1037 encode_mutability(ebml_w, mt);
1038 encode_def_id(ebml_w, local_def(id));
1044 // This is for encoding info for ctors and dtors
1046 fn encode_info_for_ctor(ecx: @EncodeContext,
1047 ebml_w: &writer::Encoder,
1050 path: &[ast_map::path_elt],
1051 item: Option<inlined_item>,
1052 generics: &ast::Generics) {
1053 ebml_w.start_tag(tag_items_data_item);
1054 encode_name(ecx, ebml_w, ident);
1055 encode_def_id(ebml_w, local_def(id));
1056 encode_family(ebml_w, purity_fn_family(ast::impure_fn));
1057 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1058 let its_ty = node_id_to_type(ecx.tcx, id);
1059 debug!("fn name = %s ty = %s its node id = %d",
1060 *ecx.tcx.sess.str_of(ident),
1061 ty_to_str(ecx.tcx, its_ty), id);
1062 encode_type(ecx, ebml_w, its_ty);
1063 encode_path(ecx, ebml_w, path, ast_map::path_name(ident));
1066 (ecx.encode_inlined_item)(ecx, ebml_w, path, it);
1069 encode_symbol(ecx, ebml_w, id);
1076 fn encode_info_for_ctor(ecx: @EncodeContext,
1077 ebml_w: &mut writer::Encoder,
1080 path: &[ast_map::path_elt],
1081 item: Option<inlined_item>,
1082 generics: &ast::Generics) {
1083 ebml_w.start_tag(tag_items_data_item);
1084 encode_name(ecx, ebml_w, ident);
1085 encode_def_id(ebml_w, local_def(id));
1086 encode_family(ebml_w, purity_fn_family(ast::impure_fn));
1087 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1088 let its_ty = node_id_to_type(ecx.tcx, id);
1089 debug!("fn name = %s ty = %s its node id = %d",
1090 *ecx.tcx.sess.str_of(ident),
1091 ty_to_str(ecx.tcx, its_ty), id);
1092 encode_type(ecx, ebml_w, its_ty);
1093 encode_path(ecx, ebml_w, path, ast_map::path_name(ident));
1096 (ecx.encode_inlined_item)(ecx, ebml_w, path, it);
1099 encode_symbol(ecx, ebml_w, id);
1106 fn encode_info_for_struct_ctor(ecx: @EncodeContext,
1107 ebml_w: &writer::Encoder,
1108 path: &[ast_map::path_elt],
1111 index: @mut ~[entry<int>]) {
1112 index.push(entry { val: ctor_id, pos: ebml_w.writer.tell() });
1114 ebml_w.start_tag(tag_items_data_item);
1115 encode_def_id(ebml_w, local_def(ctor_id));
1116 encode_family(ebml_w, 'f');
1117 encode_name(ecx, ebml_w, name);
1118 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
1119 encode_path(ecx, ebml_w, path, ast_map::path_name(name));
1121 if ecx.item_symbols.contains_key(&ctor_id) {
1122 encode_symbol(ecx, ebml_w, ctor_id);
1129 fn encode_info_for_struct_ctor(ecx: @EncodeContext,
1130 ebml_w: &mut writer::Encoder,
1131 path: &[ast_map::path_elt],
1134 index: @mut ~[entry<int>]) {
1135 index.push(entry { val: ctor_id, pos: ebml_w.writer.tell() });
1137 ebml_w.start_tag(tag_items_data_item);
1138 encode_def_id(ebml_w, local_def(ctor_id));
1139 encode_family(ebml_w, 'f');
1140 encode_name(ecx, ebml_w, name);
1141 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
1142 encode_path(ecx, ebml_w, path, ast_map::path_name(name));
1144 if ecx.item_symbols.contains_key(&ctor_id) {
1145 encode_symbol(ecx, ebml_w, ctor_id);
1152 fn encode_method_ty_fields(ecx: @EncodeContext,
1153 ebml_w: &writer::Encoder,
1154 method_ty: &ty::method) {
1155 encode_def_id(ebml_w, method_ty.def_id);
1156 encode_name(ecx, ebml_w, method_ty.ident);
1157 encode_ty_type_param_defs(ebml_w, ecx,
1158 method_ty.generics.type_param_defs,
1159 tag_item_method_tps);
1160 encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty);
1161 encode_method_fty(ecx, ebml_w, &method_ty.fty);
1162 encode_visibility(ebml_w, method_ty.vis);
1163 encode_self_type(ebml_w, method_ty.self_ty);
1167 fn encode_method_ty_fields(ecx: @EncodeContext,
1168 ebml_w: &mut writer::Encoder,
1169 method_ty: &ty::method) {
1170 encode_def_id(ebml_w, method_ty.def_id);
1171 encode_name(ecx, ebml_w, method_ty.ident);
1172 encode_ty_type_param_defs(ebml_w, ecx,
1173 method_ty.generics.type_param_defs,
1174 tag_item_method_tps);
1175 encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty);
1176 encode_method_fty(ecx, ebml_w, &method_ty.fty);
1177 encode_visibility(ebml_w, method_ty.vis);
1178 encode_self_type(ebml_w, method_ty.self_ty);
1182 fn encode_info_for_method(ecx: @EncodeContext,
1183 ebml_w: &writer::Encoder,
1184 impl_path: &[ast_map::path_elt],
1185 should_inline: bool,
1188 owner_generics: &ast::Generics,
1189 method_generics: &ast::Generics) {
1190 debug!("encode_info_for_method: %d %s %u %u", m.id,
1191 *ecx.tcx.sess.str_of(m.ident),
1192 owner_generics.ty_params.len(),
1193 method_generics.ty_params.len());
1194 ebml_w.start_tag(tag_items_data_item);
1196 let method_def_id = local_def(m.id);
1197 let method_ty: @ty::method = ty::method(ecx.tcx, method_def_id);
1198 encode_method_ty_fields(ecx, ebml_w, method_ty);
1200 match m.self_ty.node {
1201 ast::sty_static => {
1202 encode_family(ebml_w, purity_static_method_family(m.purity));
1204 _ => encode_family(ebml_w, purity_fn_family(m.purity))
1207 let mut combined_ty_params = opt_vec::Empty;
1208 combined_ty_params.push_all(&owner_generics.ty_params);
1209 combined_ty_params.push_all(&method_generics.ty_params);
1210 let len = combined_ty_params.len();
1211 encode_type_param_bounds(ebml_w, ecx, &combined_ty_params);
1213 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
1214 encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
1216 if len > 0u || should_inline {
1217 (ecx.encode_inlined_item)(
1218 ecx, ebml_w, impl_path,
1219 ii_method(local_def(parent_id), m));
1221 encode_symbol(ecx, ebml_w, m.id);
1228 fn encode_info_for_method(ecx: @EncodeContext,
1229 ebml_w: &mut writer::Encoder,
1230 impl_path: &[ast_map::path_elt],
1231 should_inline: bool,
1234 owner_generics: &ast::Generics,
1235 method_generics: &ast::Generics) {
1236 debug!("encode_info_for_method: %d %s %u %u", m.id,
1237 *ecx.tcx.sess.str_of(m.ident),
1238 owner_generics.ty_params.len(),
1239 method_generics.ty_params.len());
1240 ebml_w.start_tag(tag_items_data_item);
1242 let method_def_id = local_def(m.id);
1243 let method_ty: @ty::method = ty::method(ecx.tcx, method_def_id);
1244 encode_method_ty_fields(ecx, ebml_w, method_ty);
1246 match m.self_ty.node {
1247 ast::sty_static => {
1248 encode_family(ebml_w, purity_static_method_family(m.purity));
1250 _ => encode_family(ebml_w, purity_fn_family(m.purity))
1253 let mut combined_ty_params = opt_vec::Empty;
1254 combined_ty_params.push_all(&owner_generics.ty_params);
1255 combined_ty_params.push_all(&method_generics.ty_params);
1256 let len = combined_ty_params.len();
1257 encode_type_param_bounds(ebml_w, ecx, &combined_ty_params);
1259 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
1260 encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
1262 if len > 0u || should_inline {
1263 (ecx.encode_inlined_item)(
1264 ecx, ebml_w, impl_path,
1265 ii_method(local_def(parent_id), m));
1267 encode_symbol(ecx, ebml_w, m.id);
1273 fn purity_fn_family(p: purity) -> char {
1282 fn purity_static_method_family(p: purity) -> char {
1287 _ => fail!(~"extern fn can't be static")
1292 fn should_inline(attrs: &[attribute]) -> bool {
1293 match attr::find_inline_attr(attrs) {
1294 attr::ia_none | attr::ia_never => false,
1295 attr::ia_hint | attr::ia_always => true
1300 fn encode_info_for_item(ecx: @EncodeContext,
1301 ebml_w: &writer::Encoder,
1303 index: @mut ~[entry<int>],
1304 path: &[ast_map::path_elt]) {
1308 item_enum(_, _) | item_impl(*) | item_trait(*) | item_struct(*) |
1309 item_mod(*) | item_foreign_mod(*) | item_const(*) => true,
1312 if !must_write && !reachable(ecx, item.id) { return; }
1314 fn add_to_index_(item: @item, ebml_w: &writer::Encoder,
1315 index: @mut ~[entry<int>]) {
1316 index.push(entry { val: item.id, pos: ebml_w.writer.tell() });
1318 let add_to_index: &fn() = || add_to_index_(item, ebml_w, index);
1320 debug!("encoding info for item at %s",
1321 ecx.tcx.sess.codemap.span_to_str(item.span));
1324 item_const(_, _) => {
1326 ebml_w.start_tag(tag_items_data_item);
1327 encode_def_id(ebml_w, local_def(item.id));
1328 encode_family(ebml_w, 'c');
1329 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
1330 encode_symbol(ecx, ebml_w, item.id);
1331 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1332 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
1335 item_fn(_, purity, _, ref generics, _) => {
1337 ebml_w.start_tag(tag_items_data_item);
1338 encode_def_id(ebml_w, local_def(item.id));
1339 encode_family(ebml_w, purity_fn_family(purity));
1340 let tps_len = generics.ty_params.len();
1341 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1342 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
1343 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1344 encode_attributes(ebml_w, item.attrs);
1345 if tps_len > 0u || should_inline(item.attrs) {
1346 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
1348 encode_symbol(ecx, ebml_w, item.id);
1352 item_mod(ref m) => {
1354 encode_info_for_mod(ecx, ebml_w, m, item.id, path, item.ident);
1356 item_foreign_mod(_) => {
1358 ebml_w.start_tag(tag_items_data_item);
1359 encode_def_id(ebml_w, local_def(item.id));
1360 encode_family(ebml_w, 'n');
1361 encode_name(ecx, ebml_w, item.ident);
1362 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1365 item_ty(_, ref generics) => {
1367 ebml_w.start_tag(tag_items_data_item);
1368 encode_def_id(ebml_w, local_def(item.id));
1369 encode_family(ebml_w, 'y');
1370 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1371 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
1372 encode_name(ecx, ebml_w, item.ident);
1373 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1374 encode_region_param(ecx, ebml_w, item);
1377 item_enum(ref enum_definition, ref generics) => {
1379 do ebml_w.wr_tag(tag_items_data_item) {
1380 encode_def_id(ebml_w, local_def(item.id));
1381 encode_family(ebml_w, 't');
1382 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1383 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
1384 encode_name(ecx, ebml_w, item.ident);
1385 for (*enum_definition).variants.each |v| {
1386 encode_variant_id(ebml_w, local_def(v.node.id));
1388 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
1389 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1390 encode_region_param(ecx, ebml_w, item);
1392 encode_enum_variant_info(ecx,
1395 (*enum_definition).variants,
1400 item_struct(struct_def, ref generics) => {
1401 /* First, encode the fields
1402 These come first because we need to write them to make
1403 the index, and the index needs to be in the item for the
1405 let idx = encode_info_for_struct(ecx, ebml_w, path,
1406 struct_def.fields, index);
1408 /* Index the class*/
1411 /* Now, make an item for the class itself */
1412 ebml_w.start_tag(tag_items_data_item);
1413 encode_def_id(ebml_w, local_def(item.id));
1414 encode_family(ebml_w, 'S');
1415 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1416 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
1418 // If this is a tuple- or enum-like struct, encode the type of the
1420 if struct_def.fields.len() > 0 &&
1421 struct_def.fields[0].node.kind == ast::unnamed_field {
1422 let ctor_id = match struct_def.ctor_id {
1423 Some(ctor_id) => ctor_id,
1424 None => ecx.tcx.sess.bug(~"struct def didn't have ctor id"),
1427 encode_info_for_struct_ctor(ecx,
1435 encode_name(ecx, ebml_w, item.ident);
1436 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1437 encode_region_param(ecx, ebml_w, item);
1439 /* Encode def_ids for each field and method
1440 for methods, write all the stuff get_trait_method
1442 for struct_def.fields.each |f| {
1444 named_field(ident, _, vis) => {
1445 ebml_w.start_tag(tag_item_field);
1446 encode_struct_field_family(ebml_w, vis);
1447 encode_name(ecx, ebml_w, ident);
1448 encode_def_id(ebml_w, local_def(f.node.id));
1452 ebml_w.start_tag(tag_item_unnamed_field);
1453 encode_def_id(ebml_w, local_def(f.node.id));
1459 /* Each class has its own index -- encode it */
1460 let bkts = create_index(idx);
1461 encode_index(ebml_w, bkts, write_int);
1464 item_impl(ref generics, opt_trait, ty, ref methods) => {
1466 ebml_w.start_tag(tag_items_data_item);
1467 encode_def_id(ebml_w, local_def(item.id));
1468 encode_family(ebml_w, 'i');
1469 encode_region_param(ecx, ebml_w, item);
1470 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1471 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
1472 encode_name(ecx, ebml_w, item.ident);
1473 encode_attributes(ebml_w, item.attrs);
1475 ast::ty_path(path, _) if path.idents.len() == 1 => {
1476 encode_impl_type_basename(ecx, ebml_w,
1477 ast_util::path_to_ident(path));
1481 for methods.each |m| {
1482 ebml_w.start_tag(tag_item_impl_method);
1483 let method_def_id = local_def(m.id);
1484 ebml_w.writer.write(str::to_bytes(def_to_str(method_def_id)));
1487 for opt_trait.each |ast_trait_ref| {
1488 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1489 encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
1491 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1495 let mut impl_path = vec::append(~[], path);
1496 impl_path += ~[ast_map::path_name(item.ident)];
1498 for methods.each |m| {
1499 index.push(entry {val: m.id, pos: ebml_w.writer.tell()});
1500 encode_info_for_method(ecx,
1503 should_inline(m.attrs),
1510 item_trait(ref generics, ref super_traits, ref ms) => {
1512 ebml_w.start_tag(tag_items_data_item);
1513 encode_def_id(ebml_w, local_def(item.id));
1514 encode_family(ebml_w, 'I');
1515 encode_region_param(ecx, ebml_w, item);
1516 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1517 let trait_def = ty::lookup_trait_def(tcx, local_def(item.id));
1518 encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
1519 encode_name(ecx, ebml_w, item.ident);
1520 encode_attributes(ebml_w, item.attrs);
1521 for ty::trait_method_def_ids(tcx, local_def(item.id)).each |&method_def_id| {
1522 ebml_w.start_tag(tag_item_trait_method);
1523 encode_def_id(ebml_w, method_def_id);
1526 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1527 for super_traits.each |ast_trait_ref| {
1528 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1529 encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
1533 // Now output the method info for each method.
1534 for ty::trait_method_def_ids(tcx, local_def(item.id)).eachi |i, &method_def_id| {
1535 assert!(method_def_id.crate == ast::local_crate);
1537 let method_ty: @ty::method = ty::method(tcx, method_def_id);
1539 index.push(entry {val: method_def_id.node, pos: ebml_w.writer.tell()});
1541 ebml_w.start_tag(tag_items_data_item);
1543 encode_method_ty_fields(ecx, ebml_w, method_ty);
1545 encode_parent_item(ebml_w, local_def(item.id));
1547 let mut trait_path = vec::append(~[], path);
1548 trait_path.push(ast_map::path_name(item.ident));
1549 encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
1551 match method_ty.self_ty {
1553 encode_family(ebml_w,
1554 purity_static_method_family(
1555 method_ty.fty.purity));
1557 let tpt = ty::lookup_item_type(tcx, method_def_id);
1558 encode_ty_type_param_defs(ebml_w, ecx,
1559 tpt.generics.type_param_defs,
1560 tag_items_data_item_ty_param_bounds);
1561 encode_type(ecx, ebml_w, tpt.ty);
1565 encode_family(ebml_w,
1567 method_ty.fty.purity));
1573 encode_method_sort(ebml_w, 'r');
1577 // This is obviously a bogus assert but I don't think this
1578 // ever worked before anyhow...near as I can tell, before
1579 // we would emit two items.
1580 if method_ty.self_ty == sty_static {
1581 tcx.sess.span_unimpl(
1583 fmt!("Method %s is both provided and static",
1584 *tcx.sess.intr().get(method_ty.ident)));
1586 encode_type_param_bounds(ebml_w, ecx,
1587 &m.generics.ty_params);
1588 encode_method_sort(ebml_w, 'p');
1589 (ecx.encode_inlined_item)(
1591 ii_method(local_def(item.id), m));
1598 item_mac(*) => fail!(~"item macros unimplemented")
1603 fn encode_info_for_item(ecx: @EncodeContext,
1604 ebml_w: &mut writer::Encoder,
1606 index: @mut ~[entry<int>],
1607 path: &[ast_map::path_elt]) {
1611 item_enum(_, _) | item_impl(*) | item_trait(*) | item_struct(*) |
1612 item_mod(*) | item_foreign_mod(*) | item_const(*) => true,
1615 if !must_write && !reachable(ecx, item.id) { return; }
1617 fn add_to_index_(item: @item, ebml_w: &writer::Encoder,
1618 index: @mut ~[entry<int>]) {
1619 index.push(entry { val: item.id, pos: ebml_w.writer.tell() });
1621 let add_to_index: &fn() = || add_to_index_(item, ebml_w, index);
1623 debug!("encoding info for item at %s",
1624 ecx.tcx.sess.codemap.span_to_str(item.span));
1627 item_const(_, _) => {
1629 ebml_w.start_tag(tag_items_data_item);
1630 encode_def_id(ebml_w, local_def(item.id));
1631 encode_family(ebml_w, 'c');
1632 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
1633 encode_symbol(ecx, ebml_w, item.id);
1634 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1635 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
1638 item_fn(_, purity, _, ref generics, _) => {
1640 ebml_w.start_tag(tag_items_data_item);
1641 encode_def_id(ebml_w, local_def(item.id));
1642 encode_family(ebml_w, purity_fn_family(purity));
1643 let tps_len = generics.ty_params.len();
1644 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1645 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
1646 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1647 encode_attributes(ebml_w, item.attrs);
1648 if tps_len > 0u || should_inline(item.attrs) {
1649 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
1651 encode_symbol(ecx, ebml_w, item.id);
1655 item_mod(ref m) => {
1657 encode_info_for_mod(ecx, ebml_w, m, item.id, path, item.ident);
1659 item_foreign_mod(_) => {
1661 ebml_w.start_tag(tag_items_data_item);
1662 encode_def_id(ebml_w, local_def(item.id));
1663 encode_family(ebml_w, 'n');
1664 encode_name(ecx, ebml_w, item.ident);
1665 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1668 item_ty(_, ref generics) => {
1670 ebml_w.start_tag(tag_items_data_item);
1671 encode_def_id(ebml_w, local_def(item.id));
1672 encode_family(ebml_w, 'y');
1673 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1674 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
1675 encode_name(ecx, ebml_w, item.ident);
1676 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1677 encode_region_param(ecx, ebml_w, item);
1680 item_enum(ref enum_definition, ref generics) => {
1683 ebml_w.start_tag(tag_items_data_item);
1684 encode_def_id(ebml_w, local_def(item.id));
1685 encode_family(ebml_w, 't');
1686 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1687 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
1688 encode_name(ecx, ebml_w, item.ident);
1689 for (*enum_definition).variants.each |v| {
1690 encode_variant_id(ebml_w, local_def(v.node.id));
1692 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
1693 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1694 encode_region_param(ecx, ebml_w, item);
1697 encode_enum_variant_info(ecx,
1700 (*enum_definition).variants,
1705 item_struct(struct_def, ref generics) => {
1706 /* First, encode the fields
1707 These come first because we need to write them to make
1708 the index, and the index needs to be in the item for the
1710 let idx = encode_info_for_struct(ecx, ebml_w, path,
1711 struct_def.fields, index);
1713 /* Index the class*/
1716 /* Now, make an item for the class itself */
1717 ebml_w.start_tag(tag_items_data_item);
1718 encode_def_id(ebml_w, local_def(item.id));
1719 encode_family(ebml_w, 'S');
1720 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1721 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
1723 // If this is a tuple- or enum-like struct, encode the type of the
1725 if struct_def.fields.len() > 0 &&
1726 struct_def.fields[0].node.kind == ast::unnamed_field {
1727 let ctor_id = match struct_def.ctor_id {
1728 Some(ctor_id) => ctor_id,
1729 None => ecx.tcx.sess.bug(~"struct def didn't have ctor id"),
1732 encode_info_for_struct_ctor(ecx,
1740 encode_name(ecx, ebml_w, item.ident);
1741 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1742 encode_region_param(ecx, ebml_w, item);
1744 /* Encode def_ids for each field and method
1745 for methods, write all the stuff get_trait_method
1747 for struct_def.fields.each |f| {
1749 named_field(ident, _, vis) => {
1750 ebml_w.start_tag(tag_item_field);
1751 encode_struct_field_family(ebml_w, vis);
1752 encode_name(ecx, ebml_w, ident);
1753 encode_def_id(ebml_w, local_def(f.node.id));
1757 ebml_w.start_tag(tag_item_unnamed_field);
1758 encode_def_id(ebml_w, local_def(f.node.id));
1764 /* Each class has its own index -- encode it */
1765 let bkts = create_index(idx);
1766 encode_index(ebml_w, bkts, write_int);
1769 item_impl(ref generics, opt_trait, ty, ref methods) => {
1771 ebml_w.start_tag(tag_items_data_item);
1772 encode_def_id(ebml_w, local_def(item.id));
1773 encode_family(ebml_w, 'i');
1774 encode_region_param(ecx, ebml_w, item);
1775 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1776 encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
1777 encode_name(ecx, ebml_w, item.ident);
1778 encode_attributes(ebml_w, item.attrs);
1780 ast::ty_path(path, _) if path.idents.len() == 1 => {
1781 encode_impl_type_basename(ecx, ebml_w,
1782 ast_util::path_to_ident(path));
1786 for methods.each |m| {
1787 ebml_w.start_tag(tag_item_impl_method);
1788 let method_def_id = local_def(m.id);
1789 ebml_w.writer.write(str::to_bytes(def_to_str(method_def_id)));
1792 for opt_trait.each |ast_trait_ref| {
1793 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1794 encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
1796 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1800 let mut impl_path = vec::append(~[], path);
1801 impl_path += ~[ast_map::path_name(item.ident)];
1803 for methods.each |m| {
1804 index.push(entry {val: m.id, pos: ebml_w.writer.tell()});
1805 encode_info_for_method(ecx,
1808 should_inline(m.attrs),
1815 item_trait(ref generics, ref super_traits, ref ms) => {
1817 ebml_w.start_tag(tag_items_data_item);
1818 encode_def_id(ebml_w, local_def(item.id));
1819 encode_family(ebml_w, 'I');
1820 encode_region_param(ecx, ebml_w, item);
1821 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1822 let trait_def = ty::lookup_trait_def(tcx, local_def(item.id));
1823 encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
1824 encode_name(ecx, ebml_w, item.ident);
1825 encode_attributes(ebml_w, item.attrs);
1826 for ty::trait_method_def_ids(tcx, local_def(item.id)).each |&method_def_id| {
1827 ebml_w.start_tag(tag_item_trait_method);
1828 encode_def_id(ebml_w, method_def_id);
1831 encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1832 for super_traits.each |ast_trait_ref| {
1833 let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1834 encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
1838 // Now output the method info for each method.
1839 for ty::trait_method_def_ids(tcx, local_def(item.id)).eachi |i, &method_def_id| {
1840 assert!(method_def_id.crate == ast::local_crate);
1842 let method_ty: @ty::method = ty::method(tcx, method_def_id);
1844 index.push(entry {val: method_def_id.node, pos: ebml_w.writer.tell()});
1846 ebml_w.start_tag(tag_items_data_item);
1848 encode_method_ty_fields(ecx, ebml_w, method_ty);
1850 encode_parent_item(ebml_w, local_def(item.id));
1852 let mut trait_path = vec::append(~[], path);
1853 trait_path.push(ast_map::path_name(item.ident));
1854 encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
1856 match method_ty.self_ty {
1858 encode_family(ebml_w,
1859 purity_static_method_family(
1860 method_ty.fty.purity));
1862 let tpt = ty::lookup_item_type(tcx, method_def_id);
1863 encode_ty_type_param_defs(ebml_w, ecx,
1864 tpt.generics.type_param_defs,
1865 tag_items_data_item_ty_param_bounds);
1866 encode_type(ecx, ebml_w, tpt.ty);
1870 encode_family(ebml_w,
1872 method_ty.fty.purity));
1878 encode_method_sort(ebml_w, 'r');
1882 // This is obviously a bogus assert but I don't think this
1883 // ever worked before anyhow...near as I can tell, before
1884 // we would emit two items.
1885 if method_ty.self_ty == sty_static {
1886 tcx.sess.span_unimpl(
1888 fmt!("Method %s is both provided and static",
1889 *tcx.sess.intr().get(method_ty.ident)));
1891 encode_type_param_bounds(ebml_w, ecx,
1892 &m.generics.ty_params);
1893 encode_method_sort(ebml_w, 'p');
1894 (ecx.encode_inlined_item)(
1896 ii_method(local_def(item.id), m));
1903 item_mac(*) => fail!(~"item macros unimplemented")
1908 fn encode_info_for_foreign_item(ecx: @EncodeContext,
1909 ebml_w: &writer::Encoder,
1910 nitem: @foreign_item,
1911 index: @mut ~[entry<int>],
1912 path: ast_map::path,
1914 if !reachable(ecx, nitem.id) { return; }
1915 index.push(entry { val: nitem.id, pos: ebml_w.writer.tell() });
1917 ebml_w.start_tag(tag_items_data_item);
1919 foreign_item_fn(_, purity, ref generics) => {
1920 encode_def_id(ebml_w, local_def(nitem.id));
1921 encode_family(ebml_w, purity_fn_family(purity));
1922 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1923 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1924 if abi.is_intrinsic() {
1925 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_foreign(nitem));
1927 encode_symbol(ecx, ebml_w, nitem.id);
1929 encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident));
1931 foreign_item_const(*) => {
1932 encode_def_id(ebml_w, local_def(nitem.id));
1933 encode_family(ebml_w, 'c');
1934 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1935 encode_symbol(ecx, ebml_w, nitem.id);
1936 encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident));
1943 fn encode_info_for_foreign_item(ecx: @EncodeContext,
1944 ebml_w: &mut writer::Encoder,
1945 nitem: @foreign_item,
1946 index: @mut ~[entry<int>],
1947 path: ast_map::path,
1949 if !reachable(ecx, nitem.id) { return; }
1950 index.push(entry { val: nitem.id, pos: ebml_w.writer.tell() });
1952 ebml_w.start_tag(tag_items_data_item);
1954 foreign_item_fn(_, purity, ref generics) => {
1955 encode_def_id(ebml_w, local_def(nitem.id));
1956 encode_family(ebml_w, purity_fn_family(purity));
1957 encode_type_param_bounds(ebml_w, ecx, &generics.ty_params);
1958 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1959 if abi.is_intrinsic() {
1960 (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_foreign(nitem));
1962 encode_symbol(ecx, ebml_w, nitem.id);
1964 encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident));
1966 foreign_item_const(*) => {
1967 encode_def_id(ebml_w, local_def(nitem.id));
1968 encode_family(ebml_w, 'c');
1969 encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1970 encode_symbol(ecx, ebml_w, nitem.id);
1971 encode_path(ecx, ebml_w, path, ast_map::path_name(nitem.ident));
1978 fn encode_info_for_items(ecx: @EncodeContext,
1979 ebml_w: &writer::Encoder,
1982 let index = @mut ~[];
1983 ebml_w.start_tag(tag_items_data);
1984 index.push(entry { val: crate_node_id, pos: ebml_w.writer.tell() });
1985 encode_info_for_mod(ecx, ebml_w, &crate.node.module,
1987 syntax::parse::token::special_idents::invalid);
1988 visit::visit_crate(crate, (), visit::mk_vt(@visit::Visitor {
1989 visit_expr: |_e, _cx, _v| { },
1991 let ebml_w = copy *ebml_w;
1993 visit::visit_item(i, cx, v);
1994 match *ecx.tcx.items.get(&i.id) {
1995 ast_map::node_item(_, pt) => {
1996 encode_info_for_item(ecx, &ebml_w, i,
1999 _ => fail!(~"bad item")
2003 visit_foreign_item: {
2004 let ebml_w = copy *ebml_w;
2006 visit::visit_foreign_item(ni, cx, v);
2007 match *ecx.tcx.items.get(&ni.id) {
2008 ast_map::node_foreign_item(_, abi, _, pt) => {
2009 encode_info_for_foreign_item(ecx, &ebml_w, ni,
2010 index, /*bad*/copy *pt,
2013 // case for separate item and foreign-item tables
2014 _ => fail!(~"bad foreign item")
2018 ..*visit::default_visitor()
2021 return /*bad*/copy *index;
2025 fn encode_info_for_items(ecx: @EncodeContext,
2026 ebml_w: &mut writer::Encoder,
2029 let index = @mut ~[];
2030 ebml_w.start_tag(tag_items_data);
2031 index.push(entry { val: crate_node_id, pos: ebml_w.writer.tell() });
2032 encode_info_for_mod(ecx, ebml_w, &crate.node.module,
2034 syntax::parse::token::special_idents::invalid);
2035 visit::visit_crate(crate, (), visit::mk_vt(@visit::Visitor {
2036 visit_expr: |_e, _cx, _v| { },
2038 let ebml_w = copy *ebml_w;
2040 visit::visit_item(i, cx, v);
2041 match *ecx.tcx.items.get(&i.id) {
2042 ast_map::node_item(_, pt) => {
2043 let mut ebml_w = copy ebml_w;
2044 encode_info_for_item(ecx, &mut ebml_w, i, index, *pt);
2046 _ => fail!(~"bad item")
2050 visit_foreign_item: {
2051 let ebml_w = copy *ebml_w;
2053 visit::visit_foreign_item(ni, cx, v);
2054 match *ecx.tcx.items.get(&ni.id) {
2055 ast_map::node_foreign_item(_, abi, _, pt) => {
2056 let mut ebml_w = copy ebml_w;
2057 encode_info_for_foreign_item(ecx,
2064 // case for separate item and foreign-item tables
2065 _ => fail!(~"bad foreign item")
2069 ..*visit::default_visitor()
2072 return /*bad*/copy *index;
2076 // Path and definition ID indexing
2078 fn create_index<T:Copy + Hash + IterBytes>(index: ~[entry<T>]) ->
2080 let mut buckets: ~[@mut ~[entry<T>]] = ~[];
2081 for uint::range(0u, 256u) |_i| { buckets.push(@mut ~[]); };
2082 for index.each |elt| {
2083 let h = elt.val.hash() as uint;
2084 buckets[h % 256].push(*elt);
2087 let mut buckets_frozen = ~[];
2088 for buckets.each |bucket| {
2089 buckets_frozen.push(@/*bad*/copy **bucket);
2091 return buckets_frozen;
2095 fn encode_index<T>(ebml_w: &writer::Encoder,
2096 buckets: ~[@~[entry<T>]],
2097 write_fn: &fn(@io::Writer, &T)) {
2098 let writer = ebml_w.writer;
2099 ebml_w.start_tag(tag_index);
2100 let mut bucket_locs: ~[uint] = ~[];
2101 ebml_w.start_tag(tag_index_buckets);
2102 for buckets.each |bucket| {
2103 bucket_locs.push(ebml_w.writer.tell());
2104 ebml_w.start_tag(tag_index_buckets_bucket);
2105 for vec::each(**bucket) |elt| {
2106 ebml_w.start_tag(tag_index_buckets_bucket_elt);
2107 assert!(elt.pos < 0xffff_ffff);
2108 writer.write_be_u32(elt.pos as u32);
2109 write_fn(writer, &elt.val);
2115 ebml_w.start_tag(tag_index_table);
2116 for bucket_locs.each |pos| {
2117 assert!(*pos < 0xffff_ffff);
2118 writer.write_be_u32(*pos as u32);
2125 fn encode_index<T>(ebml_w: &mut writer::Encoder,
2126 buckets: ~[@~[entry<T>]],
2127 write_fn: &fn(@io::Writer, &T)) {
2128 let writer = ebml_w.writer;
2129 ebml_w.start_tag(tag_index);
2130 let mut bucket_locs: ~[uint] = ~[];
2131 ebml_w.start_tag(tag_index_buckets);
2132 for buckets.each |bucket| {
2133 bucket_locs.push(ebml_w.writer.tell());
2134 ebml_w.start_tag(tag_index_buckets_bucket);
2135 for vec::each(**bucket) |elt| {
2136 ebml_w.start_tag(tag_index_buckets_bucket_elt);
2137 assert!(elt.pos < 0xffff_ffff);
2138 writer.write_be_u32(elt.pos as u32);
2139 write_fn(writer, &elt.val);
2145 ebml_w.start_tag(tag_index_table);
2146 for bucket_locs.each |pos| {
2147 assert!(*pos < 0xffff_ffff);
2148 writer.write_be_u32(*pos as u32);
2154 fn write_str(writer: @io::Writer, s: ~str) {
2155 writer.write_str(s);
2158 fn write_int(writer: @io::Writer, &n: &int) {
2159 assert!(n < 0x7fff_ffff);
2160 writer.write_be_u32(n as u32);
2164 fn encode_meta_item(ebml_w: &writer::Encoder, mi: @meta_item) {
2166 meta_word(name) => {
2167 ebml_w.start_tag(tag_meta_item_word);
2168 ebml_w.start_tag(tag_meta_item_name);
2169 ebml_w.writer.write(str::to_bytes(*name));
2173 meta_name_value(name, value) => {
2176 ebml_w.start_tag(tag_meta_item_name_value);
2177 ebml_w.start_tag(tag_meta_item_name);
2178 ebml_w.writer.write(str::to_bytes(*name));
2180 ebml_w.start_tag(tag_meta_item_value);
2181 ebml_w.writer.write(str::to_bytes(*value));
2185 _ => {/* FIXME (#623): encode other variants */ }
2188 meta_list(name, ref items) => {
2189 ebml_w.start_tag(tag_meta_item_list);
2190 ebml_w.start_tag(tag_meta_item_name);
2191 ebml_w.writer.write(str::to_bytes(*name));
2193 for items.each |inner_item| {
2194 encode_meta_item(ebml_w, *inner_item);
2202 fn encode_meta_item(ebml_w: &mut writer::Encoder, mi: @meta_item) {
2204 meta_word(name) => {
2205 ebml_w.start_tag(tag_meta_item_word);
2206 ebml_w.start_tag(tag_meta_item_name);
2207 ebml_w.writer.write(str::to_bytes(*name));
2211 meta_name_value(name, value) => {
2214 ebml_w.start_tag(tag_meta_item_name_value);
2215 ebml_w.start_tag(tag_meta_item_name);
2216 ebml_w.writer.write(str::to_bytes(*name));
2218 ebml_w.start_tag(tag_meta_item_value);
2219 ebml_w.writer.write(str::to_bytes(*value));
2223 _ => {/* FIXME (#623): encode other variants */ }
2226 meta_list(name, ref items) => {
2227 ebml_w.start_tag(tag_meta_item_list);
2228 ebml_w.start_tag(tag_meta_item_name);
2229 ebml_w.writer.write(str::to_bytes(*name));
2231 for items.each |inner_item| {
2232 encode_meta_item(ebml_w, *inner_item);
2240 fn encode_attributes(ebml_w: &writer::Encoder, attrs: &[attribute]) {
2241 ebml_w.start_tag(tag_attributes);
2242 for attrs.each |attr| {
2243 ebml_w.start_tag(tag_attribute);
2244 encode_meta_item(ebml_w, attr.node.value);
2251 fn encode_attributes(ebml_w: &mut writer::Encoder, attrs: &[attribute]) {
2252 ebml_w.start_tag(tag_attributes);
2253 for attrs.each |attr| {
2254 ebml_w.start_tag(tag_attribute);
2255 encode_meta_item(ebml_w, attr.node.value);
2261 // So there's a special crate attribute called 'link' which defines the
2262 // metadata that Rust cares about for linking crates. This attribute requires
2263 // 'name' and 'vers' items, so if the user didn't provide them we will throw
2264 // them in anyway with default values.
2265 fn synthesize_crate_attrs(ecx: @EncodeContext,
2266 crate: &crate) -> ~[attribute] {
2268 fn synthesize_link_attr(ecx: @EncodeContext, items: ~[@meta_item]) ->
2271 assert!(!ecx.link_meta.name.is_empty());
2272 assert!(!ecx.link_meta.vers.is_empty());
2275 attr::mk_name_value_item_str(@~"name",
2276 @ecx.link_meta.name.to_owned());
2278 attr::mk_name_value_item_str(@~"vers",
2279 @ecx.link_meta.vers.to_owned());
2283 let tmp = attr::remove_meta_items_by_name(items, ~"name");
2284 attr::remove_meta_items_by_name(tmp, ~"vers")
2287 let meta_items = vec::append(~[name_item, vers_item], other_items);
2288 let link_item = attr::mk_list_item(@~"link", meta_items);
2290 return attr::mk_attr(link_item);
2293 let mut attrs: ~[attribute] = ~[];
2294 let mut found_link_attr = false;
2295 for crate.node.attrs.each |attr| {
2297 if *attr::get_attr_name(attr) != ~"link" {
2300 match attr.node.value.node {
2301 meta_list(_, ref l) => {
2302 found_link_attr = true;;
2303 synthesize_link_attr(ecx, /*bad*/copy *l)
2305 _ => /*bad*/copy *attr
2310 if !found_link_attr { attrs.push(synthesize_link_attr(ecx, ~[])); }
2316 fn encode_crate_deps(ecx: @EncodeContext,
2317 ebml_w: &writer::Encoder,
2318 cstore: @mut cstore::CStore) {
2319 fn get_ordered_deps(ecx: @EncodeContext, cstore: @mut cstore::CStore)
2320 -> ~[decoder::crate_dep] {
2321 type numdep = decoder::crate_dep;
2323 // Pull the cnums and name,vers,hash out of cstore
2325 do cstore::iter_crate_data(cstore) |key, val| {
2326 let dep = decoder::crate_dep {cnum: key,
2327 name: ecx.tcx.sess.ident_of(/*bad*/ copy *val.name),
2328 vers: decoder::get_crate_vers(val.data),
2329 hash: decoder::get_crate_hash(val.data)};
2334 std::sort::quick_sort(deps, |kv1, kv2| kv1.cnum <= kv2.cnum);
2336 // Sanity-check the crate numbers
2337 let mut expected_cnum = 1;
2339 assert!((n.cnum == expected_cnum));
2343 // mut -> immutable hack for vec::map
2344 deps.slice(0, deps.len()).to_owned()
2347 // We're just going to write a list of crate 'name-hash-version's, with
2348 // the assumption that they are numbered 1 to n.
2349 // FIXME (#2166): This is not nearly enough to support correct versioning
2350 // but is enough to get transitive crate dependencies working.
2351 ebml_w.start_tag(tag_crate_deps);
2352 for get_ordered_deps(ecx, cstore).each |dep| {
2353 encode_crate_dep(ecx, ebml_w, *dep);
2359 fn encode_crate_deps(ecx: @EncodeContext,
2360 ebml_w: &mut writer::Encoder,
2361 cstore: @mut cstore::CStore) {
2362 fn get_ordered_deps(ecx: @EncodeContext, cstore: @mut cstore::CStore)
2363 -> ~[decoder::crate_dep] {
2364 type numdep = decoder::crate_dep;
2366 // Pull the cnums and name,vers,hash out of cstore
2368 do cstore::iter_crate_data(cstore) |key, val| {
2369 let dep = decoder::crate_dep {cnum: key,
2370 name: ecx.tcx.sess.ident_of(/*bad*/ copy *val.name),
2371 vers: decoder::get_crate_vers(val.data),
2372 hash: decoder::get_crate_hash(val.data)};
2377 std::sort::quick_sort(deps, |kv1, kv2| kv1.cnum <= kv2.cnum);
2379 // Sanity-check the crate numbers
2380 let mut expected_cnum = 1;
2382 assert!((n.cnum == expected_cnum));
2386 // mut -> immutable hack for vec::map
2387 deps.slice(0, deps.len()).to_owned()
2390 // We're just going to write a list of crate 'name-hash-version's, with
2391 // the assumption that they are numbered 1 to n.
2392 // FIXME (#2166): This is not nearly enough to support correct versioning
2393 // but is enough to get transitive crate dependencies working.
2394 ebml_w.start_tag(tag_crate_deps);
2395 for get_ordered_deps(ecx, cstore).each |dep| {
2396 encode_crate_dep(ecx, ebml_w, *dep);
2402 fn encode_lang_items(ecx: @EncodeContext, ebml_w: &writer::Encoder) {
2403 ebml_w.start_tag(tag_lang_items);
2405 for ecx.tcx.lang_items.each_item |def_id, i| {
2406 if def_id.crate != local_crate {
2410 ebml_w.start_tag(tag_lang_items_item);
2412 ebml_w.start_tag(tag_lang_items_item_id);
2413 ebml_w.writer.write_be_u32(i as u32);
2414 ebml_w.end_tag(); // tag_lang_items_item_id
2416 ebml_w.start_tag(tag_lang_items_item_node_id);
2417 ebml_w.writer.write_be_u32(def_id.node as u32);
2418 ebml_w.end_tag(); // tag_lang_items_item_node_id
2420 ebml_w.end_tag(); // tag_lang_items_item
2423 ebml_w.end_tag(); // tag_lang_items
2427 fn encode_lang_items(ecx: @EncodeContext, ebml_w: &mut writer::Encoder) {
2428 ebml_w.start_tag(tag_lang_items);
2430 for ecx.tcx.lang_items.each_item |def_id, i| {
2431 if def_id.crate != local_crate {
2435 ebml_w.start_tag(tag_lang_items_item);
2437 ebml_w.start_tag(tag_lang_items_item_id);
2438 ebml_w.writer.write_be_u32(i as u32);
2439 ebml_w.end_tag(); // tag_lang_items_item_id
2441 ebml_w.start_tag(tag_lang_items_item_node_id);
2442 ebml_w.writer.write_be_u32(def_id.node as u32);
2443 ebml_w.end_tag(); // tag_lang_items_item_node_id
2445 ebml_w.end_tag(); // tag_lang_items_item
2448 ebml_w.end_tag(); // tag_lang_items
2452 fn encode_link_args(ecx: @EncodeContext, ebml_w: &writer::Encoder) {
2453 ebml_w.start_tag(tag_link_args);
2455 let link_args = cstore::get_used_link_args(ecx.cstore);
2456 for link_args.each |link_arg| {
2457 ebml_w.start_tag(tag_link_args_arg);
2458 ebml_w.writer.write_str(link_arg.to_str());
2466 fn encode_link_args(ecx: @EncodeContext, ebml_w: &mut writer::Encoder) {
2467 ebml_w.start_tag(tag_link_args);
2469 let link_args = cstore::get_used_link_args(ecx.cstore);
2470 for link_args.each |link_arg| {
2471 ebml_w.start_tag(tag_link_args_arg);
2472 ebml_w.writer.write_str(link_arg.to_str());
2480 fn encode_crate_dep(ecx: @EncodeContext,
2481 ebml_w: &writer::Encoder,
2482 dep: decoder::crate_dep) {
2483 ebml_w.start_tag(tag_crate_dep);
2484 ebml_w.start_tag(tag_crate_dep_name);
2485 ebml_w.writer.write(str::to_bytes(*ecx.tcx.sess.str_of(dep.name)));
2487 ebml_w.start_tag(tag_crate_dep_vers);
2488 ebml_w.writer.write(str::to_bytes(*dep.vers));
2490 ebml_w.start_tag(tag_crate_dep_hash);
2491 ebml_w.writer.write(str::to_bytes(*dep.hash));
2497 fn encode_crate_dep(ecx: @EncodeContext,
2498 ebml_w: &mut writer::Encoder,
2499 dep: decoder::crate_dep) {
2500 ebml_w.start_tag(tag_crate_dep);
2501 ebml_w.start_tag(tag_crate_dep_name);
2502 ebml_w.writer.write(str::to_bytes(*ecx.tcx.sess.str_of(dep.name)));
2504 ebml_w.start_tag(tag_crate_dep_vers);
2505 ebml_w.writer.write(str::to_bytes(*dep.vers));
2507 ebml_w.start_tag(tag_crate_dep_hash);
2508 ebml_w.writer.write(str::to_bytes(*dep.hash));
2514 fn encode_hash(ebml_w: &writer::Encoder, hash: &str) {
2515 ebml_w.start_tag(tag_crate_hash);
2516 ebml_w.writer.write(str::to_bytes(hash));
2521 fn encode_hash(ebml_w: &mut writer::Encoder, hash: &str) {
2522 ebml_w.start_tag(tag_crate_hash);
2523 ebml_w.writer.write(str::to_bytes(hash));
2527 // NB: Increment this as you change the metadata encoding version.
2528 pub static metadata_encoding_version : &'static [u8] =
2529 &[0x72, //'r' as u8,
2536 pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] {
2537 let wr = @io::BytesWriter();
2550 let EncodeParams{item_symbols, diag, tcx, reachable, reexports2,
2551 discrim_symbols, cstore, encode_inlined_item,
2552 link_meta, _} = parms;
2553 let ecx = @EncodeContext {
2557 reachable: reachable,
2558 reexports2: reexports2,
2559 item_symbols: item_symbols,
2560 discrim_symbols: discrim_symbols,
2561 link_meta: link_meta,
2563 encode_inlined_item: encode_inlined_item,
2564 type_abbrevs: @mut HashMap::new()
2567 let ebml_w = writer::Encoder(wr as @io::Writer);
2569 encode_hash(&ebml_w, ecx.link_meta.extras_hash);
2572 let crate_attrs = synthesize_crate_attrs(ecx, crate);
2573 encode_attributes(&ebml_w, crate_attrs);
2574 ecx.stats.attr_bytes = wr.pos - i;
2577 encode_crate_deps(ecx, &ebml_w, ecx.cstore);
2578 ecx.stats.dep_bytes = wr.pos - i;
2580 // Encode the language items.
2582 encode_lang_items(ecx, &ebml_w);
2583 ecx.stats.lang_item_bytes = wr.pos - i;
2585 // Encode the link args.
2587 encode_link_args(ecx, &ebml_w);
2588 ecx.stats.link_args_bytes = wr.pos - i;
2590 // Encode and index the items.
2591 ebml_w.start_tag(tag_items);
2593 let items_index = encode_info_for_items(ecx, &ebml_w, crate);
2594 ecx.stats.item_bytes = wr.pos - i;
2597 let items_buckets = create_index(items_index);
2598 encode_index(&ebml_w, items_buckets, write_int);
2599 ecx.stats.index_bytes = wr.pos - i;
2602 ecx.stats.total_bytes = wr.pos;
2604 if (tcx.sess.meta_stats()) {
2606 do wr.bytes.each |e| {
2608 ecx.stats.zero_bytes += 1;
2613 io::println("metadata stats:");
2614 io::println(fmt!(" inline bytes: %u", ecx.stats.inline_bytes));
2615 io::println(fmt!(" attribute bytes: %u", ecx.stats.attr_bytes));
2616 io::println(fmt!(" dep bytes: %u", ecx.stats.dep_bytes));
2617 io::println(fmt!(" lang item bytes: %u", ecx.stats.lang_item_bytes));
2618 io::println(fmt!(" link args bytes: %u", ecx.stats.link_args_bytes));
2619 io::println(fmt!(" item bytes: %u", ecx.stats.item_bytes));
2620 io::println(fmt!(" index bytes: %u", ecx.stats.index_bytes));
2621 io::println(fmt!(" zero bytes: %u", ecx.stats.zero_bytes));
2622 io::println(fmt!(" total bytes: %u", ecx.stats.total_bytes));
2625 // Pad this, since something (LLVM, presumably) is cutting off the
2626 // remaining % 4 bytes.
2627 wr.write(&[0u8, 0u8, 0u8, 0u8]);
2629 // FIXME #3396: weird bug here, for reasons unclear this emits random
2630 // looking bytes (mostly 0x1) if we use the version byte-array constant
2631 // above; so we use a string constant inline instead.
2635 // vec::from_slice(metadata_encoding_version) +
2637 (do str::as_bytes(&~"rust\x00\x00\x00\x01") |bytes| {
2638 vec::slice(*bytes, 0, 8).to_vec()
2639 }) + flate::deflate_bytes(wr.bytes)
2643 pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] {
2644 let wr = @io::BytesWriter();
2657 let EncodeParams{item_symbols, diag, tcx, reachable, reexports2,
2658 discrim_symbols, cstore, encode_inlined_item,
2659 link_meta, _} = parms;
2660 let ecx = @EncodeContext {
2664 reachable: reachable,
2665 reexports2: reexports2,
2666 item_symbols: item_symbols,
2667 discrim_symbols: discrim_symbols,
2668 link_meta: link_meta,
2670 encode_inlined_item: encode_inlined_item,
2671 type_abbrevs: @mut HashMap::new()
2674 let mut ebml_w = writer::Encoder(wr as @io::Writer);
2676 encode_hash(&mut ebml_w, ecx.link_meta.extras_hash);
2679 let crate_attrs = synthesize_crate_attrs(ecx, crate);
2680 encode_attributes(&mut ebml_w, crate_attrs);
2681 ecx.stats.attr_bytes = wr.pos - i;
2684 encode_crate_deps(ecx, &mut ebml_w, ecx.cstore);
2685 ecx.stats.dep_bytes = wr.pos - i;
2687 // Encode the language items.
2689 encode_lang_items(ecx, &mut ebml_w);
2690 ecx.stats.lang_item_bytes = wr.pos - i;
2692 // Encode the link args.
2694 encode_link_args(ecx, &mut ebml_w);
2695 ecx.stats.link_args_bytes = wr.pos - i;
2697 // Encode and index the items.
2698 ebml_w.start_tag(tag_items);
2700 let items_index = encode_info_for_items(ecx, &mut ebml_w, crate);
2701 ecx.stats.item_bytes = wr.pos - i;
2704 let items_buckets = create_index(items_index);
2705 encode_index(&mut ebml_w, items_buckets, write_int);
2706 ecx.stats.index_bytes = wr.pos - i;
2709 ecx.stats.total_bytes = wr.pos;
2711 if (tcx.sess.meta_stats()) {
2713 do wr.bytes.each |e| {
2715 ecx.stats.zero_bytes += 1;
2720 io::println("metadata stats:");
2721 io::println(fmt!(" inline bytes: %u", ecx.stats.inline_bytes));
2722 io::println(fmt!(" attribute bytes: %u", ecx.stats.attr_bytes));
2723 io::println(fmt!(" dep bytes: %u", ecx.stats.dep_bytes));
2724 io::println(fmt!(" lang item bytes: %u", ecx.stats.lang_item_bytes));
2725 io::println(fmt!(" link args bytes: %u", ecx.stats.link_args_bytes));
2726 io::println(fmt!(" item bytes: %u", ecx.stats.item_bytes));
2727 io::println(fmt!(" index bytes: %u", ecx.stats.index_bytes));
2728 io::println(fmt!(" zero bytes: %u", ecx.stats.zero_bytes));
2729 io::println(fmt!(" total bytes: %u", ecx.stats.total_bytes));
2732 // Pad this, since something (LLVM, presumably) is cutting off the
2733 // remaining % 4 bytes.
2734 wr.write(&[0u8, 0u8, 0u8, 0u8]);
2736 // FIXME #3396: weird bug here, for reasons unclear this emits random
2737 // looking bytes (mostly 0x1) if we use the version byte-array constant
2738 // above; so we use a string constant inline instead.
2742 // vec::from_slice(metadata_encoding_version) +
2744 (do str::as_bytes(&~"rust\x00\x00\x00\x01") |bytes| {
2745 vec::slice(*bytes, 0, 8).to_vec()
2746 }) + flate::deflate_bytes(wr.bytes)
2749 // Get the encoded string for a type
2750 pub fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str {
2751 let cx = @tyencode::ctxt {
2755 reachable: |_id| false,
2756 abbrevs: tyencode::ac_no_abbrevs};
2757 do io::with_str_writer |wr| {
2758 tyencode::enc_ty(wr, cx, t);