1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
16 use metadata
::common
::*;
18 use metadata
::decoder
;
19 use metadata
::tyencode
;
20 use middle
::trans
::reachable
;
21 use middle
::ty
::node_id_to_type
;
24 use util
::ppaux
::ty_to_str
;
27 use core
::hash
::HashUtil
;
28 use core
::hashmap
::linear
::LinearMap
;
30 use core
::io
::{Writer, WriterUtil}
;
33 use core
::to_bytes
::IterBytes
;
36 use std
::serialize
::Encodable
;
38 use syntax
::abi
::AbiSet
;
42 use syntax
::ast_util
::*;
44 use syntax
::diagnostic
::span_handler
;
45 use syntax
::parse
::token
::special_idents
;
46 use syntax
::{ast_util, visit}
;
47 use syntax
::opt_vec
::OptVec
;
50 use writer
= std
::ebml
::writer
;
53 type abbrev_map
= @
mut LinearMap
<ty
::t
, tyencode
::ty_abbrev
>;
55 pub type encode_inlined_item
= @
fn(ecx
: @EncodeContext
,
56 ebml_w
: writer
::Encoder
,
57 path
: &[ast_map
::path_elt
],
58 ii
: ast
::inlined_item
);
60 pub struct EncodeParams
{
63 reachable
: reachable
::map
,
64 reexports2
: middle
::resolve
::ExportMap2
,
65 item_symbols
: @
mut LinearMap
<ast
::node_id
, ~str>,
66 discrim_symbols
: @
mut LinearMap
<ast
::node_id
, ~str>,
68 cstore
: @
mut cstore
::CStore
,
69 encode_inlined_item
: encode_inlined_item
76 lang_item_bytes
: uint
,
77 link_args_bytes
: uint
,
86 pub struct EncodeContext
{
90 reachable
: reachable
::map
,
91 reexports2
: middle
::resolve
::ExportMap2
,
92 item_symbols
: @
mut LinearMap
<ast
::node_id
, ~str>,
93 discrim_symbols
: @
mut LinearMap
<ast
::node_id
, ~str>,
95 cstore
: @
mut cstore
::CStore
,
96 encode_inlined_item
: encode_inlined_item
,
97 type_abbrevs
: abbrev_map
100 pub fn reachable(ecx
: @EncodeContext
, id
: node_id
) -> bool
{
101 ecx
.reachable
.contains(&id
)
104 fn encode_name(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
, name
: ident
) {
105 ebml_w
.wr_tagged_str(tag_paths_data_name
, *ecx
.tcx
.sess
.str_of(name
));
108 fn encode_impl_type_basename(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
110 ebml_w
.wr_tagged_str(tag_item_impl_type_basename
,
111 *ecx
.tcx
.sess
.str_of(name
));
114 pub fn encode_def_id(ebml_w
: writer
::Encoder
, id
: def_id
) {
115 ebml_w
.wr_tagged_str(tag_def_id
, def_to_str(id
));
118 fn encode_region_param(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
120 let opt_rp
= ecx
.tcx
.region_paramd_items
.find(&it
.id
);
121 for opt_rp
.each
|rp
| {
122 do ebml_w
.wr_tag(tag_region_param
) {
123 (*rp
).encode(&ebml_w
);
128 fn encode_mutability(ebml_w
: writer
::Encoder
, mt
: struct_mutability
) {
129 do ebml_w
.wr_tag(tag_struct_mut
) {
131 struct_immutable
=> 'a'
,
132 struct_mutable
=> 'm'
134 ebml_w
.writer
.write(&[val
as u8]);
143 fn add_to_index(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
, path
: &[ident
],
144 index
: &mut ~[entry
<~str>], name
: ident
) {
145 let mut full_path
= ~[];
146 full_path
.push_all(path
);
147 full_path
.push(name
);
150 val
: ast_util
::path_name_i(full_path
,
151 ecx
.tcx
.sess
.parse_sess
.interner
),
152 pos
: ebml_w
.writer
.tell()
156 fn encode_trait_ref(ebml_w
: writer
::Encoder
, ecx
: @EncodeContext
,
158 ebml_w
.start_tag(tag_impl_trait
);
159 encode_type(ecx
, ebml_w
, node_id_to_type(ecx
.tcx
, t
.ref_id
));
164 // Item info table encoding
165 fn encode_family(ebml_w
: writer
::Encoder
, c
: char) {
166 ebml_w
.start_tag(tag_items_data_item_family
);
167 ebml_w
.writer
.write(&[c
as u8]);
171 pub fn def_to_str(did
: def_id
) -> ~str { fmt!("%d:%d", did.crate, did.node) }
173 fn encode_ty_type_param_bounds(ebml_w
: writer
::Encoder
, ecx
: @EncodeContext
,
174 params
: @
~[ty
::param_bounds
]) {
175 let ty_str_ctxt
= @tyencode
::ctxt
{
179 reachable
: |a
| reachable(ecx
, a
),
180 abbrevs
: tyencode
::ac_use_abbrevs(ecx
.type_abbrevs
)};
181 for params
.each
|param
| {
182 ebml_w
.start_tag(tag_items_data_item_ty_param_bounds
);
183 tyencode
::enc_bounds(ebml_w
.writer
, ty_str_ctxt
, *param
);
188 fn encode_type_param_bounds(ebml_w
: writer
::Encoder
,
190 params
: &OptVec
<TyParam
>) {
191 let ty_param_bounds
=
192 @params
.map_to_vec(|param
| *ecx
.tcx
.ty_param_bounds
.get(¶m
.id
));
193 encode_ty_type_param_bounds(ebml_w
, ecx
, ty_param_bounds
);
197 fn encode_variant_id(ebml_w
: writer
::Encoder
, vid
: def_id
) {
198 ebml_w
.start_tag(tag_items_data_item_variant
);
199 ebml_w
.writer
.write(str::to_bytes(def_to_str(vid
)));
203 pub fn write_type(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
, typ
: ty
::t
) {
204 let ty_str_ctxt
= @tyencode
::ctxt
{
208 reachable
: |a
| reachable(ecx
, a
),
209 abbrevs
: tyencode
::ac_use_abbrevs(ecx
.type_abbrevs
)};
210 tyencode
::enc_ty(ebml_w
.writer
, ty_str_ctxt
, typ
);
213 pub fn write_vstore(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
214 vstore
: ty
::vstore
) {
215 let ty_str_ctxt
= @tyencode
::ctxt
{
219 reachable
: |a
| reachable(ecx
, a
),
220 abbrevs
: tyencode
::ac_use_abbrevs(ecx
.type_abbrevs
)};
221 tyencode
::enc_vstore(ebml_w
.writer
, ty_str_ctxt
, vstore
);
224 fn encode_type(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
, typ
: ty
::t
) {
225 ebml_w
.start_tag(tag_items_data_item_type
);
226 write_type(ecx
, ebml_w
, typ
);
230 fn encode_symbol(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
, id
: node_id
) {
231 ebml_w
.start_tag(tag_items_data_item_symbol
);
232 match ecx
.item_symbols
.find(&id
) {
234 debug
!("encode_symbol(id=%?, str=%s)", id
, *x
);
235 ebml_w
.writer
.write(str::to_bytes(*x
));
238 ecx
.diag
.handler().bug(
239 fmt
!("encode_symbol: id not found %d", id
));
245 fn encode_discriminant(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
247 ebml_w
.start_tag(tag_items_data_item_symbol
);
248 ebml_w
.writer
.write(str::to_bytes(*ecx
.discrim_symbols
.get(&id
)));
252 fn encode_disr_val(_ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
254 ebml_w
.start_tag(tag_disr_val
);
255 ebml_w
.writer
.write(str::to_bytes(int
::to_str(disr_val
)));
259 fn encode_parent_item(ebml_w
: writer
::Encoder
, id
: def_id
) {
260 ebml_w
.start_tag(tag_items_data_parent_item
);
261 ebml_w
.writer
.write(str::to_bytes(def_to_str(id
)));
265 fn encode_enum_variant_info(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
266 id
: node_id
, variants
: &[variant
],
267 path
: &[ast_map
::path_elt
],
268 index
: @
mut ~[entry
<int
>],
269 generics
: &ast
::Generics
) {
270 debug
!("encode_enum_variant_info(id=%?)", id
);
272 let mut disr_val
= 0;
274 let vi
= ty
::enum_variants(ecx
.tcx
,
275 ast
::def_id { crate: local_crate, node: id }
);
276 for variants
.each
|variant
| {
277 index
.push(entry {val: variant.node.id, pos: ebml_w.writer.tell()}
);
278 ebml_w
.start_tag(tag_items_data_item
);
279 encode_def_id(ebml_w
, local_def(variant
.node
.id
));
280 encode_family(ebml_w
, 'v'
);
281 encode_name(ecx
, ebml_w
, variant
.node
.name
);
282 encode_parent_item(ebml_w
, local_def(id
));
283 encode_type(ecx
, ebml_w
,
284 node_id_to_type(ecx
.tcx
, variant
.node
.id
));
285 match variant
.node
.kind
{
286 ast
::tuple_variant_kind(ref args
)
287 if args
.len() > 0 && generics
.ty_params
.len() == 0 => {
288 encode_symbol(ecx
, ebml_w
, variant
.node
.id
);
290 ast
::tuple_variant_kind(_
) | ast
::struct_variant_kind(_
) => {}
292 encode_discriminant(ecx
, ebml_w
, variant
.node
.id
);
293 if vi
[i
].disr_val
!= disr_val
{
294 encode_disr_val(ecx
, ebml_w
, vi
[i
].disr_val
);
295 disr_val
= vi
[i
].disr_val
;
297 encode_type_param_bounds(ebml_w
, ecx
, &generics
.ty_params
);
298 encode_path(ecx
, ebml_w
, path
,
299 ast_map
::path_name(variant
.node
.name
));
306 fn encode_path(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
307 path
: &[ast_map
::path_elt
], name
: ast_map
::path_elt
) {
308 fn encode_path_elt(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
309 elt
: ast_map
::path_elt
) {
310 let (tag
, name
) = match elt
{
311 ast_map
::path_mod(name
) => (tag_path_elt_mod
, name
),
312 ast_map
::path_name(name
) => (tag_path_elt_name
, name
)
315 ebml_w
.wr_tagged_str(tag
, *ecx
.tcx
.sess
.str_of(name
));
318 do ebml_w
.wr_tag(tag_path
) {
319 ebml_w
.wr_tagged_u32(tag_path_len
, (path
.len() + 1) as u32);
321 encode_path_elt(ecx
, ebml_w
, *pe
);
323 encode_path_elt(ecx
, ebml_w
, name
);
327 fn encode_info_for_mod(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
328 md
: &_mod
, id
: node_id
, path
: &[ast_map
::path_elt
],
330 ebml_w
.start_tag(tag_items_data_item
);
331 encode_def_id(ebml_w
, local_def(id
));
332 encode_family(ebml_w
, 'm'
);
333 encode_name(ecx
, ebml_w
, name
);
334 debug
!("(encoding info for module) encoding info for module ID %d", id
);
336 // Encode info about all the module children.
337 for md
.items
.each
|item
| {
340 let (ident
, did
) = (item
.ident
, item
.id
);
341 debug
!("(encoding info for module) ... encoding impl %s \
343 *ecx
.tcx
.sess
.str_of(ident
),
345 ast_map
::node_id_to_str(ecx
.tcx
.items
, did
, ecx
.tcx
346 .sess
.parse_sess
.interner
));
348 ebml_w
.start_tag(tag_mod_impl
);
349 ebml_w
.wr_str(def_to_str(local_def(did
)));
352 _
=> {}
// FIXME #4573: Encode these too.
356 encode_path(ecx
, ebml_w
, path
, ast_map
::path_mod(name
));
358 // Encode the reexports of this module.
359 debug
!("(encoding info for module) encoding reexports for %d", id
);
360 match ecx
.reexports2
.find(&id
) {
361 Some(ref exports
) => {
362 debug
!("(encoding info for module) found reexports for %d", id
);
363 for exports
.each
|exp
| {
364 debug
!("(encoding info for module) reexport '%s' for %d",
366 ebml_w
.start_tag(tag_items_data_item_reexport
);
367 ebml_w
.start_tag(tag_items_data_item_reexport_def_id
);
368 ebml_w
.wr_str(def_to_str(exp
.def_id
));
370 ebml_w
.start_tag(tag_items_data_item_reexport_name
);
371 ebml_w
.wr_str(*exp
.name
);
377 debug
!("(encoding info for module) found no reexports for %d",
385 fn encode_struct_field_family(ebml_w
: writer
::Encoder
,
386 visibility
: visibility
) {
387 encode_family(ebml_w
, match visibility
{
394 fn encode_visibility(ebml_w
: writer
::Encoder
, visibility
: visibility
) {
395 ebml_w
.start_tag(tag_items_data_item_visibility
);
396 let ch
= match visibility
{
401 ebml_w
.wr_str(str::from_char(ch
));
405 fn encode_self_type(ebml_w
: writer
::Encoder
, self_type
: ast
::self_ty_
) {
406 ebml_w
.start_tag(tag_item_trait_method_self_ty
);
408 // Encode the base self type.
411 ebml_w
.writer
.write(&[ 's'
as u8 ]);
414 ebml_w
.writer
.write(&[ 'v'
as u8 ]);
416 sty_region(_
, m
) => {
417 // FIXME(#4846) encode custom lifetime
418 ebml_w
.writer
.write(&[ '
&'
as u8 ]);
419 encode_mutability(ebml_w
, m
);
422 ebml_w
.writer
.write(&[ '@'
as u8 ]);
423 encode_mutability(ebml_w
, m
);
426 ebml_w
.writer
.write(&[ '
~'
as u8 ]);
427 encode_mutability(ebml_w
, m
);
433 fn encode_mutability(ebml_w
: writer
::Encoder
,
434 m
: ast
::mutability
) {
437 ebml_w
.writer
.write(&[ 'i'
as u8 ]);
440 ebml_w
.writer
.write(&[ 'm'
as u8 ]);
443 ebml_w
.writer
.write(&[ 'c'
as u8 ]);
449 fn encode_method_sort(ebml_w
: writer
::Encoder
, sort
: char) {
450 ebml_w
.start_tag(tag_item_trait_method_sort
);
451 ebml_w
.writer
.write(&[ sort
as u8 ]);
455 /* Returns an index of items in this class */
456 fn encode_info_for_struct(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
457 path
: &[ast_map
::path_elt
],
458 fields
: &[@struct_field
],
459 global_index
: @
mut~[entry
<int
>]) -> ~[entry
<int
>] {
460 /* Each class has its own index, since different classes
461 may have fields with the same name */
462 let index
= @
mut ~[];
464 /* We encode both private and public fields -- need to include
465 private fields to get the offsets right */
466 for fields
.each
|field
| {
467 let (nm
, mt
, vis
) = match field
.node
.kind
{
468 named_field(nm
, mt
, vis
) => (nm
, mt
, vis
),
470 special_idents
::unnamed_field
,
476 let id
= field
.node
.id
;
477 index
.push(entry {val: id, pos: ebml_w.writer.tell()}
);
478 global_index
.push(entry {val: id, pos: ebml_w.writer.tell()}
);
479 ebml_w
.start_tag(tag_items_data_item
);
480 debug
!("encode_info_for_struct: doing %s %d",
481 *tcx
.sess
.str_of(nm
), id
);
482 encode_struct_field_family(ebml_w
, vis
);
483 encode_name(ecx
, ebml_w
, nm
);
484 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(nm
));
485 encode_type(ecx
, ebml_w
, node_id_to_type(tcx
, id
));
486 encode_mutability(ebml_w
, mt
);
487 encode_def_id(ebml_w
, local_def(id
));
493 // This is for encoding info for ctors and dtors
494 fn encode_info_for_ctor(ecx
: @EncodeContext
,
495 ebml_w
: writer
::Encoder
,
498 path
: &[ast_map
::path_elt
],
499 item
: Option
<inlined_item
>,
500 generics
: &ast
::Generics
) {
501 ebml_w
.start_tag(tag_items_data_item
);
502 encode_name(ecx
, ebml_w
, ident
);
503 encode_def_id(ebml_w
, local_def(id
));
504 encode_family(ebml_w
, purity_fn_family(ast
::impure_fn
));
505 encode_type_param_bounds(ebml_w
, ecx
, &generics
.ty_params
);
506 let its_ty
= node_id_to_type(ecx
.tcx
, id
);
507 debug
!("fn name = %s ty = %s its node id = %d",
508 *ecx
.tcx
.sess
.str_of(ident
),
509 ty_to_str(ecx
.tcx
, its_ty
), id
);
510 encode_type(ecx
, ebml_w
, its_ty
);
511 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(ident
));
514 (ecx
.encode_inlined_item
)(ecx
, ebml_w
, path
, (*it
));
517 encode_symbol(ecx
, ebml_w
, id
);
523 fn encode_info_for_struct_ctor(ecx
: @EncodeContext
,
524 ebml_w
: writer
::Encoder
,
525 path
: &[ast_map
::path_elt
],
528 index
: @
mut ~[entry
<int
>]) {
529 index
.push(entry { val: ctor_id, pos: ebml_w.writer.tell() }
);
531 ebml_w
.start_tag(tag_items_data_item
);
532 encode_def_id(ebml_w
, local_def(ctor_id
));
533 encode_family(ebml_w
, 'f'
);
534 encode_name(ecx
, ebml_w
, name
);
535 encode_type(ecx
, ebml_w
, node_id_to_type(ecx
.tcx
, ctor_id
));
536 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(name
));
538 if ecx
.item_symbols
.contains_key(&ctor_id
) {
539 encode_symbol(ecx
, ebml_w
, ctor_id
);
545 fn encode_info_for_method(ecx
: @EncodeContext
,
546 ebml_w
: writer
::Encoder
,
547 impl_path
: &[ast_map
::path_elt
],
551 parent_visibility
: ast
::visibility
,
552 owner_generics
: &ast
::Generics
,
553 method_generics
: &ast
::Generics
) {
554 debug
!("encode_info_for_method: %d %s %u %u", m
.id
,
555 *ecx
.tcx
.sess
.str_of(m
.ident
),
556 owner_generics
.ty_params
.len(),
557 method_generics
.ty_params
.len());
558 ebml_w
.start_tag(tag_items_data_item
);
559 encode_def_id(ebml_w
, local_def(m
.id
));
561 match m
.self_ty
.node
{
563 encode_family(ebml_w
, purity_static_method_family(m
.purity
));
565 _
=> encode_family(ebml_w
, purity_fn_family(m
.purity
))
568 let mut combined_ty_params
= opt_vec
::Empty
;
569 combined_ty_params
.push_all(&owner_generics
.ty_params
);
570 combined_ty_params
.push_all(&method_generics
.ty_params
);
571 let len
= combined_ty_params
.len();
572 encode_type_param_bounds(ebml_w
, ecx
, &combined_ty_params
);
574 encode_type(ecx
, ebml_w
, node_id_to_type(ecx
.tcx
, m
.id
));
575 encode_name(ecx
, ebml_w
, m
.ident
);
576 encode_path(ecx
, ebml_w
, impl_path
, ast_map
::path_name(m
.ident
));
577 encode_self_type(ebml_w
, m
.self_ty
.node
);
579 // Combine parent visibility and this visibility.
580 let visibility
= match m
.vis
{
581 ast
::inherited
=> parent_visibility
,
584 encode_visibility(ebml_w
, visibility
);
586 if len
> 0u || should_inline
{
587 (ecx
.encode_inlined_item
)(
588 ecx
, ebml_w
, impl_path
,
589 ii_method(local_def(parent_id
), m
));
591 encode_symbol(ecx
, ebml_w
, m
.id
);
596 fn purity_fn_family(p
: purity
) -> char {
605 fn purity_static_method_family(p
: purity
) -> char {
610 _
=> fail
!(~"extern fn can't be static")
615 fn should_inline(attrs
: &[attribute
]) -> bool
{
616 match attr
::find_inline_attr(attrs
) {
617 attr
::ia_none
| attr
::ia_never
=> false,
618 attr
::ia_hint
| attr
::ia_always
=> true
623 fn encode_info_for_item(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
624 item
: @item
, index
: @
mut ~[entry
<int
>],
625 path
: &[ast_map
::path_elt
]) {
630 item_enum(_
, _
) | item_impl(*) | item_trait(*) | item_struct(*) |
631 item_mod(*) | item_foreign_mod(*) | item_const(*) => true,
634 if !must_write
&& !reachable(ecx
, item
.id
) { return; }
636 fn add_to_index_(item
: @item
, ebml_w
: writer
::Encoder
,
637 index
: @
mut ~[entry
<int
>]) {
638 index
.push(entry { val: item.id, pos: ebml_w.writer.tell() }
);
640 let add_to_index
: &fn() = || add_to_index_(item
, ebml_w
, index
);
642 debug
!("encoding info for item at %s",
643 ecx
.tcx
.sess
.codemap
.span_to_str(item
.span
));
646 item_const(_
, _
) => {
648 ebml_w
.start_tag(tag_items_data_item
);
649 encode_def_id(ebml_w
, local_def(item
.id
));
650 encode_family(ebml_w
, 'c'
);
651 encode_type(ecx
, ebml_w
, node_id_to_type(tcx
, item
.id
));
652 encode_symbol(ecx
, ebml_w
, item
.id
);
653 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(item
.ident
));
654 (ecx
.encode_inlined_item
)(ecx
, ebml_w
, path
, ii_item(item
));
657 item_fn(_
, purity
, _
, ref generics
, _
) => {
659 ebml_w
.start_tag(tag_items_data_item
);
660 encode_def_id(ebml_w
, local_def(item
.id
));
661 encode_family(ebml_w
, purity_fn_family(purity
));
662 let tps_len
= generics
.ty_params
.len();
663 encode_type_param_bounds(ebml_w
, ecx
, &generics
.ty_params
);
664 encode_type(ecx
, ebml_w
, node_id_to_type(tcx
, item
.id
));
665 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(item
.ident
));
666 encode_attributes(ebml_w
, item
.attrs
);
667 if tps_len
> 0u || should_inline(item
.attrs
) {
668 (ecx
.encode_inlined_item
)(ecx
, ebml_w
, path
, ii_item(item
));
670 encode_symbol(ecx
, ebml_w
, item
.id
);
676 encode_info_for_mod(ecx
, ebml_w
, m
, item
.id
, path
, item
.ident
);
678 item_foreign_mod(_
) => {
680 ebml_w
.start_tag(tag_items_data_item
);
681 encode_def_id(ebml_w
, local_def(item
.id
));
682 encode_family(ebml_w
, 'n'
);
683 encode_name(ecx
, ebml_w
, item
.ident
);
684 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(item
.ident
));
687 item_ty(_
, ref generics
) => {
689 ebml_w
.start_tag(tag_items_data_item
);
690 encode_def_id(ebml_w
, local_def(item
.id
));
691 encode_family(ebml_w
, 'y'
);
692 encode_type_param_bounds(ebml_w
, ecx
, &generics
.ty_params
);
693 encode_type(ecx
, ebml_w
, node_id_to_type(tcx
, item
.id
));
694 encode_name(ecx
, ebml_w
, item
.ident
);
695 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(item
.ident
));
696 encode_region_param(ecx
, ebml_w
, item
);
699 item_enum(ref enum_definition
, ref generics
) => {
701 do ebml_w
.wr_tag(tag_items_data_item
) {
702 encode_def_id(ebml_w
, local_def(item
.id
));
703 encode_family(ebml_w
, 't'
);
704 encode_type_param_bounds(ebml_w
, ecx
, &generics
.ty_params
);
705 encode_type(ecx
, ebml_w
, node_id_to_type(tcx
, item
.id
));
706 encode_name(ecx
, ebml_w
, item
.ident
);
707 for (*enum_definition
).variants
.each
|v
| {
708 encode_variant_id(ebml_w
, local_def(v
.node
.id
));
710 (ecx
.encode_inlined_item
)(ecx
, ebml_w
, path
, ii_item(item
));
711 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(item
.ident
));
712 encode_region_param(ecx
, ebml_w
, item
);
714 encode_enum_variant_info(ecx
,
717 (*enum_definition
).variants
,
722 item_struct(struct_def
, ref generics
) => {
723 /* First, encode the fields
724 These come first because we need to write them to make
725 the index, and the index needs to be in the item for the
727 let idx
= encode_info_for_struct(ecx
, ebml_w
, path
,
728 struct_def
.fields
, index
);
729 /* Encode the dtor */
730 for struct_def
.dtor
.each
|dtor
| {
731 index
.push(entry {val: dtor.node.id, pos: ebml_w.writer.tell()}
);
732 encode_info_for_ctor(ecx
,
735 ecx
.tcx
.sess
.ident_of(
736 *ecx
.tcx
.sess
.str_of(item
.ident
) +
739 if generics
.ty_params
.len() > 0u {
740 Some(ii_dtor(copy
*dtor
,
743 local_def(item
.id
))) }
753 /* Now, make an item for the class itself */
754 ebml_w
.start_tag(tag_items_data_item
);
755 encode_def_id(ebml_w
, local_def(item
.id
));
756 encode_family(ebml_w
, 'S'
);
757 encode_type_param_bounds(ebml_w
, ecx
, &generics
.ty_params
);
758 encode_type(ecx
, ebml_w
, node_id_to_type(tcx
, item
.id
));
760 // If this is a tuple- or enum-like struct, encode the type of the
762 if struct_def
.fields
.len() > 0 &&
763 struct_def
.fields
[0].node
.kind
== ast
::unnamed_field
{
764 let ctor_id
= match struct_def
.ctor_id
{
765 Some(ctor_id
) => ctor_id
,
766 None
=> ecx
.tcx
.sess
.bug(~"struct def didn't have ctor id"),
769 encode_info_for_struct_ctor(ecx
,
777 encode_name(ecx
, ebml_w
, item
.ident
);
778 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(item
.ident
));
779 encode_region_param(ecx
, ebml_w
, item
);
780 /* Encode the dtor */
781 /* Encode id for dtor */
782 for struct_def
.dtor
.each
|dtor
| {
783 do ebml_w
.wr_tag(tag_item_dtor
) {
784 encode_def_id(ebml_w
, local_def(dtor
.node
.id
));
788 /* Encode def_ids for each field and method
789 for methods, write all the stuff get_trait_method
791 for struct_def
.fields
.each
|f
| {
793 named_field(ident
, _
, vis
) => {
794 ebml_w
.start_tag(tag_item_field
);
795 encode_struct_field_family(ebml_w
, vis
);
796 encode_name(ecx
, ebml_w
, ident
);
797 encode_def_id(ebml_w
, local_def(f
.node
.id
));
801 ebml_w
.start_tag(tag_item_unnamed_field
);
802 encode_def_id(ebml_w
, local_def(f
.node
.id
));
808 /* Each class has its own index -- encode it */
809 let bkts
= create_index(idx
);
810 encode_index(ebml_w
, bkts
, write_int
);
813 item_impl(ref generics
, opt_trait
, ty
, ref methods
) => {
815 ebml_w
.start_tag(tag_items_data_item
);
816 encode_def_id(ebml_w
, local_def(item
.id
));
817 encode_family(ebml_w
, 'i'
);
818 encode_region_param(ecx
, ebml_w
, item
);
819 encode_type_param_bounds(ebml_w
, ecx
, &generics
.ty_params
);
820 encode_type(ecx
, ebml_w
, node_id_to_type(tcx
, item
.id
));
821 encode_name(ecx
, ebml_w
, item
.ident
);
822 encode_attributes(ebml_w
, item
.attrs
);
824 ast
::ty_path(path
, _
) if path
.idents
.len() == 1 => {
825 encode_impl_type_basename(ecx
, ebml_w
,
826 ast_util
::path_to_ident(path
));
830 for methods
.each
|m
| {
831 ebml_w
.start_tag(tag_item_impl_method
);
832 let method_def_id
= local_def(m
.id
);
833 ebml_w
.writer
.write(str::to_bytes(def_to_str(method_def_id
)));
836 for opt_trait
.each
|associated_trait
| {
837 encode_trait_ref(ebml_w
, ecx
, *associated_trait
);
839 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(item
.ident
));
843 let mut impl_path
= vec
::append(~[], path
);
844 impl_path
+= ~[ast_map
::path_name(item
.ident
)];
846 // If there is a trait reference, treat the methods as always public.
847 // This is to work around some incorrect behavior in privacy checking:
848 // when the method belongs to a trait, it should acquire the privacy
849 // from the trait, not the impl. Forcing the visibility to be public
850 // makes things sorta work.
851 let parent_visibility
= if opt_trait
.is_some() {
857 for methods
.each
|m
| {
858 index
.push(entry {val: m.id, pos: ebml_w.writer.tell()}
);
859 encode_info_for_method(ecx
,
862 should_inline(m
.attrs
),
870 item_trait(ref generics
, ref traits
, ref ms
) => {
871 let mut provided_methods
= ~[];
874 ebml_w
.start_tag(tag_items_data_item
);
875 encode_def_id(ebml_w
, local_def(item
.id
));
876 encode_family(ebml_w
, 'I'
);
877 encode_region_param(ecx
, ebml_w
, item
);
878 encode_type_param_bounds(ebml_w
, ecx
, &generics
.ty_params
);
879 encode_type(ecx
, ebml_w
, node_id_to_type(tcx
, item
.id
));
880 encode_name(ecx
, ebml_w
, item
.ident
);
881 encode_attributes(ebml_w
, item
.attrs
);
883 for vec
::each(*ty
::trait_methods(tcx
, local_def(item
.id
))) |mty
| {
885 required(ref ty_m
) => {
886 ebml_w
.start_tag(tag_item_trait_method
);
887 encode_def_id(ebml_w
, local_def((*ty_m
).id
));
888 encode_name(ecx
, ebml_w
, mty
.ident
);
889 encode_type_param_bounds(ebml_w
, ecx
,
890 &ty_m
.generics
.ty_params
);
891 encode_type(ecx
, ebml_w
,
892 ty
::mk_bare_fn(tcx
, copy mty
.fty
));
893 encode_family(ebml_w
, purity_fn_family(mty
.fty
.purity
));
894 encode_self_type(ebml_w
, mty
.self_ty
);
895 encode_method_sort(ebml_w
, 'r'
);
896 encode_visibility(ebml_w
, ast
::public
);
900 provided_methods
.push(m
);
902 ebml_w
.start_tag(tag_item_trait_method
);
903 encode_def_id(ebml_w
, local_def(m
.id
));
904 encode_name(ecx
, ebml_w
, mty
.ident
);
905 encode_type_param_bounds(ebml_w
, ecx
,
906 &m
.generics
.ty_params
);
907 encode_type(ecx
, ebml_w
,
908 ty
::mk_bare_fn(tcx
, copy mty
.fty
));
909 encode_family(ebml_w
, purity_fn_family(mty
.fty
.purity
));
910 encode_self_type(ebml_w
, mty
.self_ty
);
911 encode_method_sort(ebml_w
, 'p'
);
912 encode_visibility(ebml_w
, m
.vis
);
918 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(item
.ident
));
919 for traits
.each
|associated_trait
| {
920 encode_trait_ref(ebml_w
, ecx
, *associated_trait
)
925 // Now, output all of the static methods as items. Note that for the
926 // method info, we output static methods with type signatures as
927 // written. Here, we output the *real* type signatures. I feel like
928 // maybe we should only ever handle the real type signatures.
930 let ty_m
= ast_util
::trait_method_to_ty_method(m
);
931 if ty_m
.self_ty
.node
!= ast
::sty_static { loop; }
933 index
.push(entry { val: ty_m.id, pos: ebml_w.writer.tell() }
);
935 ebml_w
.start_tag(tag_items_data_item
);
936 encode_def_id(ebml_w
, local_def(ty_m
.id
));
937 encode_parent_item(ebml_w
, local_def(item
.id
));
938 encode_name(ecx
, ebml_w
, ty_m
.ident
);
939 encode_family(ebml_w
,
940 purity_static_method_family(ty_m
.purity
));
941 let polyty
= ecx
.tcx
.tcache
.get(&local_def(ty_m
.id
));
942 encode_ty_type_param_bounds(ebml_w
, ecx
, polyty
.bounds
);
943 encode_type(ecx
, ebml_w
, polyty
.ty
);
944 let mut m_path
= vec
::append(~[], path
); // :-(
945 m_path
+= [ast_map
::path_name(item
.ident
)];
946 encode_path(ecx
, ebml_w
, m_path
, ast_map
::path_name(ty_m
.ident
));
948 // For now, use the item visibility until trait methods can have
949 // real visibility in the AST.
950 encode_visibility(ebml_w
, item
.vis
);
955 // Finally, output all the provided methods as items.
956 for provided_methods
.each
|m
| {
957 index
.push(entry { val: m.id, pos: ebml_w.writer.tell() }
);
959 // We do not concatenate the generics of the owning impl and that
960 // of provided methods. I am not sure why this is. -ndm
961 let owner_generics
= ast_util
::empty_generics();
963 encode_info_for_method(ecx
,
974 item_mac(*) => fail
!(~"item macros unimplemented")
978 fn encode_info_for_foreign_item(ecx
: @EncodeContext
,
979 ebml_w
: writer
::Encoder
,
980 nitem
: @foreign_item
,
981 index
: @
mut ~[entry
<int
>],
982 +path
: ast_map
::path
,
984 if !reachable(ecx
, nitem
.id
) { return; }
985 index
.push(entry { val: nitem.id, pos: ebml_w.writer.tell() }
);
987 ebml_w
.start_tag(tag_items_data_item
);
989 foreign_item_fn(_
, purity
, ref generics
) => {
990 encode_def_id(ebml_w
, local_def(nitem
.id
));
991 encode_family(ebml_w
, purity_fn_family(purity
));
992 encode_type_param_bounds(ebml_w
, ecx
, &generics
.ty_params
);
993 encode_type(ecx
, ebml_w
, node_id_to_type(ecx
.tcx
, nitem
.id
));
994 if abi
.is_intrinsic() {
995 (ecx
.encode_inlined_item
)(ecx
, ebml_w
, path
, ii_foreign(nitem
));
997 encode_symbol(ecx
, ebml_w
, nitem
.id
);
999 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(nitem
.ident
));
1001 foreign_item_const(*) => {
1002 encode_def_id(ebml_w
, local_def(nitem
.id
));
1003 encode_family(ebml_w
, 'c'
);
1004 encode_type(ecx
, ebml_w
, node_id_to_type(ecx
.tcx
, nitem
.id
));
1005 encode_symbol(ecx
, ebml_w
, nitem
.id
);
1006 encode_path(ecx
, ebml_w
, path
, ast_map
::path_name(nitem
.ident
));
1012 fn encode_info_for_items(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
1013 crate: &crate) -> ~[entry
<int
>] {
1014 let index
= @
mut ~[];
1015 ebml_w
.start_tag(tag_items_data
);
1016 index
.push(entry { val: crate_node_id, pos: ebml_w.writer.tell() }
);
1017 encode_info_for_mod(ecx
, ebml_w
, &crate.node
.module
,
1019 syntax
::parse
::token
::special_idents
::invalid
);
1020 visit
::visit_crate(*crate, (), visit
::mk_vt(@visit
::Visitor
{
1021 visit_expr
: |_e
, _cx
, _v
| { }
,
1023 let ebml_w
= copy ebml_w
;
1025 visit
::visit_item(i
, cx
, v
);
1026 match *ecx
.tcx
.items
.get(&i
.id
) {
1027 ast_map
::node_item(_
, pt
) => {
1028 encode_info_for_item(ecx
, ebml_w
, i
,
1031 _
=> fail
!(~"bad item")
1035 visit_foreign_item
: {
1036 let ebml_w
= copy ebml_w
;
1038 visit
::visit_foreign_item(ni
, cx
, v
);
1039 match *ecx
.tcx
.items
.get(&ni
.id
) {
1040 ast_map
::node_foreign_item(_
, abi
, _
, pt
) => {
1041 encode_info_for_foreign_item(ecx
, ebml_w
, ni
,
1042 index
, /*bad*/copy
*pt
,
1045 // case for separate item and foreign-item tables
1046 _
=> fail
!(~"bad foreign item")
1050 ..*visit
::default_visitor()
1053 return /*bad*/copy
*index
;
1057 // Path and definition ID indexing
1059 fn create_index
<T
:Copy
+ Hash
+ IterBytes
>(index
: ~[entry
<T
>]) ->
1061 let mut buckets
: ~[@
mut ~[entry
<T
>]] = ~[];
1062 for uint
::range(0u, 256u) |_i
| { buckets.push(@mut ~[]); }
;
1063 for index
.each
|elt
| {
1064 let h
= elt
.val
.hash() as uint
;
1065 buckets
[h
% 256].push(*elt
);
1068 let mut buckets_frozen
= ~[];
1069 for buckets
.each
|bucket
| {
1070 buckets_frozen
.push(@
/*bad*/copy
**bucket
);
1072 return buckets_frozen
;
1075 fn encode_index
<T
>(ebml_w
: writer
::Encoder
, buckets
: ~[@
~[entry
<T
>]],
1076 write_fn
: &fn(@io
::Writer
, T
)) {
1077 let writer
= ebml_w
.writer
;
1078 ebml_w
.start_tag(tag_index
);
1079 let mut bucket_locs
: ~[uint
] = ~[];
1080 ebml_w
.start_tag(tag_index_buckets
);
1081 for buckets
.each
|bucket
| {
1082 bucket_locs
.push(ebml_w
.writer
.tell());
1083 ebml_w
.start_tag(tag_index_buckets_bucket
);
1084 for vec
::each(**bucket
) |elt
| {
1085 ebml_w
.start_tag(tag_index_buckets_bucket_elt
);
1086 assert
!(elt
.pos
< 0xffff_ffff);
1087 writer
.write_be_u32(elt
.pos
as u32);
1088 write_fn(writer
, elt
.val
);
1094 ebml_w
.start_tag(tag_index_table
);
1095 for bucket_locs
.each
|pos
| {
1096 assert
!(*pos
< 0xffff_ffff);
1097 writer
.write_be_u32(*pos
as u32);
1103 fn write_str(writer
: @io
::Writer
, &&s
: ~str) { writer.write_str(s); }
1105 fn write_int(writer
: @io
::Writer
, &&n
: int
) {
1106 assert
!(n
< 0x7fff_ffff);
1107 writer
.write_be_u32(n
as u32);
1110 fn encode_meta_item(ebml_w
: writer
::Encoder
, mi
: @meta_item
) {
1112 meta_word(name
) => {
1113 ebml_w
.start_tag(tag_meta_item_word
);
1114 ebml_w
.start_tag(tag_meta_item_name
);
1115 ebml_w
.writer
.write(str::to_bytes(*name
));
1119 meta_name_value(name
, value
) => {
1122 ebml_w
.start_tag(tag_meta_item_name_value
);
1123 ebml_w
.start_tag(tag_meta_item_name
);
1124 ebml_w
.writer
.write(str::to_bytes(*name
));
1126 ebml_w
.start_tag(tag_meta_item_value
);
1127 ebml_w
.writer
.write(str::to_bytes(*value
));
1131 _
=> {/* FIXME (#623): encode other variants */ }
1134 meta_list(name
, ref items
) => {
1135 ebml_w
.start_tag(tag_meta_item_list
);
1136 ebml_w
.start_tag(tag_meta_item_name
);
1137 ebml_w
.writer
.write(str::to_bytes(*name
));
1139 for items
.each
|inner_item
| {
1140 encode_meta_item(ebml_w
, *inner_item
);
1147 fn encode_attributes(ebml_w
: writer
::Encoder
, attrs
: &[attribute
]) {
1148 ebml_w
.start_tag(tag_attributes
);
1149 for attrs
.each
|attr
| {
1150 ebml_w
.start_tag(tag_attribute
);
1151 encode_meta_item(ebml_w
, attr
.node
.value
);
1157 // So there's a special crate attribute called 'link' which defines the
1158 // metadata that Rust cares about for linking crates. This attribute requires
1159 // 'name' and 'vers' items, so if the user didn't provide them we will throw
1160 // them in anyway with default values.
1161 fn synthesize_crate_attrs(ecx
: @EncodeContext
,
1162 crate: &crate) -> ~[attribute
] {
1164 fn synthesize_link_attr(ecx
: @EncodeContext
, +items
: ~[@meta_item
]) ->
1167 assert
!(!ecx
.link_meta
.name
.is_empty());
1168 assert
!(!ecx
.link_meta
.vers
.is_empty());
1171 attr
::mk_name_value_item_str(@
~"name",
1172 @ecx
.link_meta
.name
.to_owned());
1174 attr
::mk_name_value_item_str(@
~"vers",
1175 @ecx
.link_meta
.vers
.to_owned());
1179 let tmp
= attr
::remove_meta_items_by_name(items
, ~"name");
1180 attr
::remove_meta_items_by_name(tmp
, ~"vers")
1183 let meta_items
= vec
::append(~[name_item
, vers_item
], other_items
);
1184 let link_item
= attr
::mk_list_item(@
~"link", meta_items
);
1186 return attr
::mk_attr(link_item
);
1189 let mut attrs
: ~[attribute
] = ~[];
1190 let mut found_link_attr
= false;
1191 for crate.node
.attrs
.each
|attr
| {
1193 if *attr
::get_attr_name(attr
) != ~"link" {
1196 match attr
.node
.value
.node
{
1197 meta_list(_
, ref l
) => {
1198 found_link_attr
= true;;
1199 synthesize_link_attr(ecx
, /*bad*/copy
*l
)
1201 _
=> /*bad*/copy
*attr
1206 if !found_link_attr { attrs.push(synthesize_link_attr(ecx, ~[])); }
1211 fn encode_crate_deps(ecx
: @EncodeContext
,
1212 ebml_w
: writer
::Encoder
,
1213 cstore
: @
mut cstore
::CStore
) {
1214 fn get_ordered_deps(ecx
: @EncodeContext
, cstore
: @
mut cstore
::CStore
)
1215 -> ~[decoder
::crate_dep
] {
1216 type numdep
= decoder
::crate_dep
;
1218 // Pull the cnums and name,vers,hash out of cstore
1220 do cstore
::iter_crate_data(cstore
) |key
, val
| {
1221 let dep
= decoder
::crate_dep
{cnum
: key
,
1222 name
: ecx
.tcx
.sess
.ident_of(/*bad*/ copy
*val
.name
),
1223 vers
: decoder
::get_crate_vers(val
.data
),
1224 hash
: decoder
::get_crate_hash(val
.data
)};
1229 std
::sort
::quick_sort(deps
, |kv1
, kv2
| kv1
.cnum
<= kv2
.cnum
);
1231 // Sanity-check the crate numbers
1232 let mut expected_cnum
= 1;
1234 assert
!((n
.cnum
== expected_cnum
));
1238 // mut -> immutable hack for vec::map
1239 deps
.slice(0, deps
.len()).to_owned()
1242 // We're just going to write a list of crate 'name-hash-version's, with
1243 // the assumption that they are numbered 1 to n.
1244 // FIXME (#2166): This is not nearly enough to support correct versioning
1245 // but is enough to get transitive crate dependencies working.
1246 ebml_w
.start_tag(tag_crate_deps
);
1247 for get_ordered_deps(ecx
, cstore
).each
|dep
| {
1248 encode_crate_dep(ecx
, ebml_w
, *dep
);
1253 fn encode_lang_items(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
) {
1254 ebml_w
.start_tag(tag_lang_items
);
1256 for ecx
.tcx
.lang_items
.each_item
|def_id
, i
| {
1257 if def_id
.crate != local_crate
{
1261 ebml_w
.start_tag(tag_lang_items_item
);
1263 ebml_w
.start_tag(tag_lang_items_item_id
);
1264 ebml_w
.writer
.write_be_u32(i
as u32);
1265 ebml_w
.end_tag(); // tag_lang_items_item_id
1267 ebml_w
.start_tag(tag_lang_items_item_node_id
);
1268 ebml_w
.writer
.write_be_u32(def_id
.node
as u32);
1269 ebml_w
.end_tag(); // tag_lang_items_item_node_id
1271 ebml_w
.end_tag(); // tag_lang_items_item
1274 ebml_w
.end_tag(); // tag_lang_items
1277 fn encode_link_args(ecx
: @EncodeContext
,
1278 ebml_w
: writer
::Encoder
) {
1279 ebml_w
.start_tag(tag_link_args
);
1281 let link_args
= cstore
::get_used_link_args(ecx
.cstore
);
1282 for link_args
.each
|link_arg
| {
1283 ebml_w
.start_tag(tag_link_args_arg
);
1284 ebml_w
.writer
.write_str(link_arg
.to_str());
1291 fn encode_crate_dep(ecx
: @EncodeContext
, ebml_w
: writer
::Encoder
,
1292 dep
: decoder
::crate_dep
) {
1293 ebml_w
.start_tag(tag_crate_dep
);
1294 ebml_w
.start_tag(tag_crate_dep_name
);
1295 ebml_w
.writer
.write(str::to_bytes(*ecx
.tcx
.sess
.str_of(dep
.name
)));
1297 ebml_w
.start_tag(tag_crate_dep_vers
);
1298 ebml_w
.writer
.write(str::to_bytes(*dep
.vers
));
1300 ebml_w
.start_tag(tag_crate_dep_hash
);
1301 ebml_w
.writer
.write(str::to_bytes(*dep
.hash
));
1306 fn encode_hash(ebml_w
: writer
::Encoder
, hash
: &str) {
1307 ebml_w
.start_tag(tag_crate_hash
);
1308 ebml_w
.writer
.write(str::to_bytes(hash
));
1312 // NB: Increment this as you change the metadata encoding version.
1313 pub static metadata_encoding_version
: &'
static [u8] =
1314 &[0x72, //'r' as u8,
1320 pub fn encode_metadata(+parms
: EncodeParams
, crate: &crate) -> ~[u8] {
1321 let wr
= @io
::BytesWriter();
1322 let mut stats
= Stats
{
1334 let EncodeParams
{item_symbols
, diag
, tcx
, reachable
, reexports2
,
1335 discrim_symbols
, cstore
, encode_inlined_item
,
1336 link_meta
, _
} = parms
;
1337 let ecx
= @EncodeContext
{
1341 reachable
: reachable
,
1342 reexports2
: reexports2
,
1343 item_symbols
: item_symbols
,
1344 discrim_symbols
: discrim_symbols
,
1345 link_meta
: link_meta
,
1347 encode_inlined_item
: encode_inlined_item
,
1348 type_abbrevs
: @
mut LinearMap
::new()
1351 let ebml_w
= writer
::Encoder(wr
as @io
::Writer
);
1353 encode_hash(ebml_w
, ecx
.link_meta
.extras_hash
);
1356 let crate_attrs
= synthesize_crate_attrs(ecx
, crate);
1357 encode_attributes(ebml_w
, crate_attrs
);
1358 ecx
.stats
.attr_bytes
= wr
.pos
- i
;
1361 encode_crate_deps(ecx
, ebml_w
, ecx
.cstore
);
1362 ecx
.stats
.dep_bytes
= wr
.pos
- i
;
1364 // Encode the language items.
1366 encode_lang_items(ecx
, ebml_w
);
1367 ecx
.stats
.lang_item_bytes
= wr
.pos
- i
;
1369 // Encode the link args.
1371 encode_link_args(ecx
, ebml_w
);
1372 ecx
.stats
.link_args_bytes
= wr
.pos
- i
;
1374 // Encode and index the items.
1375 ebml_w
.start_tag(tag_items
);
1377 let items_index
= encode_info_for_items(ecx
, ebml_w
, crate);
1378 ecx
.stats
.item_bytes
= wr
.pos
- i
;
1381 let items_buckets
= create_index(items_index
);
1382 encode_index(ebml_w
, items_buckets
, write_int
);
1383 ecx
.stats
.index_bytes
= wr
.pos
- i
;
1386 ecx
.stats
.total_bytes
= wr
.pos
;
1388 if (tcx
.sess
.meta_stats()) {
1390 do wr
.bytes
.each
|e
| {
1392 ecx
.stats
.zero_bytes
+= 1;
1397 io
::println("metadata stats:");
1398 io
::println(fmt
!(" inline bytes: %u", ecx
.stats
.inline_bytes
));
1399 io
::println(fmt
!(" attribute bytes: %u", ecx
.stats
.attr_bytes
));
1400 io
::println(fmt
!(" dep bytes: %u", ecx
.stats
.dep_bytes
));
1401 io
::println(fmt
!(" lang item bytes: %u", ecx
.stats
.lang_item_bytes
));
1402 io
::println(fmt
!(" link args bytes: %u", ecx
.stats
.link_args_bytes
));
1403 io
::println(fmt
!(" item bytes: %u", ecx
.stats
.item_bytes
));
1404 io
::println(fmt
!(" index bytes: %u", ecx
.stats
.index_bytes
));
1405 io
::println(fmt
!(" zero bytes: %u", ecx
.stats
.zero_bytes
));
1406 io
::println(fmt
!(" total bytes: %u", ecx
.stats
.total_bytes
));
1409 // Pad this, since something (LLVM, presumably) is cutting off the
1410 // remaining % 4 bytes.
1411 wr
.write(&[0u8, 0u8, 0u8, 0u8]);
1413 // FIXME #3396: weird bug here, for reasons unclear this emits random
1414 // looking bytes (mostly 0x1) if we use the version byte-array constant
1415 // above; so we use a string constant inline instead.
1419 // vec::from_slice(metadata_encoding_version) +
1421 (do str::as_bytes(&~"rust\x00\x00\x00\x01") |bytes
| {
1422 vec
::slice(*bytes
, 0, 8).to_vec()
1423 }) + flate
::deflate_bytes(wr
.bytes
)
1426 // Get the encoded string for a type
1427 pub fn encoded_ty(tcx
: ty
::ctxt
, t
: ty
::t
) -> ~str {
1428 let cx
= @tyencode
::ctxt
{
1432 reachable
: |_id
| false,
1433 abbrevs
: tyencode
::ac_no_abbrevs
};
1434 do io
::with_str_writer
|wr
| {
1435 tyencode
::enc_ty(wr
, cx
, t
);
1443 // indent-tabs-mode: nil
1444 // c-basic-offset: 4
1445 // buffer-file-coding-system: utf-8-unix