]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/encoder.rs
Add generation of static libraries to rustc
[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 std::hashmap::{HashMap, HashSet};
25 use std::io::{Writer, Seek, Decorator};
26 use std::io::mem::MemWriter;
27 use std::str;
28 use std::vec;
29
30 use extra::flate;
31 use extra::serialize::Encodable;
32 use extra;
33
34 use syntax::abi::AbiSet;
35 use syntax::ast::*;
36 use syntax::ast;
37 use syntax::ast_map;
38 use syntax::ast_util::*;
39 use syntax::attr;
40 use syntax::attr::AttrMetaMethods;
41 use syntax::diagnostic::span_handler;
42 use syntax::parse::token::special_idents;
43 use syntax::ast_util;
44 use syntax::visit::Visitor;
45 use syntax::visit;
46 use syntax::parse::token;
47 use syntax;
48 use writer = extra::ebml::writer;
49
50 use std::cast;
51
52 // used by astencode:
53 type abbrev_map = @mut HashMap<ty::t, tyencode::ty_abbrev>;
54
55 pub type encode_inlined_item<'self> = 'self |ecx: &EncodeContext,
56                                              ebml_w: &mut writer::Encoder,
57                                              path: &[ast_map::path_elt],
58                                              ii: ast::inlined_item|;
59
60 pub struct EncodeParams<'self> {
61     diag: @mut span_handler,
62     tcx: ty::ctxt,
63     reexports2: middle::resolve::ExportMap2,
64     item_symbols: &'self HashMap<ast::NodeId, ~str>,
65     discrim_symbols: &'self HashMap<ast::NodeId, @str>,
66     non_inlineable_statics: &'self HashSet<ast::NodeId>,
67     link_meta: &'self LinkMeta,
68     cstore: @mut cstore::CStore,
69     encode_inlined_item: encode_inlined_item<'self>,
70     reachable: @mut HashSet<ast::NodeId>,
71 }
72
73 struct Stats {
74     inline_bytes: u64,
75     attr_bytes: u64,
76     dep_bytes: u64,
77     lang_item_bytes: u64,
78     native_lib_bytes: u64,
79     impl_bytes: u64,
80     misc_bytes: u64,
81     item_bytes: u64,
82     index_bytes: u64,
83     zero_bytes: u64,
84     total_bytes: u64,
85
86     n_inlines: uint
87 }
88
89 pub struct EncodeContext<'self> {
90     diag: @mut span_handler,
91     tcx: ty::ctxt,
92     stats: @mut Stats,
93     reexports2: middle::resolve::ExportMap2,
94     item_symbols: &'self HashMap<ast::NodeId, ~str>,
95     discrim_symbols: &'self HashMap<ast::NodeId, @str>,
96     non_inlineable_statics: &'self HashSet<ast::NodeId>,
97     link_meta: &'self LinkMeta,
98     cstore: &'self cstore::CStore,
99     encode_inlined_item: encode_inlined_item<'self>,
100     type_abbrevs: abbrev_map,
101     reachable: @mut HashSet<ast::NodeId>,
102 }
103
104 pub fn reachable(ecx: &EncodeContext, id: NodeId) -> bool {
105     ecx.reachable.contains(&id)
106 }
107
108 fn encode_name(ecx: &EncodeContext,
109                ebml_w: &mut writer::Encoder,
110                name: Ident) {
111     ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name));
112 }
113
114 fn encode_impl_type_basename(ecx: &EncodeContext,
115                              ebml_w: &mut writer::Encoder,
116                              name: Ident) {
117     ebml_w.wr_tagged_str(tag_item_impl_type_basename,
118                          ecx.tcx.sess.str_of(name));
119 }
120
121 pub fn encode_def_id(ebml_w: &mut writer::Encoder, id: DefId) {
122     ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
123 }
124
125 #[deriving(Clone)]
126 struct entry<T> {
127     val: T,
128     pos: u64
129 }
130
131 fn add_to_index(ebml_w: &mut writer::Encoder,
132                 path: &[Ident],
133                 index: &mut ~[entry<~str>],
134                 name: Ident) {
135     let mut full_path = ~[];
136     full_path.push_all(path);
137     full_path.push(name);
138     index.push(
139         entry {
140             val: ast_util::path_name_i(full_path),
141             pos: ebml_w.writer.tell()
142         });
143 }
144
145 fn encode_trait_ref(ebml_w: &mut writer::Encoder,
146                     ecx: &EncodeContext,
147                     trait_ref: &ty::TraitRef,
148                     tag: uint) {
149     let ty_str_ctxt = @tyencode::ctxt {
150         diag: ecx.diag,
151         ds: def_to_str,
152         tcx: ecx.tcx,
153         abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
154     };
155
156     ebml_w.start_tag(tag);
157     tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
158     ebml_w.end_tag();
159 }
160
161 fn encode_impl_vtables(ebml_w: &mut writer::Encoder,
162                        ecx: &EncodeContext,
163                        vtables: &typeck::impl_res) {
164     ebml_w.start_tag(tag_item_impl_vtables);
165     astencode::encode_vtable_res(ecx, ebml_w, vtables.trait_vtables);
166     astencode::encode_vtable_param_res(ecx, ebml_w, vtables.self_vtables);
167     ebml_w.end_tag();
168 }
169
170 // Item info table encoding
171 fn encode_family(ebml_w: &mut writer::Encoder, c: char) {
172     ebml_w.start_tag(tag_items_data_item_family);
173     ebml_w.writer.write(&[c as u8]);
174     ebml_w.end_tag();
175 }
176
177 pub fn def_to_str(did: DefId) -> ~str {
178     format!("{}:{}", did.crate, did.node)
179 }
180
181 fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
182                              ecx: &EncodeContext,
183                              params: @~[ty::TypeParameterDef],
184                              tag: uint) {
185     let ty_str_ctxt = @tyencode::ctxt {
186         diag: ecx.diag,
187         ds: def_to_str,
188         tcx: ecx.tcx,
189         abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
190     };
191     for param in params.iter() {
192         ebml_w.start_tag(tag);
193         tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
194         ebml_w.end_tag();
195     }
196 }
197
198 fn encode_region_param_defs(ebml_w: &mut writer::Encoder,
199                             ecx: &EncodeContext,
200                             params: @[ty::RegionParameterDef]) {
201     for param in params.iter() {
202         ebml_w.start_tag(tag_region_param_def);
203
204         ebml_w.start_tag(tag_region_param_def_ident);
205         encode_name(ecx, ebml_w, param.ident);
206         ebml_w.end_tag();
207
208         ebml_w.wr_tagged_str(tag_region_param_def_def_id,
209                              def_to_str(param.def_id));
210
211         ebml_w.end_tag();
212     }
213 }
214
215 fn encode_item_variances(ebml_w: &mut writer::Encoder,
216                          ecx: &EncodeContext,
217                          id: ast::NodeId) {
218     let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
219     ebml_w.start_tag(tag_item_variances);
220     v.encode(ebml_w);
221     ebml_w.end_tag();
222 }
223
224 fn encode_bounds_and_type(ebml_w: &mut writer::Encoder,
225                           ecx: &EncodeContext,
226                           tpt: &ty::ty_param_bounds_and_ty) {
227     encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs,
228                               tag_items_data_item_ty_param_bounds);
229     encode_region_param_defs(ebml_w, ecx, tpt.generics.region_param_defs);
230     encode_type(ecx, ebml_w, tpt.ty);
231 }
232
233 fn encode_variant_id(ebml_w: &mut writer::Encoder, vid: DefId) {
234     ebml_w.start_tag(tag_items_data_item_variant);
235     let s = def_to_str(vid);
236     ebml_w.writer.write(s.as_bytes());
237     ebml_w.end_tag();
238 }
239
240 pub fn write_type(ecx: &EncodeContext,
241                   ebml_w: &mut writer::Encoder,
242                   typ: ty::t) {
243     let ty_str_ctxt = @tyencode::ctxt {
244         diag: ecx.diag,
245         ds: def_to_str,
246         tcx: ecx.tcx,
247         abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
248     };
249     tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
250 }
251
252 pub fn write_vstore(ecx: &EncodeContext,
253                     ebml_w: &mut writer::Encoder,
254                     vstore: ty::vstore) {
255     let ty_str_ctxt = @tyencode::ctxt {
256         diag: ecx.diag,
257         ds: def_to_str,
258         tcx: ecx.tcx,
259         abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
260     };
261     tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
262 }
263
264 fn encode_type(ecx: &EncodeContext,
265                ebml_w: &mut writer::Encoder,
266                typ: ty::t) {
267     ebml_w.start_tag(tag_items_data_item_type);
268     write_type(ecx, ebml_w, typ);
269     ebml_w.end_tag();
270 }
271
272 fn encode_transformed_self_ty(ecx: &EncodeContext,
273                               ebml_w: &mut writer::Encoder,
274                               opt_typ: Option<ty::t>) {
275     for &typ in opt_typ.iter() {
276         ebml_w.start_tag(tag_item_method_transformed_self_ty);
277         write_type(ecx, ebml_w, typ);
278         ebml_w.end_tag();
279     }
280 }
281
282 fn encode_method_fty(ecx: &EncodeContext,
283                      ebml_w: &mut writer::Encoder,
284                      typ: &ty::BareFnTy) {
285     ebml_w.start_tag(tag_item_method_fty);
286
287     let ty_str_ctxt = @tyencode::ctxt {
288         diag: ecx.diag,
289         ds: def_to_str,
290         tcx: ecx.tcx,
291         abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
292     };
293     tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
294
295     ebml_w.end_tag();
296 }
297
298 fn encode_symbol(ecx: &EncodeContext,
299                  ebml_w: &mut writer::Encoder,
300                  id: NodeId) {
301     ebml_w.start_tag(tag_items_data_item_symbol);
302     match ecx.item_symbols.find(&id) {
303         Some(x) => {
304             debug!("encode_symbol(id={:?}, str={})", id, *x);
305             ebml_w.writer.write(x.as_bytes());
306         }
307         None => {
308             ecx.diag.handler().bug(
309                 format!("encode_symbol: id not found {}", id));
310         }
311     }
312     ebml_w.end_tag();
313 }
314
315 fn encode_disr_val(_: &EncodeContext,
316                    ebml_w: &mut writer::Encoder,
317                    disr_val: ty::Disr) {
318     ebml_w.start_tag(tag_disr_val);
319     let s = disr_val.to_str();
320     ebml_w.writer.write(s.as_bytes());
321     ebml_w.end_tag();
322 }
323
324 fn encode_parent_item(ebml_w: &mut writer::Encoder, id: DefId) {
325     ebml_w.start_tag(tag_items_data_parent_item);
326     let s = def_to_str(id);
327     ebml_w.writer.write(s.as_bytes());
328     ebml_w.end_tag();
329 }
330
331 fn encode_struct_fields(ecx: &EncodeContext,
332                              ebml_w: &mut writer::Encoder,
333                              def: @struct_def) {
334     for f in def.fields.iter() {
335         match f.node.kind {
336             named_field(ident, vis) => {
337                ebml_w.start_tag(tag_item_field);
338                encode_struct_field_family(ebml_w, vis);
339                encode_name(ecx, ebml_w, ident);
340                encode_def_id(ebml_w, local_def(f.node.id));
341                ebml_w.end_tag();
342             }
343             unnamed_field => {
344                 ebml_w.start_tag(tag_item_unnamed_field);
345                 encode_def_id(ebml_w, local_def(f.node.id));
346                 ebml_w.end_tag();
347             }
348         }
349     }
350 }
351
352 fn encode_enum_variant_info(ecx: &EncodeContext,
353                             ebml_w: &mut writer::Encoder,
354                             id: NodeId,
355                             variants: &[variant],
356                             path: &[ast_map::path_elt],
357                             index: @mut ~[entry<i64>],
358                             generics: &ast::Generics) {
359     debug!("encode_enum_variant_info(id={:?})", id);
360
361     let mut disr_val = 0;
362     let mut i = 0;
363     let vi = ty::enum_variants(ecx.tcx,
364                                ast::DefId { crate: LOCAL_CRATE, node: id });
365     for variant in variants.iter() {
366         let def_id = local_def(variant.node.id);
367         index.push(entry {val: variant.node.id as i64,
368                           pos: ebml_w.writer.tell()});
369         ebml_w.start_tag(tag_items_data_item);
370         encode_def_id(ebml_w, def_id);
371         match variant.node.kind {
372             ast::tuple_variant_kind(_) => encode_family(ebml_w, 'v'),
373             ast::struct_variant_kind(_) => encode_family(ebml_w, 'V')
374         }
375         encode_name(ecx, ebml_w, variant.node.name);
376         encode_parent_item(ebml_w, local_def(id));
377         encode_visibility(ebml_w, variant.node.vis);
378         encode_attributes(ebml_w, variant.node.attrs);
379         match variant.node.kind {
380             ast::tuple_variant_kind(ref args)
381                     if args.len() > 0 && generics.ty_params.len() == 0 => {
382                 encode_symbol(ecx, ebml_w, variant.node.id);
383             }
384             ast::tuple_variant_kind(_) => {},
385             ast::struct_variant_kind(def) => {
386                 let idx = encode_info_for_struct(ecx, ebml_w, path,
387                                          def.fields, index);
388                 encode_struct_fields(ecx, ebml_w, def);
389                 let bkts = create_index(idx);
390                 encode_index(ebml_w, bkts, write_i64);
391             }
392         }
393         if vi[i].disr_val != disr_val {
394             encode_disr_val(ecx, ebml_w, vi[i].disr_val);
395             disr_val = vi[i].disr_val;
396         }
397         encode_bounds_and_type(ebml_w, ecx,
398                                &lookup_item_type(ecx.tcx, def_id));
399         encode_path(ecx, ebml_w, path,
400                     ast_map::path_name(variant.node.name));
401         ebml_w.end_tag();
402         disr_val += 1;
403         i += 1;
404     }
405 }
406
407 fn encode_path(ecx: &EncodeContext,
408                ebml_w: &mut writer::Encoder,
409                path: &[ast_map::path_elt],
410                name: ast_map::path_elt) {
411     fn encode_path_elt(ecx: &EncodeContext,
412                        ebml_w: &mut writer::Encoder,
413                        elt: ast_map::path_elt) {
414         match elt {
415             ast_map::path_mod(n) => {
416                 ebml_w.wr_tagged_str(tag_path_elt_mod, ecx.tcx.sess.str_of(n));
417             }
418             ast_map::path_name(n) => {
419                 ebml_w.wr_tagged_str(tag_path_elt_name, ecx.tcx.sess.str_of(n));
420             }
421             ast_map::path_pretty_name(n, extra) => {
422                 ebml_w.start_tag(tag_path_elt_pretty_name);
423                 ebml_w.wr_tagged_str(tag_path_elt_pretty_name_ident,
424                                      ecx.tcx.sess.str_of(n));
425                 ebml_w.wr_tagged_u64(tag_path_elt_pretty_name_extra, extra);
426                 ebml_w.end_tag();
427             }
428         }
429     }
430
431     ebml_w.start_tag(tag_path);
432     ebml_w.wr_tagged_u32(tag_path_len, (path.len() + 1) as u32);
433     for pe in path.iter() {
434         encode_path_elt(ecx, ebml_w, *pe);
435     }
436     encode_path_elt(ecx, ebml_w, name);
437     ebml_w.end_tag();
438 }
439
440 fn encode_reexported_static_method(ecx: &EncodeContext,
441                                    ebml_w: &mut writer::Encoder,
442                                    exp: &middle::resolve::Export2,
443                                    method_def_id: DefId,
444                                    method_ident: Ident) {
445     debug!("(encode reexported static method) {}::{}",
446             exp.name, ecx.tcx.sess.str_of(method_ident));
447     ebml_w.start_tag(tag_items_data_item_reexport);
448     ebml_w.start_tag(tag_items_data_item_reexport_def_id);
449     ebml_w.wr_str(def_to_str(method_def_id));
450     ebml_w.end_tag();
451     ebml_w.start_tag(tag_items_data_item_reexport_name);
452     ebml_w.wr_str(format!("{}::{}", exp.name, ecx.tcx.sess.str_of(method_ident)));
453     ebml_w.end_tag();
454     ebml_w.end_tag();
455 }
456
457 fn encode_reexported_static_base_methods(ecx: &EncodeContext,
458                                          ebml_w: &mut writer::Encoder,
459                                          exp: &middle::resolve::Export2)
460                                          -> bool {
461     match ecx.tcx.inherent_impls.find(&exp.def_id) {
462         Some(implementations) => {
463             for &base_impl in implementations.iter() {
464                 for &m in base_impl.methods.iter() {
465                     if m.explicit_self == ast::sty_static {
466                         encode_reexported_static_method(ecx, ebml_w, exp,
467                                                         m.def_id, m.ident);
468                     }
469                 }
470             }
471
472             true
473         }
474         None => { false }
475     }
476 }
477
478 fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
479                                           ebml_w: &mut writer::Encoder,
480                                           exp: &middle::resolve::Export2)
481                                           -> bool {
482     match ecx.tcx.trait_methods_cache.find(&exp.def_id) {
483         Some(methods) => {
484             for &m in methods.iter() {
485                 if m.explicit_self == ast::sty_static {
486                     encode_reexported_static_method(ecx, ebml_w, exp,
487                                                     m.def_id, m.ident);
488                 }
489             }
490
491             true
492         }
493         None => { false }
494     }
495 }
496
497 fn encode_reexported_static_methods(ecx: &EncodeContext,
498                                     ebml_w: &mut writer::Encoder,
499                                     mod_path: &[ast_map::path_elt],
500                                     exp: &middle::resolve::Export2) {
501     match ecx.tcx.items.find(&exp.def_id.node) {
502         Some(&ast_map::node_item(item, path)) => {
503             let original_name = ecx.tcx.sess.str_of(item.ident);
504
505             //
506             // We don't need to reexport static methods on items
507             // declared in the same module as our `pub use ...` since
508             // that's done when we encode the item itself.
509             //
510             // The only exception is when the reexport *changes* the
511             // name e.g. `pub use Foo = self::Bar` -- we have
512             // encoded metadata for static methods relative to Bar,
513             // but not yet for Foo.
514             //
515             if mod_path != *path || exp.name != original_name {
516                 if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
517                     if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
518                         debug!("(encode reexported static methods) {} \
519                                  [trait]",
520                                 original_name);
521                     }
522                 }
523                 else {
524                     debug!("(encode reexported static methods) {} [base]",
525                             original_name);
526                 }
527             }
528         }
529         _ => {}
530     }
531 }
532
533 /// Iterates through "auxiliary node IDs", which are node IDs that describe
534 /// top-level items that are sub-items of the given item. Specifically:
535 ///
536 /// * For enums, iterates through the node IDs of the variants.
537 ///
538 /// * For newtype structs, iterates through the node ID of the constructor.
539 fn each_auxiliary_node_id(item: @item, callback: |NodeId| -> bool) -> bool {
540     let mut continue_ = true;
541     match item.node {
542         item_enum(ref enum_def, _) => {
543             for variant in enum_def.variants.iter() {
544                 continue_ = callback(variant.node.id);
545                 if !continue_ {
546                     break
547                 }
548             }
549         }
550         item_struct(struct_def, _) => {
551             // If this is a newtype struct, return the constructor.
552             match struct_def.ctor_id {
553                 Some(ctor_id) if struct_def.fields.len() > 0 &&
554                         struct_def.fields[0].node.kind ==
555                         ast::unnamed_field => {
556                     continue_ = callback(ctor_id);
557                 }
558                 _ => {}
559             }
560         }
561         _ => {}
562     }
563
564     continue_
565 }
566
567 fn encode_reexports(ecx: &EncodeContext,
568                     ebml_w: &mut writer::Encoder,
569                     id: NodeId,
570                     path: &[ast_map::path_elt]) {
571     debug!("(encoding info for module) encoding reexports for {}", id);
572     match ecx.reexports2.find(&id) {
573         Some(ref exports) => {
574             debug!("(encoding info for module) found reexports for {}", id);
575             for exp in exports.iter() {
576                 debug!("(encoding info for module) reexport '{}' ({}/{}) for \
577                         {}",
578                        exp.name,
579                        exp.def_id.crate,
580                        exp.def_id.node,
581                        id);
582                 ebml_w.start_tag(tag_items_data_item_reexport);
583                 ebml_w.start_tag(tag_items_data_item_reexport_def_id);
584                 ebml_w.wr_str(def_to_str(exp.def_id));
585                 ebml_w.end_tag();
586                 ebml_w.start_tag(tag_items_data_item_reexport_name);
587                 ebml_w.wr_str(exp.name);
588                 ebml_w.end_tag();
589                 ebml_w.end_tag();
590                 encode_reexported_static_methods(ecx, ebml_w, path, exp);
591             }
592         }
593         None => {
594             debug!("(encoding info for module) found no reexports for {}",
595                    id);
596         }
597     }
598 }
599
600 fn encode_info_for_mod(ecx: &EncodeContext,
601                        ebml_w: &mut writer::Encoder,
602                        md: &_mod,
603                        id: NodeId,
604                        path: &[ast_map::path_elt],
605                        name: Ident,
606                        vis: visibility) {
607     ebml_w.start_tag(tag_items_data_item);
608     encode_def_id(ebml_w, local_def(id));
609     encode_family(ebml_w, 'm');
610     encode_name(ecx, ebml_w, name);
611     debug!("(encoding info for module) encoding info for module ID {}", id);
612
613     // Encode info about all the module children.
614     for item in md.items.iter() {
615         ebml_w.start_tag(tag_mod_child);
616         ebml_w.wr_str(def_to_str(local_def(item.id)));
617         ebml_w.end_tag();
618
619         each_auxiliary_node_id(*item, |auxiliary_node_id| {
620             ebml_w.start_tag(tag_mod_child);
621             ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
622             ebml_w.end_tag();
623             true
624         });
625
626         match item.node {
627             item_impl(..) => {
628                 let (ident, did) = (item.ident, item.id);
629                 debug!("(encoding info for module) ... encoding impl {} \
630                         ({:?}/{:?})",
631                         ecx.tcx.sess.str_of(ident),
632                         did,
633                         ast_map::node_id_to_str(ecx.tcx.items, did, token::get_ident_interner()));
634
635                 ebml_w.start_tag(tag_mod_impl);
636                 ebml_w.wr_str(def_to_str(local_def(did)));
637                 ebml_w.end_tag();
638             }
639             _ => {}
640         }
641     }
642
643     encode_path(ecx, ebml_w, path, ast_map::path_mod(name));
644     encode_visibility(ebml_w, vis);
645
646     // Encode the reexports of this module, if this module is public.
647     if vis == public {
648         debug!("(encoding info for module) encoding reexports for {}", id);
649         encode_reexports(ecx, ebml_w, id, path);
650     }
651
652     ebml_w.end_tag();
653 }
654
655 fn encode_struct_field_family(ebml_w: &mut writer::Encoder,
656                               visibility: visibility) {
657     encode_family(ebml_w, match visibility {
658         public => 'g',
659         private => 'j',
660         inherited => 'N'
661     });
662 }
663
664 fn encode_visibility(ebml_w: &mut writer::Encoder, visibility: visibility) {
665     ebml_w.start_tag(tag_items_data_item_visibility);
666     let ch = match visibility {
667         public => 'y',
668         private => 'n',
669         inherited => 'i',
670     };
671     ebml_w.wr_str(str::from_char(ch));
672     ebml_w.end_tag();
673 }
674
675 fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explicit_self_) {
676     ebml_w.start_tag(tag_item_trait_method_explicit_self);
677
678     // Encode the base self type.
679     match explicit_self {
680         sty_static => {
681             ebml_w.writer.write(&[ 's' as u8 ]);
682         }
683         sty_value(m) => {
684             ebml_w.writer.write(&[ 'v' as u8 ]);
685             encode_mutability(ebml_w, m);
686         }
687         sty_region(_, m) => {
688             // FIXME(#4846) encode custom lifetime
689             ebml_w.writer.write(&[ '&' as u8 ]);
690             encode_mutability(ebml_w, m);
691         }
692         sty_box(m) => {
693             ebml_w.writer.write(&[ '@' as u8 ]);
694             encode_mutability(ebml_w, m);
695         }
696         sty_uniq(m) => {
697             ebml_w.writer.write(&[ '~' as u8 ]);
698             encode_mutability(ebml_w, m);
699         }
700     }
701
702     ebml_w.end_tag();
703
704     fn encode_mutability(ebml_w: &writer::Encoder,
705                          m: ast::Mutability) {
706         match m {
707             MutImmutable => ebml_w.writer.write(&[ 'i' as u8 ]),
708             MutMutable => ebml_w.writer.write(&[ 'm' as u8 ]),
709         }
710     }
711 }
712
713 fn encode_method_sort(ebml_w: &mut writer::Encoder, sort: char) {
714     ebml_w.start_tag(tag_item_trait_method_sort);
715     ebml_w.writer.write(&[ sort as u8 ]);
716     ebml_w.end_tag();
717 }
718
719 fn encode_provided_source(ebml_w: &mut writer::Encoder,
720                           source_opt: Option<DefId>) {
721     for source in source_opt.iter() {
722         ebml_w.start_tag(tag_item_method_provided_source);
723         let s = def_to_str(*source);
724         ebml_w.writer.write(s.as_bytes());
725         ebml_w.end_tag();
726     }
727 }
728
729 /* Returns an index of items in this class */
730 fn encode_info_for_struct(ecx: &EncodeContext,
731                           ebml_w: &mut writer::Encoder,
732                           path: &[ast_map::path_elt],
733                           fields: &[@struct_field],
734                           global_index: @mut ~[entry<i64>])
735                           -> ~[entry<i64>] {
736     /* Each class has its own index, since different classes
737        may have fields with the same name */
738     let mut index = ~[];
739     let tcx = ecx.tcx;
740      /* We encode both private and public fields -- need to include
741         private fields to get the offsets right */
742     for field in fields.iter() {
743         let (nm, vis) = match field.node.kind {
744             named_field(nm, vis) => (nm, vis),
745             unnamed_field => (special_idents::unnamed_field, inherited)
746         };
747
748         let id = field.node.id;
749         index.push(entry {val: id as i64, pos: ebml_w.writer.tell()});
750         global_index.push(entry {val: id as i64, pos: ebml_w.writer.tell()});
751         ebml_w.start_tag(tag_items_data_item);
752         debug!("encode_info_for_struct: doing {} {}",
753                tcx.sess.str_of(nm), id);
754         encode_struct_field_family(ebml_w, vis);
755         encode_name(ecx, ebml_w, nm);
756         encode_path(ecx, ebml_w, path, ast_map::path_name(nm));
757         encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
758         encode_def_id(ebml_w, local_def(id));
759         ebml_w.end_tag();
760     }
761     index
762 }
763
764 fn encode_info_for_struct_ctor(ecx: &EncodeContext,
765                                ebml_w: &mut writer::Encoder,
766                                path: &[ast_map::path_elt],
767                                name: ast::Ident,
768                                ctor_id: NodeId,
769                                index: @mut ~[entry<i64>],
770                                struct_id: NodeId) {
771     index.push(entry { val: ctor_id as i64, pos: ebml_w.writer.tell() });
772
773     ebml_w.start_tag(tag_items_data_item);
774     encode_def_id(ebml_w, local_def(ctor_id));
775     encode_family(ebml_w, 'f');
776     encode_name(ecx, ebml_w, name);
777     encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
778     encode_path(ecx, ebml_w, path, ast_map::path_name(name));
779     encode_parent_item(ebml_w, local_def(struct_id));
780
781     if ecx.item_symbols.contains_key(&ctor_id) {
782         encode_symbol(ecx, ebml_w, ctor_id);
783     }
784
785     ebml_w.end_tag();
786 }
787
788 fn encode_method_ty_fields(ecx: &EncodeContext,
789                            ebml_w: &mut writer::Encoder,
790                            method_ty: &ty::Method) {
791     encode_def_id(ebml_w, method_ty.def_id);
792     encode_name(ecx, ebml_w, method_ty.ident);
793     encode_ty_type_param_defs(ebml_w, ecx,
794                               method_ty.generics.type_param_defs,
795                               tag_item_method_tps);
796     encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty);
797     encode_method_fty(ecx, ebml_w, &method_ty.fty);
798     encode_visibility(ebml_w, method_ty.vis);
799     encode_explicit_self(ebml_w, method_ty.explicit_self);
800     let purity = method_ty.fty.purity;
801     match method_ty.explicit_self {
802         ast::sty_static => {
803             encode_family(ebml_w, purity_static_method_family(purity));
804         }
805         _ => encode_family(ebml_w, purity_fn_family(purity))
806     }
807     encode_provided_source(ebml_w, method_ty.provided_source);
808 }
809
810 fn encode_info_for_method(ecx: &EncodeContext,
811                           ebml_w: &mut writer::Encoder,
812                           m: &ty::Method,
813                           impl_path: &[ast_map::path_elt],
814                           is_default_impl: bool,
815                           parent_id: NodeId,
816                           ast_method_opt: Option<@method>) {
817
818     debug!("encode_info_for_method: {:?} {}", m.def_id,
819            ecx.tcx.sess.str_of(m.ident));
820     ebml_w.start_tag(tag_items_data_item);
821
822     encode_method_ty_fields(ecx, ebml_w, m);
823     encode_parent_item(ebml_w, local_def(parent_id));
824
825     // The type for methods gets encoded twice, which is unfortunate.
826     let tpt = lookup_item_type(ecx.tcx, m.def_id);
827     encode_bounds_and_type(ebml_w, ecx, &tpt);
828
829     encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
830
831     for ast_method in ast_method_opt.iter() {
832         let num_params = tpt.generics.type_param_defs.len();
833         if num_params > 0u || is_default_impl
834             || should_inline(ast_method.attrs) {
835             (ecx.encode_inlined_item)(
836                 ecx, ebml_w, impl_path,
837                 ii_method(local_def(parent_id), false, *ast_method));
838         } else {
839             encode_symbol(ecx, ebml_w, m.def_id.node);
840         }
841     }
842
843     ebml_w.end_tag();
844 }
845
846 fn purity_fn_family(p: purity) -> char {
847     match p {
848       unsafe_fn => 'u',
849       impure_fn => 'f',
850       extern_fn => 'e'
851     }
852 }
853
854 fn purity_static_method_family(p: purity) -> char {
855     match p {
856       unsafe_fn => 'U',
857       impure_fn => 'F',
858       _ => fail!("extern fn can't be static")
859     }
860 }
861
862
863 fn should_inline(attrs: &[Attribute]) -> bool {
864     use syntax::attr::*;
865     match find_inline_attr(attrs) {
866         InlineNone | InlineNever  => false,
867         InlineHint | InlineAlways => true
868     }
869 }
870
871 // Encodes the inherent implementations of a structure, enumeration, or trait.
872 fn encode_inherent_implementations(ecx: &EncodeContext,
873                                    ebml_w: &mut writer::Encoder,
874                                    def_id: DefId) {
875     match ecx.tcx.inherent_impls.find(&def_id) {
876         None => {}
877         Some(&implementations) => {
878             for implementation in implementations.iter() {
879                 ebml_w.start_tag(tag_items_data_item_inherent_impl);
880                 encode_def_id(ebml_w, implementation.did);
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     match ecx.tcx.trait_impls.find(&trait_def_id) {
892         None => {}
893         Some(&implementations) => {
894             for implementation in implementations.iter() {
895                 ebml_w.start_tag(tag_items_data_item_extension_impl);
896                 encode_def_id(ebml_w, implementation.did);
897                 ebml_w.end_tag();
898             }
899         }
900     }
901 }
902
903 fn encode_info_for_item(ecx: &EncodeContext,
904                         ebml_w: &mut writer::Encoder,
905                         item: @item,
906                         index: @mut ~[entry<i64>],
907                         path: &[ast_map::path_elt],
908                         vis: ast::visibility) {
909     let tcx = ecx.tcx;
910
911     fn add_to_index(item: @item, ebml_w: &writer::Encoder,
912                      index: @mut ~[entry<i64>]) {
913         index.push(entry { val: item.id as i64, pos: ebml_w.writer.tell() });
914     }
915     let add_to_index: || = || add_to_index(item, ebml_w, index);
916
917     debug!("encoding info for item at {}",
918            ecx.tcx.sess.codemap.span_to_str(item.span));
919
920     let def_id = local_def(item.id);
921     match item.node {
922       item_static(_, m, _) => {
923         add_to_index();
924         ebml_w.start_tag(tag_items_data_item);
925         encode_def_id(ebml_w, def_id);
926         if m == ast::MutMutable {
927             encode_family(ebml_w, 'b');
928         } else {
929             encode_family(ebml_w, 'c');
930         }
931         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
932         encode_symbol(ecx, ebml_w, item.id);
933         encode_name(ecx, ebml_w, item.ident);
934         let elt = ast_map::path_pretty_name(item.ident, item.id as u64);
935         encode_path(ecx, ebml_w, path, elt);
936         if !ecx.non_inlineable_statics.contains(&item.id) {
937             (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
938         }
939         encode_visibility(ebml_w, vis);
940         ebml_w.end_tag();
941       }
942       item_fn(_, purity, _, ref generics, _) => {
943         add_to_index();
944         ebml_w.start_tag(tag_items_data_item);
945         encode_def_id(ebml_w, def_id);
946         encode_family(ebml_w, purity_fn_family(purity));
947         let tps_len = generics.ty_params.len();
948         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
949         encode_name(ecx, ebml_w, item.ident);
950         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
951         encode_attributes(ebml_w, item.attrs);
952         if tps_len > 0u || should_inline(item.attrs) {
953             (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
954         } else {
955             encode_symbol(ecx, ebml_w, item.id);
956         }
957         encode_visibility(ebml_w, vis);
958         ebml_w.end_tag();
959       }
960       item_mod(ref m) => {
961         add_to_index();
962         encode_info_for_mod(ecx,
963                             ebml_w,
964                             m,
965                             item.id,
966                             path,
967                             item.ident,
968                             item.vis);
969       }
970       item_foreign_mod(ref fm) => {
971         add_to_index();
972         ebml_w.start_tag(tag_items_data_item);
973         encode_def_id(ebml_w, def_id);
974         encode_family(ebml_w, 'n');
975         encode_name(ecx, ebml_w, item.ident);
976         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
977
978         // Encode all the items in this module.
979         for foreign_item in fm.items.iter() {
980             ebml_w.start_tag(tag_mod_child);
981             ebml_w.wr_str(def_to_str(local_def(foreign_item.id)));
982             ebml_w.end_tag();
983         }
984         encode_visibility(ebml_w, vis);
985         ebml_w.end_tag();
986       }
987       item_ty(..) => {
988         add_to_index();
989         ebml_w.start_tag(tag_items_data_item);
990         encode_def_id(ebml_w, def_id);
991         encode_family(ebml_w, 'y');
992         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
993         encode_name(ecx, ebml_w, item.ident);
994         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
995         encode_visibility(ebml_w, vis);
996         ebml_w.end_tag();
997       }
998       item_enum(ref enum_definition, ref generics) => {
999         add_to_index();
1000
1001         ebml_w.start_tag(tag_items_data_item);
1002         encode_def_id(ebml_w, def_id);
1003         encode_family(ebml_w, 't');
1004         encode_item_variances(ebml_w, ecx, item.id);
1005         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1006         encode_name(ecx, ebml_w, item.ident);
1007         encode_attributes(ebml_w, item.attrs);
1008         for v in (*enum_definition).variants.iter() {
1009             encode_variant_id(ebml_w, local_def(v.node.id));
1010         }
1011         (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
1012         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1013
1014         // Encode inherent implementations for this enumeration.
1015         encode_inherent_implementations(ecx, ebml_w, def_id);
1016
1017         encode_visibility(ebml_w, vis);
1018         ebml_w.end_tag();
1019
1020         encode_enum_variant_info(ecx,
1021                                  ebml_w,
1022                                  item.id,
1023                                  (*enum_definition).variants,
1024                                  path,
1025                                  index,
1026                                  generics);
1027       }
1028       item_struct(struct_def, _) => {
1029         /* First, encode the fields
1030            These come first because we need to write them to make
1031            the index, and the index needs to be in the item for the
1032            class itself */
1033         let idx = encode_info_for_struct(ecx, ebml_w, path,
1034                                          struct_def.fields, index);
1035
1036         /* Index the class*/
1037         add_to_index();
1038
1039         /* Now, make an item for the class itself */
1040         ebml_w.start_tag(tag_items_data_item);
1041         encode_def_id(ebml_w, def_id);
1042         encode_family(ebml_w, 'S');
1043         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1044
1045         encode_item_variances(ebml_w, ecx, item.id);
1046         encode_name(ecx, ebml_w, item.ident);
1047         encode_attributes(ebml_w, item.attrs);
1048         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1049         encode_visibility(ebml_w, vis);
1050
1051         /* Encode def_ids for each field and method
1052          for methods, write all the stuff get_trait_method
1053         needs to know*/
1054         encode_struct_fields(ecx, ebml_w, struct_def);
1055
1056         (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
1057
1058         // Encode inherent implementations for this structure.
1059         encode_inherent_implementations(ecx, ebml_w, def_id);
1060
1061         /* Each class has its own index -- encode it */
1062         let bkts = create_index(idx);
1063         encode_index(ebml_w, bkts, write_i64);
1064         ebml_w.end_tag();
1065
1066         // If this is a tuple- or enum-like struct, encode the type of the
1067         // constructor.
1068         if struct_def.fields.len() > 0 &&
1069                 struct_def.fields[0].node.kind == ast::unnamed_field {
1070             let ctor_id = match struct_def.ctor_id {
1071                 Some(ctor_id) => ctor_id,
1072                 None => ecx.tcx.sess.bug("struct def didn't have ctor id"),
1073             };
1074
1075             encode_info_for_struct_ctor(ecx,
1076                                         ebml_w,
1077                                         path,
1078                                         item.ident,
1079                                         ctor_id,
1080                                         index,
1081                                         def_id.node);
1082         }
1083       }
1084       item_impl(_, ref opt_trait, ref ty, ref ast_methods) => {
1085         // We need to encode information about the default methods we
1086         // have inherited, so we drive this based on the impl structure.
1087         let imp = tcx.impls.get(&def_id);
1088
1089         add_to_index();
1090         ebml_w.start_tag(tag_items_data_item);
1091         encode_def_id(ebml_w, def_id);
1092         encode_family(ebml_w, 'i');
1093         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
1094         encode_name(ecx, ebml_w, item.ident);
1095         encode_attributes(ebml_w, item.attrs);
1096         match ty.node {
1097             ast::ty_path(ref path, ref bounds, _) if path.segments
1098                                                          .len() == 1 => {
1099                 assert!(bounds.is_none());
1100                 encode_impl_type_basename(ecx, ebml_w,
1101                                           ast_util::path_to_ident(path));
1102             }
1103             _ => {}
1104         }
1105         for method in imp.methods.iter() {
1106             ebml_w.start_tag(tag_item_impl_method);
1107             let s = def_to_str(method.def_id);
1108             ebml_w.writer.write(s.as_bytes());
1109             ebml_w.end_tag();
1110         }
1111         for ast_trait_ref in opt_trait.iter() {
1112             let trait_ref = ty::node_id_to_trait_ref(
1113                 tcx, ast_trait_ref.ref_id);
1114             encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
1115             let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
1116             encode_impl_vtables(ebml_w, ecx, &impl_vtables);
1117         }
1118         let elt = ast_map::impl_pretty_name(opt_trait, ty, item.ident);
1119         encode_path(ecx, ebml_w, path, elt);
1120         ebml_w.end_tag();
1121
1122         // >:-<
1123         let mut impl_path = vec::append(~[], path);
1124         impl_path.push(elt);
1125
1126         // Iterate down the methods, emitting them. We rely on the
1127         // assumption that all of the actually implemented methods
1128         // appear first in the impl structure, in the same order they do
1129         // in the ast. This is a little sketchy.
1130         let num_implemented_methods = ast_methods.len();
1131         for (i, m) in imp.methods.iter().enumerate() {
1132             let ast_method = if i < num_implemented_methods {
1133                 Some(ast_methods[i])
1134             } else { None };
1135
1136             index.push(entry {val: m.def_id.node as i64,
1137                               pos: ebml_w.writer.tell()});
1138             encode_info_for_method(ecx,
1139                                    ebml_w,
1140                                    *m,
1141                                    impl_path,
1142                                    false,
1143                                    item.id,
1144                                    ast_method)
1145         }
1146       }
1147       item_trait(_, ref super_traits, ref ms) => {
1148         add_to_index();
1149         ebml_w.start_tag(tag_items_data_item);
1150         encode_def_id(ebml_w, def_id);
1151         encode_family(ebml_w, 'I');
1152         encode_item_variances(ebml_w, ecx, item.id);
1153         let trait_def = ty::lookup_trait_def(tcx, def_id);
1154         encode_ty_type_param_defs(ebml_w, ecx,
1155                                   trait_def.generics.type_param_defs,
1156                                   tag_items_data_item_ty_param_bounds);
1157         encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
1158         encode_name(ecx, ebml_w, item.ident);
1159         encode_attributes(ebml_w, item.attrs);
1160         for &method_def_id in ty::trait_method_def_ids(tcx, def_id).iter() {
1161             ebml_w.start_tag(tag_item_trait_method);
1162             encode_def_id(ebml_w, method_def_id);
1163             ebml_w.end_tag();
1164
1165             ebml_w.start_tag(tag_mod_child);
1166             ebml_w.wr_str(def_to_str(method_def_id));
1167             ebml_w.end_tag();
1168         }
1169         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
1170         // FIXME(#8559): This should use the tcx's supertrait cache instead of
1171         // reading the AST's list, because the former has already filtered out
1172         // the builtin-kinds-as-supertraits. See corresponding fixme in decoder.
1173         for ast_trait_ref in super_traits.iter() {
1174             let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
1175             encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
1176         }
1177
1178         // Encode the implementations of this trait.
1179         encode_extension_implementations(ecx, ebml_w, def_id);
1180
1181         ebml_w.end_tag();
1182
1183         // Now output the method info for each method.
1184         let r = ty::trait_method_def_ids(tcx, def_id);
1185         for (i, &method_def_id) in r.iter().enumerate() {
1186             assert_eq!(method_def_id.crate, ast::LOCAL_CRATE);
1187
1188             let method_ty = ty::method(tcx, method_def_id);
1189
1190             index.push(entry {val: method_def_id.node as i64,
1191                               pos: ebml_w.writer.tell()});
1192
1193             ebml_w.start_tag(tag_items_data_item);
1194
1195             encode_method_ty_fields(ecx, ebml_w, method_ty);
1196
1197             encode_parent_item(ebml_w, def_id);
1198
1199             let mut trait_path = vec::append(~[], path);
1200             trait_path.push(ast_map::path_name(item.ident));
1201             encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
1202
1203             match method_ty.explicit_self {
1204                 sty_static => {
1205                     encode_family(ebml_w,
1206                                   purity_static_method_family(
1207                                       method_ty.fty.purity));
1208
1209                     let tpt = ty::lookup_item_type(tcx, method_def_id);
1210                     encode_bounds_and_type(ebml_w, ecx, &tpt);
1211                 }
1212
1213                 _ => {
1214                     encode_family(ebml_w,
1215                                   purity_fn_family(
1216                                       method_ty.fty.purity));
1217                 }
1218             }
1219
1220             match ms[i] {
1221                 required(_) => {
1222                     encode_method_sort(ebml_w, 'r');
1223                 }
1224
1225                 provided(m) => {
1226                     // If this is a static method, we've already encoded
1227                     // this.
1228                     if method_ty.explicit_self != sty_static {
1229                         // XXX: I feel like there is something funny going on.
1230                         let tpt = ty::lookup_item_type(tcx, method_def_id);
1231                         encode_bounds_and_type(ebml_w, ecx, &tpt);
1232                     }
1233                     encode_method_sort(ebml_w, 'p');
1234                     (ecx.encode_inlined_item)(
1235                         ecx, ebml_w, path,
1236                         ii_method(def_id, true, m));
1237                 }
1238             }
1239
1240             ebml_w.end_tag();
1241         }
1242
1243         // Encode inherent implementations for this trait.
1244         encode_inherent_implementations(ecx, ebml_w, def_id);
1245       }
1246       item_mac(..) => fail!("item macros unimplemented")
1247     }
1248 }
1249
1250 fn encode_info_for_foreign_item(ecx: &EncodeContext,
1251                                 ebml_w: &mut writer::Encoder,
1252                                 nitem: @foreign_item,
1253                                 index: @mut ~[entry<i64>],
1254                                 path: &ast_map::path,
1255                                 abi: AbiSet) {
1256     index.push(entry { val: nitem.id as i64, pos: ebml_w.writer.tell() });
1257
1258     ebml_w.start_tag(tag_items_data_item);
1259     match nitem.node {
1260       foreign_item_fn(..) => {
1261         encode_def_id(ebml_w, local_def(nitem.id));
1262         encode_family(ebml_w, purity_fn_family(impure_fn));
1263         encode_bounds_and_type(ebml_w, ecx,
1264                                &lookup_item_type(ecx.tcx,local_def(nitem.id)));
1265         encode_name(ecx, ebml_w, nitem.ident);
1266         if abi.is_intrinsic() {
1267             (ecx.encode_inlined_item)(ecx, ebml_w, *path, ii_foreign(nitem));
1268         } else {
1269             encode_symbol(ecx, ebml_w, nitem.id);
1270         }
1271         encode_path(ecx, ebml_w, *path, ast_map::path_name(nitem.ident));
1272       }
1273       foreign_item_static(_, mutbl) => {
1274         encode_def_id(ebml_w, local_def(nitem.id));
1275         if mutbl {
1276             encode_family(ebml_w, 'b');
1277         } else {
1278             encode_family(ebml_w, 'c');
1279         }
1280         encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
1281         encode_symbol(ecx, ebml_w, nitem.id);
1282         encode_name(ecx, ebml_w, nitem.ident);
1283         encode_path(ecx, ebml_w, *path, ast_map::path_name(nitem.ident));
1284       }
1285     }
1286     ebml_w.end_tag();
1287 }
1288
1289 fn my_visit_expr(_e:@Expr) { }
1290
1291 fn my_visit_item(i:@item, items: ast_map::map, ebml_w:&writer::Encoder,
1292                  ecx_ptr:*int, index: @mut ~[entry<i64>]) {
1293     match items.get_copy(&i.id) {
1294         ast_map::node_item(_, pt) => {
1295             let mut ebml_w = ebml_w.clone();
1296             // See above
1297             let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1298             encode_info_for_item(ecx, &mut ebml_w, i, index, *pt, i.vis);
1299         }
1300         _ => fail!("bad item")
1301     }
1302 }
1303
1304 fn my_visit_foreign_item(ni:@foreign_item, items: ast_map::map, ebml_w:&writer::Encoder,
1305                          ecx_ptr:*int, index: @mut ~[entry<i64>]) {
1306     match items.get_copy(&ni.id) {
1307         ast_map::node_foreign_item(_, abi, _, pt) => {
1308             debug!("writing foreign item {}::{}",
1309                    ast_map::path_to_str(
1310                        *pt,
1311                        token::get_ident_interner()),
1312                    token::ident_to_str(&ni.ident));
1313
1314             let mut ebml_w = ebml_w.clone();
1315             // See above
1316             let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
1317             encode_info_for_foreign_item(ecx,
1318                                          &mut ebml_w,
1319                                          ni,
1320                                          index,
1321                                          pt,
1322                                          abi);
1323         }
1324         // case for separate item and foreign-item tables
1325         _ => fail!("bad foreign item")
1326     }
1327 }
1328
1329 struct EncodeVisitor {
1330     ebml_w_for_visit_item: writer::Encoder,
1331     ebml_w_for_visit_foreign_item: writer::Encoder,
1332     ecx_ptr:*int,
1333     items: ast_map::map,
1334     index: @mut ~[entry<i64>],
1335 }
1336
1337 impl visit::Visitor<()> for EncodeVisitor {
1338     fn visit_expr(&mut self, ex:@Expr, _:()) {
1339         visit::walk_expr(self, ex, ());
1340         my_visit_expr(ex);
1341     }
1342     fn visit_item(&mut self, i:@item, _:()) {
1343         visit::walk_item(self, i, ());
1344         my_visit_item(i,
1345                       self.items,
1346                       &self.ebml_w_for_visit_item,
1347                       self.ecx_ptr,
1348                       self.index);
1349     }
1350     fn visit_foreign_item(&mut self, ni:@foreign_item, _:()) {
1351         visit::walk_foreign_item(self, ni, ());
1352         my_visit_foreign_item(ni,
1353                               self.items,
1354                               &self.ebml_w_for_visit_foreign_item,
1355                               self.ecx_ptr,
1356                               self.index);
1357     }
1358 }
1359
1360 fn encode_info_for_items(ecx: &EncodeContext,
1361                          ebml_w: &mut writer::Encoder,
1362                          crate: &Crate)
1363                          -> ~[entry<i64>] {
1364     let index = @mut ~[];
1365     ebml_w.start_tag(tag_items_data);
1366     index.push(entry { val: CRATE_NODE_ID as i64, pos: ebml_w.writer.tell() });
1367     encode_info_for_mod(ecx,
1368                         ebml_w,
1369                         &crate.module,
1370                         CRATE_NODE_ID,
1371                         [],
1372                         syntax::parse::token::special_idents::invalid,
1373                         public);
1374     let items = ecx.tcx.items;
1375
1376     // See comment in `encode_side_tables_for_ii` in astencode
1377     let ecx_ptr : *int = unsafe { cast::transmute(ecx) };
1378     let mut visitor = EncodeVisitor {
1379         index: index,
1380         items: items,
1381         ecx_ptr: ecx_ptr,
1382         ebml_w_for_visit_item: (*ebml_w).clone(),
1383         ebml_w_for_visit_foreign_item: (*ebml_w).clone(),
1384     };
1385
1386     visit::walk_crate(&mut visitor, crate, ());
1387
1388     ebml_w.end_tag();
1389     return /*bad*/(*index).clone();
1390 }
1391
1392
1393 // Path and definition ID indexing
1394
1395 fn create_index<T:Clone + Hash + IterBytes + 'static>(
1396                 index: ~[entry<T>])
1397                 -> ~[@~[entry<T>]] {
1398     let mut buckets: ~[@mut ~[entry<T>]] = ~[];
1399     for _ in range(0u, 256u) { buckets.push(@mut ~[]); };
1400     for elt in index.iter() {
1401         let h = elt.val.hash() as uint;
1402         buckets[h % 256].push((*elt).clone());
1403     }
1404
1405     let mut buckets_frozen = ~[];
1406     for bucket in buckets.iter() {
1407         buckets_frozen.push(@/*bad*/(**bucket).clone());
1408     }
1409     return buckets_frozen;
1410 }
1411
1412 fn encode_index<T:'static>(
1413                 ebml_w: &mut writer::Encoder,
1414                 buckets: ~[@~[entry<T>]],
1415                 write_fn: |@mut MemWriter, &T|) {
1416     ebml_w.start_tag(tag_index);
1417     let mut bucket_locs = ~[];
1418     ebml_w.start_tag(tag_index_buckets);
1419     for bucket in buckets.iter() {
1420         bucket_locs.push(ebml_w.writer.tell());
1421         ebml_w.start_tag(tag_index_buckets_bucket);
1422         for elt in (**bucket).iter() {
1423             ebml_w.start_tag(tag_index_buckets_bucket_elt);
1424             assert!(elt.pos < 0xffff_ffff);
1425             {
1426                 let wr: &mut MemWriter = ebml_w.writer;
1427                 wr.write_be_u32(elt.pos as u32);
1428             }
1429             write_fn(ebml_w.writer, &elt.val);
1430             ebml_w.end_tag();
1431         }
1432         ebml_w.end_tag();
1433     }
1434     ebml_w.end_tag();
1435     ebml_w.start_tag(tag_index_table);
1436     for pos in bucket_locs.iter() {
1437         assert!(*pos < 0xffff_ffff);
1438         let wr: &mut MemWriter = ebml_w.writer;
1439         wr.write_be_u32(*pos as u32);
1440     }
1441     ebml_w.end_tag();
1442     ebml_w.end_tag();
1443 }
1444
1445 fn write_str(writer: @mut MemWriter, s: ~str) {
1446     writer.write(s.as_bytes());
1447 }
1448
1449 fn write_i64(writer: @mut MemWriter, &n: &i64) {
1450     let wr: &mut MemWriter = writer;
1451     assert!(n < 0x7fff_ffff);
1452     wr.write_be_u32(n as u32);
1453 }
1454
1455 fn encode_meta_item(ebml_w: &mut writer::Encoder, mi: @MetaItem) {
1456     match mi.node {
1457       MetaWord(name) => {
1458         ebml_w.start_tag(tag_meta_item_word);
1459         ebml_w.start_tag(tag_meta_item_name);
1460         ebml_w.writer.write(name.as_bytes());
1461         ebml_w.end_tag();
1462         ebml_w.end_tag();
1463       }
1464       MetaNameValue(name, value) => {
1465         match value.node {
1466           lit_str(value, _) => {
1467             ebml_w.start_tag(tag_meta_item_name_value);
1468             ebml_w.start_tag(tag_meta_item_name);
1469             ebml_w.writer.write(name.as_bytes());
1470             ebml_w.end_tag();
1471             ebml_w.start_tag(tag_meta_item_value);
1472             ebml_w.writer.write(value.as_bytes());
1473             ebml_w.end_tag();
1474             ebml_w.end_tag();
1475           }
1476           _ => {/* FIXME (#623): encode other variants */ }
1477         }
1478       }
1479       MetaList(name, ref items) => {
1480         ebml_w.start_tag(tag_meta_item_list);
1481         ebml_w.start_tag(tag_meta_item_name);
1482         ebml_w.writer.write(name.as_bytes());
1483         ebml_w.end_tag();
1484         for inner_item in items.iter() {
1485             encode_meta_item(ebml_w, *inner_item);
1486         }
1487         ebml_w.end_tag();
1488       }
1489     }
1490 }
1491
1492 fn encode_attributes(ebml_w: &mut writer::Encoder, attrs: &[Attribute]) {
1493     ebml_w.start_tag(tag_attributes);
1494     for attr in attrs.iter() {
1495         ebml_w.start_tag(tag_attribute);
1496         encode_meta_item(ebml_w, attr.node.value);
1497         ebml_w.end_tag();
1498     }
1499     ebml_w.end_tag();
1500 }
1501
1502 // So there's a special crate attribute called 'link' which defines the
1503 // metadata that Rust cares about for linking crates. This attribute requires
1504 // 'name', 'vers' and 'package_id' items, so if the user didn't provide them we
1505 // will throw them in anyway with default values.
1506 fn synthesize_crate_attrs(ecx: &EncodeContext,
1507                           crate: &Crate) -> ~[Attribute] {
1508
1509     fn synthesize_link_attr(ecx: &EncodeContext, items: ~[@MetaItem]) ->
1510        Attribute {
1511
1512         assert!(!ecx.link_meta.name.is_empty());
1513         assert!(!ecx.link_meta.vers.is_empty());
1514
1515         let name_item =
1516             attr::mk_name_value_item_str(@"name",
1517                                          ecx.link_meta.name);
1518         let vers_item =
1519             attr::mk_name_value_item_str(@"vers",
1520                                          ecx.link_meta.vers);
1521
1522         let pkgid_item = match ecx.link_meta.package_id {
1523                 Some(pkg_id) =>  attr::mk_name_value_item_str(@"package_id",
1524                                                               pkg_id),
1525                 // uses package_id equal to name;
1526                 // this should never happen here but package_id is an Option
1527                 // FIXME (#10370): change package_id in LinkMeta to @str instead of Option<@str>
1528                 _ => attr::mk_name_value_item_str(@"package_id",
1529                                                   ecx.link_meta.name)
1530         };
1531
1532         let mut meta_items = ~[name_item, vers_item, pkgid_item];
1533
1534         for &mi in items.iter().filter(|mi| "name" != mi.name() && "vers" != mi.name() &&
1535                                             "package_id" != mi.name()) {
1536             meta_items.push(mi);
1537         }
1538         let link_item = attr::mk_list_item(@"link", meta_items);
1539
1540         return attr::mk_attr(link_item);
1541     }
1542
1543     let mut attrs = ~[];
1544     let mut found_link_attr = false;
1545     for attr in crate.attrs.iter() {
1546         attrs.push(
1547             if "link" != attr.name()  {
1548                 *attr
1549             } else {
1550                 match attr.meta_item_list() {
1551                   Some(l) => {
1552                     found_link_attr = true;;
1553                     synthesize_link_attr(ecx, l.to_owned())
1554                   }
1555                   _ => *attr
1556                 }
1557             });
1558     }
1559
1560     if !found_link_attr { attrs.push(synthesize_link_attr(ecx, ~[])); }
1561
1562     return attrs;
1563 }
1564
1565 fn encode_crate_deps(ecx: &EncodeContext,
1566                      ebml_w: &mut writer::Encoder,
1567                      cstore: &cstore::CStore) {
1568     fn get_ordered_deps(ecx: &EncodeContext, cstore: &cstore::CStore)
1569                      -> ~[decoder::CrateDep] {
1570         type numdep = decoder::CrateDep;
1571
1572         // Pull the cnums and name,vers,hash out of cstore
1573         let mut deps = ~[];
1574         cstore::iter_crate_data(cstore, |key, val| {
1575             let dep = decoder::CrateDep {cnum: key,
1576                        name: ecx.tcx.sess.ident_of(val.name),
1577                        vers: decoder::get_crate_vers(val.data),
1578                        hash: decoder::get_crate_hash(val.data)};
1579             deps.push(dep);
1580         });
1581
1582         // Sort by cnum
1583         extra::sort::quick_sort(deps, |kv1, kv2| kv1.cnum <= kv2.cnum);
1584
1585         // Sanity-check the crate numbers
1586         let mut expected_cnum = 1;
1587         for n in deps.iter() {
1588             assert_eq!(n.cnum, expected_cnum);
1589             expected_cnum += 1;
1590         }
1591
1592         deps
1593     }
1594
1595     // We're just going to write a list of crate 'name-hash-version's, with
1596     // the assumption that they are numbered 1 to n.
1597     // FIXME (#2166): This is not nearly enough to support correct versioning
1598     // but is enough to get transitive crate dependencies working.
1599     ebml_w.start_tag(tag_crate_deps);
1600     let r = get_ordered_deps(ecx, cstore);
1601     for dep in r.iter() {
1602         encode_crate_dep(ecx, ebml_w, *dep);
1603     }
1604     ebml_w.end_tag();
1605 }
1606
1607 fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1608     ebml_w.start_tag(tag_lang_items);
1609
1610     for (i, def_id) in ecx.tcx.lang_items.items() {
1611         for id in def_id.iter() {
1612             if id.crate == LOCAL_CRATE {
1613                 ebml_w.start_tag(tag_lang_items_item);
1614
1615                 ebml_w.start_tag(tag_lang_items_item_id);
1616                 {
1617                     let wr: &mut MemWriter = ebml_w.writer;
1618                     wr.write_be_u32(i as u32);
1619                 }
1620                 ebml_w.end_tag();   // tag_lang_items_item_id
1621
1622                 ebml_w.start_tag(tag_lang_items_item_node_id);
1623                 {
1624                     let wr: &mut MemWriter = ebml_w.writer;
1625                     wr.write_be_u32(id.node as u32);
1626                 }
1627                 ebml_w.end_tag();   // tag_lang_items_item_node_id
1628
1629                 ebml_w.end_tag();   // tag_lang_items_item
1630             }
1631         }
1632     }
1633
1634     ebml_w.end_tag();   // tag_lang_items
1635 }
1636
1637 fn encode_native_libraries(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
1638     ebml_w.start_tag(tag_native_libraries);
1639
1640     for &(ref lib, kind) in cstore::get_used_libraries(ecx.cstore).iter() {
1641         match kind {
1642             cstore::NativeStatic => {} // these libraries are not propagated
1643             cstore::NativeUnknown => {
1644                 ebml_w.start_tag(tag_native_libraries_lib);
1645                 ebml_w.writer.write(lib.as_bytes());
1646                 ebml_w.end_tag();
1647             }
1648         }
1649     }
1650
1651     ebml_w.end_tag();
1652 }
1653
1654 struct ImplVisitor<'self> {
1655     ecx: &'self EncodeContext<'self>,
1656     ebml_w: &'self mut writer::Encoder,
1657 }
1658
1659 impl<'self> Visitor<()> for ImplVisitor<'self> {
1660     fn visit_item(&mut self, item: @item, _: ()) {
1661         match item.node {
1662             item_impl(_, Some(ref trait_ref), _, _) => {
1663                 let def_map = self.ecx.tcx.def_map;
1664                 let trait_def = def_map.get_copy(&trait_ref.ref_id);
1665                 let def_id = ast_util::def_id_of_def(trait_def);
1666
1667                 // Load eagerly if this is an implementation of the Drop trait
1668                 // or if the trait is not defined in this crate.
1669                 if Some(def_id) == self.ecx.tcx.lang_items.drop_trait() ||
1670                         def_id.crate != LOCAL_CRATE {
1671                     self.ebml_w.start_tag(tag_impls_impl);
1672                     encode_def_id(self.ebml_w, local_def(item.id));
1673                     self.ebml_w.end_tag();
1674                 }
1675             }
1676             _ => {}
1677         }
1678         visit::walk_item(self, item, ());
1679     }
1680 }
1681
1682 /// Encodes implementations that are eagerly loaded.
1683 ///
1684 /// None of this is necessary in theory; we can load all implementations
1685 /// lazily. However, in two cases the optimizations to lazily load
1686 /// implementations are not yet implemented. These two cases, which require us
1687 /// to load implementations eagerly, are:
1688 ///
1689 /// * Destructors (implementations of the Drop trait).
1690 ///
1691 /// * Implementations of traits not defined in this crate.
1692 fn encode_impls(ecx: &EncodeContext,
1693                 crate: &Crate,
1694                 ebml_w: &mut writer::Encoder) {
1695     ebml_w.start_tag(tag_impls);
1696
1697     {
1698         let mut visitor = ImplVisitor {
1699             ecx: ecx,
1700             ebml_w: ebml_w,
1701         };
1702         visit::walk_crate(&mut visitor, crate, ());
1703     }
1704
1705     ebml_w.end_tag();
1706 }
1707
1708 fn encode_misc_info(ecx: &EncodeContext,
1709                     crate: &Crate,
1710                     ebml_w: &mut writer::Encoder) {
1711     ebml_w.start_tag(tag_misc_info);
1712     ebml_w.start_tag(tag_misc_info_crate_items);
1713     for &item in crate.module.items.iter() {
1714         ebml_w.start_tag(tag_mod_child);
1715         ebml_w.wr_str(def_to_str(local_def(item.id)));
1716         ebml_w.end_tag();
1717
1718         each_auxiliary_node_id(item, |auxiliary_node_id| {
1719             ebml_w.start_tag(tag_mod_child);
1720             ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
1721             ebml_w.end_tag();
1722             true
1723         });
1724     }
1725
1726     // Encode reexports for the root module.
1727     encode_reexports(ecx, ebml_w, 0, []);
1728
1729     ebml_w.end_tag();
1730     ebml_w.end_tag();
1731 }
1732
1733 fn encode_crate_dep(ecx: &EncodeContext,
1734                     ebml_w: &mut writer::Encoder,
1735                     dep: decoder::CrateDep) {
1736     ebml_w.start_tag(tag_crate_dep);
1737     ebml_w.start_tag(tag_crate_dep_name);
1738     let s = ecx.tcx.sess.str_of(dep.name);
1739     ebml_w.writer.write(s.as_bytes());
1740     ebml_w.end_tag();
1741     ebml_w.start_tag(tag_crate_dep_vers);
1742     ebml_w.writer.write(dep.vers.as_bytes());
1743     ebml_w.end_tag();
1744     ebml_w.start_tag(tag_crate_dep_hash);
1745     ebml_w.writer.write(dep.hash.as_bytes());
1746     ebml_w.end_tag();
1747     ebml_w.end_tag();
1748 }
1749
1750 fn encode_hash(ebml_w: &mut writer::Encoder, hash: &str) {
1751     ebml_w.start_tag(tag_crate_hash);
1752     ebml_w.writer.write(hash.as_bytes());
1753     ebml_w.end_tag();
1754 }
1755
1756 // NB: Increment this as you change the metadata encoding version.
1757 pub static metadata_encoding_version : &'static [u8] =
1758     &[0x72, //'r' as u8,
1759       0x75, //'u' as u8,
1760       0x73, //'s' as u8,
1761       0x74, //'t' as u8,
1762       0, 0, 0, 1 ];
1763
1764 pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
1765     let wr = @mut MemWriter::new();
1766     let stats = Stats {
1767         inline_bytes: 0,
1768         attr_bytes: 0,
1769         dep_bytes: 0,
1770         lang_item_bytes: 0,
1771         native_lib_bytes: 0,
1772         impl_bytes: 0,
1773         misc_bytes: 0,
1774         item_bytes: 0,
1775         index_bytes: 0,
1776         zero_bytes: 0,
1777         total_bytes: 0,
1778         n_inlines: 0
1779     };
1780     let EncodeParams {
1781         item_symbols,
1782         diag,
1783         tcx,
1784         reexports2,
1785         discrim_symbols,
1786         cstore,
1787         encode_inlined_item,
1788         link_meta,
1789         reachable,
1790         non_inlineable_statics,
1791         ..
1792     } = parms;
1793     let type_abbrevs = @mut HashMap::new();
1794     let stats = @mut stats;
1795     let ecx = EncodeContext {
1796         diag: diag,
1797         tcx: tcx,
1798         stats: stats,
1799         reexports2: reexports2,
1800         item_symbols: item_symbols,
1801         discrim_symbols: discrim_symbols,
1802         non_inlineable_statics: non_inlineable_statics,
1803         link_meta: link_meta,
1804         cstore: cstore,
1805         encode_inlined_item: encode_inlined_item,
1806         type_abbrevs: type_abbrevs,
1807         reachable: reachable,
1808      };
1809
1810     let mut ebml_w = writer::Encoder(wr);
1811
1812     encode_hash(&mut ebml_w, ecx.link_meta.extras_hash);
1813
1814     let mut i = wr.tell();
1815     let crate_attrs = synthesize_crate_attrs(&ecx, crate);
1816     encode_attributes(&mut ebml_w, crate_attrs);
1817     ecx.stats.attr_bytes = wr.tell() - i;
1818
1819     i = wr.tell();
1820     encode_crate_deps(&ecx, &mut ebml_w, ecx.cstore);
1821     ecx.stats.dep_bytes = wr.tell() - i;
1822
1823     // Encode the language items.
1824     i = wr.tell();
1825     encode_lang_items(&ecx, &mut ebml_w);
1826     ecx.stats.lang_item_bytes = wr.tell() - i;
1827
1828     // Encode the native libraries used
1829     i = wr.tell();
1830     encode_native_libraries(&ecx, &mut ebml_w);
1831     ecx.stats.native_lib_bytes = wr.tell() - i;
1832
1833     // Encode the def IDs of impls, for coherence checking.
1834     i = wr.tell();
1835     encode_impls(&ecx, crate, &mut ebml_w);
1836     ecx.stats.impl_bytes = wr.tell() - i;
1837
1838     // Encode miscellaneous info.
1839     i = wr.tell();
1840     encode_misc_info(&ecx, crate, &mut ebml_w);
1841     ecx.stats.misc_bytes = wr.tell() - i;
1842
1843     // Encode and index the items.
1844     ebml_w.start_tag(tag_items);
1845     i = wr.tell();
1846     let items_index = encode_info_for_items(&ecx, &mut ebml_w, crate);
1847     ecx.stats.item_bytes = wr.tell() - i;
1848
1849     i = wr.tell();
1850     let items_buckets = create_index(items_index);
1851     encode_index(&mut ebml_w, items_buckets, write_i64);
1852     ecx.stats.index_bytes = wr.tell() - i;
1853     ebml_w.end_tag();
1854
1855     ecx.stats.total_bytes = wr.tell();
1856
1857     if (tcx.sess.meta_stats()) {
1858         for e in wr.inner_ref().iter() {
1859             if *e == 0 {
1860                 ecx.stats.zero_bytes += 1;
1861             }
1862         }
1863
1864         println("metadata stats:");
1865         println!("    inline bytes: {}", ecx.stats.inline_bytes);
1866         println!(" attribute bytes: {}", ecx.stats.attr_bytes);
1867         println!("       dep bytes: {}", ecx.stats.dep_bytes);
1868         println!(" lang item bytes: {}", ecx.stats.lang_item_bytes);
1869         println!("    native bytes: {}", ecx.stats.native_lib_bytes);
1870         println!("      impl bytes: {}", ecx.stats.impl_bytes);
1871         println!("      misc bytes: {}", ecx.stats.misc_bytes);
1872         println!("      item bytes: {}", ecx.stats.item_bytes);
1873         println!("     index bytes: {}", ecx.stats.index_bytes);
1874         println!("      zero bytes: {}", ecx.stats.zero_bytes);
1875         println!("     total bytes: {}", ecx.stats.total_bytes);
1876     }
1877
1878     // Pad this, since something (LLVM, presumably) is cutting off the
1879     // remaining % 4 bytes.
1880     wr.write(&[0u8, 0u8, 0u8, 0u8]);
1881
1882     let writer_bytes: &mut ~[u8] = wr.inner_mut_ref();
1883
1884     metadata_encoding_version.to_owned() +
1885         flate::deflate_bytes(*writer_bytes)
1886 }
1887
1888 // Get the encoded string for a type
1889 pub fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str {
1890     let cx = @tyencode::ctxt {
1891         diag: tcx.diag,
1892         ds: def_to_str,
1893         tcx: tcx,
1894         abbrevs: tyencode::ac_no_abbrevs};
1895     let wr = @mut MemWriter::new();
1896     tyencode::enc_ty(wr, cx, t);
1897     str::from_utf8(*wr.inner_ref())
1898 }