about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2012-05-15 20:23:06 -0700
committerBrian Anderson <banderson@mozilla.com>2012-05-15 21:36:16 -0700
commit0e21a05e6c0bc0bfa905291a916b38bdb9daf90d (patch)
treefffd203146f2656baba17d439a2b477cd9c36d0e /src
parent4bfa19b100c0fef982bfad20c9b108c4f2e7a329 (diff)
downloadrust-0e21a05e6c0bc0bfa905291a916b38bdb9daf90d.tar.gz
rust-0e21a05e6c0bc0bfa905291a916b38bdb9daf90d.zip
rustc: Extract loader mod from creader mod
loader is a utility for locating crates and loading their metadata.
creader is a compiler pass that loads metadata for all used libraries.
Diffstat (limited to 'src')
-rw-r--r--src/rustc/driver/driver.rs2
-rw-r--r--src/rustc/metadata/creader.rs209
-rw-r--r--src/rustc/metadata/loader.rs209
-rw-r--r--src/rustc/rustc.rc2
4 files changed, 222 insertions, 200 deletions
diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs
index 6b76edbb5c7..a0a630bb10b 100644
--- a/src/rustc/driver/driver.rs
+++ b/src/rustc/driver/driver.rs
@@ -672,7 +672,7 @@ fn early_error(emitter: diagnostic::emitter, msg: str) -> ! {
 }
 
 fn list_metadata(sess: session, path: str, out: io::writer) {
-    metadata::creader::list_file_metadata(sess, path, out);
+    metadata::loader::list_file_metadata(sess, path, out);
 }
 
 #[cfg(test)]
diff --git a/src/rustc/metadata/creader.rs b/src/rustc/metadata/creader.rs
index bae50d13d17..2cc3f1a5a4a 100644
--- a/src/rustc/metadata/creader.rs
+++ b/src/rustc/metadata/creader.rs
@@ -1,20 +1,20 @@
-// Extracting metadata from crate files
+#[doc = "
+
+Validates all used crates and native libraries and loads their metadata
+
+"];
 
 import driver::session;
 import session::session;
 import syntax::{ast, ast_util};
-import lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
 import syntax::attr;
 import syntax::visit;
 import syntax::codemap::span;
-import util::{filesearch};
-import io::writer_util;
 import std::map::{hashmap, int_hash};
 import syntax::print::pprust;
 import common::*;
 
 export read_crates;
-export list_file_metadata;
 
 // Traverses an AST, reading all the information about use'd crates and native
 // libraries necessary for later resolving, typechecking, linking, etc.
