about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorVictor Ding <victording@google.com>2019-12-21 21:37:15 +1100
committerVictor Ding <victording@google.com>2020-01-23 11:00:36 +1100
commit6a6ebb4403683e1e12d3916cabc1a4898ce798cf (patch)
tree855442fe1710ff235f8ea29628dce81581b1f5e3 /src
parentd1e594f4029c6ac8feb7c2acf9f9e04c1b9c493c (diff)
downloadrust-6a6ebb4403683e1e12d3916cabc1a4898ce798cf.tar.gz
rust-6a6ebb4403683e1e12d3916cabc1a4898ce798cf.zip
Add `-Z no-link` flag
Adds a compiler option to allow rustc compile a crate without linking.
With this flag, rustc serializes codegen_results into a .rlink file.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/cstore.rs5
-rw-r--r--src/librustc/middle/dependency_format.rs2
-rw-r--r--src/librustc_codegen_llvm/Cargo.toml1
-rw-r--r--src/librustc_codegen_llvm/lib.rs14
-rw-r--r--src/librustc_codegen_ssa/back/linker.rs1
-rw-r--r--src/librustc_codegen_ssa/lib.rs14
-rw-r--r--src/librustc_hir/def_id.rs34
-rw-r--r--src/librustc_session/config.rs2
-rw-r--r--src/librustc_session/options.rs2
-rw-r--r--src/librustc_session/search_paths.rs2
10 files changed, 64 insertions, 13 deletions
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index 5b1e7673629..0e7ff3a3393 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -27,7 +27,7 @@ pub use rustc_session::utils::NativeLibraryKind;
 
 /// Where a crate came from on the local filesystem. One of these three options
 /// must be non-None.
-#[derive(PartialEq, Clone, Debug, HashStable)]
+#[derive(PartialEq, Clone, Debug, HashStable, RustcEncodable, RustcDecodable)]
 pub struct CrateSource {
     pub dylib: Option<(PathBuf, PathKind)>,
     pub rlib: Option<(PathBuf, PathKind)>,
@@ -75,7 +75,7 @@ impl DepKind {
     }
 }
 
