]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/encoder.rs
librustc: Remove uses of `token::ident_to_str()` from librustc
[rust.git] / src / librustc / metadata / encoder.rs
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.
4 //
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.
10
11 // Metadata encoding
12
13
14 use metadata::common::*;
15 use metadata::cstore;
16 use metadata::decoder;
17 use metadata::tyencode;
18 use middle::ty::{node_id_to_type, lookup_item_type};
19 use middle::astencode;
20 use middle::ty;
21 use middle::typeck;
22 use middle;
23
24 use extra::serialize::Encodable;
25 use std::cast;
26 use std::cell::{Cell, RefCell};
27 use std::hashmap::{HashMap, HashSet};
28 use std::io::MemWriter;
29 use std::str;
30 use std::vec;
31 use syntax::abi::AbiSet;
32 use syntax::ast::*;
33 use syntax::ast;
34 use syntax::ast_map;
35 use syntax::ast_util::*;
36 use syntax::ast_util;
37 use syntax::attr::AttrMetaMethods;
38 use syntax::attr;
39 use syntax::codemap;
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;
45 use syntax::visit;
46 use syntax;
47 use writer = extra::ebml::writer;
48
49 // used by astencode:
50 type abbrev_map = @RefCell<HashMap<ty::t, tyencode::ty_abbrev>>;
51
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)
57 }
58
59 pub type encode_inlined_item<'a> = 'a |ecx: &EncodeContext,
60                                        ebml_w: &mut writer::Encoder,
61                                        path: &[ast_map::PathElem],
62                                        ii: InlinedItemRef|;
63
64 pub struct EncodeParams<'a> {
65     diag: @SpanHandler,
66     tcx: ty::ctxt,
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,
75 }
76
77 struct Stats {
78     inline_bytes: Cell<u64>,
79     attr_bytes: Cell<u64>,
80     dep_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>,
91 }
92
93 pub struct EncodeContext<'a> {
94     diag: @SpanHandler,
95     tcx: ty::ctxt,
96     stats: @Stats,
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,
106 }
107
108 pub fn reachable(ecx: &EncodeContext, id: NodeId) -> bool {
109     let reachable = ecx.reachable.borrow();
110     reachable.get().contains(&id)
111 }
112
113 fn encode_name(ecx: &EncodeContext,
114                ebml_w: &mut writer::Encoder,
115                name: Ident) {
116     ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name));
117 }
118
119 fn encode_impl_type_basename(ecx: &EncodeContext,
120                              ebml_w: &mut writer::Encoder,
121                              name: Ident) {
122     ebml_w.wr_tagged_str(tag_item_impl_type_basename,
123                          ecx.tcx.sess.str_of(name));
124 }
125
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));
128 }
129
130 #[deriving(Clone)]
131 struct entry<T> {
132     val: T,
133     pos: u64
134 }
135
136 fn encode_trait_ref(ebml_w: &mut writer::Encoder,
137                     ecx: &EncodeContext,
138                     trait_ref: &ty::TraitRef,
139                     tag: uint) {
140     let ty_str_ctxt = @tyencode::ctxt {
141         diag: ecx.diag,
142         ds: def_to_str,
143         tcx: ecx.tcx,
144         abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
145     };
146
147     ebml_w.start_tag(tag);
148     tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
149     ebml_w.end_tag();
150 }
151
152 fn encode_impl_vtables(ebml_w: &mut writer::Encoder,
153                        ecx: &EncodeContext,
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);
158     ebml_w.end_tag();
159 }
160
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]);
165     ebml_w.end_tag();
166 }
167
168 pub fn def_to_str(did: DefId) -> ~str {
169     format!("{}:{}", did.crate, did.node)
170 }
171
172 fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
173                              ecx: &EncodeContext,
174                              params: @~[ty::TypeParameterDef],
175                              tag: uint) {
176     let ty_str_ctxt = @tyencode::ctxt {
177         diag: ecx.diag,
178         ds: def_to_str,
179         tcx: ecx.tcx,
180         abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
181     };
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);
185         ebml_w.end_tag();
186     }
187 }
188
189 fn encode_region_param_defs(ebml_w: &mut writer::Encoder,
190                             ecx: &EncodeContext,
191                             params: @[ty::RegionParameterDef]) {
192     for param in params.iter() {
193         ebml_w.start_tag(tag_region_param_def);
194
195         ebml_w.start_tag(tag_region_param_def_ident);
196         encode_name(ecx, ebml_w, param.ident);
197         ebml_w.end_tag();
198
199         ebml_w.wr_tagged_str(tag_region_param_def_def_id,
200                              def_to_str(param.def_id));
201
202         ebml_w.end_tag();
203     }
204 }
205
206 fn encode_item_variances(ebml_w: &mut writer::Encoder,
207                          ecx: &EncodeContext,
208                          id: ast::NodeId) {
209     let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
210     ebml_w.start_tag(tag_item_variances);
211     v.encode(ebml_w);
212     ebml_w.end_tag();
213 }
214
215 fn encode_bounds_and_type(ebml_w: &mut writer::Encoder,
216                           ecx: &EncodeContext,
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);
222 }
223
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());
228     ebml_w.end_tag();
229 }
230
231 pub fn write_type(ecx: &EncodeContext,
232                   ebml_w: &mut writer::Encoder,
233                   typ: ty::t) {
234     let ty_str_ctxt = @tyencode::ctxt {
235         diag: ecx.diag,
236         ds: def_to_str,
237         tcx: ecx.tcx,
238         abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
239     };
240     tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
241 }
242
243 pub fn write_vstore(ecx: &EncodeContext,
244                     ebml_w: &mut writer::Encoder,
245                     vstore: ty::vstore) {
246     let ty_str_ctxt = @tyencode::ctxt {
247         diag: ecx.diag,
248         ds: def_to_str,
249         tcx: ecx.tcx,
250         abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
251     };
252     tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
253 }
254
255 fn encode_type(ecx: &EncodeContext,
256                ebml_w: &mut writer::Encoder,
257                typ: ty::t) {
258     ebml_w.start_tag(tag_items_data_item_type);
259     write_type(ecx, ebml_w, typ);
260     ebml_w.end_tag();
261 }
262
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);
267
268     let ty_str_ctxt = @tyencode::ctxt {
269         diag: ecx.diag,
270         ds: def_to_str,
271         tcx: ecx.tcx,
272         abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
273     };
274     tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
275
276     ebml_w.end_tag();
277 }
278
279 fn encode_symbol(ecx: &EncodeContext,
280                  ebml_w: &mut writer::Encoder,
281                  id: NodeId) {
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) {
285         Some(x) => {
286             debug!("encode_symbol(id={:?}, str={})", id, *x);
287             ebml_w.writer.write(x.as_bytes());
288         }
289         None => {
290             ecx.diag.handler().bug(
291                 format!("encode_symbol: id not found {}", id));
292         }
293     }
294     ebml_w.end_tag();
295 }
296
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());
303     ebml_w.end_tag();
304 }
305
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());
310     ebml_w.end_tag();
311 }
312
313 fn encode_struct_fields(ecx: &EncodeContext,
314                              ebml_w: &mut writer::Encoder,
315                              def: @StructDef) {
316     for f in def.fields.iter() {
317         match f.node.kind {
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));
323                ebml_w.end_tag();
324             }
325             UnnamedField => {
326                 ebml_w.start_tag(tag_item_unnamed_field);
327                 encode_def_id(ebml_w, local_def(f.node.id));
328                 ebml_w.end_tag();
329             }
330         }
331     }
332 }
333
334 fn encode_enum_variant_info(ecx: &EncodeContext,
335                             ebml_w: &mut writer::Encoder,
336                             id: NodeId,
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);
342
343     let mut disr_val = 0;
344     let mut i = 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);
349         {
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(),
354             });
355         }
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')
361         }
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);
370             }
371             ast::TupleVariantKind(_) => {},
372             ast::StructVariantKind(def) => {
373                 let idx = encode_info_for_struct(ecx, ebml_w, path,
374                                          def.fields, index);
375                 encode_struct_fields(ecx, ebml_w, def);
376                 let bkts = create_index(idx);
377                 encode_index(ebml_w, bkts, write_i64);
378             }
379         }
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;
383         }
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));
388         ebml_w.end_tag();
389         disr_val += 1;
390         i += 1;
391     }
392 }
393
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) {
401         match elt {
402             ast_map::PathMod(n) => {
403                 ebml_w.wr_tagged_str(tag_path_elem_mod, ecx.tcx.sess.str_of(n));
404             }
405             ast_map::PathName(n) => {
406                 ebml_w.wr_tagged_str(tag_path_elem_name, ecx.tcx.sess.str_of(n));
407             }
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);
413                 ebml_w.end_tag();
414             }
415         }
416     }
417
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);
422     }
423     encode_path_elem(ecx, ebml_w, name);
424     ebml_w.end_tag();
425 }
426
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));
437     ebml_w.end_tag();
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)));
440     ebml_w.end_tag();
441     ebml_w.end_tag();
442 }
443
444 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
445                                          ebml_w: &mut writer::Encoder,
446                                          exp: &middle::resolve::Export2)
447                                          -> bool {
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,
456                                                         m.def_id, m.ident);
457                     }
458                 }
459             }
460
461             true
462         }
463         None => { false }
464     }
465 }
466
467 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
468                                           ebml_w: &mut writer::Encoder,
469                                           exp: &middle::resolve::Export2)
470                                           -> bool {
471     let trait_methods_cache = ecx.tcx.trait_methods_cache.borrow();
472     match trait_methods_cache.get().find(&exp.def_id) {
473         Some(methods) => {
474             for &m in methods.iter() {
475                 if m.explicit_self == ast::SelfStatic {
476                     encode_reexported_static_method(ecx, ebml_w, exp,
477                                                     m.def_id, m.ident);
478                 }
479             }
480
481             true
482         }
483         None => { false }
484     }
485 }
486
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);
494
495             //
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.
499             //
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.
504             //
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) {} \
509                                  [trait]",
510                                 original_name);
511                     }
512                 }
513                 else {
514                     debug!("(encode reexported static methods) {} [base]",
515                             original_name);
516                 }
517             }
518         }
519         _ => {}
520     }
521 }
522
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:
525 ///
526 /// * For enums, iterates through the node IDs of the variants.
527 ///
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;
531     match item.node {
532         ItemEnum(ref enum_def, _) => {
533             for variant in enum_def.variants.iter() {
534                 continue_ = callback(variant.node.id);
535                 if !continue_ {
536                     break
537                 }
538             }
539         }
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);
547                 }
548                 _ => {}
549             }
550         }
551         _ => {}
552     }
553
554     continue_
555 }
556
557 fn encode_reexports(ecx: &EncodeContext,
558                     ebml_w: &mut writer::Encoder,
559                     id: NodeId,
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 \
568                         {}",
569                        exp.name,
570                        exp.def_id.crate,
571                        exp.def_id.node,
572                        id);
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));
576                 ebml_w.end_tag();
577                 ebml_w.start_tag(tag_items_data_item_reexport_name);
578                 ebml_w.wr_str(exp.name);
579                 ebml_w.end_tag();
580                 ebml_w.end_tag();
581                 encode_reexported_static_methods(ecx, ebml_w, path, exp);
582             }
583         }
584         None => {
585             debug!("(encoding info for module) found no reexports for {}",
586                    id);
587         }
588     }
589 }
590
591 fn encode_info_for_mod(ecx: &EncodeContext,
592                        ebml_w: &mut writer::Encoder,
593                        md: &Mod,
594                        id: NodeId,
595                        path: &[ast_map::PathElem],
596                        name: Ident,
597                        vis: Visibility) {
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);
603
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)));
608         ebml_w.end_tag();
609
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)));
613             ebml_w.end_tag();
614             true
615         });
616
617         match item.node {
618             ItemImpl(..) => {
619                 let (ident, did) = (item.ident, item.id);
620                 debug!("(encoding info for module) ... encoding impl {} \
621                         ({:?}/{:?})",
622                         ecx.tcx.sess.str_of(ident),
623                         did,
624                         ast_map::node_id_to_str(ecx.tcx.items, did, token::get_ident_interner()));
625
626                 ebml_w.start_tag(tag_mod_impl);
627                 ebml_w.wr_str(def_to_str(local_def(did)));
628                 ebml_w.end_tag();
629             }
630             _ => {}
631         }
632     }
633
634     encode_path(ecx, ebml_w, path, ast_map::PathMod(name));
635     encode_visibility(ebml_w, vis);
636
637     // Encode the reexports of this module, if this module is public.
638     if vis == Public {
639         debug!("(encoding info for module) encoding reexports for {}", id);
640         encode_reexports(ecx, ebml_w, id, path);
641     }
642
643     ebml_w.end_tag();
644 }
645
646 fn encode_struct_field_family(ebml_w: &mut writer::Encoder,
647                               visibility: Visibility) {
648     encode_family(ebml_w, match visibility {
649         Public => 'g',
650         Private => 'j',
651         Inherited => 'N'
652     });
653 }
654
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 {
658         Public => 'y',
659         Private => 'n',
660         Inherited => 'i',
661     };
662     ebml_w.wr_str(str::from_char(ch));
663     ebml_w.end_tag();
664 }
665
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);
668
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);
679         }
680     }
681
682     ebml_w.end_tag();
683
684     fn encode_mutability(ebml_w: &writer::Encoder,
685                          m: ast::Mutability) {
686         match m {
687             MutImmutable => ebml_w.writer.write(&[ 'i' as u8 ]),
688             MutMutable => ebml_w.writer.write(&[ 'm' as u8 ]),
689         }
690     }
691 }
692
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 ]);
696     ebml_w.end_tag();
697 }
698
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());
705         ebml_w.end_tag();
706     }
707 }
708
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>]>)
715                           -> ~[entry<i64>] {
716     /* Each class has its own index, since different classes
717        may have fields with the same name */
718     let mut index = ~[];
719     let tcx = ecx.tcx;
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)
726         };
727
728         let id = field.node.id;
729         index.push(entry {val: id as i64, pos: ebml_w.writer.tell()});
730         {
731             let mut global_index = global_index.borrow_mut();
732             global_index.get().push(entry {
733                 val: id as i64,
734                 pos: ebml_w.writer.tell(),
735             });
736         }
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));
745         ebml_w.end_tag();
746     }
747     index
748 }
749
750 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
751                                ebml_w: &mut writer::Encoder,
752                                path: &[ast_map::PathElem],
753                                name: ast::Ident,
754                                ctor_id: NodeId,
755                                index: @RefCell<~[entry<i64>]>,
756                                struct_id: NodeId) {
757     {
758         let mut index = index.borrow_mut();
759         index.get().push(entry {
760             val: ctor_id as i64,
761             pos: ebml_w.writer.tell(),
762         });
763     }
764
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));
774
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);
778     }
779
780     ebml_w.end_tag();
781 }
782
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 {
796         ast::SelfStatic => {
797             encode_family(ebml_w, purity_static_method_family(purity));
798         }
799         _ => encode_family(ebml_w, purity_fn_family(purity))
800     }
801     encode_provided_source(ebml_w, method_ty.provided_source);
802 }
803
804 fn encode_info_for_method(ecx: &EncodeContext,
805                           ebml_w: &mut writer::Encoder,
806                           m: &ty::Method,
807                           impl_path: &[ast_map::PathElem],
808                           is_default_impl: bool,
809                           parent_id: NodeId,
810                           ast_method_opt: Option<@Method>) {
811
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);
815
816     encode_method_ty_fields(ecx, ebml_w, m);
817     encode_parent_item(ebml_w, local_def(parent_id));
818
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);
822
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),
826         None => ()
827     }
828
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));
836         } else {
837             encode_symbol(ecx, ebml_w, m.def_id.node);
838         }
839     }
840
841     ebml_w.end_tag();
842 }
843
844 fn purity_fn_family(p: Purity) -> char {
845     match p {
846         UnsafeFn => 'u',
847         ImpureFn => 'f',
848         ExternFn => 'e'
849     }
850 }
851
852 fn purity_static_method_family(p: Purity) -> char {
853     match p {
854         UnsafeFn => 'U',
855         ImpureFn => 'F',
856         _ => fail!("extern fn can't be static")
857     }
858 }
859
860
861 fn should_inline(attrs: &[Attribute]) -> bool {
862     use syntax::attr::*;
863     match find_inline_attr(attrs) {
864         InlineNone | InlineNever  => false,
865         InlineHint | InlineAlways => true
866     }
867 }
868
869 // Encodes the inherent implementations of a structure, enumeration, or trait.
870 fn encode_inherent_implementations(ecx: &EncodeContext,
871                                    ebml_w: &mut writer::Encoder,
872                                    def_id: DefId) {
873     let inherent_impls = ecx.tcx.inherent_impls.borrow();
874     match inherent_impls.get().find(&def_id) {
875         None => {}
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);
881                 ebml_w.end_tag();
882             }
883         }
884     }
885 }
886
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) {
893         None => {}
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);
899                 ebml_w.end_tag();
900             }
901         }
902     }
903 }
904
905 fn encode_info_for_item(ecx: &EncodeContext,
906                         ebml_w: &mut writer::Encoder,
907                         item: &Item,
908                         index: @RefCell<~[entry<i64>]>,
909                         path: &[ast_map::PathElem],
910                         vis: ast::Visibility) {
911     let tcx = ecx.tcx;
912
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 {
917             val: item.id as i64,
918             pos: ebml_w.writer.tell(),
919         });
920     }
921     let add_to_index: || = || add_to_index(item, ebml_w, index);
922
923     debug!("encoding info for item at {}",
924            ecx.tcx.sess.codemap.span_to_str(item.span));
925
926     let def_id = local_def(item.id);
927     match item.node {
928       ItemStatic(_, m, _) => {
929         add_to_index();
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');
934         } else {
935             encode_family(ebml_w, 'c');
936         }
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);
942
943         let non_inlineable;
944         {
945             let non_inlineable_statics = ecx.non_inlineable_statics.borrow();
946             non_inlineable = non_inlineable_statics.get().contains(&item.id);
947         }
948
949         if !non_inlineable {
950             (ecx.encode_inlined_item)(ecx, ebml_w, path, IIItemRef(item));
951         }
952         encode_visibility(ebml_w, vis);
953         ebml_w.end_tag();
954       }
955       ItemFn(_, purity, _, ref generics, _) => {
956         add_to_index();
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));
967         } else {
968             encode_symbol(ecx, ebml_w, item.id);
969         }
970         encode_visibility(ebml_w, vis);
971         ebml_w.end_tag();
972       }
973       ItemMod(ref m) => {
974         add_to_index();
975         encode_info_for_mod(ecx,
976                             ebml_w,
977                             m,
978                             item.id,
979                             path,
980                             item.ident,
981                             item.vis);
982       }
983       ItemForeignMod(ref fm) => {
984         add_to_index();
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));
990
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)));
995             ebml_w.end_tag();
996         }
997         encode_visibility(ebml_w, vis);
998         ebml_w.end_tag();
999       }
1000       ItemTy(..) => {
1001         add_to_index();
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);
1009         ebml_w.end_tag();
1010       }
1011       ItemEnum(ref enum_definition, ref generics) => {
1012         add_to_index();
1013
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));
1023         }
1024         (ecx.encode_inlined_item)(ecx, ebml_w, path, IIItemRef(item));
1025         encode_path(ecx, ebml_w, path, ast_map::PathName(item.ident));
1026
1027         // Encode inherent implementations for this enumeration.
1028         encode_inherent_implementations(ecx, ebml_w, def_id);
1029
1030         encode_visibility(ebml_w, vis);
1031         ebml_w.end_tag();
1032
1033         encode_enum_variant_info(ecx,
1034                                  ebml_w,
1035                                  item.id,
1036                                  (*enum_definition).variants,
1037                                  path,
1038                                  index,
1039                                  generics);
1040       }
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
1045            class itself */
1046         let idx = encode_info_for_struct(ecx, ebml_w, path,
1047                                          struct_def.fields, index);
1048
1049         /* Index the class*/
1050         add_to_index();
1051
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));
1057
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);
1063
1064         /* Encode def_ids for each field and method
1065          for methods, write all the stuff get_trait_method
1066         needs to know*/
1067         encode_struct_fields(ecx, ebml_w, struct_def);
1068
1069         (ecx.encode_inlined_item)(ecx, ebml_w, path, IIItemRef(item));
1070
1071         // Encode inherent implementations for this structure.
1072         encode_inherent_implementations(ecx, ebml_w, def_id);
1073
1074         /* Each class has its own index -- encode it */
1075         let bkts = create_index(idx);
1076         encode_index(ebml_w, bkts, write_i64);
1077         ebml_w.end_tag();
1078
1079         // If this is a tuple- or enum-like struct, encode the type of the
1080         // constructor.
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"),
1086             };
1087
1088             encode_info_for_struct_ctor(ecx,
1089                                         ebml_w,
1090                                         path,
1091                                         item.ident,
1092                                         ctor_id,
1093                                         index,
1094                                         def_id.node);
1095         }
1096       }
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);
1102
1103         add_to_index();
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);
1110         match ty.node {
1111             ast::TyPath(ref path, ref bounds, _) if path.segments
1112                                                         .len() == 1 => {
1113                 assert!(bounds.is_none());
1114                 encode_impl_type_basename(ecx, ebml_w,
1115                                           ast_util::path_to_ident(path));
1116             }
1117             _ => {}
1118         }
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());
1123             ebml_w.end_tag();
1124         }
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);
1131         }
1132         let elt = ast_map::impl_pretty_name(opt_trait, ty);
1133         encode_path(ecx, ebml_w, path, elt);
1134         ebml_w.end_tag();
1135
1136         // >:-<
1137         let mut impl_path = vec::append(~[], path);
1138         impl_path.push(elt);
1139
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])
1148             } else { None };
1149
1150             {
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(),
1155                 });
1156             }
1157             encode_info_for_method(ecx,
1158                                    ebml_w,
1159                                    *m,
1160                                    impl_path,
1161                                    false,
1162                                    item.id,
1163                                    ast_method)
1164         }
1165       }
1166       ItemTrait(_, ref super_traits, ref ms) => {
1167         add_to_index();
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);
1185             ebml_w.end_tag();
1186
1187             ebml_w.start_tag(tag_mod_child);
1188             ebml_w.wr_str(def_to_str(method_def_id));
1189             ebml_w.end_tag();
1190         }
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);
1198         }
1199
1200         // Encode the implementations of this trait.
1201         encode_extension_implementations(ecx, ebml_w, def_id);
1202
1203         ebml_w.end_tag();
1204
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);
1209
1210             let method_ty = ty::method(tcx, method_def_id);
1211
1212             {
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(),
1217                 });
1218             }
1219
1220             ebml_w.start_tag(tag_items_data_item);
1221
1222             encode_method_ty_fields(ecx, ebml_w, method_ty);
1223
1224             encode_parent_item(ebml_w, def_id);
1225
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));
1229
1230             match method_ty.explicit_self {
1231                 SelfStatic => {
1232                     encode_family(ebml_w,
1233                                   purity_static_method_family(
1234                                       method_ty.fty.purity));
1235
1236                     let tpt = ty::lookup_item_type(tcx, method_def_id);
1237                     encode_bounds_and_type(ebml_w, ecx, &tpt);
1238                 }
1239
1240                 _ => {
1241                     encode_family(ebml_w,
1242                                   purity_fn_family(
1243                                       method_ty.fty.purity));
1244                 }
1245             }
1246
1247             match ms[i] {
1248                 Required(ref tm) => {
1249                     encode_attributes(ebml_w, tm.attrs);
1250                     encode_method_sort(ebml_w, 'r');
1251                 }
1252
1253                 Provided(m) => {
1254                     encode_attributes(ebml_w, m.attrs);
1255                     // If this is a static method, we've already encoded
1256                     // this.
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);
1261                     }
1262                     encode_method_sort(ebml_w, 'p');
1263                     (ecx.encode_inlined_item)(
1264                         ecx, ebml_w, path,
1265                         IIMethodRef(def_id, true, m));
1266                 }
1267             }
1268
1269             ebml_w.end_tag();
1270         }
1271
1272         // Encode inherent implementations for this trait.
1273         encode_inherent_implementations(ecx, ebml_w, def_id);
1274       }
1275       ItemMac(..) => {
1276         // macros are encoded separately
1277       }
1278     }
1279 }
1280
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,
1286                                 abi: AbiSet) {
1287     {
1288         let mut index = index.borrow_mut();
1289         index.get().push(entry {
1290             val: nitem.id as i64,
1291             pos: ebml_w.writer.tell(),
1292         });
1293     }
1294
1295     ebml_w.start_tag(tag_items_data_item);
1296     match nitem.node {
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));
1305         } else {
1306             encode_symbol(ecx, ebml_w, nitem.id);
1307         }
1308         encode_path(ecx, ebml_w, *path, ast_map::PathName(nitem.ident));
1309       }
1310       ForeignItemStatic(_, mutbl) => {
1311         encode_def_id(ebml_w, local_def(nitem.id));
1312         if mutbl {
1313             encode_family(ebml_w, 'b');
1314         } else {
1315             encode_family(ebml_w, 'c');
1316         }
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));
1321       }
1322     }
1323     ebml_w.end_tag();
1324 }
1325
1326 fn my_visit_expr(_e: &Expr) { }
1327
1328 fn my_visit_item(i: &Item,
1329                  items: ast_map::Map,
1330                  ebml_w: &mut writer::Encoder,
1331                  ecx_ptr: *int,
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()
1337             };
1338             // See above
1339             let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1340             encode_info_for_item(ecx, &mut ebml_w, i, index, *pt, i.vis);
1341         }
1342         _ => fail!("bad item")
1343     }
1344 }
1345
1346 fn my_visit_foreign_item(ni: &ForeignItem,
1347                          items: ast_map::Map,
1348                          ebml_w: &mut writer::Encoder,
1349                          ecx_ptr:*int,
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()),
1356                    string.get());
1357
1358             let mut ebml_w = unsafe {
1359                 ebml_w.unsafe_clone()
1360             };
1361             // See above
1362             let ecx: &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1363             encode_info_for_foreign_item(ecx,
1364                                          &mut ebml_w,
1365                                          ni,
1366                                          index,
1367                                          pt,
1368                                          abi);
1369         }
1370         // case for separate item and foreign-item tables
1371         _ => fail!("bad foreign item")
1372     }
1373 }
1374
1375 struct EncodeVisitor<'a,'b> {
1376     ebml_w_for_visit_item: &'a mut writer::Encoder<'b>,
1377     ecx_ptr:*int,
1378     items: ast_map::Map,
1379     index: @RefCell<~[entry<i64>]>,
1380 }
1381
1382 impl<'a,'b> visit::Visitor<()> for EncodeVisitor<'a,'b> {
1383     fn visit_expr(&mut self, ex: &Expr, _: ()) {
1384         visit::walk_expr(self, ex, ());
1385         my_visit_expr(ex);
1386     }
1387     fn visit_item(&mut self, i: &Item, _: ()) {
1388         visit::walk_item(self, i, ());
1389         my_visit_item(i,
1390                       self.items,
1391                       self.ebml_w_for_visit_item,
1392                       self.ecx_ptr,
1393                       self.index);
1394     }
1395     fn visit_foreign_item(&mut self, ni: &ForeignItem, _: ()) {
1396         visit::walk_foreign_item(self, ni, ());
1397         my_visit_foreign_item(ni,
1398                               self.items,
1399                               self.ebml_w_for_visit_item,
1400                               self.ecx_ptr,
1401                               self.index);
1402     }
1403 }
1404
1405 fn encode_info_for_items(ecx: &EncodeContext,
1406                          ebml_w: &mut writer::Encoder,
1407                          crate: &Crate)
1408                          -> ~[entry<i64>] {
1409     let index = @RefCell::new(~[]);
1410     ebml_w.start_tag(tag_items_data);
1411     {
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(),
1416         });
1417     }
1418     encode_info_for_mod(ecx,
1419                         ebml_w,
1420                         &crate.module,
1421                         CRATE_NODE_ID,
1422                         [],
1423                         syntax::parse::token::special_idents::invalid,
1424                         Public);
1425     let items = ecx.tcx.items;
1426
1427     // See comment in `encode_side_tables_for_ii` in astencode
1428     let ecx_ptr : *int = unsafe { cast::transmute(ecx) };
1429     {
1430         let mut visitor = EncodeVisitor {
1431             index: index,
1432             items: items,
1433             ecx_ptr: ecx_ptr,
1434             ebml_w_for_visit_item: &mut *ebml_w,
1435         };
1436
1437         visit::walk_crate(&mut visitor, crate, ());
1438     }
1439
1440     ebml_w.end_tag();
1441     return /*bad*/(*index).get();
1442 }
1443
1444
1445 // Path and definition ID indexing
1446
1447 fn create_index<T:Clone + Hash + IterBytes + 'static>(
1448                 index: ~[entry<T>])
1449                 -> ~[@~[entry<T>]] {
1450     let mut buckets: ~[@RefCell<~[entry<T>]>] = ~[];
1451     for _ in range(0u, 256u) {
1452         buckets.push(@RefCell::new(~[]));
1453     }
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());
1458     }
1459
1460     let mut buckets_frozen = ~[];
1461     for bucket in buckets.iter() {
1462         buckets_frozen.push(@/*bad*/(**bucket).get());
1463     }
1464     return buckets_frozen;
1465 }
1466
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);
1480             {
1481                 let wr: &mut MemWriter = ebml_w.writer;
1482                 wr.write_be_u32(elt.pos as u32);
1483             }
1484             write_fn(ebml_w.writer, &elt.val);
1485             ebml_w.end_tag();
1486         }
1487         ebml_w.end_tag();
1488     }
1489     ebml_w.end_tag();
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);
1495     }
1496     ebml_w.end_tag();
1497     ebml_w.end_tag();
1498 }
1499
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);
1504 }
1505
1506 fn encode_meta_item(ebml_w: &mut writer::Encoder, mi: @MetaItem) {
1507     match mi.node {
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());
1512         ebml_w.end_tag();
1513         ebml_w.end_tag();
1514       }
1515       MetaNameValue(ref name, ref value) => {
1516         match value.node {
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());
1521             ebml_w.end_tag();
1522             ebml_w.start_tag(tag_meta_item_value);
1523             ebml_w.writer.write(value.get().as_bytes());
1524             ebml_w.end_tag();
1525             ebml_w.end_tag();
1526           }
1527           _ => {/* FIXME (#623): encode other variants */ }
1528         }
1529       }
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());
1534         ebml_w.end_tag();
1535         for inner_item in items.iter() {
1536             encode_meta_item(ebml_w, *inner_item);
1537         }
1538         ebml_w.end_tag();
1539       }
1540     }
1541 }
1542
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);
1548         ebml_w.end_tag();
1549     }
1550     ebml_w.end_tag();
1551 }
1552
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] {
1558
1559     fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute {
1560         assert!(!ecx.link_meta.crateid.name.is_empty());
1561
1562         attr::mk_attr(
1563             attr::mk_name_value_item_str(
1564                 InternedString::new("crate_id"),
1565                 token::intern_and_get_ident(ecx.link_meta.crateid.to_str())))
1566     }
1567
1568     let mut attrs = ~[];
1569     for attr in crate.attrs.iter() {
1570         if !attr.name().equiv(&("crate_id")) {
1571             attrs.push(*attr);
1572         }
1573     }
1574     attrs.push(synthesize_crateid_attr(ecx));
1575
1576     attrs
1577 }
1578
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;
1585
1586         // Pull the cnums and name,vers,hash out of cstore
1587         let mut deps = ~[];
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())};
1593             deps.push(dep);
1594         });
1595
1596         // Sort by cnum
1597         deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
1598
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);
1603             expected_cnum += 1;
1604         }
1605
1606         deps
1607     }
1608
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());
1617     }
1618     ebml_w.end_tag();
1619 }
1620
1621 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1622     ebml_w.start_tag(tag_lang_items);
1623
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);
1628
1629                 ebml_w.start_tag(tag_lang_items_item_id);
1630                 {
1631                     let wr: &mut MemWriter = ebml_w.writer;
1632                     wr.write_be_u32(i as u32);
1633                 }
1634                 ebml_w.end_tag();   // tag_lang_items_item_id
1635
1636                 ebml_w.start_tag(tag_lang_items_item_node_id);
1637                 {
1638                     let wr: &mut MemWriter = ebml_w.writer;
1639                     wr.write_be_u32(id.node as u32);
1640                 }
1641                 ebml_w.end_tag();   // tag_lang_items_item_node_id
1642
1643                 ebml_w.end_tag();   // tag_lang_items_item
1644             }
1645         }
1646     }
1647
1648     ebml_w.end_tag();   // tag_lang_items
1649 }
1650
1651 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1652     ebml_w.start_tag(tag_native_libraries);
1653
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() {
1657         match kind {
1658             cstore::NativeStatic => {} // these libraries are not propagated
1659             cstore::NativeFramework | cstore::NativeUnknown => {
1660                 ebml_w.start_tag(tag_native_libraries_lib);
1661
1662                 ebml_w.start_tag(tag_native_libraries_kind);
1663                 ebml_w.writer.write_be_u32(kind as u32);
1664                 ebml_w.end_tag();
1665
1666                 ebml_w.start_tag(tag_native_libraries_name);
1667                 ebml_w.writer.write(lib.as_bytes());
1668                 ebml_w.end_tag();
1669
1670                 ebml_w.end_tag();
1671             }
1672         }
1673     }
1674
1675     ebml_w.end_tag();
1676 }
1677
1678 fn encode_macro_registrar_fn(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1679     let ptr = ecx.tcx.sess.macro_registrar_fn.borrow();
1680     match *ptr.get() {
1681         Some(did) => {
1682             ebml_w.start_tag(tag_macro_registrar_fn);
1683             encode_def_id(ebml_w, did);
1684             ebml_w.end_tag();
1685         }
1686         None => {}
1687     }
1688 }
1689
1690 struct MacroDefVisitor<'a, 'b> {
1691     ecx: &'a EncodeContext<'a>,
1692     ebml_w: &'a mut writer::Encoder<'b>
1693 }
1694
1695 impl<'a, 'b> Visitor<()> for MacroDefVisitor<'a, 'b> {
1696     fn visit_item(&mut self, item: &Item, _: ()) {
1697         match item.node {
1698             ItemMac(..) => {
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();
1704             }
1705             _ => {}
1706         }
1707         visit::walk_item(self, item, ());
1708     }
1709 }
1710
1711 fn encode_macro_defs(ecx: &EncodeContext,
1712                      crate: &Crate,
1713                      ebml_w: &mut writer::Encoder) {
1714     ebml_w.start_tag(tag_exported_macros);
1715     {
1716         let mut visitor = MacroDefVisitor {
1717             ecx: ecx,
1718             ebml_w: ebml_w,
1719         };
1720         visit::walk_crate(&mut visitor, crate, ());
1721     }
1722     ebml_w.end_tag();
1723 }
1724
1725 struct ImplVisitor<'a,'b> {
1726     ecx: &'a EncodeContext<'a>,
1727     ebml_w: &'a mut writer::Encoder<'b>,
1728 }
1729
1730 impl<'a,'b> Visitor<()> for ImplVisitor<'a,'b> {
1731     fn visit_item(&mut self, item: &Item, _: ()) {
1732         match item.node {
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);
1738
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();
1746                 }
1747             }
1748             _ => {}
1749         }
1750         visit::walk_item(self, item, ());
1751     }
1752 }
1753
1754 /// Encodes implementations that are eagerly loaded.
1755 ///
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:
1760 ///
1761 /// * Destructors (implementations of the Drop trait).
1762 ///
1763 /// * Implementations of traits not defined in this crate.
1764 fn encode_impls(ecx: &EncodeContext,
1765                 crate: &Crate,
1766                 ebml_w: &mut writer::Encoder) {
1767     ebml_w.start_tag(tag_impls);
1768
1769     {
1770         let mut visitor = ImplVisitor {
1771             ecx: ecx,
1772             ebml_w: ebml_w,
1773         };
1774         visit::walk_crate(&mut visitor, crate, ());
1775     }
1776
1777     ebml_w.end_tag();
1778 }
1779
1780 fn encode_misc_info(ecx: &EncodeContext,
1781                     crate: &Crate,
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)));
1788         ebml_w.end_tag();
1789
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)));
1793             ebml_w.end_tag();
1794             true
1795         });
1796     }
1797
1798     // Encode reexports for the root module.
1799     encode_reexports(ecx, ebml_w, 0, []);
1800
1801     ebml_w.end_tag();
1802     ebml_w.end_tag();
1803 }
1804
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());
1812     ebml_w.end_tag();
1813     ebml_w.start_tag(tag_crate_dep_vers);
1814     ebml_w.writer.write(dep.vers.as_bytes());
1815     ebml_w.end_tag();
1816     ebml_w.start_tag(tag_crate_dep_hash);
1817     ebml_w.writer.write(dep.hash.as_bytes());
1818     ebml_w.end_tag();
1819     ebml_w.end_tag();
1820 }
1821
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());
1825     ebml_w.end_tag();
1826 }
1827
1828 // NB: Increment this as you change the metadata encoding version.
1829 pub static metadata_encoding_version : &'static [u8] =
1830     &[0x72, //'r' as u8,
1831       0x75, //'u' as u8,
1832       0x73, //'s' as u8,
1833       0x74, //'t' as u8,
1834       0, 0, 0, 1 ];
1835
1836 pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
1837     let mut wr = MemWriter::new();
1838     encode_metadata_inner(&mut wr, parms, crate);
1839     wr.unwrap()
1840 }
1841
1842 fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, crate: &Crate) {
1843     let stats = Stats {
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),
1857     };
1858     let EncodeParams {
1859         item_symbols,
1860         diag,
1861         tcx,
1862         reexports2,
1863         cstore,
1864         encode_inlined_item,
1865         link_meta,
1866         reachable,
1867         non_inlineable_statics,
1868         codemap,
1869         ..
1870     } = parms;
1871     let type_abbrevs = @RefCell::new(HashMap::new());
1872     let stats = @stats;
1873     let ecx = EncodeContext {
1874         diag: diag,
1875         tcx: tcx,
1876         stats: stats,
1877         reexports2: reexports2,
1878         item_symbols: item_symbols,
1879         non_inlineable_statics: non_inlineable_statics,
1880         link_meta: link_meta,
1881         cstore: cstore,
1882         encode_inlined_item: encode_inlined_item,
1883         type_abbrevs: type_abbrevs,
1884         reachable: reachable,
1885         codemap: codemap,
1886      };
1887
1888     let mut ebml_w = writer::Encoder(wr);
1889
1890     encode_hash(&mut ebml_w, ecx.link_meta.crate_hash);
1891
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);
1896
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);
1900
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);
1905
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);
1910
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);
1915
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);
1920
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);
1925
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);
1930
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);
1936
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);
1941     ebml_w.end_tag();
1942
1943     ecx.stats.total_bytes.set(ebml_w.writer.tell());
1944
1945     if tcx.sess.meta_stats() {
1946         for e in ebml_w.writer.get_ref().iter() {
1947             if *e == 0 {
1948                 ecx.stats.zero_bytes.set(ecx.stats.zero_bytes.get() + 1);
1949             }
1950         }
1951
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());
1966     }
1967 }
1968
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 {
1972         diag: tcx.diag,
1973         ds: def_to_str,
1974         tcx: tcx,
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()
1979 }