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:30:17 -0700
committerBrian Anderson <banderson@mozilla.com>2011-06-27 16:30:27 -0700
commita3a2cc3d9851aef277df40c5f53998ec72181686 (patch)
tree6ca00518c735e2138f06a6943b8416c428117d6d /src/comp
parent33294c7293f101d3a0fd02aeb8976751e343f46f (diff)
Extract metadata::tydecode from metadata::creader
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/metadata/creader.rs409
-rw-r--r--src/comp/metadata/tydecode.rs377
-rw-r--r--src/comp/rustc.rc1
3 files changed, 400 insertions, 387 deletions
diff --git a/src/comp/metadata/creader.rs b/src/comp/metadata/creader.rs
index 7642b80fa41..7763b7b73d9 100644
--- a/src/comp/metadata/creader.rs
+++ b/src/comp/metadata/creader.rs
@@ -14,11 +14,6 @@ import middle::trans;
 import middle::ty;
 import back::x86;
 import util::common;
-import util::common::span;
-import util::common::respan;
-import util::common::a_bang;
-import util::common::a_ty;
-import util::common::may_begin_ident;
 import std::str;
 import std::uint;
 import std::vec;
@@ -31,6 +26,8 @@ import std::option::some;
 import std::os;
 import std::map::hashmap;
 import defs::*;
+import tydecode::parse_def_id;
+import tydecode::parse_ty_data;
 
 export get_symbol;
 export get_tag_variants;
@@ -40,368 +37,6 @@ export lookup_defs;
 export get_type;
 export list_file_metadata;
 
