rustc: Encode reexports in the metadata and don't have each_path search tag_paths

This commit is contained in:
Patrick Walton 2012-08-17 12:41:34 -07:00
parent 7bae3449ce
commit 578b7266f2
8 changed files with 163 additions and 69 deletions

View file

@ -176,6 +176,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
let { def_map: def_map,
exp_map: exp_map,
exp_map2: exp_map2,
impl_map: impl_map,
trait_map: trait_map } =
time(time_passes, ~"resolution", ||
@ -238,7 +239,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
let (llmod, link_meta) = time(time_passes, ~"translation", ||
trans::base::trans_crate(sess, crate, ty_cx, outputs.obj_filename,
exp_map, maps));
exp_map, exp_map2, maps));
time(time_passes, ~"LLVM passes", ||
link::write::run_passes(sess, llmod, outputs.obj_filename));

View file

@ -5,6 +5,8 @@
mod middle {
import ty = middle_::ty;
export ty;
import resolve3 = middle_::resolve3;
export resolve3;
}
mod front {

View file

@ -100,6 +100,12 @@ const tag_paths_foreign_path: uint = 0x4a;
const tag_item_trait_method_self_ty: uint = 0x4b;
const tag_item_trait_method_self_ty_region: uint = 0x4c;
// Reexports are found within module tags. Each reexport contains def_ids
// and names.
const tag_items_data_item_reexport: uint = 0x4d;
const tag_items_data_item_reexport_def_id: uint = 0x4e;
const tag_items_data_item_reexport_name: uint = 0x4f;
// used to encode crate_ctxt side tables
enum astencode_tag { // Reserves 0x50 -- 0x6f
tag_ast = 0x50,
@ -115,15 +121,15 @@ enum astencode_tag { // Reserves 0x50 -- 0x6f
tag_table_node_type = 0x57,
tag_table_node_type_subst = 0x58,
tag_table_freevars = 0x59,
tag_table_tcache,
tag_table_param_bounds,
tag_table_inferred_modes,
tag_table_mutbl,
tag_table_last_use,
tag_table_spill,
tag_table_method_map,
tag_table_vtable_map,
tag_table_borrowings
tag_table_tcache = 0x5a,
tag_table_param_bounds = 0x5b,
tag_table_inferred_modes = 0x5c,
tag_table_mutbl = 0x5d,
tag_table_last_use = 0x5e,
tag_table_spill = 0x5f,
tag_table_method_map = 0x60,
tag_table_vtable_map = 0x61,
tag_table_borrowings = 0x62
}
// djb's cdb hashes.

View file

@ -127,6 +127,14 @@ fn item_def_id(d: ebml::doc, cdata: cmd) -> ast::def_id {
|d| parse_def_id(d)));
}
fn each_reexport(d: ebml::doc, f: fn(ebml::doc) -> bool) {
for ebml::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| {
if !f(reexport_doc) {
return;
}
}
}
fn field_mutability(d: ebml::doc) -> ast::class_mutability {
// Use maybe_get_doc in case it's a method
option::map_default(
@ -426,22 +434,67 @@ fn each_path(cdata: cmd, f: fn(path_entry) -> bool) {
// First, go through all the explicit items.
for ebml::tagged_docs(items_data, tag_items_data_item) |item_doc| {
if !broken {
let name = ast_map::path_to_str_with_sep(item_path(item_doc),
let path = ast_map::path_to_str_with_sep(item_path(item_doc),
~"::");
if name != ~"" {
if path != ~"" {
// Extract the def ID.
let def_id = item_def_id(item_doc, cdata);
// Construct the def for this item.
debug!{"(each_path) yielding explicit item: %s", name};
debug!{"(each_path) yielding explicit item: %s", path};
let def_like = item_to_def_like(item_doc, def_id, cdata.cnum);
// Hand the information off to the iteratee.
let this_path_entry = path_entry(name, def_like);
let this_path_entry = path_entry(path, def_like);
if !f(this_path_entry) {
broken = true; // XXX: This is awful.
}
}
// If this is a module, find the reexports.
for each_reexport(item_doc) |reexport_doc| {
if !broken {
let def_id_doc =
ebml::get_doc(reexport_doc,
tag_items_data_item_reexport_def_id);
let def_id =
ebml::with_doc_data(def_id_doc, |d| parse_def_id(d));
let def_id = translate_def_id(cdata, def_id);
let reexport_name_doc =
ebml::get_doc(reexport_doc,
tag_items_data_item_reexport_name);
let reexport_name = ebml::doc_as_str(reexport_name_doc);
let reexport_path;
if path == ~"" {
reexport_path = reexport_name;
} else {
reexport_path = path + ~"::" + reexport_name;
}
// Get the item.
match maybe_find_item(def_id.node, items) {
none => {}
some(item_doc) => {
// Construct the def for this item.
let def_like = item_to_def_like(item_doc,
def_id,
cdata.cnum);
// Hand the information off to the iteratee.
debug!("(each_path) yielding reexported \
item: %s", reexport_path);
let this_path_entry =
path_entry(reexport_path, def_like);
if (!f(this_path_entry)) {
broken = true; // XXX: This is awful.
}
}
}
}
}
}
}
@ -449,54 +502,6 @@ fn each_path(cdata: cmd, f: fn(path_entry) -> bool) {
if broken {
return;
}
// Next, go through all the paths. We will find items that we didn't know
// about before (reexports in particular).
//
// XXX: This is broken; the paths are actually hierarchical.
let outer_paths = ebml::get_doc(root, tag_paths);
let inner_paths = ebml::get_doc(outer_paths, tag_paths);
fn g(cdata: cmd, items: ebml::doc, path_doc: ebml::doc, &broken: bool,
f: fn(path_entry) -> bool) {
if !broken {
let path = item_name(path_doc);
// Extract the def ID.
let def_id = item_def_id(path_doc, cdata);
// Get the item.
match maybe_find_item(def_id.node, items) {
none => {
debug!{"(each_path) ignoring implicit item: %s",
*path};
}
some(item_doc) => {
// Construct the def for this item.
let def_like = item_to_def_like(item_doc, def_id,
cdata.cnum);
// Hand the information off to the iteratee.
debug!{"(each_path) yielding implicit item: %s",
*path};
let this_path_entry = path_entry(*path, def_like);
if (!f(this_path_entry)) {
broken = true; // XXX: This is awful.
}
}
}
}
}
for ebml::tagged_docs(inner_paths, tag_paths_data_item) |path_doc| {
g(cdata, items, path_doc, broken, f);
}
for ebml::tagged_docs(inner_paths, tag_paths_foreign_path) |path_doc| {
g(cdata, items, path_doc, broken, f);
}
}
fn get_item_path(cdata: cmd, id: ast::node_id) -> ast_map::path {

View file

@ -13,6 +13,7 @@ import syntax::ast_util::*;
import common::*;
import middle::ty;
import middle::ty::node_id_to_type;
import middle::resolve3;
import syntax::ast_map;
import syntax::attr;
import std::serialization::serializer;
@ -44,6 +45,7 @@ type encode_parms = {
tcx: ty::ctxt,
reachable: hashmap<ast::node_id, ()>,
reexports: ~[(~str, def_id)],
reexports2: middle::resolve3::ExportMap2,
impl_map: fn@(ast::node_id) -> ~[(ident, def_id)],
item_symbols: hashmap<ast::node_id, ~str>,
discrim_symbols: hashmap<ast::node_id, ~str>,
@ -57,6 +59,7 @@ enum encode_ctxt = {
tcx: ty::ctxt,
reachable: hashmap<ast::node_id, ()>,
reexports: ~[(~str, def_id)],
reexports2: middle::resolve3::ExportMap2,
impl_map: fn@(ast::node_id) -> ~[(ident, def_id)],
item_symbols: hashmap<ast::node_id, ~str>,
discrim_symbols: hashmap<ast::node_id, ~str>,
@ -278,7 +281,7 @@ fn encode_trait_ref(ebml_w: ebml::writer, ecx: @encode_ctxt, t: @trait_ref) {
}
fn encode_item_paths(ebml_w: ebml::writer, ecx: @encode_ctxt, crate: @crate)
-> ~[entry<~str>] {
-> ~[entry<~str>] {
let mut index: ~[entry<~str>] = ~[];
let mut path: ~[ident] = ~[];
ebml_w.start_tag(tag_paths);
@ -478,6 +481,31 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: ebml::writer, md: _mod,
} // for
encode_path(ebml_w, path, ast_map::path_mod(name));
// Encode the reexports of this module.
debug!("(encoding info for module) encoding reexports for %d", id);
match ecx.reexports2.find(id) {
some(exports) => {
debug!("(encoding info for module) found reexports for %d", id);
for exports.each |exp| {
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();
}
}
none => {
debug!("(encoding info for module) found no reexports for %d",
id);
}
}
ebml_w.end_tag();
}
@ -1228,6 +1256,7 @@ fn encode_metadata(parms: encode_parms, crate: @crate) -> ~[u8] {
tcx: parms.tcx,
reachable: parms.reachable,
reexports: parms.reexports,
reexports2: parms.reexports2,
impl_map: parms.impl_map,
item_symbols: parms.item_symbols,
discrim_symbols: parms.discrim_symbols,

View file

@ -96,6 +96,16 @@ type TraitMap = @hashmap<node_id,@DVec<def_id>>;
type Export = { reexp: bool, id: def_id };
type ExportMap = hashmap<node_id, ~[Export]>;
// This is the replacement export map. It maps a module to all of the exports
// within.
type ExportMap2 = hashmap<node_id, ~[Export2]>;
struct Export2 {
name: ~str; // The name of the target.
def_id: def_id; // The definition of the target.
reexport: bool; // Whether this is a reexport.
}
enum PatternBindingMode {
RefutableMode,
IrrefutableMode
@ -701,6 +711,7 @@ struct Resolver {
let def_map: DefMap;
let impl_map: ImplMap;
let export_map: ExportMap;
let export_map2: ExportMap2;
let trait_map: TraitMap;
new(session: session, lang_items: LanguageItems, crate: @crate) {
@ -741,6 +752,7 @@ struct Resolver {
self.def_map = int_hash();
self.impl_map = int_hash();
self.export_map = int_hash();
self.export_map2 = int_hash();
self.trait_map = @int_hash();
}
@ -2734,6 +2746,7 @@ struct Resolver {
}
fn record_exports_for_module(module_: @Module) {
let mut exports2 = ~[];
for module_.exported_names.each |name, node_id| {
let mut exports = ~[];
for self.namespaces.each |namespace| {
@ -2752,22 +2765,49 @@ struct Resolver {
// Nothing to do.
}
ChildNameDefinition(target_def) => {
debug!("(computing exports) found child export '%s' \
for %?",
*self.atom_table.atom_to_str(name),
module_.def_id);
vec::push(exports, {
reexp: false,
id: def_id_of_def(target_def)
});
vec::push(exports2, Export2 {
reexport: false,
name: copy *self.atom_table.atom_to_str(name),
def_id: def_id_of_def(target_def)
});
}
ImportNameDefinition(target_def) => {
debug!("(computing exports) found reexport '%s' for \
%?",
*self.atom_table.atom_to_str(name),
module_.def_id);
vec::push(exports, {
reexp: true,
id: def_id_of_def(target_def)
});
vec::push(exports2, Export2 {
reexport: true,
name: copy *self.atom_table.atom_to_str(name),
def_id: def_id_of_def(target_def)
});
}
}
}
self.export_map.insert(node_id, exports);
}
match copy module_.def_id {
some(def_id) => {
self.export_map2.insert(def_id.node, move exports2);
debug!("(computing exports) writing exports for %d (some)",
def_id.node);
}
none => {}
}
}
// Implementation scope creation
@ -4846,6 +4886,7 @@ struct Resolver {
fn resolve_crate(session: session, lang_items: LanguageItems, crate: @crate)
-> { def_map: DefMap,
exp_map: ExportMap,
exp_map2: ExportMap2,
impl_map: ImplMap,
trait_map: TraitMap } {
@ -4854,6 +4895,7 @@ fn resolve_crate(session: session, lang_items: LanguageItems, crate: @crate)
return {
def_map: resolver.def_map,
exp_map: resolver.export_map,
exp_map2: resolver.export_map2,
impl_map: resolver.impl_map,
trait_map: resolver.trait_map
};

View file

@ -5648,6 +5648,7 @@ fn crate_ctxt_to_encode_parms(cx: @crate_ctxt)
tcx: cx.tcx,
reachable: cx.reachable,
reexports: reexports(cx),
reexports2: cx.exp_map2,
impl_map: |a| impl_map(cx, a),
item_symbols: cx.item_symbols,
discrim_symbols: cx.discrim_symbols,
@ -5662,9 +5663,10 @@ fn crate_ctxt_to_encode_parms(cx: @crate_ctxt)
for defs.each |def| {
if !def.reexp { again; }
let path = match check cx.tcx.items.get(exp_id) {
ast_map::node_export(_, path) => {
ast_map::path_to_str(*path)
}
ast_map::node_export(_, path) => {
ast_map::path_to_str(*path)
}
};
vec::push(reexports, (path, def.id));
}
@ -5711,10 +5713,15 @@ fn write_abi_version(ccx: @crate_ctxt) {
false);
}
fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
output: ~str, emap: resolve3::ExportMap,
fn trans_crate(sess: session::session,
crate: @ast::crate,
tcx: ty::ctxt,
output: ~str,
emap: resolve3::ExportMap,
emap2: resolve3::ExportMap2,
maps: astencode::maps)
-> (ModuleRef, link_meta) {
-> (ModuleRef, link_meta) {
let symbol_hasher = @hash::default_state();
let link_meta =
link::build_link_meta(sess, *crate, output, symbol_hasher);
@ -5773,6 +5780,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
intrinsics: intrinsics,
item_vals: int_hash::<ValueRef>(),
exp_map: emap,
exp_map2: emap2,
reachable: reachable,
item_symbols: int_hash::<~str>(),
mut main_fn: none::<ValueRef>,

View file

@ -88,6 +88,7 @@ type crate_ctxt = {
intrinsics: hashmap<~str, ValueRef>,
item_vals: hashmap<ast::node_id, ValueRef>,
exp_map: resolve3::ExportMap,
exp_map2: resolve3::ExportMap2,
reachable: reachable::map,
item_symbols: hashmap<ast::node_id, ~str>,
mut main_fn: option<ValueRef>,