-#[derive(PartialEq, Clone, Debug)]
+#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
 pub enum LibSource {
     Some(PathBuf),
     MetadataOnly,
@@ -160,6 +160,7 @@ pub enum ExternCrateSource {
     Path,
 }
 
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct EncodedMetadata {
     pub raw_data: Vec<u8>,
 }
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index 8b2bf55ccc1..6ece51fe866 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -19,7 +19,7 @@ pub type DependencyList = Vec<Linkage>;
 /// This is local to the tcx, and is generally relevant to one session.
 pub type Dependencies = Vec<(config::CrateType, DependencyList)>;
 
-#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
+#[derive(Copy, Clone, PartialEq, Debug, HashStable, RustcEncodable, RustcDecodable)]
 pub enum Linkage {
     NotLinked,
     IncludedFromDylib,
diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml
index 3ff5495e291..dd9eadde098 100644
--- a/src/librustc_codegen_llvm/Cargo.toml
+++ b/src/librustc_codegen_llvm/Cargo.toml
@@ -28,6 +28,7 @@ rustc_incremental = { path = "../librustc_incremental" }
 rustc_index = { path = "../librustc_index" }
 rustc_llvm = { path = "../librustc_llvm" }
 rustc_session = { path = "../librustc_session" }
+rustc_serialize = { path = "../libserialize", package = "serialize" }
 rustc_target = { path = "../librustc_target" }
 smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 syntax = { path = "../libsyntax" }
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index a6168128c4d..70e3874035b 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -33,6 +33,7 @@ use rustc_codegen_ssa::CompiledModule;
 use rustc_errors::{FatalError, Handler};
 use std::any::Any;
 use std::ffi::CStr;
+use std::fs;
 use std::sync::Arc;
 use syntax::expand::allocator::AllocatorKind;
 
@@ -44,6 +45,7 @@ use rustc::ty::{self, TyCtxt};
 use rustc::util::common::ErrorReported;
 use rustc_codegen_ssa::ModuleCodegen;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_serialize::json;
 
 mod back {
     pub mod archive;
@@ -298,6 +300,18 @@ impl CodegenBackend for LlvmCodegenBackend {
             return Ok(());
         }
 
+        if sess.opts.debugging_opts.no_link {
+            // FIXME: use a binary format to encode the `.rlink` file
+            let rlink_data = json::encode(&codegen_results).map_err(|err| {
+                sess.fatal(&format!("failed to encode rlink: {}", err));
+            })?;
+            let rlink_file = outputs.with_extension("rlink");
+            fs::write(&rlink_file, rlink_data).map_err(|err| {
+                sess.fatal(&format!("failed to write file {}: {}", rlink_file.display(), err));
+            })?;
+            return Ok(());
+        }
+
         // Run the linker on any artifacts that resulted from the LLVM run.
         // This should produce either a finished executable or library.
         sess.time("link_crate", || {
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index 4679f650133..695f171dfb4 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -20,6 +20,7 @@ use rustc_target::spec::{LinkerFlavor, LldFlavor};
 
 /// For all the linkers we support, and information they might
 /// need out of the shared crate context before we get rid of it.
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct LinkerInfo {
     exports: FxHashMap<CrateType, Vec<String>>,
 }
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index aba77231268..b69def5428c 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -87,7 +87,7 @@ impl<M> ModuleCodegen<M> {
     }
 }
 
-#[derive(Debug)]
+#[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct CompiledModule {
     pub name: String,
     pub kind: ModuleKind,
@@ -101,7 +101,7 @@ pub struct CachedModuleCodegen {
     pub source: WorkProduct,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
 pub enum ModuleKind {
     Regular,
     Metadata,
@@ -117,7 +117,14 @@ bitflags::bitflags! {
 }
 
 /// Misc info we load from metadata to persist beyond the tcx.
-#[derive(Debug)]
+///
+/// Note: though `CrateNum` is only meaningful within the same tcx, information within `CrateInfo`
+/// is self-contained. `CrateNum` can be viewed as a unique identifier within a `CrateInfo`, where
+/// `used_crate_source` contains all `CrateSource` of the dependents, and maintains a mapping from
+/// identifiers (`CrateNum`) to `CrateSource`. The other fields map `CrateNum` to the crate's own
+/// additional properties, so that effectively we can retrieve each dependent crate's `CrateSource`
+/// and the corresponding properties without referencing information outside of a `CrateInfo`.
+#[derive(Debug, RustcEncodable, RustcDecodable)]
 pub struct CrateInfo {
     pub panic_runtime: Option<CrateNum>,
     pub compiler_builtins: Option<CrateNum>,
@@ -135,6 +142,7 @@ pub struct CrateInfo {
     pub dependency_formats: Lrc<Dependencies>,
 }
 
+#[derive(RustcEncodable, RustcDecodable)]
 pub struct CodegenResults {
     pub crate_name: Symbol,
     pub modules: Vec<CompiledModule>,
diff --git a/src/librustc_hir/def_id.rs b/src/librustc_hir/def_id.rs
index f8cacdc6238..7ee778ddd8e 100644
--- a/src/librustc_hir/def_id.rs
+++ b/src/librustc_hir/def_id.rs
@@ -1,7 +1,8 @@
 use rustc_data_structures::AtomicRef;
 use rustc_index::vec::Idx;
+use rustc_serialize::{Decoder, Encoder};
 use std::fmt;
-use std::u32;
+use std::{u32, u64};
 
 rustc_index::newtype_index! {
     pub struct CrateId {
@@ -86,8 +87,18 @@ impl fmt::Display for CrateNum {
     }
 }
 
-impl rustc_serialize::UseSpecializedEncodable for CrateNum {}
-impl rustc_serialize::UseSpecializedDecodable for CrateNum {}
+/// As a local identifier, a `CrateNum` is only meaningful within its context, e.g. within a tcx.
+/// Therefore, make sure to include the context when encode a `CrateNum`.
+impl rustc_serialize::UseSpecializedEncodable for CrateNum {
+    fn default_encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+        e.emit_u32(self.as_u32())
+    }
+}
+impl rustc_serialize::UseSpecializedDecodable for CrateNum {
+    fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
+        Ok(CrateNum::from_u32(d.read_u32()?))
+    }
+}
 
 rustc_index::newtype_index! {
     /// A DefIndex is an index into the hir-map for a crate, identifying a
@@ -135,8 +146,21 @@ impl DefId {
     }
 }
 
-impl rustc_serialize::UseSpecializedEncodable for DefId {}
-impl rustc_serialize::UseSpecializedDecodable for DefId {}
+impl rustc_serialize::UseSpecializedEncodable for DefId {
+    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        let krate = u64::from(self.krate.as_u32());
+        let index = u64::from(self.index.as_u32());
+        s.emit_u64((krate << 32) | index)
+    }
+}
+impl rustc_serialize::UseSpecializedDecodable for DefId {
+    fn default_decode<D: Decoder>(d: &mut D) -> Result<DefId, D::Error> {
+        let def_id = d.read_u64()?;
+        let krate = CrateNum::from_u32((def_id >> 32) as u32);
+        let index = DefIndex::from_u32((def_id & 0xffffffff) as u32);
+        Ok(DefId { krate, index })
+    }
+}
 
 pub fn default_def_id_debug(def_id: DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     f.debug_struct("DefId").field("krate", &def_id.krate).field("index", &def_id.index).finish()
diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs
index b6b22e298ca..b1ba81aa95b 100644
--- a/src/librustc_session/config.rs
+++ b/src/librustc_session/config.rs
@@ -619,7 +619,7 @@ pub enum EntryFnType {
 
 impl_stable_hash_via_hash!(EntryFnType);
 
-#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
+#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub enum CrateType {
     Executable,
     Dylib,
diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs
index 2a0ed27b63b..34da2188a51 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -950,4 +950,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
          (such as entering an empty infinite loop) by inserting llvm.sideeffect"),
     deduplicate_diagnostics: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
         "deduplicate identical diagnostics"),
+    no_link: bool = (false, parse_bool, [TRACKED],
+        "compile without linking"),
 }
diff --git a/src/librustc_session/search_paths.rs b/src/librustc_session/search_paths.rs
index b15f4e8f6c1..06f408b4a8d 100644
--- a/src/librustc_session/search_paths.rs
+++ b/src/librustc_session/search_paths.rs
@@ -9,7 +9,7 @@ pub struct SearchPath {
     pub files: Vec<PathBuf>,
 }
 
-#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq)]
+#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, RustcEncodable, RustcDecodable)]
 pub enum PathKind {
     Native,
     Crate,