about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-06-27 15:20:17 -0700
committerBrian Anderson <banderson@mozilla.com>2011-06-27 16:30:27 -0700
commit33294c7293f101d3a0fd02aeb8976751e343f46f (patch)
treedffa5fb88f40f5f2804bde0cbc5d4f616e2dd45c /src/comp
parent279a229414bea59804548f8c7606c518a15261e2 (diff)
downloadrust-33294c7293f101d3a0fd02aeb8976751e343f46f.tar.gz
rust-33294c7293f101d3a0fd02aeb8976751e343f46f.zip
Extract llvm-independent code from cwriter to metadata::encoder
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/back/link.rs3
-rw-r--r--src/comp/metadata/creader.rs4
-rw-r--r--src/comp/metadata/cwriter.rs485
-rw-r--r--src/comp/metadata/encoder.rs478
-rw-r--r--src/comp/rustc.rc1
5 files changed, 485 insertions, 486 deletions
diff --git a/src/comp/back/link.rs b/src/comp/back/link.rs
index 3ec46ff4326..afea8b85e8a 100644
--- a/src/comp/back/link.rs
+++ b/src/comp/back/link.rs
@@ -398,7 +398,7 @@ fn symbol_hash(ty::ctxt tcx, sha1 sha, &ty::t t, str crate_meta_name,
     // to be independent of one another in the crate.
 
     auto cx =
-        @rec(ds=metadata::cwriter::def_to_str,
+        @rec(ds=metadata::encoder::def_to_str,
              tcx=tcx,
              abbrevs=metadata::tyencode::ac_no_abbrevs);
     sha.reset();
@@ -452,7 +452,6 @@ fn mangle_exported_name(&@crate_ctxt ccx, &vec[str] path, &ty::t t) -> str {
 
 fn mangle_internal_name_by_type_only(&@crate_ctxt ccx, &ty::t t, &str name) ->
    str {
-    auto f = metadata::cwriter::def_to_str;
     auto s = pretty::ppaux::ty_to_short_str(ccx.tcx, t);
     auto hash = get_symbol_hash(ccx, t);
     ret mangle([name, s, hash]);
diff --git a/src/comp/metadata/creader.rs b/src/comp/metadata/creader.rs
index 5b4fe44fe16..7642b80fa41 100644
--- a/src/comp/metadata/creader.rs
+++ b/src/comp/metadata/creader.rs
@@ -435,7 +435,7 @@ fn resolve_path(vec[ast::ident] path, vec[u8] data) -> vec[ast::def_id] {
     auto paths = ebml::get_doc(md, tag_paths);
     auto eqer = bind eq_item(_, s);
     let vec[ast::def_id] result = [];
-    for (ebml::doc doc in lookup_hash(paths, eqer, cwriter::hash_path(s))) {
+    for (ebml::doc doc in lookup_hash(paths, eqer, encoder::hash_path(s))) {
         auto did_doc = ebml::get_doc(doc, tag_def_id);
         vec::push(result, parse_def_id(ebml::doc_data(did_doc)));
     }
@@ -447,7 +447,7 @@ fn maybe_find_item(int item_id, &ebml::doc items) -> option::t[ebml::doc] {
         ret ebml::be_uint_from_bytes(bytes, 0u, 4u) as int == item_id;
     }
     auto eqer = bind eq_item(_, item_id);
-    auto found = lookup_hash(items, eqer, cwriter::hash_def_id(item_id));
+    auto found = lookup_hash(items, eqer, encoder::hash_def_id(item_id));
     if (vec::len(found) == 0u) {
         ret option::none[ebml::doc];
     } else { ret option::some[ebml::doc](found.(0)); }
diff --git a/src/comp/metadata/cwriter.rs b/src/comp/metadata/cwriter.rs
index ef605da77ce..bd3d691ee39 100644
--- a/src/comp/metadata/cwriter.rs
+++ b/src/comp/metadata/cwriter.rs
@@ -1,502 +1,22 @@
 
 import std::str;
-import std::uint;
-import std::vec;
-import std::map::hashmap;
-import std::ebml;
-import std::io;
-import std::option;
-import std::option::some;
-import std::option::none;
-import front::ast::*;
 import middle::trans;
-import middle::ty;
-import middle::ty::path_to_str;
+import front::ast::crate;
 import back::x86;
-import back::link;
-import util::common;
-import pretty::ppaux::lit_to_str;
 import lib::llvm::llvm;
 import lib::llvm::llvm::ValueRef;
 import lib::llvm::False;
-import defs::*;
 
-export ac_no_abbrevs;
-export def_to_str;
-export encode;
-export hash_def_id;
-export hash_path;
-export ty_abbrev;
 export write_metadata;
 
-
 // Returns a Plain Old LLVM String:
 fn C_postr(&str s) -> ValueRef {
     ret llvm::LLVMConstString(str::buf(s), str::byte_len(s), False);
 }
 
-
-// Path table encoding
-fn encode_name(&ebml::writer ebml_w, &str name) {
-    ebml::start_tag(ebml_w, tag_paths_data_name);
-    ebml_w.writer.write(str::bytes(name));
-    ebml::end_tag(ebml_w);
-}
-
-fn encode_def_id(&ebml::writer ebml_w, &def_id id) {
-    ebml::start_tag(ebml_w, tag_def_id);
-    ebml_w.writer.write(str::bytes(def_to_str(id)));
-    ebml::end_tag(ebml_w);
-}
-
-fn encode_tag_variant_paths(&ebml::writer ebml_w, &vec[variant] variants,
-                            &vec[str] path,
-                            &mutable vec[tup(str, uint)] index) {
-    for (variant variant in variants) {
-        add_to_index(ebml_w, path, index, variant.node.name);
-        ebml::start_tag(ebml_w, tag_paths_data_item);
-        encode_name(ebml_w, variant.node.name);
-        encode_def_id(ebml_w, local_def(variant.node.id));
-        ebml::end_tag(ebml_w);
-    }
-}
-
-fn add_to_index(&ebml::writer ebml_w, &vec[str] path,
-                &mutable vec[tup(str, uint)] index, &str name) {
-    auto full_path = path + [name];
-    index += [tup(str::connect(full_path, "::"), ebml_w.writer.tell())];
-}
-
-fn encode_native_module_item_paths(&ebml::writer ebml_w,
-                                   &native_mod nmod, &vec[str] path,
-                                   &mutable vec[tup(str, uint)] index) {
-    for (@native_item nitem in nmod.items) {
-        add_to_index(ebml_w, path, index, nitem.ident);
-        ebml::start_tag(ebml_w, tag_paths_data_item);
-        encode_name(ebml_w, nitem.ident);
-        encode_def_id(ebml_w, local_def(nitem.id));
-        ebml::end_tag(ebml_w);
-    }
-}
-
-fn encode_module_item_paths(&ebml::writer ebml_w, &_mod module,
-                            &vec[str] path,
-                            &mutable vec[tup(str, uint)] index) {
-    for (@item it in module.items) {
-        if (!is_exported(it.ident, module)) { cont; }
-        alt (it.node) {
-            case (item_const(_, _)) {
-                add_to_index(ebml_w, path, index, it.ident);
-                ebml::start_tag(ebml_w, tag_paths_data_item);
-                encode_name(ebml_w, it.ident);
-                encode_def_id(ebml_w, local_def(it.id));
-                ebml::end_tag(ebml_w);
-            }
-            case (item_fn(_, ?tps)) {
-                add_to_index(ebml_w, path, index, it.ident);
-                ebml::start_tag(ebml_w, tag_paths_data_item);
-                encode_name(ebml_w, it.ident);
-                encode_def_id(ebml_w, local_def(it.id));
-                ebml::end_tag(ebml_w);
-            }
-            case (item_mod(?_mod)) {
-                add_to_index(ebml_w, path, index, it.ident);
-                ebml::start_tag(ebml_w, tag_paths_data_mod);
-                encode_name(ebml_w, it.ident);
-                encode_def_id(ebml_w, local_def(it.id));
-                encode_module_item_paths(ebml_w, _mod, path + [it.ident],
-                                         index);
-                ebml::end_tag(ebml_w);
-            }
-            case (item_native_mod(?nmod)) {
-                add_to_index(ebml_w, path, index, it.ident);
-                ebml::start_tag(ebml_w, tag_paths_data_mod);
-                encode_name(ebml_w, it.ident);
-                encode_def_id(ebml_w, local_def(it.id));
-                encode_native_module_item_paths(ebml_w, nmod,
-                                                path + [it.ident], index);
-                ebml::end_tag(ebml_w);
-            }
-            case (item_ty(_, ?tps)) {
-                add_to_index(ebml_w, path, index, it.ident);
-                ebml::start_tag(ebml_w, tag_paths_data_item);
-                encode_name(ebml_w, it.ident);
-                encode_def_id(ebml_w, local_def(it.id));
-                ebml::end_tag(ebml_w);
-            }
-            case (item_res(_, _, ?tps, ?ctor_id)) {
-                add_to_index(ebml_w, path, index, it.ident);
-                ebml::start_tag(ebml_w, tag_paths_data_item);
-                encode_name(ebml_w, it.ident);
-                encode_def_id(ebml_w, local_def(ctor_id));
-                ebml::end_tag(ebml_w);
-                add_to_index(ebml_w, path, index, it.ident);
-                ebml::start_tag(ebml_w, tag_paths_data_item);
-                encode_name(ebml_w, it.ident);
-                encode_def_id(ebml_w, local_def(it.id));
-                ebml::end_tag(ebml_w);
-            }
-            case (item_tag(?variants, ?tps)) {
-                add_to_index(ebml_w, path, index, it.ident);
-                ebml::start_tag(ebml_w, tag_paths_data_item);
-                encode_name(ebml_w, it.ident);
-                encode_def_id(ebml_w, local_def(it.id));
-                ebml::end_tag(ebml_w);
-                encode_tag_variant_paths(ebml_w, variants, path, index);
-            }
-            case (item_obj(_, ?tps, ?ctor_id)) {
-                add_to_index(ebml_w, path, index, it.ident);
-                ebml::start_tag(ebml_w, tag_paths_data_item);
-                encode_name(ebml_w, it.ident);
-                encode_def_id(ebml_w, local_def(ctor_id));
-                ebml::end_tag(ebml_w);
-                add_to_index(ebml_w, path, index, it.ident);
-                ebml::start_tag(ebml_w, tag_paths_data_item);
-                encode_name(ebml_w, it.ident);
-                encode_def_id(ebml_w, local_def(it.id));
-                ebml::end_tag(ebml_w);
-            }
-        }
-    }
-}
-
-fn encode_item_paths(&ebml::writer ebml_w, &@crate crate) ->
-   vec[tup(str, uint)] {
-    let vec[tup(str, uint)] index = [];
-    let vec[str] path = [];
-    ebml::start_tag(ebml_w, tag_paths);
-    encode_module_item_paths(ebml_w, crate.node.module, path, index);
-    ebml::end_tag(ebml_w);
-    ret index;
-}
-
-
-// Item info table encoding
-fn encode_kind(&ebml::writer ebml_w, u8 c) {
-    ebml::start_tag(ebml_w, tag_items_data_item_kind);
-    ebml_w.writer.write([c]);
-    ebml::end_tag(ebml_w);
-}
-
-fn def_to_str(&def_id did) -> str { ret #fmt("%d:%d", did._0, did._1); }
-
-fn encode_type_param_count(&ebml::writer ebml_w, &vec[ty_param] tps) {
-    ebml::start_tag(ebml_w, tag_items_data_item_ty_param_count);
-    ebml::write_vint(ebml_w.writer, vec::len[ty_param](tps));
-    ebml::end_tag(ebml_w);
-}
-
-fn encode_variant_id(&ebml::writer ebml_w, &def_id vid) {
-    ebml::start_tag(ebml_w, tag_items_data_item_variant);
-    ebml_w.writer.write(str::bytes(def_to_str(vid)));
-    ebml::end_tag(ebml_w);
-}
-
-fn encode_type(&@trans::crate_ctxt cx, &ebml::writer ebml_w, &ty::t typ) {
-    ebml::start_tag(ebml_w, tag_items_data_item_type);
-    auto f = def_to_str;
-    auto ty_str_ctxt =
-        @rec(ds=f, tcx=cx.tcx, abbrevs=tyencode::ac_use_abbrevs(cx.type_abbrevs));
-    tyencode::enc_ty(io::new_writer_(ebml_w.writer), ty_str_ctxt, typ);
-    ebml::end_tag(ebml_w);
-}
-
-fn encode_symbol(&@trans::crate_ctxt cx, &ebml::writer ebml_w,
-                 node_id id) {
-    ebml::start_tag(ebml_w, tag_items_data_item_symbol);
-    ebml_w.writer.write(str::bytes(cx.item_symbols.get(id)));
-    ebml::end_tag(ebml_w);
-}
-
-fn encode_discriminant(&@trans::crate_ctxt cx, &ebml::writer ebml_w,
-                       node_id id) {
-    ebml::start_tag(ebml_w, tag_items_data_item_symbol);
-    ebml_w.writer.write(str::bytes(cx.discrim_symbols.get(id)));
-    ebml::end_tag(ebml_w);
-}
-
-fn encode_tag_id(&ebml::writer ebml_w, &def_id id) {
-    ebml::start_tag(ebml_w, tag_items_data_item_tag_id);
-    ebml_w.writer.write(str::bytes(def_to_str(id)));
-    ebml::end_tag(ebml_w);
-}
-
-fn encode_tag_variant_info(&@trans::crate_ctxt cx, &ebml::writer ebml_w,
-                           node_id id, &vec[variant] variants,
-                           &mutable vec[tup(int, uint)] index,
-                           &vec[ty_param] ty_params) {
-    for (variant variant in variants) {
-        index += [tup(variant.node.id, ebml_w.writer.tell())];
-        ebml::start_tag(ebml_w, tag_items_data_item);
-        encode_def_id(ebml_w, local_def(variant.node.id));
-        encode_kind(ebml_w, 'v' as u8);
-        encode_tag_id(ebml_w, local_def(id));
-        encode_type(cx, ebml_w, trans::node_id_type(cx, variant.node.id));
-        if (vec::len[variant_arg](variant.node.args) > 0u) {
-            encode_symbol(cx, ebml_w, variant.node.id);
-        }
-        encode_discriminant(cx, ebml_w, variant.node.id);
-        encode_type_param_count(ebml_w, ty_params);
-        ebml::end_tag(ebml_w);
-    }
-}
-
-fn encode_info_for_item(@trans::crate_ctxt cx, &ebml::writer ebml_w,
-                        @item item, &mutable vec[tup(int, uint)] index) {
-    alt (item.node) {
-        case (item_const(_, _)) {
-            ebml::start_tag(ebml_w, tag_items_data_item);
-            encode_def_id(ebml_w, local_def(item.id));
-            encode_kind(ebml_w, 'c' as u8);
-            encode_type(cx, ebml_w, trans::node_id_type(cx, item.id));
-            encode_symbol(cx, ebml_w, item.id);
-            ebml::end_tag(ebml_w);
-        }
-        case (item_fn(?fd, ?tps)) {
-            ebml::start_tag(ebml_w, tag_items_data_item);
-            encode_def_id(ebml_w, local_def(item.id));
-            encode_kind(ebml_w, alt (fd.decl.purity) {
-                                  case (pure_fn) { 'p' }
-                                  case (impure_fn) { 'f' } } as u8);
-            encode_type_param_count(ebml_w, tps);
-            encode_type(cx, ebml_w, trans::node_id_type(cx, item.id));
-            encode_symbol(cx, ebml_w, item.id);
-            ebml::end_tag(ebml_w);
-        }
-        case (item_mod(_)) {
-            ebml::start_tag(ebml_w, tag_items_data_item);
-            encode_def_id(ebml_w, local_def(item.id));
-            encode_kind(ebml_w, 'm' as u8);
-            ebml::end_tag(ebml_w);
-        }
-        case (item_native_mod(_)) {
-            ebml::start_tag(ebml_w, tag_items_data_item);
-            encode_def_id(ebml_w, local_def(item.id));
-            encode_kind(ebml_w, 'n' as u8);
-            ebml::end_tag(ebml_w);
-        }
-        case (item_ty(_, ?tps)) {
-            ebml::start_tag(ebml_w, tag_items_data_item);
-            encode_def_id(ebml_w, local_def(item.id));
-            encode_kind(ebml_w, 'y' as u8);
-            encode_type_param_count(ebml_w, tps);
-            encode_type(cx, ebml_w, trans::node_id_type(cx, item.id));
-            ebml::end_tag(ebml_w);
-        }
-        case (item_tag(?variants, ?tps)) {
-            ebml::start_tag(ebml_w, tag_items_data_item);
-            encode_def_id(ebml_w, local_def(item.id));
-            encode_kind(ebml_w, 't' as u8);
-            encode_type_param_count(ebml_w, tps);
-            encode_type(cx, ebml_w, trans::node_id_type(cx, item.id));
-            for (variant v in variants) {
-                encode_variant_id(ebml_w, local_def(v.node.id));
-            }
-            ebml::end_tag(ebml_w);
-            encode_tag_variant_info(cx, ebml_w, item.id, variants, index,
-                                    tps);
-        }
-        case (item_res(_, _, ?tps, ?ctor_id)) {
-            auto fn_ty = trans::node_id_type(cx, item.id);
-
-            ebml::start_tag(ebml_w, tag_items_data_item);
-            encode_def_id(ebml_w, local_def(item.id));
-            encode_kind(ebml_w, 'y' as u8);
-            encode_type_param_count(ebml_w, tps);
-            encode_type(cx, ebml_w, ty::ty_fn_ret(cx.tcx, fn_ty));
-            ebml::end_tag(ebml_w);
-
-            index += [tup(ctor_id, ebml_w.writer.tell())];
-            ebml::start_tag(ebml_w, tag_items_data_item);
-            encode_def_id(ebml_w, local_def(ctor_id));
-            encode_kind(ebml_w, 'f' as u8);
-            encode_type_param_count(ebml_w, tps);
-            encode_type(cx, ebml_w, fn_ty);
-            encode_symbol(cx, ebml_w, ctor_id);
-            ebml::end_tag(ebml_w);
-        }
-        case (item_obj(_, ?tps, ?ctor_id)) {
-            auto fn_ty = trans::node_id_type(cx, ctor_id);
-
-            ebml::start_tag(ebml_w, tag_items_data_item);
-            encode_def_id(ebml_w, local_def(item.id));
-            encode_kind(ebml_w, 'y' as u8);
-            encode_type_param_count(ebml_w, tps);
-            encode_type(cx, ebml_w, ty::ty_fn_ret(cx.tcx, fn_ty));
-            ebml::end_tag(ebml_w);
-
-            index += [tup(ctor_id, ebml_w.writer.tell())];
-            ebml::start_tag(ebml_w, tag_items_data_item);
-            encode_def_id(ebml_w, local_def(ctor_id));
-            encode_kind(ebml_w, 'f' as u8);
-            encode_type_param_count(ebml_w, tps);
-            encode_type(cx, ebml_w, fn_ty);
-            encode_symbol(cx, ebml_w, ctor_id);
-            ebml::end_tag(ebml_w);
-        }
-    }
-}
-
-fn encode_info_for_native_item(&@trans::crate_ctxt cx, &ebml::writer ebml_w,
-                               &@native_item nitem) {
-    ebml::start_tag(ebml_w, tag_items_data_item);
-    alt (nitem.node) {
-        case (native_item_ty) {
-            encode_def_id(ebml_w, local_def(nitem.id));
-            encode_kind(ebml_w, 'T' as u8);
-            encode_type(cx, ebml_w, ty::mk_native(cx.tcx));
-        }
-        case (native_item_fn(_, _, ?tps)) {
-            encode_def_id(ebml_w, local_def(nitem.id));
-            encode_kind(ebml_w, 'F' as u8);
-            encode_type_param_count(ebml_w, tps);
-            encode_type(cx, ebml_w, trans::node_id_type(cx, nitem.id));
-            encode_symbol(cx, ebml_w, nitem.id);
-        }
-    }
-    ebml::end_tag(ebml_w);
-}
-
-fn encode_info_for_items(&@trans::crate_ctxt cx, &ebml::writer ebml_w) ->
-   vec[tup(int, uint)] {
-    let vec[tup(int, uint)] index = [];
-    ebml::start_tag(ebml_w, tag_items_data);
-    for each (@tup(node_id, middle::ast_map::ast_node) kvp in cx.ast_map.items()) {
-        alt (kvp._1) {
-            case (middle::ast_map::node_item(?i)) {
-                index += [tup(kvp._0, ebml_w.writer.tell())];
-                encode_info_for_item(cx, ebml_w, i, index);
-            }
-            case (middle::ast_map::node_native_item(?i)) {
-                index += [tup(kvp._0, ebml_w.writer.tell())];
-                encode_info_for_native_item(cx, ebml_w, i);
-            }
-            case (_) {}
-        }
-    }
-    ebml::end_tag(ebml_w);
-    ret index;
-}
-
-
-// Path and definition ID indexing
-
-// djb's cdb hashes.
-fn hash_def_id(&int def_id) -> uint { ret 177573u ^ (def_id as uint); }
-
-fn hash_path(&str s) -> uint {
-    auto h = 5381u;
-    for (u8 ch in str::bytes(s)) { h = (h << 5u) + h ^ (ch as uint); }
-    ret h;
-}
-
-fn create_index[T](&vec[tup(T, uint)] index, fn(&T) -> uint  hash_fn) ->
-   vec[vec[tup(T, uint)]] {
-    let vec[mutable vec[tup(T, uint)]] buckets = vec::empty_mut();
-    for each (uint i in uint::range(0u, 256u)) { buckets += [mutable []]; }
-    for (tup(T, uint) elt in index) {
-        auto h = hash_fn(elt._0);
-        buckets.(h % 256u) += [elt];
-    }
-    ret vec::freeze(buckets);
-}
-
-fn encode_index[T](&ebml::writer ebml_w, &vec[vec[tup(T, uint)]] buckets,
-                   fn(&io::writer, &T)  write_fn) {
-    auto writer = io::new_writer_(ebml_w.writer);
-    ebml::start_tag(ebml_w, tag_index);
-    let vec[uint] bucket_locs = [];
-    ebml::start_tag(ebml_w, tag_index_buckets);
-    for (vec[tup(T, uint)] bucket in buckets) {
-        bucket_locs += [ebml_w.writer.tell()];
-        ebml::start_tag(ebml_w, tag_index_buckets_bucket);
-        for (tup(T, uint) elt in bucket) {
-            ebml::start_tag(ebml_w, tag_index_buckets_bucket_elt);
-            writer.write_be_uint(elt._1, 4u);
-            write_fn(writer, elt._0);
-            ebml::end_tag(ebml_w);
-        }
-        ebml::end_tag(ebml_w);
-    }
-    ebml::end_tag(ebml_w);
-    ebml::start_tag(ebml_w, tag_index_table);
-    for (uint pos in bucket_locs) { writer.write_be_uint(pos, 4u); }
-    ebml::end_tag(ebml_w);
-    ebml::end_tag(ebml_w);
-}
-
-fn write_str(&io::writer writer, &str s) { writer.write_str(s); }
-
-fn write_int(&io::writer writer, &int n) {
-    writer.write_be_uint(n as uint, 4u);
-}
-
-fn encode_meta_items(&ebml::writer ebml_w, &crate crate) {
-    fn encode_meta_item(&ebml::writer ebml_w, &meta_item mi) {
-        // FIXME (#487): Support all forms of meta item
-        ebml::start_tag(ebml_w, tag_meta_item);
-        alt (mi.node) {
-            case (meta_key_value(?key, ?value)) {
-                ebml::start_tag(ebml_w, tag_meta_item_key);
-                ebml_w.writer.write(str::bytes(key));
-                ebml::end_tag(ebml_w);
-                ebml::start_tag(ebml_w, tag_meta_item_value);
-                ebml_w.writer.write(str::bytes(value));
-                ebml::end_tag(ebml_w);
-            }
-            case (_) {
-                log_err "unimplemented meta_item type";
-            }
-        }
-        ebml::end_tag(ebml_w);
-    }
-    ebml::start_tag(ebml_w, tag_meta_export);
-    for each (@meta_item mi in link::crate_export_metas(crate)) {
-        encode_meta_item(ebml_w, *mi);
-    }
-    ebml::end_tag(ebml_w);
-    ebml::start_tag(ebml_w, tag_meta_local);
-    for each (@meta_item mi in link::crate_local_metas(crate)) {
-        encode_meta_item(ebml_w, *mi);
-    }
-    ebml::end_tag(ebml_w);
-}
-
-fn encode_metadata(&@trans::crate_ctxt cx, &@crate crate) -> ValueRef {
-    auto string_w = io::string_writer();
-    auto buf_w = string_w.get_writer().get_buf_writer();
-    auto ebml_w = ebml::create_writer(buf_w);
-    // Encode the meta items
-
-    encode_meta_items(ebml_w, *crate);
-    // Encode and index the paths.
-
-    ebml::start_tag(ebml_w, tag_paths);
-    auto paths_index = encode_item_paths(ebml_w, crate);
-    auto str_writer = write_str;
-    auto path_hasher = hash_path;
-    auto paths_buckets = create_index[str](paths_index, path_hasher);
-    encode_index[str](ebml_w, paths_buckets, str_writer);
-    ebml::end_tag(ebml_w);
-    // Encode and index the items.
-
-    ebml::start_tag(ebml_w, tag_items);
-    auto items_index = encode_info_for_items(cx, ebml_w);
-    auto int_writer = write_int;
-    auto item_hasher = hash_def_id;
-    auto items_buckets = create_index[int](items_index, item_hasher);
-    encode_index[int](ebml_w, items_buckets, int_writer);
-    ebml::end_tag(ebml_w);
-    // Pad this, since something (LLVM, presumably) is cutting off the
-    // remaining % 4 bytes.
-
-    buf_w.write([0u8, 0u8, 0u8, 0u8]);
-    ret C_postr(string_w.get_str());
-}
-
 fn write_metadata(&@trans::crate_ctxt cx, &@crate crate) {
     if (!cx.sess.get_opts().shared) { ret; }
-    auto llmeta = encode_metadata(cx, crate);
+    auto llmeta = C_postr(encoder::encode_metadata(cx, crate));
     auto llconst = trans::C_struct([llmeta]);
     auto llglobal =
         llvm::LLVMAddGlobal(cx.llmod, trans::val_ty(llconst),
@@ -504,6 +24,7 @@ fn write_metadata(&@trans::crate_ctxt cx, &@crate crate) {
     llvm::LLVMSetInitializer(llglobal, llconst);
     llvm::LLVMSetSection(llglobal, str::buf(x86::get_meta_sect_name()));
 }
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/comp/metadata/encoder.rs b/src/comp/metadata/encoder.rs
new file mode 100644
index 00000000000..88804a344c3
--- /dev/null
+++ b/src/comp/metadata/encoder.rs
@@ -0,0 +1,478 @@
+import std::str;
+import std::vec;
+import std::uint;
+import std::io;
+import std::option;
+import std::option::some;
+import std::option::none;
+import std::ebml;
+import front::ast::*;
+import defs::*;
+import middle::trans::crate_ctxt;
+import middle::trans::node_id_type;
+import middle::ty;
+import back::link::crate_export_metas;
+import back::link::crate_local_metas;
+
+export def_to_str;
+export hash_path;
+export hash_def_id;
+export encode_metadata;
+
+// Path table encoding
+fn encode_name(&ebml::writer ebml_w, &str name) {
+    ebml::start_tag(ebml_w, tag_paths_data_name);
+    ebml_w.writer.write(str::bytes(name));
+    ebml::end_tag(ebml_w);
+}
+
+fn encode_def_id(&ebml::writer ebml_w, &def_id id) {
+    ebml::start_tag(ebml_w, tag_def_id);
+    ebml_w.writer.write(str::bytes(def_to_str(id)));
+    ebml::end_tag(ebml_w);
+}
+
+fn encode_tag_variant_paths(&ebml::writer ebml_w, &vec[variant] variants,
+                            &vec[str] path,
+                            &mutable vec[tup(str, uint)] index) {
+    for (variant variant in variants) {
+        add_to_index(ebml_w, path, index, variant.node.name);
+        ebml::start_tag(ebml_w, tag_paths_data_item);
+        encode_name(ebml_w, variant.node.name);
+        encode_def_id(ebml_w, local_def(variant.node.id));
+        ebml::end_tag(ebml_w);
+    }
+}
+
+fn add_to_index(&ebml::writer ebml_w, &vec[str] path,
+                &mutable vec[tup(str, uint)] index, &str name) {
+    auto full_path = path + [name];
+    index += [tup(str::connect(full_path, "::"), ebml_w.writer.tell())];
+}
+
+fn encode_native_module_item_paths(&ebml::writer ebml_w,
+                                   &native_mod nmod, &vec[str] path,
+                                   &mutable vec[tup(str, uint)] index) {
+    for (@native_item nitem in nmod.items) {
+        add_to_index(ebml_w, path, index, nitem.ident);
+        ebml::start_tag(ebml_w, tag_paths_data_item);
+        encode_name(ebml_w, nitem.ident);
+        encode_def_id(ebml_w, local_def(nitem.id));
+        ebml::end_tag(ebml_w);
+    }
+}
+
+fn encode_module_item_paths(&ebml::writer ebml_w, &_mod module,
+                            &vec[str] path,
+                            &mutable vec[tup(str, uint)] index) {
+    for (@item it in module.items) {
+        if (!is_exported(it.ident, module)) { cont; }
+        alt (it.node) {
+            case (item_const(_, _)) {
+                add_to_index(ebml_w, path, index, it.ident);
+                ebml::start_tag(ebml_w, tag_paths_data_item);
+                encode_name(ebml_w, it.ident);
+                encode_def_id(ebml_w, local_def(it.id));
+                ebml::end_tag(ebml_w);
+            }
+            case (item_fn(_, ?tps)) {
+                add_to_index(ebml_w, path, index, it.ident);
+                ebml::start_tag(ebml_w, tag_paths_data_item);
+                encode_name(ebml_w, it.ident);
+                encode_def_id(ebml_w, local_def(it.id));
+                ebml::end_tag(ebml_w);
+            }
+            case (item_mod(?_mod)) {
+                add_to_index(ebml_w, path, index, it.ident);
+                ebml::start_tag(ebml_w, tag_paths_data_mod);
+                encode_name(ebml_w, it.ident);
+                encode_def_id(ebml_w, local_def(it.id));
+                encode_module_item_paths(ebml_w, _mod, path + [it.ident],
+                                         index);
+                ebml::end_tag(ebml_w);
+            }
+            case (item_native_mod(?nmod)) {
+                add_to_index(ebml_w, path, index, it.ident);
+                ebml::start_tag(ebml_w, tag_paths_data_mod);
+                encode_name(ebml_w, it.ident);
+                encode_def_id(ebml_w, local_def(it.id));
+                encode_native_module_item_paths(ebml_w, nmod,
+                                                path + [it.ident], index);
+                ebml::end_tag(ebml_w);
+            }
+            case (item_ty(_, ?tps)) {
+                add_to_index(ebml_w, path, index, it.ident);
+                ebml::start_tag(ebml_w, tag_paths_data_item);
+                encode_name(ebml_w, it.ident);
+                encode_def_id(ebml_w, local_def(it.id));
+                ebml::end_tag(ebml_w);
+            }
+            case (item_res(_, _, ?tps, ?ctor_id)) {
+                add_to_index(ebml_w, path, index, it.ident);
+                ebml::start_tag(ebml_w, tag_paths_data_item);
+                encode_name(ebml_w, it.ident);
+                encode_def_id(ebml_w, local_def(ctor_id));
+                ebml::end_tag(ebml_w);
+                add_to_index(ebml_w, path, index, it.ident);
+                ebml::start_tag(ebml_w, tag_paths_data_item);
+                encode_name(ebml_w, it.ident);
+                encode_def_id(ebml_w, local_def(it.id));
+                ebml::end_tag(ebml_w);
+            }
+            case (item_tag(?variants, ?tps)) {
+                add_to_index(ebml_w, path, index, it.ident);
+                ebml::start_tag(ebml_w, tag_paths_data_item);
+                encode_name(ebml_w, it.ident);
+                encode_def_id(ebml_w, local_def(it.id));
+                ebml::end_tag(ebml_w);
+                encode_tag_variant_paths(ebml_w, variants, path, index);
+            }
+            case (item_obj(_, ?tps, ?ctor_id)) {
+                add_to_index(ebml_w, path, index, it.ident);
+                ebml::start_tag(ebml_w, tag_paths_data_item);
+                encode_name(ebml_w, it.ident);
+                encode_def_id(ebml_w, local_def(ctor_id));
+                ebml::end_tag(ebml_w);
+                add_to_index(ebml_w, path, index, it.ident);
+                ebml::start_tag(ebml_w, tag_paths_data_item);
+                encode_name(ebml_w, it.ident);
+                encode_def_id(ebml_w, local_def(it.id));
+                ebml::end_tag(ebml_w);
+            }
+        }
+    }
+}
+
+fn encode_item_paths(&ebml::writer ebml_w, &@crate crate) ->
+   vec[tup(str, uint)] {
+    let vec[tup(str, uint)] index = [];
+    let vec[str] path = [];
+    ebml::start_tag(ebml_w, tag_paths);
+    encode_module_item_paths(ebml_w, crate.node.module, path, index);
+    ebml::end_tag(ebml_w);
+    ret index;
+}
+
+
+// Item info table encoding
+fn encode_kind(&ebml::writer ebml_w, u8 c) {
+    ebml::start_tag(ebml_w, tag_items_data_item_kind);
+    ebml_w.writer.write([c]);
+    ebml::end_tag(ebml_w);
+}
+
+fn def_to_str(&def_id did) -> str { ret #fmt("%d:%d", did._0, did._1); }
+
+fn encode_type_param_count(&ebml::writer ebml_w, &vec[ty_param] tps) {
+    ebml::start_tag(ebml_w, tag_items_data_item_ty_param_count);
+    ebml::write_vint(ebml_w.writer, vec::len[ty_param](tps));
+    ebml::end_tag(ebml_w);
+}
+
+fn encode_variant_id(&ebml::writer ebml_w, &def_id vid) {
+    ebml::start_tag(ebml_w, tag_items_data_item_variant);
+    ebml_w.writer.write(str::bytes(def_to_str(vid)));
+    ebml::end_tag(ebml_w);
+}
+
+fn encode_type(&@crate_ctxt cx, &ebml::writer ebml_w, &ty::t typ) {
+    ebml::start_tag(ebml_w, tag_items_data_item_type);
+    auto f = def_to_str;
+    auto ty_str_ctxt =
+        @rec(ds=f, tcx=cx.tcx, abbrevs=tyencode::ac_use_abbrevs(cx.type_abbrevs));
+    tyencode::enc_ty(io::new_writer_(ebml_w.writer), ty_str_ctxt, typ);
+    ebml::end_tag(ebml_w);
+}
+
+fn encode_symbol(&@crate_ctxt cx, &ebml::writer ebml_w,
+                 node_id id) {
+    ebml::start_tag(ebml_w, tag_items_data_item_symbol);
+    ebml_w.writer.write(str::bytes(cx.item_symbols.get(id)));
+    ebml::end_tag(ebml_w);
+}
+
+fn encode_discriminant(&@crate_ctxt cx, &ebml::writer ebml_w,
+                       node_id id) {
+    ebml::start_tag(ebml_w, tag_items_data_item_symbol);
+    ebml_w.writer.write(str::bytes(cx.discrim_symbols.get(id)));
+    ebml::end_tag(ebml_w);
+}
+
+fn encode_tag_id(&ebml::writer ebml_w, &def_id id) {
+    ebml::start_tag(ebml_w, tag_items_data_item_tag_id);
+    ebml_w.writer.write(str::bytes(def_to_str(id)));
+    ebml::end_tag(ebml_w);
+}
+
+fn encode_tag_variant_info(&@crate_ctxt cx, &ebml::writer ebml_w,
+                           node_id id, &vec[variant] variants,
+                           &mutable vec[tup(int, uint)] index,
+                           &vec[ty_param] ty_params) {
+    for (variant variant in variants) {
+        index += [tup(variant.node.id, ebml_w.writer.tell())];
+        ebml::start_tag(ebml_w, tag_items_data_item);
+        encode_def_id(ebml_w, local_def(variant.node.id));
+        encode_kind(ebml_w, 'v' as u8);
+        encode_tag_id(ebml_w, local_def(id));
+        encode_type(cx, ebml_w, node_id_type(cx, variant.node.id));
+        if (vec::len[variant_arg](variant.node.args) > 0u) {
+            encode_symbol(cx, ebml_w, variant.node.id);
+        }
+        encode_discriminant(cx, ebml_w, variant.node.id);
+        encode_type_param_count(ebml_w, ty_params);
+        ebml::end_tag(ebml_w);
+    }
+}
+
+fn encode_info_for_item(@crate_ctxt cx, &ebml::writer ebml_w,
+                        @item item, &mutable vec[tup(int, uint)] index) {
+    alt (item.node) {
+        case (item_const(_, _)) {
+            ebml::start_tag(ebml_w, tag_items_data_item);
+            encode_def_id(ebml_w, local_def(item.id));
+            encode_kind(ebml_w, 'c' as u8);
+            encode_type(cx, ebml_w, node_id_type(cx, item.id));
+            encode_symbol(cx, ebml_w, item.id);
+            ebml::end_tag(ebml_w);
+        }
+        case (item_fn(?fd, ?tps)) {
+            ebml::start_tag(ebml_w, tag_items_data_item);
+            encode_def_id(ebml_w, local_def(item.id));
+            encode_kind(ebml_w, alt (fd.decl.purity) {
+                                  case (pure_fn) { 'p' }
+                                  case (impure_fn) { 'f' } } as u8);
+            encode_type_param_count(ebml_w, tps);
+            encode_type(cx, ebml_w, node_id_type(cx, item.id));
+            encode_symbol(cx, ebml_w, item.id);
+            ebml::end_tag(ebml_w);
+        }
+        case (item_mod(_)) {
+            ebml::start_tag(ebml_w, tag_items_data_item);
+            encode_def_id(ebml_w, local_def(item.id));
+            encode_kind(ebml_w, 'm' as u8);
+            ebml::end_tag(ebml_w);
+        }
+        case (item_native_mod(_)) {
+            ebml::start_tag(ebml_w, tag_items_data_item);
+            encode_def_id(ebml_w, local_def(item.id));
+            encode_kind(ebml_w, 'n' as u8);
+            ebml::end_tag(ebml_w);
+        }
+        case (item_ty(_, ?tps)) {
+            ebml::start_tag(ebml_w, tag_items_data_item);
+            encode_def_id(ebml_w, local_def(item.id));
+            encode_kind(ebml_w, 'y' as u8);
+            encode_type_param_count(ebml_w, tps);
+            encode_type(cx, ebml_w, node_id_type(cx, item.id));
+            ebml::end_tag(ebml_w);
+        }
+        case (item_tag(?variants, ?tps)) {
+            ebml::start_tag(ebml_w, tag_items_data_item);
+            encode_def_id(ebml_w, local_def(item.id));
+            encode_kind(ebml_w, 't' as u8);
+            encode_type_param_count(ebml_w, tps);
+            encode_type(cx, ebml_w, node_id_type(cx, item.id));
+            for (variant v in variants) {
+                encode_variant_id(ebml_w, local_def(v.node.id));
+            }
+            ebml::end_tag(ebml_w);
+            encode_tag_variant_info(cx, ebml_w, item.id, variants, index,
+                                    tps);
+        }
+        case (item_res(_, _, ?tps, ?ctor_id)) {
+            auto fn_ty = node_id_type(cx, item.id);
+
+            ebml::start_tag(ebml_w, tag_items_data_item);
+            encode_def_id(ebml_w, local_def(item.id));
+            encode_kind(ebml_w, 'y' as u8);
+            encode_type_param_count(ebml_w, tps);
+            encode_type(cx, ebml_w, ty::ty_fn_ret(cx.tcx, fn_ty));
+            ebml::end_tag(ebml_w);
+
+            index += [tup(ctor_id, ebml_w.writer.tell())];
+            ebml::start_tag(ebml_w, tag_items_data_item);
+            encode_def_id(ebml_w, local_def(ctor_id));
+            encode_kind(ebml_w, 'f' as u8);
+            encode_type_param_count(ebml_w, tps);
+            encode_type(cx, ebml_w, fn_ty);
+            encode_symbol(cx, ebml_w, ctor_id);
+            ebml::end_tag(ebml_w);
+        }
+        case (item_obj(_, ?tps, ?ctor_id)) {
+            auto fn_ty = node_id_type(cx, ctor_id);
+
+            ebml::start_tag(ebml_w, tag_items_data_item);
+            encode_def_id(ebml_w, local_def(item.id));
+            encode_kind(ebml_w, 'y' as u8);
+            encode_type_param_count(ebml_w, tps);
+            encode_type(cx, ebml_w, ty::ty_fn_ret(cx.tcx, fn_ty));
+            ebml::end_tag(ebml_w);
+
+            index += [tup(ctor_id, ebml_w.writer.tell())];
+            ebml::start_tag(ebml_w, tag_items_data_item);
+            encode_def_id(ebml_w, local_def(ctor_id));
+            encode_kind(ebml_w, 'f' as u8);
+            encode_type_param_count(ebml_w, tps);
+            encode_type(cx, ebml_w, fn_ty);
+            encode_symbol(cx, ebml_w, ctor_id);
+            ebml::end_tag(ebml_w);
+        }
+    }
+}
+
+fn encode_info_for_native_item(&@crate_ctxt cx, &ebml::writer ebml_w,
+                               &@native_item nitem) {
+    ebml::start_tag(ebml_w, tag_items_data_item);
+    alt (nitem.node) {
+        case (native_item_ty) {
+            encode_def_id(ebml_w, local_def(nitem.id));
+            encode_kind(ebml_w, 'T' as u8);
+            encode_type(cx, ebml_w, ty::mk_native(cx.tcx));
+        }
+        case (native_item_fn(_, _, ?tps)) {
+            encode_def_id(ebml_w, local_def(nitem.id));
+            encode_kind(ebml_w, 'F' as u8);
+            encode_type_param_count(ebml_w, tps);
+            encode_type(cx, ebml_w, node_id_type(cx, nitem.id));
+            encode_symbol(cx, ebml_w, nitem.id);
+        }
+    }
+    ebml::end_tag(ebml_w);
+}
+
+fn encode_info_for_items(&@crate_ctxt cx, &ebml::writer ebml_w) ->
+   vec[tup(int, uint)] {
+    let vec[tup(int, uint)] index = [];
+    ebml::start_tag(ebml_w, tag_items_data);
+    for each (@tup(node_id, middle::ast_map::ast_node) kvp in cx.ast_map.items()) {
+        alt (kvp._1) {
+            case (middle::ast_map::node_item(?i)) {
+                index += [tup(kvp._0, ebml_w.writer.tell())];
+                encode_info_for_item(cx, ebml_w, i, index);
+            }
+            case (middle::ast_map::node_native_item(?i)) {
+                index += [tup(kvp._0, ebml_w.writer.tell())];
+                encode_info_for_native_item(cx, ebml_w, i);
+            }
+            case (_) {}
+        }
+    }
+    ebml::end_tag(ebml_w);
+    ret index;
+}
+
+
+// Path and definition ID indexing
+
+// djb's cdb hashes.
+fn hash_def_id(&int def_id) -> uint { ret 177573u ^ (def_id as uint); }
+
+fn hash_path(&str s) -> uint {
+    auto h = 5381u;
+    for (u8 ch in str::bytes(s)) { h = (h << 5u) + h ^ (ch as uint); }
+    ret h;
+}
+
+fn create_index[T](&vec[tup(T, uint)] index, fn(&T) -> uint  hash_fn) ->
+   vec[vec[tup(T, uint)]] {
+    let vec[mutable vec[tup(T, uint)]] buckets = vec::empty_mut();
+    for each (uint i in uint::range(0u, 256u)) { buckets += [mutable []]; }
+    for (tup(T, uint) elt in index) {
+        auto h = hash_fn(elt._0);
+        buckets.(h % 256u) += [elt];
+    }
+    ret vec::freeze(buckets);
+}
+
+fn encode_index[T](&ebml::writer ebml_w, &vec[vec[tup(T, uint)]] buckets,
+                   fn(&io::writer, &T)  write_fn) {
+    auto writer = io::new_writer_(ebml_w.writer);
+    ebml::start_tag(ebml_w, tag_index);
+    let vec[uint] bucket_locs = [];
+    ebml::start_tag(ebml_w, tag_index_buckets);
+    for (vec[tup(T, uint)] bucket in buckets) {
+        bucket_locs += [ebml_w.writer.tell()];
+        ebml::start_tag(ebml_w, tag_index_buckets_bucket);
+        for (tup(T, uint) elt in bucket) {
+            ebml::start_tag(ebml_w, tag_index_buckets_bucket_elt);
+            writer.write_be_uint(elt._1, 4u);
+            write_fn(writer, elt._0);
+            ebml::end_tag(ebml_w);
+        }
+        ebml::end_tag(ebml_w);
+    }
+    ebml::end_tag(ebml_w);
+    ebml::start_tag(ebml_w, tag_index_table);
+    for (uint pos in bucket_locs) { writer.write_be_uint(pos, 4u); }
+    ebml::end_tag(ebml_w);
+    ebml::end_tag(ebml_w);
+}
+
+fn write_str(&io::writer writer, &str s) { writer.write_str(s); }
+
+fn write_int(&io::writer writer, &int n) {
+    writer.write_be_uint(n as uint, 4u);
+}
+
+fn encode_meta_items(&ebml::writer ebml_w, &crate crate) {
+    fn encode_meta_item(&ebml::writer ebml_w, &meta_item mi) {
+        // FIXME (#487): Support all forms of meta item
+        ebml::start_tag(ebml_w, tag_meta_item);
+        alt (mi.node) {
+            case (meta_key_value(?key, ?value)) {
+                ebml::start_tag(ebml_w, tag_meta_item_key);
+                ebml_w.writer.write(str::bytes(key));
+                ebml::end_tag(ebml_w);
+                ebml::start_tag(ebml_w, tag_meta_item_value);
+                ebml_w.writer.write(str::bytes(value));
+                ebml::end_tag(ebml_w);
+            }
+            case (_) {
+                log_err "unimplemented meta_item type";
+            }
+        }
+        ebml::end_tag(ebml_w);
+    }
+    ebml::start_tag(ebml_w, tag_meta_export);
+    for each (@meta_item mi in crate_export_metas(crate)) {
+        encode_meta_item(ebml_w, *mi);
+    }
+    ebml::end_tag(ebml_w);
+    ebml::start_tag(ebml_w, tag_meta_local);
+    for each (@meta_item mi in crate_local_metas(crate)) {
+        encode_meta_item(ebml_w, *mi);
+    }
+    ebml::end_tag(ebml_w);
+}
+
+fn encode_metadata(&@crate_ctxt cx, &@crate crate) -> str {
+    auto string_w = io::string_writer();
+    auto buf_w = string_w.get_writer().get_buf_writer();
+    auto ebml_w = ebml::create_writer(buf_w);
+    // Encode the meta items
+
+    encode_meta_items(ebml_w, *crate);
+    // Encode and index the paths.
+
+    ebml::start_tag(ebml_w, tag_paths);
+    auto paths_index = encode_item_paths(ebml_w, crate);
+    auto str_writer = write_str;
+    auto path_hasher = hash_path;
+    auto paths_buckets = create_index[str](paths_index, path_hasher);
+    encode_index[str](ebml_w, paths_buckets, str_writer);
+    ebml::end_tag(ebml_w);
+    // Encode and index the items.
+
+    ebml::start_tag(ebml_w, tag_items);
+    auto items_index = encode_info_for_items(cx, ebml_w);
+    auto int_writer = write_int;
+    auto item_hasher = hash_def_id;
+    auto items_buckets = create_index[int](items_index, item_hasher);
+    encode_index[int](ebml_w, items_buckets, int_writer);
+    ebml::end_tag(ebml_w);
+    // Pad this, since something (LLVM, presumably) is cutting off the
+    // remaining % 4 bytes.
+
+    buf_w.write([0u8, 0u8, 0u8, 0u8]);
+    ret string_w.get_str();
+}
diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc
index 8310bee8123..0cc2aa27048 100644
--- a/src/comp/rustc.rc
+++ b/src/comp/rustc.rc
@@ -65,6 +65,7 @@ mod back {
 mod metadata {
     mod defs;
     mod tyencode;
+    mod encoder;
     mod creader;
     mod cwriter;
 }