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