2012-12-03 16:48:01 -08:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2011-06-27 16:03:01 -07:00
|
|
|
// Metadata encoding
|
|
|
|
|
2013-05-17 15:28:44 -07:00
|
|
|
|
2012-12-23 17:41:37 -05:00
|
|
|
use metadata::common::*;
|
|
|
|
use metadata::cstore;
|
|
|
|
use metadata::decoder;
|
|
|
|
use metadata::tyencode;
|
2013-07-16 16:28:33 -07:00
|
|
|
use middle::ty::{node_id_to_type, lookup_item_type};
|
2012-12-23 17:41:37 -05:00
|
|
|
use middle::ty;
|
|
|
|
use middle;
|
2012-04-26 12:15:46 -07:00
|
|
|
|
2013-06-28 18:32:26 -04:00
|
|
|
use std::hash::HashUtil;
|
|
|
|
use std::hashmap::{HashMap, HashSet};
|
|
|
|
use std::int;
|
|
|
|
use std::io;
|
|
|
|
use std::str;
|
|
|
|
use std::uint;
|
|
|
|
use std::vec;
|
2013-05-24 19:35:29 -07:00
|
|
|
use extra::flate;
|
2013-05-18 12:39:17 -07:00
|
|
|
use extra::serialize::Encodable;
|
|
|
|
use extra;
|
2013-03-13 22:25:28 -04:00
|
|
|
use syntax::abi::AbiSet;
|
2012-09-04 11:54:36 -07:00
|
|
|
use syntax::ast::*;
|
2012-12-23 17:41:37 -05:00
|
|
|
use syntax::ast;
|
2012-09-04 11:54:36 -07:00
|
|
|
use syntax::ast_map;
|
2012-12-23 17:41:37 -05:00
|
|
|
use syntax::ast_util::*;
|
2012-09-04 11:54:36 -07:00
|
|
|
use syntax::attr;
|
|
|
|
use syntax::diagnostic::span_handler;
|
2013-05-24 19:35:29 -07:00
|
|
|
use syntax::parse::token::special_idents;
|
|
|
|
use syntax::{ast_util, visit};
|
2013-05-14 17:27:27 -07:00
|
|
|
use syntax::parse::token;
|
2012-12-23 17:41:37 -05:00
|
|
|
use syntax;
|
2013-05-18 12:39:17 -07:00
|
|
|
use writer = extra::ebml::writer;
|
2012-09-19 13:13:24 -07:00
|
|
|
|
2013-06-28 18:32:26 -04:00
|
|
|
use std::cast;
|
2013-06-13 19:19:50 +12:00
|
|
|
|
2012-02-14 15:21:53 -08:00
|
|
|
// used by astencode:
|
2013-04-03 09:28:36 -04:00
|
|
|
type abbrev_map = @mut HashMap<ty::t, tyencode::ty_abbrev>;
|
2011-07-07 23:55:41 -07:00
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
pub type encode_inlined_item<'self> = &'self fn(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2013-01-22 11:57:39 -08:00
|
|
|
path: &[ast_map::path_elt],
|
2013-01-15 16:33:20 -08:00
|
|
|
ii: ast::inlined_item);
|
2012-05-14 17:38:17 -07:00
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
pub struct EncodeParams<'self> {
|
2013-03-12 13:00:50 -07:00
|
|
|
diag: @span_handler,
|
2012-05-13 17:01:52 -07:00
|
|
|
tcx: ty::ctxt,
|
2012-08-29 13:26:26 -07:00
|
|
|
reexports2: middle::resolve::ExportMap2,
|
2013-06-13 19:19:50 +12:00
|
|
|
item_symbols: &'self HashMap<ast::node_id, ~str>,
|
|
|
|
discrim_symbols: &'self HashMap<ast::node_id, @str>,
|
|
|
|
link_meta: &'self LinkMeta,
|
2013-02-04 14:02:01 -08:00
|
|
|
cstore: @mut cstore::CStore,
|
2013-06-18 09:39:16 -07:00
|
|
|
encode_inlined_item: encode_inlined_item<'self>,
|
|
|
|
reachable: @mut HashSet<ast::node_id>,
|
2013-02-19 02:40:42 -05:00
|
|
|
}
|
2012-05-13 17:01:52 -07:00
|
|
|
|
2013-02-04 14:02:01 -08:00
|
|
|
struct Stats {
|
|
|
|
inline_bytes: uint,
|
|
|
|
attr_bytes: uint,
|
|
|
|
dep_bytes: uint,
|
|
|
|
lang_item_bytes: uint,
|
2013-03-06 22:06:53 -08:00
|
|
|
link_args_bytes: uint,
|
2013-06-18 09:39:16 -07:00
|
|
|
misc_bytes: uint,
|
2013-02-04 14:02:01 -08:00
|
|
|
item_bytes: uint,
|
|
|
|
index_bytes: uint,
|
|
|
|
zero_bytes: uint,
|
|
|
|
total_bytes: uint,
|
|
|
|
|
|
|
|
n_inlines: uint
|
|
|
|
}
|
2012-08-27 16:53:54 -07:00
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
pub struct EncodeContext<'self> {
|
2013-03-12 13:00:50 -07:00
|
|
|
diag: @span_handler,
|
2012-05-13 17:01:52 -07:00
|
|
|
tcx: ty::ctxt,
|
2013-02-04 14:02:01 -08:00
|
|
|
stats: @mut Stats,
|
2012-08-29 13:26:26 -07:00
|
|
|
reexports2: middle::resolve::ExportMap2,
|
2013-06-13 19:19:50 +12:00
|
|
|
item_symbols: &'self HashMap<ast::node_id, ~str>,
|
|
|
|
discrim_symbols: &'self HashMap<ast::node_id, @str>,
|
|
|
|
link_meta: &'self LinkMeta,
|
|
|
|
cstore: &'self cstore::CStore,
|
|
|
|
encode_inlined_item: encode_inlined_item<'self>,
|
2013-06-18 09:39:16 -07:00
|
|
|
type_abbrevs: abbrev_map,
|
|
|
|
reachable: @mut HashSet<ast::node_id>,
|
2013-02-19 02:40:42 -05:00
|
|
|
}
|
2011-07-07 23:55:41 -07:00
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
pub fn reachable(ecx: &EncodeContext, id: node_id) -> bool {
|
2013-03-22 22:26:41 -04:00
|
|
|
ecx.reachable.contains(&id)
|
2012-04-23 23:40:53 -07:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_name(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
name: ident) {
|
2013-06-13 03:02:55 +10:00
|
|
|
ebml_w.wr_tagged_str(tag_paths_data_name, ecx.tcx.sess.str_of(name));
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_impl_type_basename(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2012-10-18 13:29:34 -07:00
|
|
|
name: ident) {
|
|
|
|
ebml_w.wr_tagged_str(tag_item_impl_type_basename,
|
2013-06-13 03:02:55 +10:00
|
|
|
ecx.tcx.sess.str_of(name));
|
2012-10-18 13:29:34 -07:00
|
|
|
}
|
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
pub fn encode_def_id(ebml_w: &mut writer::Encoder, id: def_id) {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
|
2012-02-06 07:13:14 -08:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_region_param(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2012-07-11 10:28:30 -07:00
|
|
|
it: @ast::item) {
|
2013-02-05 19:41:45 -08:00
|
|
|
let opt_rp = ecx.tcx.region_paramd_items.find(&it.id);
|
2013-06-10 17:50:12 -04:00
|
|
|
for opt_rp.iter().advance |rp| {
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w.start_tag(tag_region_param);
|
|
|
|
rp.encode(ebml_w);
|
|
|
|
ebml_w.end_tag();
|
2012-08-09 09:59:50 -07:00
|
|
|
}
|
2012-04-18 21:26:25 -07:00
|
|
|
}
|
|
|
|
|
2013-07-02 12:47:32 -07:00
|
|
|
#[deriving(Clone)]
|
2013-02-19 02:40:42 -05:00
|
|
|
struct entry<T> {
|
|
|
|
val: T,
|
|
|
|
pos: uint
|
|
|
|
}
|
2011-07-26 14:06:02 +02:00
|
|
|
|
2013-06-04 15:14:56 -07:00
|
|
|
fn add_to_index(ebml_w: &mut writer::Encoder,
|
2013-05-01 17:54:54 -07:00
|
|
|
path: &[ident],
|
|
|
|
index: &mut ~[entry<~str>],
|
|
|
|
name: ident) {
|
2012-06-29 16:26:56 -07:00
|
|
|
let mut full_path = ~[];
|
2012-09-26 17:33:34 -07:00
|
|
|
full_path.push_all(path);
|
|
|
|
full_path.push(name);
|
|
|
|
index.push(
|
2013-02-19 02:40:42 -05:00
|
|
|
entry {
|
2013-06-04 11:09:18 -07:00
|
|
|
val: ast_util::path_name_i(full_path),
|
2013-02-19 02:40:42 -05:00
|
|
|
pos: ebml_w.writer.tell()
|
|
|
|
});
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
fn encode_trait_ref(ebml_w: &mut writer::Encoder,
|
2013-06-13 19:19:50 +12:00
|
|
|
ecx: &EncodeContext,
|
2013-03-27 06:16:28 -04:00
|
|
|
trait_ref: &ty::TraitRef,
|
2013-05-01 17:54:54 -07:00
|
|
|
tag: uint) {
|
2013-03-27 06:16:28 -04:00
|
|
|
let ty_str_ctxt = @tyencode::ctxt {
|
|
|
|
diag: ecx.diag,
|
|
|
|
ds: def_to_str,
|
|
|
|
tcx: ecx.tcx,
|
2013-06-14 18:21:47 -07:00
|
|
|
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
|
|
|
|
};
|
2013-03-27 06:16:28 -04:00
|
|
|
|
|
|
|
ebml_w.start_tag(tag);
|
|
|
|
tyencode::enc_trait_ref(ebml_w.writer, ty_str_ctxt, trait_ref);
|
2012-04-26 12:15:46 -07:00
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
2011-06-27 15:20:17 -07:00
|
|
|
// Item info table encoding
|
2013-05-01 17:54:54 -07:00
|
|
|
fn encode_family(ebml_w: &mut writer::Encoder, c: char) {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item_family);
|
2012-06-29 16:26:56 -07:00
|
|
|
ebml_w.writer.write(&[c as u8]);
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
pub fn def_to_str(did: def_id) -> ~str {
|
|
|
|
fmt!("%d:%d", did.crate, did.node)
|
|
|
|
}
|
2011-06-27 15:20:17 -07:00
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
|
2013-06-13 19:19:50 +12:00
|
|
|
ecx: &EncodeContext,
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-08 22:54:49 -07:00
|
|
|
params: @~[ty::TypeParameterDef],
|
|
|
|
tag: uint) {
|
2013-01-08 14:00:45 -08:00
|
|
|
let ty_str_ctxt = @tyencode::ctxt {
|
|
|
|
diag: ecx.diag,
|
|
|
|
ds: def_to_str,
|
|
|
|
tcx: ecx.tcx,
|
2013-06-14 18:21:47 -07:00
|
|
|
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
|
|
|
|
};
|
2013-06-21 08:29:53 -04:00
|
|
|
for params.iter().advance |param| {
|
2013-03-27 10:26:57 -04:00
|
|
|
ebml_w.start_tag(tag);
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-08 22:54:49 -07:00
|
|
|
tyencode::enc_type_param_def(ebml_w.writer, ty_str_ctxt, param);
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-07-29 16:40:23 -07:00
|
|
|
}
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-07-16 16:28:33 -07:00
|
|
|
fn encode_bounds_and_type(ebml_w: &mut writer::Encoder,
|
|
|
|
ecx: &EncodeContext,
|
|
|
|
tpt: &ty::ty_param_bounds_and_ty) {
|
|
|
|
encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs,
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-08 22:54:49 -07:00
|
|
|
tag_items_data_item_ty_param_bounds);
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_type(ecx, ebml_w, tpt.ty);
|
2012-08-02 16:01:38 -07:00
|
|
|
}
|
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
fn encode_variant_id(ebml_w: &mut writer::Encoder, vid: def_id) {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item_variant);
|
2013-06-11 13:10:37 +10:00
|
|
|
let s = def_to_str(vid);
|
|
|
|
ebml_w.writer.write(s.as_bytes());
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
pub fn write_type(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
typ: ty::t) {
|
2013-01-08 14:00:45 -08:00
|
|
|
let ty_str_ctxt = @tyencode::ctxt {
|
|
|
|
diag: ecx.diag,
|
|
|
|
ds: def_to_str,
|
|
|
|
tcx: ecx.tcx,
|
2013-06-14 18:21:47 -07:00
|
|
|
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
|
|
|
|
};
|
2012-01-11 15:15:54 +01:00
|
|
|
tyencode::enc_ty(ebml_w.writer, ty_str_ctxt, typ);
|
2012-01-05 10:57:19 +01:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
pub fn write_vstore(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2013-01-29 16:51:16 -08:00
|
|
|
vstore: ty::vstore) {
|
2013-01-08 14:00:45 -08:00
|
|
|
let ty_str_ctxt = @tyencode::ctxt {
|
|
|
|
diag: ecx.diag,
|
|
|
|
ds: def_to_str,
|
|
|
|
tcx: ecx.tcx,
|
2013-06-14 18:21:47 -07:00
|
|
|
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
|
|
|
|
};
|
2012-10-05 16:55:42 -07:00
|
|
|
tyencode::enc_vstore(ebml_w.writer, ty_str_ctxt, vstore);
|
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_type(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
typ: ty::t) {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item_type);
|
2012-01-05 10:57:19 +01:00
|
|
|
write_type(ecx, ebml_w, typ);
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_transformed_self_ty(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
opt_typ: Option<ty::t>) {
|
2013-06-10 17:50:12 -04:00
|
|
|
for opt_typ.iter().advance |&typ| {
|
2013-03-29 16:02:55 -04:00
|
|
|
ebml_w.start_tag(tag_item_method_transformed_self_ty);
|
|
|
|
write_type(ecx, ebml_w, typ);
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_method_fty(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
typ: &ty::BareFnTy) {
|
2013-03-27 10:26:57 -04:00
|
|
|
ebml_w.start_tag(tag_item_method_fty);
|
|
|
|
|
|
|
|
let ty_str_ctxt = @tyencode::ctxt {
|
|
|
|
diag: ecx.diag,
|
|
|
|
ds: def_to_str,
|
|
|
|
tcx: ecx.tcx,
|
2013-06-14 18:21:47 -07:00
|
|
|
abbrevs: tyencode::ac_use_abbrevs(ecx.type_abbrevs)
|
|
|
|
};
|
2013-03-27 10:26:57 -04:00
|
|
|
tyencode::enc_bare_fn_ty(ebml_w.writer, ty_str_ctxt, typ);
|
|
|
|
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_symbol(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
id: node_id) {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item_symbol);
|
2013-03-06 12:27:23 -05:00
|
|
|
match ecx.item_symbols.find(&id) {
|
2013-03-22 22:26:41 -04:00
|
|
|
Some(x) => {
|
2013-03-06 12:27:23 -05:00
|
|
|
debug!("encode_symbol(id=%?, str=%s)", id, *x);
|
2013-06-11 13:10:37 +10:00
|
|
|
ebml_w.writer.write(x.as_bytes());
|
2013-03-06 12:27:23 -05:00
|
|
|
}
|
|
|
|
None => {
|
|
|
|
ecx.diag.handler().bug(
|
|
|
|
fmt!("encode_symbol: id not found %d", id));
|
|
|
|
}
|
|
|
|
}
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_discriminant(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2012-10-07 10:31:34 -07:00
|
|
|
id: node_id) {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item_symbol);
|
2013-06-11 13:10:37 +10:00
|
|
|
ebml_w.writer.write(ecx.discrim_symbols.get_copy(&id).as_bytes());
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_disr_val(_: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2012-10-07 10:31:34 -07:00
|
|
|
disr_val: int) {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_disr_val);
|
2013-06-11 13:10:37 +10:00
|
|
|
let s = int::to_str(disr_val);
|
|
|
|
ebml_w.writer.write(s.as_bytes());
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2012-01-10 14:50:40 -07:00
|
|
|
}
|
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
fn encode_parent_item(ebml_w: &mut writer::Encoder, id: def_id) {
|
2012-03-08 23:13:57 +01:00
|
|
|
ebml_w.start_tag(tag_items_data_parent_item);
|
2013-06-11 13:10:37 +10:00
|
|
|
let s = def_to_str(id);
|
|
|
|
ebml_w.writer.write(s.as_bytes());
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_enum_variant_info(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
id: node_id,
|
|
|
|
variants: &[variant],
|
2013-01-22 11:57:39 -08:00
|
|
|
path: &[ast_map::path_elt],
|
|
|
|
index: @mut ~[entry<int>],
|
2013-02-14 21:50:03 -08:00
|
|
|
generics: &ast::Generics) {
|
2013-03-06 12:27:23 -05:00
|
|
|
debug!("encode_enum_variant_info(id=%?)", id);
|
|
|
|
|
2012-03-15 09:47:03 -04:00
|
|
|
let mut disr_val = 0;
|
|
|
|
let mut i = 0;
|
2013-01-13 11:05:40 -08:00
|
|
|
let vi = ty::enum_variants(ecx.tcx,
|
|
|
|
ast::def_id { crate: local_crate, node: id });
|
2013-06-21 08:29:53 -04:00
|
|
|
for variants.iter().advance |variant| {
|
2013-07-16 16:28:33 -07:00
|
|
|
let def_id = local_def(variant.node.id);
|
2013-02-19 02:40:42 -05:00
|
|
|
index.push(entry {val: variant.node.id, pos: ebml_w.writer.tell()});
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_def_id(ebml_w, def_id);
|
2012-02-13 20:55:23 +01:00
|
|
|
encode_family(ebml_w, 'v');
|
2012-07-18 16:18:02 -07:00
|
|
|
encode_name(ecx, ebml_w, variant.node.name);
|
2012-03-08 23:13:57 +01:00
|
|
|
encode_parent_item(ebml_w, local_def(id));
|
2013-05-16 15:37:52 -07:00
|
|
|
encode_visibility(ebml_w, variant.node.vis);
|
2012-08-07 14:24:04 -07:00
|
|
|
match variant.node.kind {
|
2013-01-07 14:16:52 -08:00
|
|
|
ast::tuple_variant_kind(ref args)
|
2013-02-14 21:50:03 -08:00
|
|
|
if args.len() > 0 && generics.ty_params.len() == 0 => {
|
2012-08-07 14:24:04 -07:00
|
|
|
encode_symbol(ecx, ebml_w, variant.node.id);
|
|
|
|
}
|
2013-03-28 11:29:21 -07:00
|
|
|
ast::tuple_variant_kind(_) | ast::struct_variant_kind(_) => {}
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
2011-07-07 23:55:41 -07:00
|
|
|
encode_discriminant(ecx, ebml_w, variant.node.id);
|
2012-01-16 02:36:47 -07:00
|
|
|
if vi[i].disr_val != disr_val {
|
|
|
|
encode_disr_val(ecx, ebml_w, vi[i].disr_val);
|
|
|
|
disr_val = vi[i].disr_val;
|
2012-01-10 14:50:40 -07:00
|
|
|
}
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_bounds_and_type(ebml_w, ecx,
|
|
|
|
&lookup_item_type(ecx.tcx, def_id));
|
2013-01-22 11:57:39 -08:00
|
|
|
encode_path(ecx, ebml_w, path,
|
2013-01-07 14:16:52 -08:00
|
|
|
ast_map::path_name(variant.node.name));
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2012-01-10 14:50:40 -07:00
|
|
|
disr_val += 1;
|
2012-01-16 02:36:47 -07:00
|
|
|
i += 1;
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_path(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
path: &[ast_map::path_elt],
|
|
|
|
name: ast_map::path_elt) {
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_path_elt(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2012-07-18 16:18:02 -07:00
|
|
|
elt: ast_map::path_elt) {
|
2012-08-06 12:34:08 -07:00
|
|
|
let (tag, name) = match elt {
|
2012-08-03 19:59:04 -07:00
|
|
|
ast_map::path_mod(name) => (tag_path_elt_mod, name),
|
|
|
|
ast_map::path_name(name) => (tag_path_elt_name, name)
|
2012-02-10 06:01:32 -08:00
|
|
|
};
|
|
|
|
|
2013-06-13 03:02:55 +10:00
|
|
|
ebml_w.wr_tagged_str(tag, ecx.tcx.sess.str_of(name));
|
2012-02-10 06:01:32 -08:00
|
|
|
}
|
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w.start_tag(tag_path);
|
|
|
|
ebml_w.wr_tagged_u32(tag_path_len, (path.len() + 1) as u32);
|
2013-06-21 08:29:53 -04:00
|
|
|
for path.iter().advance |pe| {
|
2013-05-01 17:54:54 -07:00
|
|
|
encode_path_elt(ecx, ebml_w, *pe);
|
2012-02-10 06:01:32 -08:00
|
|
|
}
|
2013-05-01 17:54:54 -07:00
|
|
|
encode_path_elt(ecx, ebml_w, name);
|
|
|
|
ebml_w.end_tag();
|
2012-02-10 06:01:32 -08:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_reexported_static_method(ecx: &EncodeContext,
|
2013-05-08 23:13:53 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
exp: &middle::resolve::Export2,
|
2013-06-01 02:54:39 -07:00
|
|
|
method_def_id: def_id,
|
|
|
|
method_ident: ident) {
|
|
|
|
debug!("(encode reexported static method) %s::%s",
|
2013-06-13 03:02:55 +10:00
|
|
|
exp.name, ecx.tcx.sess.str_of(method_ident));
|
2013-05-08 23:13:53 -07:00
|
|
|
ebml_w.start_tag(tag_items_data_item_reexport);
|
|
|
|
ebml_w.start_tag(tag_items_data_item_reexport_def_id);
|
2013-06-01 02:54:39 -07:00
|
|
|
ebml_w.wr_str(def_to_str(method_def_id));
|
2013-05-08 23:13:53 -07:00
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.start_tag(tag_items_data_item_reexport_name);
|
2013-06-13 03:02:55 +10:00
|
|
|
ebml_w.wr_str(fmt!("%s::%s", exp.name, ecx.tcx.sess.str_of(method_ident)));
|
2013-05-08 23:13:53 -07:00
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_reexported_static_base_methods(ecx: &EncodeContext,
|
2013-06-01 02:54:39 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
exp: &middle::resolve::Export2)
|
|
|
|
-> bool {
|
2013-07-12 18:26:07 -07:00
|
|
|
match ecx.tcx.inherent_impls.find(&exp.def_id) {
|
2013-06-01 02:54:39 -07:00
|
|
|
Some(implementations) => {
|
2013-06-21 08:29:53 -04:00
|
|
|
for implementations.iter().advance |&base_impl| {
|
|
|
|
for base_impl.methods.iter().advance |&m| {
|
2013-06-01 02:54:39 -07:00
|
|
|
if m.explicit_self == ast::sty_static {
|
|
|
|
encode_reexported_static_method(ecx, ebml_w, exp,
|
2013-07-15 15:24:16 -07:00
|
|
|
m.def_id, m.ident);
|
2013-06-01 02:54:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
true
|
|
|
|
}
|
|
|
|
None => { false }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_reexported_static_trait_methods(ecx: &EncodeContext,
|
2013-06-01 02:54:39 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
exp: &middle::resolve::Export2)
|
|
|
|
-> bool {
|
|
|
|
match ecx.tcx.trait_methods_cache.find(&exp.def_id) {
|
|
|
|
Some(methods) => {
|
2013-06-21 08:29:53 -04:00
|
|
|
for methods.iter().advance |&m| {
|
2013-06-01 02:54:39 -07:00
|
|
|
if m.explicit_self == ast::sty_static {
|
|
|
|
encode_reexported_static_method(ecx, ebml_w, exp,
|
|
|
|
m.def_id, m.ident);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
true
|
|
|
|
}
|
|
|
|
None => { false }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_reexported_static_methods(ecx: &EncodeContext,
|
2013-05-08 23:13:53 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
mod_path: &[ast_map::path_elt],
|
|
|
|
exp: &middle::resolve::Export2) {
|
2013-06-01 02:54:39 -07:00
|
|
|
match ecx.tcx.items.find(&exp.def_id.node) {
|
|
|
|
Some(&ast_map::node_item(item, path)) => {
|
|
|
|
let original_name = ecx.tcx.sess.str_of(item.ident);
|
|
|
|
|
|
|
|
//
|
|
|
|
// We don't need to reexport static methods on items
|
|
|
|
// declared in the same module as our `pub use ...` since
|
2013-06-01 04:24:31 -07:00
|
|
|
// that's done when we encode the item itself.
|
2013-06-01 02:54:39 -07:00
|
|
|
//
|
|
|
|
// The only exception is when the reexport *changes* the
|
|
|
|
// name e.g. `pub use Foo = self::Bar` -- we have
|
|
|
|
// encoded metadata for static methods relative to Bar,
|
|
|
|
// but not yet for Foo.
|
|
|
|
//
|
2013-06-13 03:02:55 +10:00
|
|
|
if mod_path != *path || exp.name != original_name {
|
2013-06-01 02:54:39 -07:00
|
|
|
if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
|
|
|
|
if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
|
|
|
|
debug!(fmt!("(encode reexported static methods) %s \
|
|
|
|
[trait]",
|
2013-06-13 03:02:55 +10:00
|
|
|
original_name));
|
2013-05-08 23:13:53 -07:00
|
|
|
}
|
|
|
|
}
|
2013-06-01 02:54:39 -07:00
|
|
|
else {
|
|
|
|
debug!(fmt!("(encode reexported static methods) %s [base]",
|
2013-06-13 03:02:55 +10:00
|
|
|
original_name));
|
2013-06-01 02:54:39 -07:00
|
|
|
}
|
2013-05-08 23:13:53 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-18 09:39:16 -07:00
|
|
|
/// Iterates through "auxiliary node IDs", which are node IDs that describe
|
|
|
|
/// top-level items that are sub-items of the given item. Specifically:
|
|
|
|
///
|
|
|
|
/// * For enums, iterates through the node IDs of the variants.
|
|
|
|
///
|
|
|
|
/// * For newtype structs, iterates through the node ID of the constructor.
|
|
|
|
fn each_auxiliary_node_id(item: @item, callback: &fn(node_id) -> bool)
|
|
|
|
-> bool {
|
|
|
|
let mut continue = true;
|
|
|
|
match item.node {
|
|
|
|
item_enum(ref enum_def, _) => {
|
2013-06-25 18:25:27 -07:00
|
|
|
for enum_def.variants.iter().advance |variant| {
|
2013-06-18 09:39:16 -07:00
|
|
|
continue = callback(variant.node.id);
|
|
|
|
if !continue {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
item_struct(struct_def, _) => {
|
|
|
|
// If this is a newtype struct, return the constructor.
|
|
|
|
match struct_def.ctor_id {
|
|
|
|
Some(ctor_id) if struct_def.fields.len() > 0 &&
|
|
|
|
struct_def.fields[0].node.kind ==
|
|
|
|
ast::unnamed_field => {
|
|
|
|
continue = callback(ctor_id);
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
fn encode_reexports(ecx: &EncodeContext,
|
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
id: node_id,
|
|
|
|
path: &[ast_map::path_elt]) {
|
|
|
|
debug!("(encoding info for module) encoding reexports for %d", id);
|
|
|
|
match ecx.reexports2.find(&id) {
|
|
|
|
Some(ref exports) => {
|
|
|
|
debug!("(encoding info for module) found reexports for %d", id);
|
2013-06-25 18:25:27 -07:00
|
|
|
for exports.iter().advance |exp| {
|
2013-06-18 09:39:16 -07:00
|
|
|
debug!("(encoding info for module) reexport '%s' for %d",
|
|
|
|
exp.name, id);
|
|
|
|
ebml_w.start_tag(tag_items_data_item_reexport);
|
|
|
|
ebml_w.start_tag(tag_items_data_item_reexport_def_id);
|
|
|
|
ebml_w.wr_str(def_to_str(exp.def_id));
|
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.start_tag(tag_items_data_item_reexport_name);
|
|
|
|
ebml_w.wr_str(exp.name);
|
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.end_tag();
|
|
|
|
encode_reexported_static_methods(ecx, ebml_w, path, exp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
debug!("(encoding info for module) found no reexports for %d",
|
|
|
|
id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_info_for_mod(ecx: &EncodeContext,
|
2013-05-04 14:25:41 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2013-05-01 17:54:54 -07:00
|
|
|
md: &_mod,
|
|
|
|
id: node_id,
|
|
|
|
path: &[ast_map::path_elt],
|
2013-06-18 09:39:16 -07:00
|
|
|
name: ident,
|
|
|
|
vis: visibility) {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2011-12-16 14:41:12 +01:00
|
|
|
encode_def_id(ebml_w, local_def(id));
|
2012-02-13 20:55:23 +01:00
|
|
|
encode_family(ebml_w, 'm');
|
2012-07-18 16:18:02 -07:00
|
|
|
encode_name(ecx, ebml_w, name);
|
2012-08-22 17:24:52 -07:00
|
|
|
debug!("(encoding info for module) encoding info for module ID %d", id);
|
2012-08-17 16:38:07 -07:00
|
|
|
|
|
|
|
// Encode info about all the module children.
|
2013-06-21 08:29:53 -04:00
|
|
|
for md.items.iter().advance |item| {
|
2013-06-18 09:39:16 -07:00
|
|
|
ebml_w.start_tag(tag_mod_child);
|
|
|
|
ebml_w.wr_str(def_to_str(local_def(item.id)));
|
|
|
|
ebml_w.end_tag();
|
|
|
|
|
|
|
|
for each_auxiliary_node_id(*item) |auxiliary_node_id| {
|
|
|
|
ebml_w.start_tag(tag_mod_child);
|
|
|
|
ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
2012-08-17 16:38:07 -07:00
|
|
|
match item.node {
|
2013-02-11 16:28:39 -08:00
|
|
|
item_impl(*) => {
|
2012-08-17 16:38:07 -07:00
|
|
|
let (ident, did) = (item.ident, item.id);
|
2012-08-22 17:24:52 -07:00
|
|
|
debug!("(encoding info for module) ... encoding impl %s \
|
2013-01-30 17:20:02 -08:00
|
|
|
(%?/%?)",
|
2013-06-13 03:02:55 +10:00
|
|
|
ecx.tcx.sess.str_of(ident),
|
2012-07-18 16:18:02 -07:00
|
|
|
did,
|
2013-05-14 17:27:27 -07:00
|
|
|
ast_map::node_id_to_str(ecx.tcx.items, did, token::get_ident_interner()));
|
2012-08-17 16:38:07 -07:00
|
|
|
|
|
|
|
ebml_w.start_tag(tag_mod_impl);
|
|
|
|
ebml_w.wr_str(def_to_str(local_def(did)));
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
2013-06-18 09:39:16 -07:00
|
|
|
_ => {}
|
2012-08-17 16:38:07 -07:00
|
|
|
}
|
|
|
|
}
|
2012-05-16 22:28:01 -07:00
|
|
|
|
2013-01-22 11:57:39 -08:00
|
|
|
encode_path(ecx, ebml_w, path, ast_map::path_mod(name));
|
2012-08-17 12:41:34 -07:00
|
|
|
|
2013-06-18 09:39:16 -07:00
|
|
|
// Encode the reexports of this module, if this module is public.
|
|
|
|
if vis == public {
|
|
|
|
debug!("(encoding info for module) encoding reexports for %d", id);
|
|
|
|
encode_reexports(ecx, ebml_w, id, path);
|
2012-08-17 12:41:34 -07:00
|
|
|
}
|
|
|
|
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-12-16 14:41:12 +01:00
|
|
|
}
|
|
|
|
|
2013-05-04 14:25:41 -07:00
|
|
|
fn encode_struct_field_family(ebml_w: &mut writer::Encoder,
|
2013-02-27 13:45:37 -08:00
|
|
|
visibility: visibility) {
|
2012-08-06 12:34:08 -07:00
|
|
|
encode_family(ebml_w, match visibility {
|
2012-08-03 19:59:04 -07:00
|
|
|
public => 'g',
|
|
|
|
private => 'j',
|
|
|
|
inherited => 'N'
|
2012-05-08 16:06:24 +02:00
|
|
|
});
|
2012-03-26 09:59:59 -07:00
|
|
|
}
|
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
fn encode_visibility(ebml_w: &mut writer::Encoder, visibility: visibility) {
|
2013-02-27 13:45:37 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item_visibility);
|
|
|
|
let ch = match visibility {
|
|
|
|
public => 'y',
|
|
|
|
private => 'n',
|
|
|
|
inherited => 'i',
|
|
|
|
};
|
|
|
|
ebml_w.wr_str(str::from_char(ch));
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
2013-04-30 08:49:48 -07:00
|
|
|
fn encode_explicit_self(ebml_w: &mut writer::Encoder, explicit_self: ast::explicit_self_) {
|
|
|
|
ebml_w.start_tag(tag_item_trait_method_explicit_self);
|
2012-07-31 16:32:37 -07:00
|
|
|
|
|
|
|
// Encode the base self type.
|
2013-04-30 08:49:48 -07:00
|
|
|
match explicit_self {
|
2013-03-09 19:43:53 -05:00
|
|
|
sty_static => {
|
|
|
|
ebml_w.writer.write(&[ 's' as u8 ]);
|
|
|
|
}
|
|
|
|
sty_value => {
|
|
|
|
ebml_w.writer.write(&[ 'v' as u8 ]);
|
|
|
|
}
|
|
|
|
sty_region(_, m) => {
|
|
|
|
// FIXME(#4846) encode custom lifetime
|
|
|
|
ebml_w.writer.write(&[ '&' as u8 ]);
|
|
|
|
encode_mutability(ebml_w, m);
|
2012-07-31 16:32:37 -07:00
|
|
|
}
|
2013-03-09 19:43:53 -05:00
|
|
|
sty_box(m) => {
|
|
|
|
ebml_w.writer.write(&[ '@' as u8 ]);
|
|
|
|
encode_mutability(ebml_w, m);
|
2012-07-31 16:32:37 -07:00
|
|
|
}
|
2013-06-23 21:12:17 -07:00
|
|
|
sty_uniq => {
|
2013-03-09 19:43:53 -05:00
|
|
|
ebml_w.writer.write(&[ '~' as u8 ]);
|
2012-07-31 16:32:37 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ebml_w.end_tag();
|
2013-03-09 19:43:53 -05:00
|
|
|
|
2013-04-17 12:15:37 -04:00
|
|
|
fn encode_mutability(ebml_w: &writer::Encoder,
|
2013-03-09 19:43:53 -05:00
|
|
|
m: ast::mutability) {
|
|
|
|
match m {
|
|
|
|
m_imm => {
|
|
|
|
ebml_w.writer.write(&[ 'i' as u8 ]);
|
|
|
|
}
|
|
|
|
m_mutbl => {
|
|
|
|
ebml_w.writer.write(&[ 'm' as u8 ]);
|
|
|
|
}
|
|
|
|
m_const => {
|
|
|
|
ebml_w.writer.write(&[ 'c' as u8 ]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-07-31 16:32:37 -07:00
|
|
|
}
|
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
fn encode_method_sort(ebml_w: &mut writer::Encoder, sort: char) {
|
2012-10-08 12:39:30 -07:00
|
|
|
ebml_w.start_tag(tag_item_trait_method_sort);
|
|
|
|
ebml_w.writer.write(&[ sort as u8 ]);
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
2013-07-11 17:07:57 -07:00
|
|
|
fn encode_provided_source(ebml_w: &mut writer::Encoder,
|
|
|
|
source_opt: Option<def_id>) {
|
|
|
|
for source_opt.iter().advance |source| {
|
|
|
|
ebml_w.start_tag(tag_item_method_provided_source);
|
|
|
|
let s = def_to_str(*source);
|
|
|
|
ebml_w.writer.write(s.as_bytes());
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-19 10:19:00 -07:00
|
|
|
/* Returns an index of items in this class */
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_info_for_struct(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
path: &[ast_map::path_elt],
|
|
|
|
fields: &[@struct_field],
|
|
|
|
global_index: @mut ~[entry<int>])
|
|
|
|
-> ~[entry<int>] {
|
2012-06-25 16:49:14 -07:00
|
|
|
/* Each class has its own index, since different classes
|
|
|
|
may have fields with the same name */
|
2013-07-02 12:47:32 -07:00
|
|
|
let mut index = ~[];
|
2012-05-13 17:01:52 -07:00
|
|
|
let tcx = ecx.tcx;
|
2012-03-19 10:19:00 -07:00
|
|
|
/* We encode both private and public fields -- need to include
|
|
|
|
private fields to get the offsets right */
|
2013-06-21 08:29:53 -04:00
|
|
|
for fields.iter().advance |field| {
|
2013-05-03 18:51:58 -07:00
|
|
|
let (nm, vis) = match field.node.kind {
|
|
|
|
named_field(nm, vis) => (nm, vis),
|
|
|
|
unnamed_field => (special_idents::unnamed_field, inherited)
|
2013-02-11 16:28:39 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
let id = field.node.id;
|
2013-02-19 02:40:42 -05:00
|
|
|
index.push(entry {val: id, pos: ebml_w.writer.tell()});
|
|
|
|
global_index.push(entry {val: id, pos: ebml_w.writer.tell()});
|
2013-02-11 16:28:39 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
|
|
|
debug!("encode_info_for_struct: doing %s %d",
|
2013-06-13 03:02:55 +10:00
|
|
|
tcx.sess.str_of(nm), id);
|
2013-02-27 13:45:37 -08:00
|
|
|
encode_struct_field_family(ebml_w, vis);
|
2013-02-11 16:28:39 -08:00
|
|
|
encode_name(ecx, ebml_w, nm);
|
|
|
|
encode_path(ecx, ebml_w, path, ast_map::path_name(nm));
|
|
|
|
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
|
|
|
|
encode_def_id(ebml_w, local_def(id));
|
|
|
|
ebml_w.end_tag();
|
2012-08-15 15:53:58 -07:00
|
|
|
}
|
2013-07-02 12:47:32 -07:00
|
|
|
index
|
2012-03-06 08:02:13 -08:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_info_for_struct_ctor(ecx: &EncodeContext,
|
2013-05-04 14:25:41 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2013-02-11 16:28:39 -08:00
|
|
|
path: &[ast_map::path_elt],
|
|
|
|
name: ast::ident,
|
|
|
|
ctor_id: node_id,
|
|
|
|
index: @mut ~[entry<int>]) {
|
2013-02-19 02:40:42 -05:00
|
|
|
index.push(entry { val: ctor_id, pos: ebml_w.writer.tell() });
|
2013-02-11 16:28:39 -08:00
|
|
|
|
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
|
|
|
encode_def_id(ebml_w, local_def(ctor_id));
|
|
|
|
encode_family(ebml_w, 'f');
|
|
|
|
encode_name(ecx, ebml_w, name);
|
|
|
|
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
|
|
|
|
encode_path(ecx, ebml_w, path, ast_map::path_name(name));
|
|
|
|
|
|
|
|
if ecx.item_symbols.contains_key(&ctor_id) {
|
|
|
|
encode_symbol(ecx, ebml_w, ctor_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_method_ty_fields(ecx: &EncodeContext,
|
2013-05-04 14:25:41 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2013-05-02 08:11:15 -07:00
|
|
|
method_ty: &ty::Method) {
|
2013-03-28 14:27:54 -04:00
|
|
|
encode_def_id(ebml_w, method_ty.def_id);
|
|
|
|
encode_name(ecx, ebml_w, method_ty.ident);
|
Cleanup substitutions and treatment of generics around traits in a number of ways.
- In a TraitRef, use the self type consistently to refer to the Self type:
- trait ref in `impl Trait<A,B,C> for S` has a self type of `S`.
- trait ref in `A:Trait` has the self type `A`
- trait ref associated with a trait decl has self type `Self`
- trait ref associated with a supertype has self type `Self`
- trait ref in an object type `@Trait` has no self type
- Rewrite `each_bound_traits_and_supertraits` to perform
substitutions as it goes, and thus yield a series of trait refs
that are always in the same 'namespace' as the type parameter
bound given as input. Before, we left this to the caller, but
this doesn't work because the caller lacks adequare information
to perform the type substitutions correctly.
- For provided methods, substitute the generics involved in the provided
method correctly.
- Introduce TypeParameterDef, which tracks the bounds declared on a type
parameter and brings them together with the def_id and (in the future)
other information (maybe even the parameter's name!).
- Introduce Subst trait, which helps to cleanup a lot of the
repetitive code involved with doing type substitution.
- Introduce Repr trait, which makes debug printouts far more convenient.
Fixes #4183. Needed for #5656.
2013-04-08 22:54:49 -07:00
|
|
|
encode_ty_type_param_defs(ebml_w, ecx,
|
|
|
|
method_ty.generics.type_param_defs,
|
|
|
|
tag_item_method_tps);
|
2013-03-29 16:02:55 -04:00
|
|
|
encode_transformed_self_ty(ecx, ebml_w, method_ty.transformed_self_ty);
|
2013-03-28 14:27:54 -04:00
|
|
|
encode_method_fty(ecx, ebml_w, &method_ty.fty);
|
|
|
|
encode_visibility(ebml_w, method_ty.vis);
|
2013-04-30 08:49:48 -07:00
|
|
|
encode_explicit_self(ebml_w, method_ty.explicit_self);
|
2013-07-16 16:28:33 -07:00
|
|
|
let purity = method_ty.fty.purity;
|
|
|
|
match method_ty.explicit_self {
|
|
|
|
ast::sty_static => {
|
|
|
|
encode_family(ebml_w, purity_static_method_family(purity));
|
|
|
|
}
|
|
|
|
_ => encode_family(ebml_w, purity_fn_family(purity))
|
|
|
|
}
|
2013-07-11 17:07:57 -07:00
|
|
|
encode_provided_source(ebml_w, method_ty.provided_source);
|
2013-03-28 14:27:54 -04:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_info_for_method(ecx: &EncodeContext,
|
2013-05-04 14:25:41 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2013-07-16 16:28:33 -07:00
|
|
|
m: &ty::Method,
|
2013-01-22 11:57:39 -08:00
|
|
|
impl_path: &[ast_map::path_elt],
|
2013-07-16 16:28:33 -07:00
|
|
|
is_default_impl: bool,
|
2012-03-19 10:19:00 -07:00
|
|
|
parent_id: node_id,
|
2013-07-16 16:28:33 -07:00
|
|
|
ast_method_opt: Option<@method>) {
|
|
|
|
|
|
|
|
debug!("encode_info_for_method: %? %s", m.def_id,
|
|
|
|
ecx.tcx.sess.str_of(m.ident));
|
2012-03-19 10:19:00 -07:00
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2013-03-28 14:27:54 -04:00
|
|
|
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_method_ty_fields(ecx, ebml_w, m);
|
2013-07-15 17:26:56 -07:00
|
|
|
encode_parent_item(ebml_w, local_def(parent_id));
|
2013-02-27 13:45:37 -08:00
|
|
|
|
2013-07-16 16:28:33 -07:00
|
|
|
// The type for methods gets encoded twice, which is unfortunate.
|
|
|
|
let tpt = lookup_item_type(ecx.tcx, m.def_id);
|
|
|
|
encode_bounds_and_type(ebml_w, ecx, &tpt);
|
2013-02-14 21:50:03 -08:00
|
|
|
|
2013-01-22 11:57:39 -08:00
|
|
|
encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
|
2013-02-27 13:45:37 -08:00
|
|
|
|
2013-07-16 16:28:33 -07:00
|
|
|
for ast_method_opt.iter().advance |ast_method| {
|
|
|
|
let num_params = tpt.generics.type_param_defs.len();
|
|
|
|
if num_params > 0u || is_default_impl
|
|
|
|
|| should_inline(ast_method.attrs) {
|
|
|
|
(ecx.encode_inlined_item)(
|
|
|
|
ecx, ebml_w, impl_path,
|
|
|
|
ii_method(local_def(parent_id), false, *ast_method));
|
|
|
|
} else {
|
|
|
|
encode_symbol(ecx, ebml_w, m.def_id.node);
|
|
|
|
}
|
2012-03-19 10:19:00 -07:00
|
|
|
}
|
2013-03-28 14:27:54 -04:00
|
|
|
|
2012-03-19 10:19:00 -07:00
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
2012-02-13 18:56:09 +01:00
|
|
|
fn purity_fn_family(p: purity) -> char {
|
2012-08-06 12:34:08 -07:00
|
|
|
match p {
|
2012-08-03 19:59:04 -07:00
|
|
|
unsafe_fn => 'u',
|
|
|
|
impure_fn => 'f',
|
2012-08-02 16:01:38 -07:00
|
|
|
extern_fn => 'e'
|
|
|
|
}
|
|
|
|
}
|
2013-02-27 13:45:37 -08:00
|
|
|
|
2012-08-02 16:01:38 -07:00
|
|
|
fn purity_static_method_family(p: purity) -> char {
|
|
|
|
match p {
|
|
|
|
unsafe_fn => 'U',
|
|
|
|
impure_fn => 'F',
|
2013-05-06 00:18:51 +02:00
|
|
|
_ => fail!("extern fn can't be static")
|
2012-02-10 13:39:15 -08:00
|
|
|
}
|
2012-02-13 18:56:09 +01:00
|
|
|
}
|
|
|
|
|
2012-03-02 13:14:10 -08:00
|
|
|
|
2013-01-22 11:57:39 -08:00
|
|
|
fn should_inline(attrs: &[attribute]) -> bool {
|
2012-08-06 12:34:08 -07:00
|
|
|
match attr::find_inline_attr(attrs) {
|
2012-08-03 19:59:04 -07:00
|
|
|
attr::ia_none | attr::ia_never => false,
|
|
|
|
attr::ia_hint | attr::ia_always => true
|
2012-03-02 13:14:10 -08:00
|
|
|
}
|
2012-03-19 10:19:00 -07:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_info_for_item(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
item: @item,
|
|
|
|
index: @mut ~[entry<int>],
|
2013-01-22 11:57:39 -08:00
|
|
|
path: &[ast_map::path_elt]) {
|
2012-05-13 17:01:52 -07:00
|
|
|
let tcx = ecx.tcx;
|
2012-03-22 18:03:12 -07:00
|
|
|
|
2013-04-17 12:15:37 -04:00
|
|
|
fn add_to_index_(item: @item, ebml_w: &writer::Encoder,
|
2012-06-29 16:26:56 -07:00
|
|
|
index: @mut ~[entry<int>]) {
|
2013-02-19 02:40:42 -05:00
|
|
|
index.push(entry { val: item.id, pos: ebml_w.writer.tell() });
|
2012-03-22 18:03:12 -07:00
|
|
|
}
|
2013-01-15 16:33:20 -08:00
|
|
|
let add_to_index: &fn() = || add_to_index_(item, ebml_w, index);
|
2012-03-06 12:52:13 +01:00
|
|
|
|
2012-10-30 11:19:15 -07:00
|
|
|
debug!("encoding info for item at %s",
|
2012-11-12 18:24:56 -08:00
|
|
|
ecx.tcx.sess.codemap.span_to_str(item.span));
|
2012-10-30 11:19:15 -07:00
|
|
|
|
2013-07-16 16:28:33 -07:00
|
|
|
let def_id = local_def(item.id);
|
2013-03-20 01:17:42 -04:00
|
|
|
match item.node {
|
2013-06-21 18:46:34 -07:00
|
|
|
item_static(_, m, _) => {
|
2012-03-22 18:03:12 -07:00
|
|
|
add_to_index();
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_def_id(ebml_w, def_id);
|
2013-06-21 18:46:34 -07:00
|
|
|
if m == ast::m_mutbl {
|
|
|
|
encode_family(ebml_w, 'b');
|
|
|
|
} else {
|
|
|
|
encode_family(ebml_w, 'c');
|
|
|
|
}
|
2012-01-30 17:28:30 +01:00
|
|
|
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
|
2011-07-27 14:19:39 +02:00
|
|
|
encode_symbol(ecx, ebml_w, item.id);
|
2013-06-18 09:39:16 -07:00
|
|
|
encode_name(ecx, ebml_w, item.ident);
|
2013-01-22 11:57:39 -08:00
|
|
|
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
|
2013-03-07 01:30:20 -05:00
|
|
|
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2013-03-13 22:25:28 -04:00
|
|
|
item_fn(_, purity, _, ref generics, _) => {
|
2012-03-22 18:03:12 -07:00
|
|
|
add_to_index();
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_def_id(ebml_w, def_id);
|
2012-08-23 18:17:16 -07:00
|
|
|
encode_family(ebml_w, purity_fn_family(purity));
|
2013-02-14 21:50:03 -08:00
|
|
|
let tps_len = generics.ty_params.len();
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
|
2013-06-18 09:39:16 -07:00
|
|
|
encode_name(ecx, ebml_w, item.ident);
|
2013-01-22 11:57:39 -08:00
|
|
|
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
|
|
|
|
encode_attributes(ebml_w, item.attrs);
|
2013-01-07 14:16:52 -08:00
|
|
|
if tps_len > 0u || should_inline(item.attrs) {
|
2012-11-29 17:51:16 -08:00
|
|
|
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
|
2012-03-08 13:30:22 +01:00
|
|
|
} else {
|
|
|
|
encode_symbol(ecx, ebml_w, item.id);
|
2012-02-14 15:21:53 -08:00
|
|
|
}
|
|
|
|
ebml_w.end_tag();
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2013-02-17 22:20:36 -08:00
|
|
|
item_mod(ref m) => {
|
2012-03-22 18:03:12 -07:00
|
|
|
add_to_index();
|
2013-06-18 09:39:16 -07:00
|
|
|
encode_info_for_mod(ecx,
|
|
|
|
ebml_w,
|
|
|
|
m,
|
|
|
|
item.id,
|
|
|
|
path,
|
|
|
|
item.ident,
|
|
|
|
item.vis);
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2013-06-18 09:39:16 -07:00
|
|
|
item_foreign_mod(ref fm) => {
|
2012-03-22 18:03:12 -07:00
|
|
|
add_to_index();
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_def_id(ebml_w, def_id);
|
2012-02-13 20:55:23 +01:00
|
|
|
encode_family(ebml_w, 'n');
|
2012-07-18 16:18:02 -07:00
|
|
|
encode_name(ecx, ebml_w, item.ident);
|
2013-01-22 11:57:39 -08:00
|
|
|
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
|
2013-06-18 09:39:16 -07:00
|
|
|
|
|
|
|
// Encode all the items in this module.
|
2013-06-25 18:25:27 -07:00
|
|
|
for fm.items.iter().advance |foreign_item| {
|
2013-06-18 09:39:16 -07:00
|
|
|
ebml_w.start_tag(tag_mod_child);
|
|
|
|
ebml_w.wr_str(def_to_str(local_def(foreign_item.id)));
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2013-07-16 16:28:33 -07:00
|
|
|
item_ty(*) => {
|
2012-03-22 18:03:12 -07:00
|
|
|
add_to_index();
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_def_id(ebml_w, def_id);
|
2012-02-13 20:55:23 +01:00
|
|
|
encode_family(ebml_w, 'y');
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
|
2012-07-18 16:18:02 -07:00
|
|
|
encode_name(ecx, ebml_w, item.ident);
|
2013-01-22 11:57:39 -08:00
|
|
|
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
|
2012-07-11 10:28:30 -07:00
|
|
|
encode_region_param(ecx, ebml_w, item);
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2013-02-14 21:50:03 -08:00
|
|
|
item_enum(ref enum_definition, ref generics) => {
|
2012-03-22 18:03:12 -07:00
|
|
|
add_to_index();
|
2013-05-01 17:54:54 -07:00
|
|
|
|
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_def_id(ebml_w, def_id);
|
2013-05-01 17:54:54 -07:00
|
|
|
encode_family(ebml_w, 't');
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
|
2013-05-01 17:54:54 -07:00
|
|
|
encode_name(ecx, ebml_w, item.ident);
|
2013-06-21 08:29:53 -04:00
|
|
|
for (*enum_definition).variants.iter().advance |v| {
|
2013-05-01 17:54:54 -07:00
|
|
|
encode_variant_id(ebml_w, local_def(v.node.id));
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
2013-05-01 17:54:54 -07:00
|
|
|
(ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
|
|
|
|
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
|
|
|
|
encode_region_param(ecx, ebml_w, item);
|
|
|
|
ebml_w.end_tag();
|
|
|
|
|
2012-12-04 21:13:02 -08:00
|
|
|
encode_enum_variant_info(ecx,
|
|
|
|
ebml_w,
|
|
|
|
item.id,
|
2013-01-22 11:57:39 -08:00
|
|
|
(*enum_definition).variants,
|
2012-12-04 21:13:02 -08:00
|
|
|
path,
|
|
|
|
index,
|
2013-02-14 21:50:03 -08:00
|
|
|
generics);
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2013-07-16 16:28:33 -07:00
|
|
|
item_struct(struct_def, _) => {
|
2012-12-10 13:47:54 -08:00
|
|
|
/* First, encode the fields
|
2012-03-22 18:03:12 -07:00
|
|
|
These come first because we need to write them to make
|
|
|
|
the index, and the index needs to be in the item for the
|
|
|
|
class itself */
|
2013-01-22 11:57:39 -08:00
|
|
|
let idx = encode_info_for_struct(ecx, ebml_w, path,
|
|
|
|
struct_def.fields, index);
|
2012-06-12 16:25:09 -07:00
|
|
|
|
2012-03-22 18:03:12 -07:00
|
|
|
/* Index the class*/
|
|
|
|
add_to_index();
|
2013-02-14 21:50:03 -08:00
|
|
|
|
2012-03-22 18:03:12 -07:00
|
|
|
/* Now, make an item for the class itself */
|
2012-03-16 19:19:37 -07:00
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_def_id(ebml_w, def_id);
|
2012-10-08 11:49:01 -07:00
|
|
|
encode_family(ebml_w, 'S');
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
|
2013-02-11 16:28:39 -08:00
|
|
|
|
2012-07-18 16:18:02 -07:00
|
|
|
encode_name(ecx, ebml_w, item.ident);
|
2013-05-06 23:35:27 +09:00
|
|
|
encode_attributes(ebml_w, item.attrs);
|
2013-01-22 11:57:39 -08:00
|
|
|
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
|
2012-07-11 10:28:30 -07:00
|
|
|
encode_region_param(ecx, ebml_w, item);
|
2012-06-12 16:25:09 -07:00
|
|
|
|
2012-03-22 18:03:12 -07:00
|
|
|
/* Encode def_ids for each field and method
|
2012-07-03 16:30:42 -07:00
|
|
|
for methods, write all the stuff get_trait_method
|
2012-03-22 18:03:12 -07:00
|
|
|
needs to know*/
|
2013-06-21 08:29:53 -04:00
|
|
|
for struct_def.fields.iter().advance |f| {
|
2012-08-15 15:53:58 -07:00
|
|
|
match f.node.kind {
|
2013-05-03 18:51:58 -07:00
|
|
|
named_field(ident, vis) => {
|
2012-08-15 15:53:58 -07:00
|
|
|
ebml_w.start_tag(tag_item_field);
|
2013-02-27 13:45:37 -08:00
|
|
|
encode_struct_field_family(ebml_w, vis);
|
2012-07-18 16:18:02 -07:00
|
|
|
encode_name(ecx, ebml_w, ident);
|
2012-08-15 15:53:58 -07:00
|
|
|
encode_def_id(ebml_w, local_def(f.node.id));
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
2013-02-11 16:28:39 -08:00
|
|
|
unnamed_field => {
|
|
|
|
ebml_w.start_tag(tag_item_unnamed_field);
|
|
|
|
encode_def_id(ebml_w, local_def(f.node.id));
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
2012-08-15 15:53:58 -07:00
|
|
|
}
|
2012-03-22 18:03:12 -07:00
|
|
|
}
|
2012-08-15 15:53:58 -07:00
|
|
|
|
2012-03-22 18:03:12 -07:00
|
|
|
/* Each class has its own index -- encode it */
|
2012-09-19 13:13:24 -07:00
|
|
|
let bkts = create_index(idx);
|
2012-03-19 10:19:00 -07:00
|
|
|
encode_index(ebml_w, bkts, write_int);
|
2012-03-16 19:19:37 -07:00
|
|
|
ebml_w.end_tag();
|
2013-06-14 18:21:47 -07:00
|
|
|
|
|
|
|
// If this is a tuple- or enum-like struct, encode the type of the
|
|
|
|
// constructor.
|
|
|
|
if struct_def.fields.len() > 0 &&
|
|
|
|
struct_def.fields[0].node.kind == ast::unnamed_field {
|
|
|
|
let ctor_id = match struct_def.ctor_id {
|
|
|
|
Some(ctor_id) => ctor_id,
|
|
|
|
None => ecx.tcx.sess.bug("struct def didn't have ctor id"),
|
|
|
|
};
|
|
|
|
|
|
|
|
encode_info_for_struct_ctor(ecx,
|
|
|
|
ebml_w,
|
|
|
|
path,
|
|
|
|
item.ident,
|
|
|
|
ctor_id,
|
|
|
|
index);
|
|
|
|
}
|
2012-01-31 19:30:40 -08:00
|
|
|
}
|
2013-07-16 16:28:33 -07:00
|
|
|
item_impl(_, ref opt_trait, ref ty, ref ast_methods) => {
|
|
|
|
// We need to encode information about the default methods we
|
|
|
|
// have inherited, so we drive this based on the impl structure.
|
|
|
|
let imp = tcx.impls.get(&def_id);
|
|
|
|
|
2012-03-22 18:03:12 -07:00
|
|
|
add_to_index();
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_def_id(ebml_w, def_id);
|
2012-02-13 20:55:23 +01:00
|
|
|
encode_family(ebml_w, 'i');
|
2012-07-11 10:28:30 -07:00
|
|
|
encode_region_param(ecx, ebml_w, item);
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
|
2012-07-18 16:18:02 -07:00
|
|
|
encode_name(ecx, ebml_w, item.ident);
|
2013-01-22 11:57:39 -08:00
|
|
|
encode_attributes(ebml_w, item.attrs);
|
2012-10-18 13:29:34 -07:00
|
|
|
match ty.node {
|
2013-07-06 13:38:56 +12:00
|
|
|
ast::ty_path(ref path, ref bounds, _) if path.idents.len() == 1 => {
|
2013-06-20 18:23:25 -04:00
|
|
|
assert!(bounds.is_none());
|
2012-10-18 13:29:34 -07:00
|
|
|
encode_impl_type_basename(ecx, ebml_w,
|
|
|
|
ast_util::path_to_ident(path));
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2013-07-16 16:28:33 -07:00
|
|
|
for imp.methods.iter().advance |method| {
|
2012-11-13 19:08:01 -08:00
|
|
|
ebml_w.start_tag(tag_item_impl_method);
|
2013-07-16 16:28:33 -07:00
|
|
|
let s = def_to_str(method.def_id);
|
2013-06-11 13:10:37 +10:00
|
|
|
ebml_w.writer.write(s.as_bytes());
|
2012-11-13 19:08:01 -08:00
|
|
|
ebml_w.end_tag();
|
2011-12-16 14:17:52 +01:00
|
|
|
}
|
2013-06-10 17:50:12 -04:00
|
|
|
for opt_trait.iter().advance |ast_trait_ref| {
|
2013-07-16 16:28:33 -07:00
|
|
|
let trait_ref = ty::node_id_to_trait_ref(
|
|
|
|
tcx, ast_trait_ref.ref_id);
|
2013-03-27 06:16:28 -04:00
|
|
|
encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_trait_ref);
|
2012-07-18 09:31:53 -07:00
|
|
|
}
|
2013-01-22 11:57:39 -08:00
|
|
|
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-12-16 14:17:52 +01:00
|
|
|
|
2013-01-22 11:57:39 -08:00
|
|
|
// >:-<
|
|
|
|
let mut impl_path = vec::append(~[], path);
|
2013-06-11 19:13:42 -07:00
|
|
|
impl_path.push(ast_map::path_name(item.ident));
|
2013-01-22 11:57:39 -08:00
|
|
|
|
2013-07-11 17:07:57 -07:00
|
|
|
// Iterate down the methods, emitting them. We rely on the
|
|
|
|
// assumption that all of the actually implemented methods
|
|
|
|
// appear first in the impl structure, in the same order they do
|
|
|
|
// in the ast. This is a little sketchy.
|
|
|
|
let num_implemented_methods = ast_methods.len();
|
|
|
|
for imp.methods.iter().enumerate().advance |(i, m)| {
|
|
|
|
let ast_method = if i < num_implemented_methods {
|
|
|
|
Some(ast_methods[i])
|
|
|
|
} else { None };
|
|
|
|
|
2013-07-16 16:28:33 -07:00
|
|
|
index.push(entry {val: m.def_id.node, pos: ebml_w.writer.tell()});
|
2013-02-27 13:45:37 -08:00
|
|
|
encode_info_for_method(ecx,
|
|
|
|
ebml_w,
|
2013-07-11 17:07:57 -07:00
|
|
|
*m,
|
2013-02-27 13:45:37 -08:00
|
|
|
impl_path,
|
2013-07-16 16:28:33 -07:00
|
|
|
false,
|
2013-02-27 13:45:37 -08:00
|
|
|
item.id,
|
2013-07-11 17:07:57 -07:00
|
|
|
ast_method)
|
2011-12-16 14:17:52 +01:00
|
|
|
}
|
|
|
|
}
|
2013-07-16 16:28:33 -07:00
|
|
|
item_trait(_, ref super_traits, ref ms) => {
|
2012-03-22 18:03:12 -07:00
|
|
|
add_to_index();
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_def_id(ebml_w, def_id);
|
2012-02-13 20:55:23 +01:00
|
|
|
encode_family(ebml_w, 'I');
|
2012-07-11 10:28:30 -07:00
|
|
|
encode_region_param(ecx, ebml_w, item);
|
2013-07-16 16:28:33 -07:00
|
|
|
let trait_def = ty::lookup_trait_def(tcx, def_id);
|
|
|
|
encode_ty_type_param_defs(ebml_w, ecx,
|
|
|
|
trait_def.generics.type_param_defs,
|
|
|
|
tag_items_data_item_ty_param_bounds);
|
2013-03-27 06:16:28 -04:00
|
|
|
encode_trait_ref(ebml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
|
2012-07-18 16:18:02 -07:00
|
|
|
encode_name(ecx, ebml_w, item.ident);
|
2013-01-22 11:57:39 -08:00
|
|
|
encode_attributes(ebml_w, item.attrs);
|
2013-07-16 16:28:33 -07:00
|
|
|
for ty::trait_method_def_ids(tcx, def_id).iter().advance |&method_def_id| {
|
2013-03-27 10:26:57 -04:00
|
|
|
ebml_w.start_tag(tag_item_trait_method);
|
|
|
|
encode_def_id(ebml_w, method_def_id);
|
|
|
|
ebml_w.end_tag();
|
2013-06-18 09:39:16 -07:00
|
|
|
|
|
|
|
ebml_w.start_tag(tag_mod_child);
|
|
|
|
ebml_w.wr_str(def_to_str(method_def_id));
|
|
|
|
ebml_w.end_tag();
|
2012-01-05 13:57:27 +01:00
|
|
|
}
|
2013-01-22 11:57:39 -08:00
|
|
|
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
|
2013-06-21 08:29:53 -04:00
|
|
|
for super_traits.iter().advance |ast_trait_ref| {
|
2013-03-27 06:16:28 -04:00
|
|
|
let trait_ref = ty::node_id_to_trait_ref(ecx.tcx, ast_trait_ref.ref_id);
|
|
|
|
encode_trait_ref(ebml_w, ecx, trait_ref, tag_item_super_trait_ref);
|
2012-08-03 15:02:01 -07:00
|
|
|
}
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2012-08-02 16:01:38 -07:00
|
|
|
|
2013-03-27 10:26:57 -04:00
|
|
|
// Now output the method info for each method.
|
2013-07-16 16:28:33 -07:00
|
|
|
let r = ty::trait_method_def_ids(tcx, def_id);
|
2013-06-17 19:43:22 -04:00
|
|
|
for r.iter().enumerate().advance |(i, &method_def_id)| {
|
2013-05-18 22:02:45 -04:00
|
|
|
assert_eq!(method_def_id.crate, ast::local_crate);
|
2012-08-02 16:01:38 -07:00
|
|
|
|
2013-05-02 08:11:15 -07:00
|
|
|
let method_ty = ty::method(tcx, method_def_id);
|
2013-03-27 10:26:57 -04:00
|
|
|
|
|
|
|
index.push(entry {val: method_def_id.node, pos: ebml_w.writer.tell()});
|
2012-08-02 16:01:38 -07:00
|
|
|
|
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2013-03-27 10:26:57 -04:00
|
|
|
|
2013-03-28 14:27:54 -04:00
|
|
|
encode_method_ty_fields(ecx, ebml_w, method_ty);
|
|
|
|
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_parent_item(ebml_w, def_id);
|
2013-03-28 14:27:54 -04:00
|
|
|
|
|
|
|
let mut trait_path = vec::append(~[], path);
|
|
|
|
trait_path.push(ast_map::path_name(item.ident));
|
|
|
|
encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
|
2013-03-27 10:26:57 -04:00
|
|
|
|
2013-04-30 08:49:48 -07:00
|
|
|
match method_ty.explicit_self {
|
2013-03-27 10:26:57 -04:00
|
|
|
sty_static => {
|
|
|
|
encode_family(ebml_w,
|
|
|
|
purity_static_method_family(
|
|
|
|
method_ty.fty.purity));
|
|
|
|
|
|
|
|
let tpt = ty::lookup_item_type(tcx, method_def_id);
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_bounds_and_type(ebml_w, ecx, &tpt);
|
2013-03-27 10:26:57 -04:00
|
|
|
}
|
2013-03-18 17:20:45 -07:00
|
|
|
|
2013-03-27 10:26:57 -04:00
|
|
|
_ => {
|
|
|
|
encode_family(ebml_w,
|
|
|
|
purity_fn_family(
|
|
|
|
method_ty.fty.purity));
|
|
|
|
}
|
|
|
|
}
|
2012-08-02 16:01:38 -07:00
|
|
|
|
2013-03-27 10:26:57 -04:00
|
|
|
match ms[i] {
|
|
|
|
required(_) => {
|
|
|
|
encode_method_sort(ebml_w, 'r');
|
|
|
|
}
|
2013-02-14 21:50:03 -08:00
|
|
|
|
2013-03-27 10:26:57 -04:00
|
|
|
provided(m) => {
|
2013-07-11 15:08:43 -07:00
|
|
|
// If this is a static method, we've already encoded
|
|
|
|
// this.
|
|
|
|
if method_ty.explicit_self != sty_static {
|
2013-07-16 16:28:33 -07:00
|
|
|
// XXX: I feel like there is something funny going on.
|
|
|
|
let tpt = ty::lookup_item_type(tcx, method_def_id);
|
|
|
|
encode_bounds_and_type(ebml_w, ecx, &tpt);
|
2013-03-27 10:26:57 -04:00
|
|
|
}
|
|
|
|
encode_method_sort(ebml_w, 'p');
|
|
|
|
(ecx.encode_inlined_item)(
|
|
|
|
ecx, ebml_w, path,
|
2013-07-16 16:28:33 -07:00
|
|
|
ii_method(def_id, true, m));
|
2013-03-27 10:26:57 -04:00
|
|
|
}
|
|
|
|
}
|
2013-02-14 21:50:03 -08:00
|
|
|
|
2013-03-27 10:26:57 -04:00
|
|
|
ebml_w.end_tag();
|
2012-10-08 12:39:30 -07:00
|
|
|
}
|
2012-01-05 13:57:27 +01:00
|
|
|
}
|
2013-05-06 00:18:51 +02:00
|
|
|
item_mac(*) => fail!("item macros unimplemented")
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_info_for_foreign_item(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2012-06-26 16:18:37 -07:00
|
|
|
nitem: @foreign_item,
|
2012-06-29 16:26:56 -07:00
|
|
|
index: @mut ~[entry<int>],
|
2013-07-02 12:47:32 -07:00
|
|
|
path: &ast_map::path,
|
2013-03-13 22:25:28 -04:00
|
|
|
abi: AbiSet) {
|
2013-02-19 02:40:42 -05:00
|
|
|
index.push(entry { val: nitem.id, pos: ebml_w.writer.tell() });
|
2012-03-08 23:37:45 +01:00
|
|
|
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data_item);
|
2013-02-14 21:50:03 -08:00
|
|
|
match nitem.node {
|
2013-07-16 16:28:33 -07:00
|
|
|
foreign_item_fn(_, purity, _) => {
|
2011-07-27 14:19:39 +02:00
|
|
|
encode_def_id(ebml_w, local_def(nitem.id));
|
2012-08-23 18:17:16 -07:00
|
|
|
encode_family(ebml_w, purity_fn_family(purity));
|
2013-07-16 16:28:33 -07:00
|
|
|
encode_bounds_and_type(ebml_w, ecx,
|
|
|
|
&lookup_item_type(ecx.tcx,local_def(nitem.id)));
|
2013-06-18 09:39:16 -07:00
|
|
|
encode_name(ecx, ebml_w, nitem.ident);
|
2013-03-13 22:25:28 -04:00
|
|
|
if abi.is_intrinsic() {
|
2013-07-02 12:47:32 -07:00
|
|
|
(ecx.encode_inlined_item)(ecx, ebml_w, *path, ii_foreign(nitem));
|
2012-03-21 15:42:20 +01:00
|
|
|
} else {
|
|
|
|
encode_symbol(ecx, ebml_w, nitem.id);
|
|
|
|
}
|
2013-07-02 12:47:32 -07:00
|
|
|
encode_path(ecx, ebml_w, *path, ast_map::path_name(nitem.ident));
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2013-06-21 22:46:27 -07:00
|
|
|
foreign_item_static(_, mutbl) => {
|
2012-08-25 15:09:33 -07:00
|
|
|
encode_def_id(ebml_w, local_def(nitem.id));
|
2013-06-21 22:46:27 -07:00
|
|
|
if mutbl {
|
|
|
|
encode_family(ebml_w, 'b');
|
|
|
|
} else {
|
|
|
|
encode_family(ebml_w, 'c');
|
|
|
|
}
|
2012-08-25 15:09:33 -07:00
|
|
|
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, nitem.id));
|
|
|
|
encode_symbol(ecx, ebml_w, nitem.id);
|
2013-06-18 09:39:16 -07:00
|
|
|
encode_name(ecx, ebml_w, nitem.ident);
|
2013-07-02 12:47:32 -07:00
|
|
|
encode_path(ecx, ebml_w, *path, ast_map::path_name(nitem.ident));
|
2012-08-25 15:09:33 -07:00
|
|
|
}
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_info_for_items(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
crate: &crate)
|
|
|
|
-> ~[entry<int>] {
|
2012-06-29 16:26:56 -07:00
|
|
|
let index = @mut ~[];
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items_data);
|
2013-02-19 02:40:42 -05:00
|
|
|
index.push(entry { val: crate_node_id, pos: ebml_w.writer.tell() });
|
2013-06-18 09:39:16 -07:00
|
|
|
encode_info_for_mod(ecx,
|
|
|
|
ebml_w,
|
|
|
|
&crate.node.module,
|
|
|
|
crate_node_id,
|
|
|
|
[],
|
|
|
|
syntax::parse::token::special_idents::invalid,
|
|
|
|
public);
|
2013-06-13 19:19:50 +12:00
|
|
|
let items = ecx.tcx.items;
|
|
|
|
|
|
|
|
// See comment in `encode_side_tables_for_ii` in astencode
|
|
|
|
let ecx_ptr : *() = unsafe { cast::transmute(ecx) };
|
|
|
|
|
2013-06-12 04:55:16 +02:00
|
|
|
visit::visit_crate(crate, ((), visit::mk_vt(@visit::Visitor {
|
|
|
|
visit_expr: |_e, (_cx, _v)| { },
|
2013-01-10 10:59:58 -08:00
|
|
|
visit_item: {
|
2013-07-02 12:47:32 -07:00
|
|
|
let ebml_w = (*ebml_w).clone();
|
2013-06-12 04:55:16 +02:00
|
|
|
|i, (cx, v)| {
|
|
|
|
visit::visit_item(i, (cx, v));
|
2013-06-13 19:19:50 +12:00
|
|
|
match items.get_copy(&i.id) {
|
2013-01-10 10:59:58 -08:00
|
|
|
ast_map::node_item(_, pt) => {
|
2013-07-02 12:47:32 -07:00
|
|
|
let mut ebml_w = ebml_w.clone();
|
2013-06-13 19:19:50 +12:00
|
|
|
// See above
|
|
|
|
let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
|
2013-05-01 17:54:54 -07:00
|
|
|
encode_info_for_item(ecx, &mut ebml_w, i, index, *pt);
|
2013-01-10 10:59:58 -08:00
|
|
|
}
|
2013-05-06 00:18:51 +02:00
|
|
|
_ => fail!("bad item")
|
2013-01-10 10:59:58 -08:00
|
|
|
}
|
2012-03-06 08:02:13 -08:00
|
|
|
}
|
2012-03-08 23:37:45 +01:00
|
|
|
},
|
2013-01-10 10:59:58 -08:00
|
|
|
visit_foreign_item: {
|
2013-07-02 12:47:32 -07:00
|
|
|
let ebml_w = (*ebml_w).clone();
|
2013-06-12 04:55:16 +02:00
|
|
|
|ni, (cx, v)| {
|
|
|
|
visit::visit_foreign_item(ni, (cx, v));
|
2013-06-13 19:19:50 +12:00
|
|
|
match items.get_copy(&ni.id) {
|
2013-03-18 17:20:45 -07:00
|
|
|
ast_map::node_foreign_item(_, abi, _, pt) => {
|
2013-06-14 18:21:47 -07:00
|
|
|
debug!("writing foreign item %s::%s",
|
|
|
|
ast_map::path_to_str(
|
|
|
|
*pt,
|
|
|
|
token::get_ident_interner()),
|
2013-06-14 19:40:11 -07:00
|
|
|
token::ident_to_str(&ni.ident));
|
2013-06-14 18:21:47 -07:00
|
|
|
|
2013-07-02 12:47:32 -07:00
|
|
|
let mut ebml_w = ebml_w.clone();
|
2013-06-13 19:19:50 +12:00
|
|
|
// See above
|
|
|
|
let ecx : &EncodeContext = unsafe { cast::transmute(ecx_ptr) };
|
2013-05-01 17:54:54 -07:00
|
|
|
encode_info_for_foreign_item(ecx,
|
|
|
|
&mut ebml_w,
|
|
|
|
ni,
|
|
|
|
index,
|
2013-07-02 12:47:32 -07:00
|
|
|
pt,
|
2013-01-10 10:59:58 -08:00
|
|
|
abi);
|
|
|
|
}
|
|
|
|
// case for separate item and foreign-item tables
|
2013-05-06 00:18:51 +02:00
|
|
|
_ => fail!("bad foreign item")
|
2013-01-10 10:59:58 -08:00
|
|
|
}
|
2012-03-09 13:35:20 +01:00
|
|
|
}
|
2013-01-10 10:59:58 -08:00
|
|
|
},
|
|
|
|
..*visit::default_visitor()
|
2013-06-12 04:55:16 +02:00
|
|
|
})));
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2013-07-02 12:47:32 -07:00
|
|
|
return /*bad*/(*index).clone();
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Path and definition ID indexing
|
|
|
|
|
2013-07-18 17:12:46 -07:00
|
|
|
fn create_index<T:Clone + Hash + IterBytes + 'static>(
|
|
|
|
index: ~[entry<T>])
|
|
|
|
-> ~[@~[entry<T>]] {
|
2012-06-29 16:26:56 -07:00
|
|
|
let mut buckets: ~[@mut ~[entry<T>]] = ~[];
|
2012-09-26 17:33:34 -07:00
|
|
|
for uint::range(0u, 256u) |_i| { buckets.push(@mut ~[]); };
|
2013-06-21 08:29:53 -04:00
|
|
|
for index.iter().advance |elt| {
|
2012-09-19 13:13:24 -07:00
|
|
|
let h = elt.val.hash() as uint;
|
2013-07-02 12:47:32 -07:00
|
|
|
buckets[h % 256].push((*elt).clone());
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
2011-07-14 14:25:43 -07:00
|
|
|
|
2012-06-29 16:26:56 -07:00
|
|
|
let mut buckets_frozen = ~[];
|
2013-06-21 08:29:53 -04:00
|
|
|
for buckets.iter().advance |bucket| {
|
2013-07-02 12:47:32 -07:00
|
|
|
buckets_frozen.push(@/*bad*/(**bucket).clone());
|
2011-07-14 14:25:43 -07:00
|
|
|
}
|
2012-08-01 17:30:05 -07:00
|
|
|
return buckets_frozen;
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-07-18 17:12:46 -07:00
|
|
|
fn encode_index<T:'static>(
|
|
|
|
ebml_w: &mut writer::Encoder,
|
|
|
|
buckets: ~[@~[entry<T>]],
|
|
|
|
write_fn: &fn(@io::Writer, &T)) {
|
2012-01-11 12:52:25 -08:00
|
|
|
let writer = ebml_w.writer;
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_index);
|
2012-06-29 16:26:56 -07:00
|
|
|
let mut bucket_locs: ~[uint] = ~[];
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_index_buckets);
|
2013-06-21 08:29:53 -04:00
|
|
|
for buckets.iter().advance |bucket| {
|
2012-09-26 17:33:34 -07:00
|
|
|
bucket_locs.push(ebml_w.writer.tell());
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_index_buckets_bucket);
|
2013-06-21 08:29:53 -04:00
|
|
|
for (**bucket).iter().advance |elt| {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_index_buckets_bucket_elt);
|
2013-03-28 18:39:09 -07:00
|
|
|
assert!(elt.pos < 0xffff_ffff);
|
2012-08-02 17:17:07 -07:00
|
|
|
writer.write_be_u32(elt.pos as u32);
|
2013-04-17 12:15:37 -04:00
|
|
|
write_fn(writer, &elt.val);
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.start_tag(tag_index_table);
|
2013-06-21 08:29:53 -04:00
|
|
|
for bucket_locs.iter().advance |pos| {
|
2013-03-28 18:39:09 -07:00
|
|
|
assert!(*pos < 0xffff_ffff);
|
2012-09-19 16:55:01 -07:00
|
|
|
writer.write_be_u32(*pos as u32);
|
2012-08-02 17:17:07 -07:00
|
|
|
}
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.end_tag();
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
fn write_str(writer: @io::Writer, s: ~str) {
|
|
|
|
writer.write_str(s);
|
|
|
|
}
|
2011-06-27 15:20:17 -07:00
|
|
|
|
2013-04-17 12:15:37 -04:00
|
|
|
fn write_int(writer: @io::Writer, &n: &int) {
|
2013-03-28 18:39:09 -07:00
|
|
|
assert!(n < 0x7fff_ffff);
|
2012-08-02 17:17:07 -07:00
|
|
|
writer.write_be_u32(n as u32);
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
fn encode_meta_item(ebml_w: &mut writer::Encoder, mi: @meta_item) {
|
2012-08-06 12:34:08 -07:00
|
|
|
match mi.node {
|
2013-02-14 07:34:21 -08:00
|
|
|
meta_word(name) => {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_meta_item_word);
|
|
|
|
ebml_w.start_tag(tag_meta_item_name);
|
2013-06-11 13:10:37 +10:00
|
|
|
ebml_w.writer.write(name.as_bytes());
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.end_tag();
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2013-02-14 07:34:21 -08:00
|
|
|
meta_name_value(name, value) => {
|
2012-08-06 12:34:08 -07:00
|
|
|
match value.node {
|
2012-08-03 19:59:04 -07:00
|
|
|
lit_str(value) => {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_meta_item_name_value);
|
|
|
|
ebml_w.start_tag(tag_meta_item_name);
|
2013-06-11 13:10:37 +10:00
|
|
|
ebml_w.writer.write(name.as_bytes());
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.start_tag(tag_meta_item_value);
|
2013-06-11 13:10:37 +10:00
|
|
|
ebml_w.writer.write(value.as_bytes());
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.end_tag();
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2012-08-03 19:59:04 -07:00
|
|
|
_ => {/* FIXME (#623): encode other variants */ }
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
|
|
|
}
|
2013-02-14 07:34:21 -08:00
|
|
|
meta_list(name, ref items) => {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_meta_item_list);
|
|
|
|
ebml_w.start_tag(tag_meta_item_name);
|
2013-06-11 13:10:37 +10:00
|
|
|
ebml_w.writer.write(name.as_bytes());
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2013-06-21 08:29:53 -04:00
|
|
|
for items.iter().advance |inner_item| {
|
2013-02-25 06:19:44 -08:00
|
|
|
encode_meta_item(ebml_w, *inner_item);
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2011-06-27 19:41:48 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
fn encode_attributes(ebml_w: &mut writer::Encoder, attrs: &[attribute]) {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_attributes);
|
2013-06-21 08:29:53 -04:00
|
|
|
for attrs.iter().advance |attr| {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_attribute);
|
2011-06-27 19:41:48 -07:00
|
|
|
encode_meta_item(ebml_w, attr.node.value);
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-06-27 19:41:48 -07:00
|
|
|
}
|
|
|
|
|
2011-06-29 15:11:20 -07:00
|
|
|
// So there's a special crate attribute called 'link' which defines the
|
|
|
|
// metadata that Rust cares about for linking crates. This attribute requires
|
2011-06-30 17:03:08 -07:00
|
|
|
// 'name' and 'vers' items, so if the user didn't provide them we will throw
|
2011-06-29 15:11:20 -07:00
|
|
|
// them in anyway with default values.
|
2013-06-13 19:19:50 +12:00
|
|
|
fn synthesize_crate_attrs(ecx: &EncodeContext,
|
2013-02-19 00:14:56 -08:00
|
|
|
crate: &crate) -> ~[attribute] {
|
2011-06-29 14:17:23 -07:00
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn synthesize_link_attr(ecx: &EncodeContext, items: ~[@meta_item]) ->
|
2011-07-27 14:19:39 +02:00
|
|
|
attribute {
|
2011-06-29 14:17:23 -07:00
|
|
|
|
2013-03-28 18:39:09 -07:00
|
|
|
assert!(!ecx.link_meta.name.is_empty());
|
|
|
|
assert!(!ecx.link_meta.vers.is_empty());
|
2011-06-29 14:17:23 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
let name_item =
|
2013-06-13 03:02:55 +10:00
|
|
|
attr::mk_name_value_item_str(@"name",
|
|
|
|
ecx.link_meta.name);
|
2011-07-27 14:19:39 +02:00
|
|
|
let vers_item =
|
2013-06-13 03:02:55 +10:00
|
|
|
attr::mk_name_value_item_str(@"vers",
|
|
|
|
ecx.link_meta.vers);
|
2011-06-29 14:17:23 -07:00
|
|
|
|
2011-07-27 14:19:39 +02:00
|
|
|
let other_items =
|
|
|
|
{
|
2013-05-19 01:07:44 -04:00
|
|
|
let tmp = attr::remove_meta_items_by_name(items, "name");
|
|
|
|
attr::remove_meta_items_by_name(tmp, "vers")
|
2011-07-27 14:19:39 +02:00
|
|
|
};
|
2011-06-29 14:17:23 -07:00
|
|
|
|
2012-06-29 16:26:56 -07:00
|
|
|
let meta_items = vec::append(~[name_item, vers_item], other_items);
|
2013-06-13 03:02:55 +10:00
|
|
|
let link_item = attr::mk_list_item(@"link", meta_items);
|
2011-06-29 14:17:23 -07:00
|
|
|
|
2012-08-01 17:30:05 -07:00
|
|
|
return attr::mk_attr(link_item);
|
2011-06-29 14:17:23 -07:00
|
|
|
}
|
|
|
|
|
2012-06-29 16:26:56 -07:00
|
|
|
let mut attrs: ~[attribute] = ~[];
|
2012-03-15 09:47:03 -04:00
|
|
|
let mut found_link_attr = false;
|
2013-06-21 08:29:53 -04:00
|
|
|
for crate.node.attrs.iter().advance |attr| {
|
2012-09-26 17:33:34 -07:00
|
|
|
attrs.push(
|
2013-06-13 03:02:55 +10:00
|
|
|
if "link" != attr::get_attr_name(attr) {
|
2013-06-27 17:41:35 -07:00
|
|
|
*attr
|
2011-07-27 14:19:39 +02:00
|
|
|
} else {
|
2013-03-20 01:17:42 -04:00
|
|
|
match attr.node.value.node {
|
|
|
|
meta_list(_, ref l) => {
|
2011-09-12 11:27:30 +02:00
|
|
|
found_link_attr = true;;
|
2013-07-02 12:47:32 -07:00
|
|
|
synthesize_link_attr(ecx, (*l).clone())
|
2011-07-27 14:19:39 +02:00
|
|
|
}
|
2013-06-27 17:41:35 -07:00
|
|
|
_ => *attr
|
2011-06-29 14:17:23 -07:00
|
|
|
}
|
2012-06-28 15:00:03 -07:00
|
|
|
});
|
2011-06-29 14:17:23 -07:00
|
|
|
}
|
|
|
|
|
2012-09-26 17:33:34 -07:00
|
|
|
if !found_link_attr { attrs.push(synthesize_link_attr(ecx, ~[])); }
|
2011-06-29 14:17:23 -07:00
|
|
|
|
2012-08-01 17:30:05 -07:00
|
|
|
return attrs;
|
2011-06-29 14:17:23 -07:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_crate_deps(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2013-06-13 19:19:50 +12:00
|
|
|
cstore: &cstore::CStore) {
|
|
|
|
fn get_ordered_deps(ecx: &EncodeContext, cstore: &cstore::CStore)
|
2013-02-04 14:02:01 -08:00
|
|
|
-> ~[decoder::crate_dep] {
|
2012-04-08 01:59:37 +08:00
|
|
|
type numdep = decoder::crate_dep;
|
2011-07-08 11:29:56 -07:00
|
|
|
|
2012-04-08 01:59:37 +08:00
|
|
|
// Pull the cnums and name,vers,hash out of cstore
|
2013-02-11 08:36:42 -08:00
|
|
|
let mut deps = ~[];
|
2012-06-30 16:19:07 -07:00
|
|
|
do cstore::iter_crate_data(cstore) |key, val| {
|
2013-02-19 02:40:42 -05:00
|
|
|
let dep = decoder::crate_dep {cnum: key,
|
2013-06-13 03:02:55 +10:00
|
|
|
name: ecx.tcx.sess.ident_of(val.name),
|
2012-04-08 01:59:37 +08:00
|
|
|
vers: decoder::get_crate_vers(val.data),
|
2012-06-10 00:49:59 -07:00
|
|
|
hash: decoder::get_crate_hash(val.data)};
|
2012-09-26 17:33:34 -07:00
|
|
|
deps.push(dep);
|
2011-10-21 12:21:27 +02:00
|
|
|
};
|
2011-07-08 11:29:56 -07:00
|
|
|
|
|
|
|
// Sort by cnum
|
2013-05-18 12:39:17 -07:00
|
|
|
extra::sort::quick_sort(deps, |kv1, kv2| kv1.cnum <= kv2.cnum);
|
2011-07-08 11:29:56 -07:00
|
|
|
|
|
|
|
// Sanity-check the crate numbers
|
2012-03-15 09:47:03 -04:00
|
|
|
let mut expected_cnum = 1;
|
2013-06-21 08:29:53 -04:00
|
|
|
for deps.iter().advance |n| {
|
2013-05-18 22:02:45 -04:00
|
|
|
assert_eq!(n.cnum, expected_cnum);
|
2011-07-08 11:29:56 -07:00
|
|
|
expected_cnum += 1;
|
|
|
|
}
|
|
|
|
|
2013-06-29 15:05:50 +10:00
|
|
|
deps
|
2011-07-08 11:29:56 -07:00
|
|
|
}
|
|
|
|
|
2012-04-08 01:59:37 +08:00
|
|
|
// We're just going to write a list of crate 'name-hash-version's, with
|
|
|
|
// the assumption that they are numbered 1 to n.
|
2012-06-21 16:44:10 -07:00
|
|
|
// FIXME (#2166): This is not nearly enough to support correct versioning
|
2011-07-08 11:29:56 -07:00
|
|
|
// but is enough to get transitive crate dependencies working.
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_crate_deps);
|
2013-06-21 08:29:53 -04:00
|
|
|
let r = get_ordered_deps(ecx, cstore);
|
|
|
|
for r.iter().advance |dep| {
|
2012-09-19 16:55:01 -07:00
|
|
|
encode_crate_dep(ecx, ebml_w, *dep);
|
2011-07-08 11:29:56 -07:00
|
|
|
}
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-07-08 11:29:56 -07:00
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_lang_items(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
|
2013-01-07 10:51:53 -08:00
|
|
|
ebml_w.start_tag(tag_lang_items);
|
|
|
|
|
|
|
|
for ecx.tcx.lang_items.each_item |def_id, i| {
|
|
|
|
if def_id.crate != local_crate {
|
|
|
|
loop;
|
|
|
|
}
|
|
|
|
|
|
|
|
ebml_w.start_tag(tag_lang_items_item);
|
|
|
|
|
|
|
|
ebml_w.start_tag(tag_lang_items_item_id);
|
|
|
|
ebml_w.writer.write_be_u32(i as u32);
|
|
|
|
ebml_w.end_tag(); // tag_lang_items_item_id
|
|
|
|
|
|
|
|
ebml_w.start_tag(tag_lang_items_item_node_id);
|
|
|
|
ebml_w.writer.write_be_u32(def_id.node as u32);
|
|
|
|
ebml_w.end_tag(); // tag_lang_items_item_node_id
|
|
|
|
|
|
|
|
ebml_w.end_tag(); // tag_lang_items_item
|
|
|
|
}
|
|
|
|
|
|
|
|
ebml_w.end_tag(); // tag_lang_items
|
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_link_args(ecx: &EncodeContext, ebml_w: &mut writer::Encoder) {
|
2013-03-06 22:06:53 -08:00
|
|
|
ebml_w.start_tag(tag_link_args);
|
|
|
|
|
|
|
|
let link_args = cstore::get_used_link_args(ecx.cstore);
|
2013-06-21 08:29:53 -04:00
|
|
|
for link_args.iter().advance |link_arg| {
|
2013-03-06 22:06:53 -08:00
|
|
|
ebml_w.start_tag(tag_link_args_arg);
|
|
|
|
ebml_w.writer.write_str(link_arg.to_str());
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
2013-06-18 09:39:16 -07:00
|
|
|
fn encode_misc_info(ecx: &EncodeContext,
|
|
|
|
crate: &crate,
|
|
|
|
ebml_w: &mut writer::Encoder) {
|
|
|
|
ebml_w.start_tag(tag_misc_info);
|
|
|
|
ebml_w.start_tag(tag_misc_info_crate_items);
|
2013-06-25 18:25:27 -07:00
|
|
|
for crate.node.module.items.iter().advance |&item| {
|
2013-06-18 09:39:16 -07:00
|
|
|
ebml_w.start_tag(tag_mod_child);
|
|
|
|
ebml_w.wr_str(def_to_str(local_def(item.id)));
|
|
|
|
ebml_w.end_tag();
|
|
|
|
|
|
|
|
for each_auxiliary_node_id(item) |auxiliary_node_id| {
|
|
|
|
ebml_w.start_tag(tag_mod_child);
|
|
|
|
ebml_w.wr_str(def_to_str(local_def(auxiliary_node_id)));
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encode reexports for the root module.
|
|
|
|
encode_reexports(ecx, ebml_w, 0, []);
|
|
|
|
|
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
2013-06-13 19:19:50 +12:00
|
|
|
fn encode_crate_dep(ecx: &EncodeContext,
|
2013-05-01 17:54:54 -07:00
|
|
|
ebml_w: &mut writer::Encoder,
|
2012-07-18 16:18:02 -07:00
|
|
|
dep: decoder::crate_dep) {
|
2012-04-08 01:59:37 +08:00
|
|
|
ebml_w.start_tag(tag_crate_dep);
|
|
|
|
ebml_w.start_tag(tag_crate_dep_name);
|
2013-06-11 13:10:37 +10:00
|
|
|
let s = ecx.tcx.sess.str_of(dep.name);
|
|
|
|
ebml_w.writer.write(s.as_bytes());
|
2012-04-08 01:59:37 +08:00
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.start_tag(tag_crate_dep_vers);
|
2013-06-11 13:10:37 +10:00
|
|
|
ebml_w.writer.write(dep.vers.as_bytes());
|
2012-04-08 01:59:37 +08:00
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.start_tag(tag_crate_dep_hash);
|
2013-06-11 13:10:37 +10:00
|
|
|
ebml_w.writer.write(dep.hash.as_bytes());
|
2012-04-08 01:59:37 +08:00
|
|
|
ebml_w.end_tag();
|
|
|
|
ebml_w.end_tag();
|
|
|
|
}
|
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
fn encode_hash(ebml_w: &mut writer::Encoder, hash: &str) {
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_crate_hash);
|
2013-06-11 13:10:37 +10:00
|
|
|
ebml_w.writer.write(hash.as_bytes());
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2011-12-11 23:23:38 +08:00
|
|
|
}
|
|
|
|
|
2012-09-05 15:27:22 -07:00
|
|
|
// NB: Increment this as you change the metadata encoding version.
|
2013-03-22 14:00:15 -07:00
|
|
|
pub static metadata_encoding_version : &'static [u8] =
|
2013-02-26 14:34:00 -05:00
|
|
|
&[0x72, //'r' as u8,
|
|
|
|
0x75, //'u' as u8,
|
|
|
|
0x73, //'s' as u8,
|
|
|
|
0x74, //'t' as u8,
|
|
|
|
0, 0, 0, 1 ];
|
2012-09-05 15:27:22 -07:00
|
|
|
|
2013-04-17 12:15:37 -04:00
|
|
|
pub fn encode_metadata(parms: EncodeParams, crate: &crate) -> ~[u8] {
|
2013-06-04 12:47:45 +02:00
|
|
|
let wr = @io::BytesWriter::new();
|
2013-04-12 01:15:30 -04:00
|
|
|
let stats = Stats {
|
2013-02-04 14:02:01 -08:00
|
|
|
inline_bytes: 0,
|
|
|
|
attr_bytes: 0,
|
|
|
|
dep_bytes: 0,
|
|
|
|
lang_item_bytes: 0,
|
2013-03-06 22:06:53 -08:00
|
|
|
link_args_bytes: 0,
|
2013-06-18 09:39:16 -07:00
|
|
|
misc_bytes: 0,
|
2013-02-04 14:02:01 -08:00
|
|
|
item_bytes: 0,
|
|
|
|
index_bytes: 0,
|
|
|
|
zero_bytes: 0,
|
|
|
|
total_bytes: 0,
|
|
|
|
n_inlines: 0
|
|
|
|
};
|
2013-06-18 09:39:16 -07:00
|
|
|
let EncodeParams {
|
|
|
|
item_symbols,
|
|
|
|
diag,
|
|
|
|
tcx,
|
|
|
|
reexports2,
|
|
|
|
discrim_symbols,
|
|
|
|
cstore,
|
|
|
|
encode_inlined_item,
|
|
|
|
link_meta,
|
|
|
|
reachable,
|
|
|
|
_
|
|
|
|
} = parms;
|
2013-06-13 19:19:50 +12:00
|
|
|
let type_abbrevs = @mut HashMap::new();
|
|
|
|
let stats = @mut stats;
|
|
|
|
let ecx = EncodeContext {
|
2013-03-22 22:26:41 -04:00
|
|
|
diag: diag,
|
|
|
|
tcx: tcx,
|
2013-06-13 19:19:50 +12:00
|
|
|
stats: stats,
|
2013-03-22 22:26:41 -04:00
|
|
|
reexports2: reexports2,
|
|
|
|
item_symbols: item_symbols,
|
|
|
|
discrim_symbols: discrim_symbols,
|
|
|
|
link_meta: link_meta,
|
|
|
|
cstore: cstore,
|
|
|
|
encode_inlined_item: encode_inlined_item,
|
2013-06-18 09:39:16 -07:00
|
|
|
type_abbrevs: type_abbrevs,
|
|
|
|
reachable: reachable,
|
2013-02-19 02:40:42 -05:00
|
|
|
};
|
2011-07-07 23:55:41 -07:00
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
let mut ebml_w = writer::Encoder(wr as @io::Writer);
|
2011-06-27 15:20:17 -07:00
|
|
|
|
2013-05-01 17:54:54 -07:00
|
|
|
encode_hash(&mut ebml_w, ecx.link_meta.extras_hash);
|
2011-12-11 23:23:38 +08:00
|
|
|
|
2013-05-03 17:37:08 -07:00
|
|
|
let mut i = *wr.pos;
|
2013-06-13 19:19:50 +12:00
|
|
|
let crate_attrs = synthesize_crate_attrs(&ecx, crate);
|
2013-05-01 17:54:54 -07:00
|
|
|
encode_attributes(&mut ebml_w, crate_attrs);
|
2013-05-03 17:37:08 -07:00
|
|
|
ecx.stats.attr_bytes = *wr.pos - i;
|
2011-07-08 11:29:56 -07:00
|
|
|
|
2013-05-03 17:37:08 -07:00
|
|
|
i = *wr.pos;
|
2013-06-13 19:19:50 +12:00
|
|
|
encode_crate_deps(&ecx, &mut ebml_w, ecx.cstore);
|
2013-05-03 17:37:08 -07:00
|
|
|
ecx.stats.dep_bytes = *wr.pos - i;
|
2011-07-08 11:29:56 -07:00
|
|
|
|
2013-01-07 10:51:53 -08:00
|
|
|
// Encode the language items.
|
2013-05-03 17:37:08 -07:00
|
|
|
i = *wr.pos;
|
2013-06-13 19:19:50 +12:00
|
|
|
encode_lang_items(&ecx, &mut ebml_w);
|
2013-05-03 17:37:08 -07:00
|
|
|
ecx.stats.lang_item_bytes = *wr.pos - i;
|
2013-01-07 10:51:53 -08:00
|
|
|
|
2013-03-06 22:06:53 -08:00
|
|
|
// Encode the link args.
|
2013-05-03 17:37:08 -07:00
|
|
|
i = *wr.pos;
|
2013-06-13 19:19:50 +12:00
|
|
|
encode_link_args(&ecx, &mut ebml_w);
|
2013-05-03 17:37:08 -07:00
|
|
|
ecx.stats.link_args_bytes = *wr.pos - i;
|
2013-03-06 22:06:53 -08:00
|
|
|
|
2013-06-18 09:39:16 -07:00
|
|
|
// Encode miscellaneous info.
|
|
|
|
i = *wr.pos;
|
|
|
|
encode_misc_info(&ecx, crate, &mut ebml_w);
|
|
|
|
ecx.stats.misc_bytes = *wr.pos - i;
|
|
|
|
|
2012-01-11 15:15:54 +01:00
|
|
|
// Encode and index the items.
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.start_tag(tag_items);
|
2013-05-03 17:37:08 -07:00
|
|
|
i = *wr.pos;
|
2013-06-13 19:19:50 +12:00
|
|
|
let items_index = encode_info_for_items(&ecx, &mut ebml_w, crate);
|
2013-05-03 17:37:08 -07:00
|
|
|
ecx.stats.item_bytes = *wr.pos - i;
|
2012-08-27 16:53:54 -07:00
|
|
|
|
2013-05-03 17:37:08 -07:00
|
|
|
i = *wr.pos;
|
2012-09-19 13:13:24 -07:00
|
|
|
let items_buckets = create_index(items_index);
|
2013-05-01 17:54:54 -07:00
|
|
|
encode_index(&mut ebml_w, items_buckets, write_int);
|
2013-05-03 17:37:08 -07:00
|
|
|
ecx.stats.index_bytes = *wr.pos - i;
|
2012-02-14 15:21:53 -08:00
|
|
|
ebml_w.end_tag();
|
2012-01-11 15:15:54 +01:00
|
|
|
|
2013-05-03 17:37:08 -07:00
|
|
|
ecx.stats.total_bytes = *wr.pos;
|
2012-08-27 16:53:54 -07:00
|
|
|
|
2013-03-22 22:26:41 -04:00
|
|
|
if (tcx.sess.meta_stats()) {
|
2013-06-21 08:29:53 -04:00
|
|
|
for wr.bytes.iter().advance |e| {
|
2013-03-07 18:37:14 -05:00
|
|
|
if *e == 0 {
|
|
|
|
ecx.stats.zero_bytes += 1;
|
2012-08-27 16:53:54 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
io::println("metadata stats:");
|
|
|
|
io::println(fmt!(" inline bytes: %u", ecx.stats.inline_bytes));
|
|
|
|
io::println(fmt!(" attribute bytes: %u", ecx.stats.attr_bytes));
|
|
|
|
io::println(fmt!(" dep bytes: %u", ecx.stats.dep_bytes));
|
2013-01-07 10:51:53 -08:00
|
|
|
io::println(fmt!(" lang item bytes: %u", ecx.stats.lang_item_bytes));
|
2013-03-06 22:06:53 -08:00
|
|
|
io::println(fmt!(" link args bytes: %u", ecx.stats.link_args_bytes));
|
2013-06-18 09:39:16 -07:00
|
|
|
io::println(fmt!(" misc bytes: %u", ecx.stats.misc_bytes));
|
2012-08-27 16:53:54 -07:00
|
|
|
io::println(fmt!(" item bytes: %u", ecx.stats.item_bytes));
|
|
|
|
io::println(fmt!(" index bytes: %u", ecx.stats.index_bytes));
|
|
|
|
io::println(fmt!(" zero bytes: %u", ecx.stats.zero_bytes));
|
|
|
|
io::println(fmt!(" total bytes: %u", ecx.stats.total_bytes));
|
|
|
|
}
|
|
|
|
|
2011-06-27 15:20:17 -07:00
|
|
|
// Pad this, since something (LLVM, presumably) is cutting off the
|
2011-08-11 16:36:20 -07:00
|
|
|
// remaining % 4 bytes.
|
2012-09-14 09:40:28 -07:00
|
|
|
wr.write(&[0u8, 0u8, 0u8, 0u8]);
|
2012-09-05 15:27:22 -07:00
|
|
|
|
2013-05-03 17:37:08 -07:00
|
|
|
let writer_bytes: &mut ~[u8] = wr.bytes;
|
|
|
|
|
2013-07-12 00:53:03 -07:00
|
|
|
metadata_encoding_version.to_owned() +
|
2013-05-22 15:35:25 -07:00
|
|
|
flate::deflate_bytes(*writer_bytes)
|
2011-06-27 15:20:17 -07:00
|
|
|
}
|
2011-06-27 19:16:16 -07:00
|
|
|
|
2011-07-07 12:47:39 -07:00
|
|
|
// Get the encoded string for a type
|
2013-01-29 16:51:16 -08:00
|
|
|
pub fn encoded_ty(tcx: ty::ctxt, t: ty::t) -> ~str {
|
2013-01-08 14:00:45 -08:00
|
|
|
let cx = @tyencode::ctxt {
|
|
|
|
diag: tcx.diag,
|
|
|
|
ds: def_to_str,
|
|
|
|
tcx: tcx,
|
|
|
|
abbrevs: tyencode::ac_no_abbrevs};
|
2012-09-14 09:40:28 -07:00
|
|
|
do io::with_str_writer |wr| {
|
|
|
|
tyencode::enc_ty(wr, cx, t);
|
|
|
|
}
|
2011-07-07 12:47:39 -07:00
|
|
|
}
|