-// Type decoding
-
-// Compact string representation for ty::t values. API ty_str & parse_from_str
-// (The second has to be authed pure.) Extra parameters are for converting
-// to/from def_ids in the data buffer. Whatever format you choose should not
-// contain pipe characters.
-
-// Callback to translate defs to strs or back:
-type str_def = fn(str) -> ast::def_id ;
-
-type pstate =
-    rec(vec[u8] data, int crate, mutable uint pos, uint len, ty::ctxt tcx);
-
-type ty_or_bang = util::common::ty_or_bang[ty::t];
-
-fn peek(@pstate st) -> u8 { ret st.data.(st.pos); }
-
-fn next(@pstate st) -> u8 {
-    auto ch = st.data.(st.pos);
-    st.pos = st.pos + 1u;
-    ret ch;
-}
-
-fn parse_ident(@pstate st, str_def sd, char last) -> ast::ident {
-    fn is_last(char b, char c) -> bool {
-        ret c == b;
-    }
-    ret parse_ident_(st, sd, bind is_last(last, _));
-}
-
-fn parse_ident_(@pstate st, str_def sd, fn(char) -> bool is_last)
-    -> ast::ident {
-    auto rslt = "";
-    while (! is_last(peek(st) as char)) {
-        rslt += str::unsafe_from_byte(next(st));
-    }
-    ret rslt;
-}
-
-
-fn parse_ty_data(vec[u8] data, int crate_num, uint pos, uint len, str_def sd,
-                 ty::ctxt tcx) -> ty::t {
-    auto st =
-        @rec(data=data, crate=crate_num, mutable pos=pos, len=len, tcx=tcx);
-    auto result = parse_ty(st, sd);
-    ret result;
-}
-
-fn parse_ty_or_bang(@pstate st, str_def sd) -> ty_or_bang {
-    alt (peek(st) as char) {
-        case ('!') { auto ignore = next(st); ret a_bang[ty::t]; }
-        case (_) { ret a_ty[ty::t](parse_ty(st, sd)); }
-    }
-}
-
-fn parse_constrs(@pstate st, str_def sd) -> vec[@ty::constr_def] {
-    let vec[@ty::constr_def] rslt = [];
-    alt (peek(st) as char) {
-        case (':') {
-            do  {
-                auto ignore = next(st);
-                vec::push(rslt, parse_constr(st, sd));
-            } while (peek(st) as char == ';')
-        }
-        case (_) { }
-    }
-    ret rslt;
-}
-
-fn parse_path(@pstate st, str_def sd) -> ast::path {
-    let vec[ast::ident] idents = [];
-    fn is_last(char c) -> bool {
-        ret (c == '(' || c == ':');
-    }
-    idents += [parse_ident_(st, sd, is_last)];
-    while (true) {
-        alt (peek(st) as char) {
-            case (':') {
-                auto ignore = next(st);
-                ignore = next(st);
-            }
-            case (?c) {
-                if (c == '(') {
-                    ret respan(rec(lo=0u, hi=0u),
-                               rec(idents=idents, types=[]));
-                }
-                else {
-                    idents += [parse_ident_(st, sd, is_last)];
-                }
-            }
-        }
-    }
-    fail "parse_path: ill-formed path";
-}
-
-fn parse_constr(@pstate st, str_def sd) -> @ty::constr_def {
-    let vec[@ast::constr_arg] args = [];
-    auto sp = rec(lo=0u,hi=0u); // FIXME: use a real span
-    let ast::path pth = parse_path(st, sd);
-    let char ignore = next(st) as char;
-    assert(ignore as char == '(');
-    auto def = parse_def(st, sd);
-    do {
-        alt (peek(st) as char) {
-            case ('*') {
-                st.pos += 1u;
-                args += [@respan(sp, ast::carg_base)];
-            }
-            case (?c) {
-                /* how will we disambiguate between
-                 an arg index and a lit argument? */
-                if (c >= '0' && c <= '9') {
-                    // FIXME
-                    args += [@respan(sp, ast::carg_ident((c as uint) - 48u))];
-                    ignore = next(st) as char;
-                }
-                else {
-                    log_err("Lit args are unimplemented");
-                    fail; // FIXME
-                }
-                /*
-                else {
-                    auto lit = parse_lit(st, sd, ',');
-                    args += [respan(st.span, ast::carg_lit(lit))];
-                }
-                */
-            }
-        }
-        ignore = next(st) as char;
-    } while (ignore == ';');
-    assert(ignore == ')');
-    ret @respan(sp, rec(path=pth, args=args, id=def));
-}
-
-fn parse_ty(@pstate st, str_def sd) -> ty::t {
-    alt (next(st) as char) {
-        case ('n') { ret ty::mk_nil(st.tcx); }
-        case ('z') { ret ty::mk_bot(st.tcx); }
-        case ('b') { ret ty::mk_bool(st.tcx); }
-        case ('i') { ret ty::mk_int(st.tcx); }
-        case ('u') { ret ty::mk_uint(st.tcx); }
-        case ('l') { ret ty::mk_float(st.tcx); }
-        case ('M') {
-            alt (next(st) as char) {
-                case ('b') { ret ty::mk_mach(st.tcx, common::ty_u8); }
-                case ('w') { ret ty::mk_mach(st.tcx, common::ty_u16); }
-                case ('l') { ret ty::mk_mach(st.tcx, common::ty_u32); }
-                case ('d') { ret ty::mk_mach(st.tcx, common::ty_u64); }
-                case ('B') { ret ty::mk_mach(st.tcx, common::ty_i8); }
-                case ('W') { ret ty::mk_mach(st.tcx, common::ty_i16); }
-                case ('L') { ret ty::mk_mach(st.tcx, common::ty_i32); }
-                case ('D') { ret ty::mk_mach(st.tcx, common::ty_i64); }
-                case ('f') { ret ty::mk_mach(st.tcx, common::ty_f32); }
-                case ('F') { ret ty::mk_mach(st.tcx, common::ty_f64); }
-            }
-        }
-        case ('c') { ret ty::mk_char(st.tcx); }
-        case ('s') { ret ty::mk_str(st.tcx); }
-        case ('S') { ret ty::mk_istr(st.tcx); }
-        case ('t') {
-            assert (next(st) as char == '[');
-            auto def = parse_def(st, sd);
-            let vec[ty::t] params = [];
-            while (peek(st) as char != ']') { params += [parse_ty(st, sd)]; }
-            st.pos = st.pos + 1u;
-            ret ty::mk_tag(st.tcx, def, params);
-        }
-        case ('p') { ret ty::mk_param(st.tcx, parse_int(st) as uint); }
-        case ('@') { ret ty::mk_box(st.tcx, parse_mt(st, sd)); }
-        case ('*') { ret ty::mk_ptr(st.tcx, parse_mt(st, sd)); }
-        case ('V') { ret ty::mk_vec(st.tcx, parse_mt(st, sd)); }
-        case ('I') { ret ty::mk_ivec(st.tcx, parse_mt(st, sd)); }
-        case ('a') { ret ty::mk_task(st.tcx); }
-        case ('P') { ret ty::mk_port(st.tcx, parse_ty(st, sd)); }
-        case ('C') { ret ty::mk_chan(st.tcx, parse_ty(st, sd)); }
-        case ('T') {
-            assert (next(st) as char == '[');
-            let vec[ty::mt] params = [];
-            while (peek(st) as char != ']') { params += [parse_mt(st, sd)]; }
-            st.pos = st.pos + 1u;
-            ret ty::mk_tup(st.tcx, params);
-        }
-        case ('R') {
-            assert (next(st) as char == '[');
-            let vec[ty::field] fields = [];
-            while (peek(st) as char != ']') {
-                auto name = "";
-                while (peek(st) as char != '=') {
-                    name += str::unsafe_from_byte(next(st));
-                }
-                st.pos = st.pos + 1u;
-                fields += [rec(ident=name, mt=parse_mt(st, sd))];
-            }
-            st.pos = st.pos + 1u;
-            ret ty::mk_rec(st.tcx, fields);
-        }
-        case ('F') {
-            auto func = parse_ty_fn(st, sd);
-            ret ty::mk_fn(st.tcx, ast::proto_fn, func._0, func._1, func._2,
-                          func._3);
-        }
-        case ('W') {
-            auto func = parse_ty_fn(st, sd);
-            ret ty::mk_fn(st.tcx, ast::proto_iter, func._0, func._1, func._2,
-                          func._3);
-        }
-        case ('N') {
-            auto abi;
-            alt (next(st) as char) {
-                case ('r') { abi = ast::native_abi_rust; }
-                case ('i') { abi = ast::native_abi_rust_intrinsic; }
-                case ('c') { abi = ast::native_abi_cdecl; }
-                case ('l') { abi = ast::native_abi_llvm; }
-            }
-            auto func = parse_ty_fn(st, sd);
-            ret ty::mk_native_fn(st.tcx, abi, func._0, func._1);
-        }
-        case ('O') {
-            assert (next(st) as char == '[');
-            let vec[ty::method] methods = [];
-            while (peek(st) as char != ']') {
-                auto proto;
-                alt (next(st) as char) {
-                    case ('W') { proto = ast::proto_iter; }
-                    case ('F') { proto = ast::proto_fn; }
-                }
-                auto name = "";
-                while (peek(st) as char != '[') {
-                    name += str::unsafe_from_byte(next(st));
-                }
-                auto func = parse_ty_fn(st, sd);
-                methods +=
-                    [rec(proto=proto,
-                         ident=name,
-                         inputs=func._0,
-                         output=func._1,
-                         cf=func._2,
-                         constrs=func._3)];
-            }
-            st.pos += 1u;
-            ret ty::mk_obj(st.tcx, methods);
-        }
-        case ('r') {
-            auto def = parse_def(st, sd);
-            auto inner = parse_ty(st, sd);
-            ret ty::mk_res(st.tcx, def, inner);
-        }
-        case ('X') { ret ty::mk_var(st.tcx, parse_int(st)); }
-        case ('E') { ret ty::mk_native(st.tcx); }
-        case ('Y') { ret ty::mk_type(st.tcx); }
-        case ('#') {
-            auto pos = parse_hex(st);
-            assert (next(st) as char == ':');
-            auto len = parse_hex(st);
-            assert (next(st) as char == '#');
-            alt (st.tcx.rcache.find(tup(st.crate, pos, len))) {
-                case (some(?tt)) { ret tt; }
-                case (none) {
-                    auto ps = @rec(pos=pos, len=len with *st);
-                    auto tt = parse_ty(ps, sd);
-                    st.tcx.rcache.insert(tup(st.crate, pos, len), tt);
-                    ret tt;
-                }
-            }
-        }
-        case (?c) {
-            log_err "unexpected char in type string: ";
-            log_err c;
-            fail;
-        }
-    }
-}
-
-fn parse_mt(@pstate st, str_def sd) -> ty::mt {
-    auto mut;
-    alt (peek(st) as char) {
-        case ('m') { next(st); mut = ast::mut; }
-        case ('?') { next(st); mut = ast::maybe_mut; }
-        case (_) { mut = ast::imm; }
-    }
-    ret rec(ty=parse_ty(st, sd), mut=mut);
-}
-
-fn parse_def(@pstate st, str_def sd) -> ast::def_id {
-    auto def = "";
-    while (peek(st) as char != '|') {
-        def += str::unsafe_from_byte(next(st));
-    }
-    st.pos = st.pos + 1u;
-    ret sd(def);
-}
-
-fn parse_int(@pstate st) -> int {
-    auto n = 0;
-    while (true) {
-        auto cur = peek(st) as char;
-        if (cur < '0' || cur > '9') { break; }
-        st.pos = st.pos + 1u;
-        n *= 10;
-        n += (cur as int) - ('0' as int);
-    }
-    ret n;
-}
-
-fn parse_hex(@pstate st) -> uint {
-    auto n = 0u;
-    while (true) {
-        auto cur = peek(st) as char;
-        if ((cur < '0' || cur > '9') && (cur < 'a' || cur > 'f')) { break; }
-        st.pos = st.pos + 1u;
-        n *= 16u;
-        if ('0' <= cur && cur <= '9') {
-            n += (cur as uint) - ('0' as uint);
-        } else { n += 10u + (cur as uint) - ('a' as uint); }
-    }
-    ret n;
-}
-
-fn parse_ty_fn(@pstate st, str_def sd) ->
-   tup(vec[ty::arg], ty::t, ast::controlflow, vec[@ty::constr_def]) {
-    assert (next(st) as char == '[');
-    let vec[ty::arg] inputs = [];
-    while (peek(st) as char != ']') {
-        auto mode = ty::mo_val;
-        if (peek(st) as char == '&') {
-            mode = ty::mo_alias(false);
-            st.pos += 1u;
-            if (peek(st) as char == 'm') {
-                mode = ty::mo_alias(true);
-                st.pos += 1u;
-            }
-        }
-        inputs += [rec(mode=mode, ty=parse_ty(st, sd))];
-    }
-    st.pos += 1u; // eat the ']'
-    auto cs = parse_constrs(st, sd);
-    alt (parse_ty_or_bang(st, sd)) {
-        case (a_bang) {
-            ret tup(inputs, ty::mk_bot(st.tcx), ast::noreturn, cs);
-        }
-        case (a_ty(?t)) { ret tup(inputs, t, ast::return, cs); }
-    }
-}
-
-
-// Rust metadata parsing
-fn parse_def_id(vec[u8] buf) -> ast::def_id {
-    auto colon_idx = 0u;
-    auto len = vec::len[u8](buf);
-    while (colon_idx < len && buf.(colon_idx) != ':' as u8) {
-        colon_idx += 1u;
-    }
-    if (colon_idx == len) {
-        log_err "didn't find ':' when parsing def id";
-        fail;
-    }
-    auto crate_part = vec::slice[u8](buf, 0u, colon_idx);
-    auto def_part = vec::slice[u8](buf, colon_idx + 1u, len);
-    auto crate_num = uint::parse_buf(crate_part, 10u) as int;
-    auto def_id = uint::parse_buf(def_part, 10u) as int;
-    ret tup(crate_num, def_id);
-}
 
 fn lookup_hash(&ebml::doc d, fn(vec[u8]) -> bool  eq_fn, uint hash) ->
    vec[ebml::doc] {
@@ -516,26 +151,6 @@ fn tag_variant_ids(&ebml::doc item, int this_cnum) -> vec[ast::def_id] {
     ret ids;
 }
 
-fn get_metadata_section(str filename) -> option::t[vec[u8]] {
-    auto b = str::buf(filename);
-    auto mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(b);
-    if (mb as int == 0) { ret option::none[vec[u8]]; }
-    auto of = mk_object_file(mb);
-    auto si = mk_section_iter(of.llof);
-    while (llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False) {
-        auto name_buf = llvm::LLVMGetSectionName(si.llsi);
-        auto name = str::str_from_cstr(name_buf);
-        if (str::eq(name, x86::get_meta_sect_name())) {
-            auto cbuf = llvm::LLVMGetSectionContents(si.llsi);
-            auto csz = llvm::LLVMGetSectionSize(si.llsi);
-            auto cvbuf = cbuf as vec::vbuf;
-            ret option::some[vec[u8]](vec::vec_from_vbuf[u8](cvbuf, csz));
-        }
-        llvm::LLVMMoveToNextSection(si.llsi);
-    }
-    ret option::none[vec[u8]];
-}
-
 fn get_exported_metadata(&session::session sess, &str path, &vec[u8] data) ->
    hashmap[str, str] {
     auto meta_items =
@@ -653,6 +268,26 @@ fn find_library_crate(&session::session sess, &ast::ident ident,
     ret none;
 }
 
+fn get_metadata_section(str filename) -> option::t[vec[u8]] {
+    auto b = str::buf(filename);
+    auto mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(b);
+    if (mb as int == 0) { ret option::none[vec[u8]]; }
+    auto of = mk_object_file(mb);
+    auto si = mk_section_iter(of.llof);
+    while (llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False) {
+        auto name_buf = llvm::LLVMGetSectionName(si.llsi);
+        auto name = str::str_from_cstr(name_buf);
+        if (str::eq(name, x86::get_meta_sect_name())) {
+            auto cbuf = llvm::LLVMGetSectionContents(si.llsi);
+            auto csz = llvm::LLVMGetSectionSize(si.llsi);
+            auto cvbuf = cbuf as vec::vbuf;
+            ret option::some[vec[u8]](vec::vec_from_vbuf[u8](cvbuf, csz));
+        }
+        llvm::LLVMMoveToNextSection(si.llsi);
+    }
+    ret option::none[vec[u8]];
+}
+
 fn load_library_crate(&session::session sess, int cnum, &ast::ident ident,
                       &vec[@ast::meta_item] metas,
                       &vec[str] library_search_paths) {
diff --git a/src/comp/metadata/tydecode.rs b/src/comp/metadata/tydecode.rs
new file mode 100644
index 00000000000..2627459e297
--- /dev/null
+++ b/src/comp/metadata/tydecode.rs
@@ -0,0 +1,377 @@
+// Type decoding
+import std::str;
+import std::vec;
+import std::uint;
+import std::option;
+import std::option::none;
+import std::option::some;
+import front::ast;
+import middle::ty;
+import util::common;
+import util::common::respan;
+import util::common::a_ty;
+import util::common::a_bang;
+
+export parse_def_id;
+export parse_ty_data;
+
+// Compact string representation for ty::t values. API ty_str & parse_from_str
+// (The second has to be authed pure.) Extra parameters are for converting
+// to/from def_ids in the data buffer. Whatever format you choose should not
+// contain pipe characters.
+
+// Callback to translate defs to strs or back:
+type str_def = fn(str) -> ast::def_id ;
+
+type pstate =
+    rec(vec[u8] data, int crate, mutable uint pos, uint len, ty::ctxt tcx);
+
+type ty_or_bang = util::common::ty_or_bang[ty::t];
+
+fn peek(@pstate st) -> u8 { ret st.data.(st.pos); }
+
+fn next(@pstate st) -> u8 {
+    auto ch = st.data.(st.pos);
+    st.pos = st.pos + 1u;
+    ret ch;
+}
+
+fn parse_ident(@pstate st, str_def sd, char last) -> ast::ident {
+    fn is_last(char b, char c) -> bool {
+        ret c == b;
+    }
+    ret parse_ident_(st, sd, bind is_last(last, _));
+}
+
+fn parse_ident_(@pstate st, str_def sd, fn(char) -> bool is_last)
+    -> ast::ident {
+    auto rslt = "";
+    while (! is_last(peek(st) as char)) {
+        rslt += str::unsafe_from_byte(next(st));
+    }
+    ret rslt;
+}
+
+
+fn parse_ty_data(vec[u8] data, int crate_num, uint pos, uint len, str_def sd,
+                 ty::ctxt tcx) -> ty::t {
+    auto st =
+        @rec(data=data, crate=crate_num, mutable pos=pos, len=len, tcx=tcx);
+    auto result = parse_ty(st, sd);
+    ret result;
+}
+
+fn parse_ty_or_bang(@pstate st, str_def sd) -> ty_or_bang {
+    alt (peek(st) as char) {
+        case ('!') { auto ignore = next(st); ret a_bang[ty::t]; }
+        case (_) { ret a_ty[ty::t](parse_ty(st, sd)); }
+    }
+}
+
+fn parse_constrs(@pstate st, str_def sd) -> vec[@ty::constr_def] {
+    let vec[@ty::constr_def] rslt = [];
+    alt (peek(st) as char) {
+        case (':') {
+            do  {
+                auto ignore = next(st);
+                vec::push(rslt, parse_constr(st, sd));
+            } while (peek(st) as char == ';')
+        }
+        case (_) { }
+    }
+    ret rslt;
+}
+
+fn parse_path(@pstate st, str_def sd) -> ast::path {
+    let vec[ast::ident] idents = [];
+    fn is_last(char c) -> bool {
+        ret (c == '(' || c == ':');
+    }
+    idents += [parse_ident_(st, sd, is_last)];
+    while (true) {
+        alt (peek(st) as char) {
+            case (':') {
+                auto ignore = next(st);
+                ignore = next(st);
+            }
+            case (?c) {
+                if (c == '(') {
+                    ret respan(rec(lo=0u, hi=0u),
+                               rec(idents=idents, types=[]));
+                }
+                else {
+                    idents += [parse_ident_(st, sd, is_last)];
+                }
+            }
+        }
+    }
+    fail "parse_path: ill-formed path";
+}
+
+fn parse_constr(@pstate st, str_def sd) -> @ty::constr_def {
+    let vec[@ast::constr_arg] args = [];
+    auto sp = rec(lo=0u,hi=0u); // FIXME: use a real span
+    let ast::path pth = parse_path(st, sd);
+    let char ignore = next(st) as char;
+    assert(ignore as char == '(');
+    auto def = parse_def(st, sd);
+    do {
+        alt (peek(st) as char) {
+            case ('*') {
+                st.pos += 1u;
+                args += [@respan(sp, ast::carg_base)];
+            }
+            case (?c) {
+                /* how will we disambiguate between
+                 an arg index and a lit argument? */
+                if (c >= '0' && c <= '9') {
+                    // FIXME
+                    args += [@respan(sp, ast::carg_ident((c as uint) - 48u))];
+                    ignore = next(st) as char;
+                }
+                else {
+                    log_err("Lit args are unimplemented");
+                    fail; // FIXME
+                }
+                /*
+                else {
+                    auto lit = parse_lit(st, sd, ',');
+                    args += [respan(st.span, ast::carg_lit(lit))];
+                }
+                */
+            }
+        }
+        ignore = next(st) as char;
+    } while (ignore == ';');
+    assert(ignore == ')');
+    ret @respan(sp, rec(path=pth, args=args, id=def));
+}
+
+fn parse_ty(@pstate st, str_def sd) -> ty::t {
+    alt (next(st) as char) {
+        case ('n') { ret ty::mk_nil(st.tcx); }
+        case ('z') { ret ty::mk_bot(st.tcx); }
+        case ('b') { ret ty::mk_bool(st.tcx); }
+        case ('i') { ret ty::mk_int(st.tcx); }
+        case ('u') { ret ty::mk_uint(st.tcx); }
+        case ('l') { ret ty::mk_float(st.tcx); }
+        case ('M') {
+            alt (next(st) as char) {
+                case ('b') { ret ty::mk_mach(st.tcx, common::ty_u8); }
+                case ('w') { ret ty::mk_mach(st.tcx, common::ty_u16); }
+                case ('l') { ret ty::mk_mach(st.tcx, common::ty_u32); }
+                case ('d') { ret ty::mk_mach(st.tcx, common::ty_u64); }
+                case ('B') { ret ty::mk_mach(st.tcx, common::ty_i8); }
+                case ('W') { ret ty::mk_mach(st.tcx, common::ty_i16); }
+                case ('L') { ret ty::mk_mach(st.tcx, common::ty_i32); }
+                case ('D') { ret ty::mk_mach(st.tcx, common::ty_i64); }
+                case ('f') { ret ty::mk_mach(st.tcx, common::ty_f32); }
+                case ('F') { ret ty::mk_mach(st.tcx, common::ty_f64); }
+            }
+        }
+        case ('c') { ret ty::mk_char(st.tcx); }
+        case ('s') { ret ty::mk_str(st.tcx); }
+        case ('S') { ret ty::mk_istr(st.tcx); }
+        case ('t') {
+            assert (next(st) as char == '[');
+            auto def = parse_def(st, sd);
+            let vec[ty::t] params = [];
+            while (peek(st) as char != ']') { params += [parse_ty(st, sd)]; }
+            st.pos = st.pos + 1u;
+            ret ty::mk_tag(st.tcx, def, params);
+        }
+        case ('p') { ret ty::mk_param(st.tcx, parse_int(st) as uint); }
+        case ('@') { ret ty::mk_box(st.tcx, parse_mt(st, sd)); }
+        case ('*') { ret ty::mk_ptr(st.tcx, parse_mt(st, sd)); }
+        case ('V') { ret ty::mk_vec(st.tcx, parse_mt(st, sd)); }
+        case ('I') { ret ty::mk_ivec(st.tcx, parse_mt(st, sd)); }
+        case ('a') { ret ty::mk_task(st.tcx); }
+        case ('P') { ret ty::mk_port(st.tcx, parse_ty(st, sd)); }
+        case ('C') { ret ty::mk_chan(st.tcx, parse_ty(st, sd)); }
+        case ('T') {
+            assert (next(st) as char == '[');
+            let vec[ty::mt] params = [];
+            while (peek(st) as char != ']') { params += [parse_mt(st, sd)]; }
+            st.pos = st.pos + 1u;
+            ret ty::mk_tup(st.tcx, params);
+        }
+        case ('R') {
+            assert (next(st) as char == '[');
+            let vec[ty::field] fields = [];
+            while (peek(st) as char != ']') {
+                auto name = "";
+                while (peek(st) as char != '=') {
+                    name += str::unsafe_from_byte(next(st));
+                }
+                st.pos = st.pos + 1u;
+                fields += [rec(ident=name, mt=parse_mt(st, sd))];
+            }
+            st.pos = st.pos + 1u;
+            ret ty::mk_rec(st.tcx, fields);
+        }
+        case ('F') {
+            auto func = parse_ty_fn(st, sd);
+            ret ty::mk_fn(st.tcx, ast::proto_fn, func._0, func._1, func._2,
+                          func._3);
+        }
+        case ('W') {
+            auto func = parse_ty_fn(st, sd);
+            ret ty::mk_fn(st.tcx, ast::proto_iter, func._0, func._1, func._2,
+                          func._3);
+        }
+        case ('N') {
+            auto abi;
+            alt (next(st) as char) {
+                case ('r') { abi = ast::native_abi_rust; }
+                case ('i') { abi = ast::native_abi_rust_intrinsic; }
+                case ('c') { abi = ast::native_abi_cdecl; }
+                case ('l') { abi = ast::native_abi_llvm; }
+            }
+            auto func = parse_ty_fn(st, sd);
+            ret ty::mk_native_fn(st.tcx, abi, func._0, func._1);
+        }
+        case ('O') {
+            assert (next(st) as char == '[');
+            let vec[ty::method] methods = [];
+            while (peek(st) as char != ']') {
+                auto proto;
+                alt (next(st) as char) {
+                    case ('W') { proto = ast::proto_iter; }
+                    case ('F') { proto = ast::proto_fn; }
+                }
+                auto name = "";
+                while (peek(st) as char != '[') {
+                    name += str::unsafe_from_byte(next(st));
+                }
+                auto func = parse_ty_fn(st, sd);
+                methods +=
+                    [rec(proto=proto,
+                         ident=name,
+                         inputs=func._0,
+                         output=func._1,
+                         cf=func._2,
+                         constrs=func._3)];
+            }
+            st.pos += 1u;
+            ret ty::mk_obj(st.tcx, methods);
+        }
+        case ('r') {
+            auto def = parse_def(st, sd);
+            auto inner = parse_ty(st, sd);
+            ret ty::mk_res(st.tcx, def, inner);
+        }
+        case ('X') { ret ty::mk_var(st.tcx, parse_int(st)); }
+        case ('E') { ret ty::mk_native(st.tcx); }
+        case ('Y') { ret ty::mk_type(st.tcx); }
+        case ('#') {
+            auto pos = parse_hex(st);
+            assert (next(st) as char == ':');
+            auto len = parse_hex(st);
+            assert (next(st) as char == '#');
+            alt (st.tcx.rcache.find(tup(st.crate, pos, len))) {
+                case (some(?tt)) { ret tt; }
+                case (none) {
+                    auto ps = @rec(pos=pos, len=len with *st);
+                    auto tt = parse_ty(ps, sd);
+                    st.tcx.rcache.insert(tup(st.crate, pos, len), tt);
+                    ret tt;
+                }
+            }
+        }
+        case (?c) {
+            log_err "unexpected char in type string: ";
+            log_err c;
+            fail;
+        }
+    }
+}
+
+fn parse_mt(@pstate st, str_def sd) -> ty::mt {
+    auto mut;
+    alt (peek(st) as char) {
+        case ('m') { next(st); mut = ast::mut; }
+        case ('?') { next(st); mut = ast::maybe_mut; }
+        case (_) { mut = ast::imm; }
+    }
+    ret rec(ty=parse_ty(st, sd), mut=mut);
+}
+
+fn parse_def(@pstate st, str_def sd) -> ast::def_id {
+    auto def = "";
+    while (peek(st) as char != '|') {
+        def += str::unsafe_from_byte(next(st));
+    }
+    st.pos = st.pos + 1u;
+    ret sd(def);
+}
+
+fn parse_int(@pstate st) -> int {
+    auto n = 0;
+    while (true) {
+        auto cur = peek(st) as char;
+        if (cur < '0' || cur > '9') { break; }
+        st.pos = st.pos + 1u;
+        n *= 10;
+        n += (cur as int) - ('0' as int);
+    }
+    ret n;
+}
+
+fn parse_hex(@pstate st) -> uint {
+    auto n = 0u;
+    while (true) {
+        auto cur = peek(st) as char;
+        if ((cur < '0' || cur > '9') && (cur < 'a' || cur > 'f')) { break; }
+        st.pos = st.pos + 1u;
+        n *= 16u;
+        if ('0' <= cur && cur <= '9') {
+            n += (cur as uint) - ('0' as uint);
+        } else { n += 10u + (cur as uint) - ('a' as uint); }
+    }
+    ret n;
+}
+
+fn parse_ty_fn(@pstate st, str_def sd) ->
+   tup(vec[ty::arg], ty::t, ast::controlflow, vec[@ty::constr_def]) {
+    assert (next(st) as char == '[');
+    let vec[ty::arg] inputs = [];
+    while (peek(st) as char != ']') {
+        auto mode = ty::mo_val;
+        if (peek(st) as char == '&') {
+            mode = ty::mo_alias(false);
+            st.pos += 1u;
+            if (peek(st) as char == 'm') {
+                mode = ty::mo_alias(true);
+                st.pos += 1u;
+            }
+        }
+        inputs += [rec(mode=mode, ty=parse_ty(st, sd))];
+    }
+    st.pos += 1u; // eat the ']'
+    auto cs = parse_constrs(st, sd);
+    alt (parse_ty_or_bang(st, sd)) {
+        case (a_bang) {
+            ret tup(inputs, ty::mk_bot(st.tcx), ast::noreturn, cs);
+        }
+        case (a_ty(?t)) { ret tup(inputs, t, ast::return, cs); }
+    }
+}
+
+
+// Rust metadata parsing
+fn parse_def_id(vec[u8] buf) -> ast::def_id {
+    auto colon_idx = 0u;
+    auto len = vec::len[u8](buf);
+    while (colon_idx < len && buf.(colon_idx) != ':' as u8) {
+        colon_idx += 1u;
+    }
+    if (colon_idx == len) {
+        log_err "didn't find ':' when parsing def id";
+        fail;
+    }
+    auto crate_part = vec::slice[u8](buf, 0u, colon_idx);
+    auto def_part = vec::slice[u8](buf, colon_idx + 1u, len);
+    auto crate_num = uint::parse_buf(crate_part, 10u) as int;
+    auto def_id = uint::parse_buf(def_part, 10u) as int;
+    ret tup(crate_num, def_id);
+}
diff --git a/src/comp/rustc.rc b/src/comp/rustc.rc
index 0cc2aa27048..f00dd877ebf 100644
--- a/src/comp/rustc.rc
+++ b/src/comp/rustc.rc
@@ -65,6 +65,7 @@ mod back {
 mod metadata {
     mod defs;
     mod tyencode;
+    mod tydecode;
     mod encoder;
     mod creader;
     mod cwriter;