@@ -59,10 +59,10 @@ fn warn_if_multiple_versions(sess: session::session,
     import either::*;
 
     if crate_cache.is_not_empty() {
-        let name = crate_name_from_metas(*crate_cache.last().metas);
+        let name = loader::crate_name_from_metas(*crate_cache.last().metas);
         let {lefts: matches, rights: non_matches} =
             partition(crate_cache.map {|entry|
-                let othername = crate_name_from_metas(*entry.metas);
+                let othername = loader::crate_name_from_metas(*entry.metas);
                 if name == othername {
                     left(entry)
                 } else {
@@ -79,7 +79,7 @@ fn warn_if_multiple_versions(sess: session::session,
                 let attrs = [
                     attr::mk_attr(attr::mk_list_item("link", *match.metas))
                 ];
-                note_linkage_attrs(sess, attrs);
+                loader::note_linkage_attrs(sess, attrs);
             }
         }
 
@@ -148,195 +148,6 @@ fn visit_item(e: env, i: @ast::item) {
     }
 }
 
-// A diagnostic function for dumping crate metadata to an output stream
-fn list_file_metadata(sess: session::session, path: str, out: io::writer) {
-    alt get_metadata_section(sess, path) {
-      option::some(bytes) { decoder::list_crate_metadata(bytes, out); }
-      option::none {
-        out.write_str("could not find metadata in " + path + ".\n");
-      }
-    }
-}
-
-fn crate_matches(crate_data: @[u8], metas: [@ast::meta_item], hash: str) ->
-    bool {
-    let attrs = decoder::get_crate_attributes(crate_data);
-    let linkage_metas = attr::find_linkage_metas(attrs);
-    if hash.is_not_empty() {
-        let chash = decoder::get_crate_hash(crate_data);
-        if chash != hash { ret false; }
-    }
-    metadata_matches(linkage_metas, metas)
-}
-
-fn metadata_matches(extern_metas: [@ast::meta_item],
-                    local_metas: [@ast::meta_item]) -> bool {
-
-    #debug("matching %u metadata requirements against %u items",
-           vec::len(local_metas), vec::len(extern_metas));
-
-    #debug("crate metadata:");
-    for extern_metas.each {|have|
-        #debug("  %s", pprust::meta_item_to_str(*have));
-    }
-
-    for local_metas.each {|needed|
-        #debug("looking for %s", pprust::meta_item_to_str(*needed));
-        if !attr::contains(extern_metas, needed) {
-            #debug("missing %s", pprust::meta_item_to_str(*needed));
-            ret false;
-        }
-    }
-    ret true;
-}
-
-fn default_native_lib_naming(sess: session::session, static: bool) ->
-   {prefix: str, suffix: str} {
-    if static { ret {prefix: "lib", suffix: ".rlib"}; }
-    alt sess.targ_cfg.os {
-      session::os_win32 { ret {prefix: "", suffix: ".dll"}; }
-      session::os_macos { ret {prefix: "lib", suffix: ".dylib"}; }
-      session::os_linux { ret {prefix: "lib", suffix: ".so"}; }
-      session::os_freebsd { ret {prefix: "lib", suffix: ".so"}; }
-    }
-}
-
-fn crate_name_from_metas(metas: [@ast::meta_item]) -> str {
-    let name_items = attr::find_meta_items_by_name(metas, "name");
-    alt vec::last_opt(name_items) {
-      some(i) {
-        alt attr::get_meta_item_value_str(i) {
-          some(n) { n }
-          // FIXME: Probably want a warning here since the user
-          // is using the wrong type of meta item
-          _ { fail }
-        }
-      }
-      none { fail "expected to find the crate name" }
-    }
-}
-
-fn find_library_crate(sess: session::session, span: span,
-                      metas: [@ast::meta_item], hash: str)
-   -> option<{ident: str, data: @[u8]}> {
-
-    attr::require_unique_names(sess.diagnostic(), metas);
-    let metas = metas;
-
-    let nn = default_native_lib_naming(sess, sess.opts.static);
-    let x =
-        find_library_crate_aux(sess, span, nn,
-                               metas, hash, sess.filesearch);
-    if x != none || sess.opts.static { ret x; }
-    let nn2 = default_native_lib_naming(sess, true);
-    ret find_library_crate_aux(sess, span, nn2, metas, hash,
-                               sess.filesearch);
-}
-
-fn find_library_crate_aux(sess: session::session,
-                          span: span,
-                          nn: {prefix: str, suffix: str},
-                          metas: [@ast::meta_item],
-                          hash: str,
-                          filesearch: filesearch::filesearch) ->
-   option<{ident: str, data: @[u8]}> {
-    let crate_name = crate_name_from_metas(metas);
-    let prefix: str = nn.prefix + crate_name + "-";
-    let suffix: str = nn.suffix;
-
-    let mut matches = [];
-    filesearch::search(filesearch, { |path|
-        #debug("inspecting file %s", path);
-        let f: str = path::basename(path);
-        if !(str::starts_with(f, prefix) && str::ends_with(f, suffix)) {
-            #debug("skipping %s, doesn't look like %s*%s", path, prefix,
-                   suffix);
-            option::none::<()>
-        } else {
-            #debug("%s is a candidate", path);
-            alt get_metadata_section(sess, path) {
-              option::some(cvec) {
-                if !crate_matches(cvec, metas, hash) {
-                    #debug("skipping %s, metadata doesn't match", path);
-                    option::none::<()>
-                } else {
-                    #debug("found %s with matching metadata", path);
-                    matches += [{ident: path, data: cvec}];
-                    option::none::<()>
-                }
-              }
-              _ {
-                #debug("could not load metadata for %s", path);
-                option::none::<()>
-              }
-            }
-        }
-    });
-
-    if matches.is_empty() {
-        none
-    } else if matches.len() == 1u {
-        some(matches[0])
-    } else {
-        sess.span_err(
-            span, #fmt("multiple matching crates for `%s`", crate_name));
-        sess.note("candidates:");
-        for matches.each {|match|
-            sess.note(#fmt("path: %s", match.ident));
-            let attrs = decoder::get_crate_attributes(match.data);
-            note_linkage_attrs(sess, attrs);
-        }
-        sess.abort_if_errors();
-        none
-    }
-}
-
-fn note_linkage_attrs(sess: session::session, attrs: [ast::attribute]) {
-    for attr::find_linkage_attrs(attrs).each {|attr|
-        sess.note(#fmt("meta: %s", pprust::attr_to_str(attr)));
-    }
-}
-
-fn get_metadata_section(sess: session::session,
-                        filename: str) -> option<@[u8]> unsafe {
-    let mb = str::as_c_str(filename, {|buf|
-        llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
-                                   });
-    if mb as int == 0 { ret option::none::<@[u8]>; }
-    let of = alt mk_object_file(mb) {
-        option::some(of) { of }
-        _ { ret option::none::<@[u8]>; }
-    };
-    let si = mk_section_iter(of.llof);
-    while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
-        let name_buf = llvm::LLVMGetSectionName(si.llsi);
-        let name = unsafe { str::unsafe::from_c_str(name_buf) };
-        if str::eq(name, sess.targ_cfg.target_strs.meta_sect_name) {
-            let cbuf = llvm::LLVMGetSectionContents(si.llsi);
-            let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
-            unsafe {
-                let cvbuf: *u8 = unsafe::reinterpret_cast(cbuf);
-                ret some(@vec::unsafe::from_buf(cvbuf, csz));
-            }
-        }
-        llvm::LLVMMoveToNextSection(si.llsi);
-    }
-    ret option::none::<@[u8]>;
-}
-
-fn load_library_crate(sess: session::session, ident: ast::ident, span: span,
-                      metas: [@ast::meta_item], hash: str)
-   -> {ident: str, data: @[u8]} {
-
-
-    alt find_library_crate(sess, span, metas, hash) {
-      some(t) { ret t; }
-      none {
-        sess.span_fatal(span, #fmt["can't find crate for '%s'", ident]);
-      }
-    }
-}
-
 fn metas_with(ident: ast::ident, key: str,
                     metas: [@ast::meta_item]) -> [@ast::meta_item] {
     let name_items = attr::find_meta_items_by_name(metas, key);
@@ -355,7 +166,7 @@ fn metas_with_ident(ident: ast::ident,
 fn existing_match(e: env, metas: [@ast::meta_item], hash: str) ->
     option<int> {
     let maybe_entry = e.crate_cache.find {|c|
-        metadata_matches(*c.metas, metas) &&
+        loader::metadata_matches(*c.metas, metas) &&
             (hash.is_empty() || c.hash == hash)
     };
 
@@ -369,7 +180,7 @@ fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
     alt existing_match(e, metas, hash) {
       none {
         let cinfo =
-            load_library_crate(e.sess, ident, span, metas, hash);
+            loader::load_library_crate(e.sess, ident, span, metas, hash);
 
         let cfilename = cinfo.ident;
         let cdata = cinfo.data;
diff --git a/src/rustc/metadata/loader.rs b/src/rustc/metadata/loader.rs
new file mode 100644
index 00000000000..4ef60c4a8cc
--- /dev/null
+++ b/src/rustc/metadata/loader.rs
@@ -0,0 +1,209 @@
+#[doc = "
+
+Finds crate binaries and loads their metadata
+
+"];
+
+import driver::session;
+import session::session;
+import syntax::{ast, attr};
+import syntax::print::pprust;
+import syntax::codemap::span;
+import lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
+import util::{filesearch};
+import io::writer_util;
+
+export load_library_crate;
+export list_file_metadata;
+export note_linkage_attrs;
+export crate_name_from_metas;
+export metadata_matches;
+
+fn load_library_crate(sess: session::session, ident: ast::ident, span: span,
+                      metas: [@ast::meta_item], hash: str)
+   -> {ident: str, data: @[u8]} {
+
+
+    alt find_library_crate(sess, span, metas, hash) {
+      some(t) { ret t; }
+      none {
+        sess.span_fatal(span, #fmt["can't find crate for '%s'", ident]);
+      }
+    }
+}
+
+fn find_library_crate(sess: session::session, span: span,
+                      metas: [@ast::meta_item], hash: str)
+   -> option<{ident: str, data: @[u8]}> {
+
+    attr::require_unique_names(sess.diagnostic(), metas);
+    let metas = metas;
+
+    let nn = default_native_lib_naming(sess, sess.opts.static);
+    let x =
+        find_library_crate_aux(sess, span, nn,
+                               metas, hash, sess.filesearch);
+    if x != none || sess.opts.static { ret x; }
+    let nn2 = default_native_lib_naming(sess, true);
+    ret find_library_crate_aux(sess, span, nn2, metas, hash,
+                               sess.filesearch);
+}
+
+fn default_native_lib_naming(sess: session::session, static: bool) ->
+   {prefix: str, suffix: str} {
+    if static { ret {prefix: "lib", suffix: ".rlib"}; }
+    alt sess.targ_cfg.os {
+      session::os_win32 { ret {prefix: "", suffix: ".dll"}; }
+      session::os_macos { ret {prefix: "lib", suffix: ".dylib"}; }
+      session::os_linux { ret {prefix: "lib", suffix: ".so"}; }
+      session::os_freebsd { ret {prefix: "lib", suffix: ".so"}; }
+    }
+}
+
+fn find_library_crate_aux(sess: session::session,
+                          span: span,
+                          nn: {prefix: str, suffix: str},
+                          metas: [@ast::meta_item],
+                          hash: str,
+                          filesearch: filesearch::filesearch) ->
+   option<{ident: str, data: @[u8]}> {
+    let crate_name = crate_name_from_metas(metas);
+    let prefix: str = nn.prefix + crate_name + "-";
+    let suffix: str = nn.suffix;
+
+    let mut matches = [];
+    filesearch::search(filesearch, { |path|
+        #debug("inspecting file %s", path);
+        let f: str = path::basename(path);
+        if !(str::starts_with(f, prefix) && str::ends_with(f, suffix)) {
+            #debug("skipping %s, doesn't look like %s*%s", path, prefix,
+                   suffix);
+            option::none::<()>
+        } else {
+            #debug("%s is a candidate", path);
+            alt get_metadata_section(sess, path) {
+              option::some(cvec) {
+                if !crate_matches(cvec, metas, hash) {
+                    #debug("skipping %s, metadata doesn't match", path);
+                    option::none::<()>
+                } else {
+                    #debug("found %s with matching metadata", path);
+                    matches += [{ident: path, data: cvec}];
+                    option::none::<()>
+                }
+              }
+              _ {
+                #debug("could not load metadata for %s", path);
+                option::none::<()>
+              }
+            }
+        }
+    });
+
+    if matches.is_empty() {
+        none
+    } else if matches.len() == 1u {
+        some(matches[0])
+    } else {
+        sess.span_err(
+            span, #fmt("multiple matching crates for `%s`", crate_name));
+        sess.note("candidates:");
+        for matches.each {|match|
+            sess.note(#fmt("path: %s", match.ident));
+            let attrs = decoder::get_crate_attributes(match.data);
+            note_linkage_attrs(sess, attrs);
+        }
+        sess.abort_if_errors();
+        none
+    }
+}
+
+fn crate_name_from_metas(metas: [@ast::meta_item]) -> str {
+    let name_items = attr::find_meta_items_by_name(metas, "name");
+    alt vec::last_opt(name_items) {
+      some(i) {
+        alt attr::get_meta_item_value_str(i) {
+          some(n) { n }
+          // FIXME: Probably want a warning here since the user
+          // is using the wrong type of meta item
+          _ { fail }
+        }
+      }
+      none { fail "expected to find the crate name" }
+    }
+}
+
+fn note_linkage_attrs(sess: session::session, attrs: [ast::attribute]) {
+    for attr::find_linkage_attrs(attrs).each {|attr|
+        sess.note(#fmt("meta: %s", pprust::attr_to_str(attr)));
+    }
+}
+
+fn crate_matches(crate_data: @[u8], metas: [@ast::meta_item], hash: str) ->
+    bool {
+    let attrs = decoder::get_crate_attributes(crate_data);
+    let linkage_metas = attr::find_linkage_metas(attrs);
+    if hash.is_not_empty() {
+        let chash = decoder::get_crate_hash(crate_data);
+        if chash != hash { ret false; }
+    }
+    metadata_matches(linkage_metas, metas)
+}
+
+fn metadata_matches(extern_metas: [@ast::meta_item],
+                    local_metas: [@ast::meta_item]) -> bool {
+
+    #debug("matching %u metadata requirements against %u items",
+           vec::len(local_metas), vec::len(extern_metas));
+
+    #debug("crate metadata:");
+    for extern_metas.each {|have|
+        #debug("  %s", pprust::meta_item_to_str(*have));
+    }
+
+    for local_metas.each {|needed|
+        #debug("looking for %s", pprust::meta_item_to_str(*needed));
+        if !attr::contains(extern_metas, needed) {
+            #debug("missing %s", pprust::meta_item_to_str(*needed));
+            ret false;
+        }
+    }
+    ret true;
+}
+
+fn get_metadata_section(sess: session::session,
+                        filename: str) -> option<@[u8]> unsafe {
+    let mb = str::as_c_str(filename, {|buf|
+        llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
+                                   });
+    if mb as int == 0 { ret option::none::<@[u8]>; }
+    let of = alt mk_object_file(mb) {
+        option::some(of) { of }
+        _ { ret option::none::<@[u8]>; }
+    };
+    let si = mk_section_iter(of.llof);
+    while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
+        let name_buf = llvm::LLVMGetSectionName(si.llsi);
+        let name = unsafe { str::unsafe::from_c_str(name_buf) };
+        if str::eq(name, sess.targ_cfg.target_strs.meta_sect_name) {
+            let cbuf = llvm::LLVMGetSectionContents(si.llsi);
+            let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
+            unsafe {
+                let cvbuf: *u8 = unsafe::reinterpret_cast(cbuf);
+                ret some(@vec::unsafe::from_buf(cvbuf, csz));
+            }
+        }
+        llvm::LLVMMoveToNextSection(si.llsi);
+    }
+    ret option::none::<@[u8]>;
+}
+
+// A diagnostic function for dumping crate metadata to an output stream
+fn list_file_metadata(sess: session::session, path: str, out: io::writer) {
+    alt get_metadata_section(sess, path) {
+      option::some(bytes) { decoder::list_crate_metadata(bytes, out); }
+      option::none {
+        out.write_str("could not find metadata in " + path + ".\n");
+      }
+    }
+}
diff --git a/src/rustc/rustc.rc b/src/rustc/rustc.rc
index 67e583eb5f9..69f225e5ed8 100644
--- a/src/rustc/rustc.rc
+++ b/src/rustc/rustc.rc
@@ -117,6 +117,7 @@ mod metadata {
     export decoder;
     export tyencode;
     export tydecode;
+    export loader;
 
     mod common;
     mod tyencode;
@@ -126,6 +127,7 @@ mod metadata {
     mod creader;
     mod cstore;
     mod csearch;
+    mod loader;
 }
 
 mod driver {