Skip to content

Commit aad22f2

Browse files
authored
Rollup merge of rust-lang#67195 - 0dvictor:nolink, r=tmandry
[experiment] 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. Part of Issue rust-lang#64191
2 parents ae66171 + be86fb3 commit aad22f2

File tree

11 files changed

+64
-13
lines changed

11 files changed

+64
-13
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3428,6 +3428,7 @@ dependencies = [
34283428
"rustc_session",
34293429
"rustc_span",
34303430
"rustc_target",
3431+
"serialize",
34313432
"smallvec 1.0.0",
34323433
"syntax",
34333434
]

src/librustc/middle/cstore.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub use rustc_session::utils::NativeLibraryKind;
2727

2828
/// Where a crate came from on the local filesystem. One of these three options
2929
/// must be non-None.
30-
#[derive(PartialEq, Clone, Debug, HashStable)]
30+
#[derive(PartialEq, Clone, Debug, HashStable, RustcEncodable, RustcDecodable)]
3131
pub struct CrateSource {
3232
pub dylib: Option<(PathBuf, PathKind)>,
3333
pub rlib: Option<(PathBuf, PathKind)>,
@@ -75,7 +75,7 @@ impl DepKind {
7575
}
7676
}
7777

78-
#[derive(PartialEq, Clone, Debug)]
78+
#[derive(PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
7979
pub enum LibSource {
8080
Some(PathBuf),
8181
MetadataOnly,
@@ -160,6 +160,7 @@ pub enum ExternCrateSource {
160160
Path,
161161
}
162162

163+
#[derive(RustcEncodable, RustcDecodable)]
163164
pub struct EncodedMetadata {
164165
pub raw_data: Vec<u8>,
165166
}

src/librustc/middle/dependency_format.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub type DependencyList = Vec<Linkage>;
1919
/// This is local to the tcx, and is generally relevant to one session.
2020
pub type Dependencies = Vec<(config::CrateType, DependencyList)>;
2121

22-
#[derive(Copy, Clone, PartialEq, Debug, HashStable)]
22+
#[derive(Copy, Clone, PartialEq, Debug, HashStable, RustcEncodable, RustcDecodable)]
2323
pub enum Linkage {
2424
NotLinked,
2525
IncludedFromDylib,

src/librustc_codegen_llvm/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ rustc_incremental = { path = "../librustc_incremental" }
2828
rustc_index = { path = "../librustc_index" }
2929
rustc_llvm = { path = "../librustc_llvm" }
3030
rustc_session = { path = "../librustc_session" }
31+
rustc_serialize = { path = "../libserialize", package = "serialize" }
3132
rustc_target = { path = "../librustc_target" }
3233
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
3334
syntax = { path = "../libsyntax" }

src/librustc_codegen_llvm/lib.rs

+14
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use rustc_codegen_ssa::CompiledModule;
3333
use rustc_errors::{FatalError, Handler};
3434
use std::any::Any;
3535
use std::ffi::CStr;
36+
use std::fs;
3637
use std::sync::Arc;
3738
use syntax::expand::allocator::AllocatorKind;
3839

@@ -44,6 +45,7 @@ use rustc::ty::{self, TyCtxt};
4445
use rustc::util::common::ErrorReported;
4546
use rustc_codegen_ssa::ModuleCodegen;
4647
use rustc_codegen_utils::codegen_backend::CodegenBackend;
48+
use rustc_serialize::json;
4749

4850
mod back {
4951
pub mod archive;
@@ -298,6 +300,18 @@ impl CodegenBackend for LlvmCodegenBackend {
298300
return Ok(());
299301
}
300302

303+
if sess.opts.debugging_opts.no_link {
304+
// FIXME: use a binary format to encode the `.rlink` file
305+
let rlink_data = json::encode(&codegen_results).map_err(|err| {
306+
sess.fatal(&format!("failed to encode rlink: {}", err));
307+
})?;
308+
let rlink_file = outputs.with_extension("rlink");
309+
fs::write(&rlink_file, rlink_data).map_err(|err| {
310+
sess.fatal(&format!("failed to write file {}: {}", rlink_file.display(), err));
311+
})?;
312+
return Ok(());
313+
}
314+
301315
// Run the linker on any artifacts that resulted from the LLVM run.
302316
// This should produce either a finished executable or library.
303317
sess.time("link_crate", || {

src/librustc_codegen_ssa/back/linker.rs

+1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc_target::spec::{LinkerFlavor, LldFlavor};
2020

2121
/// For all the linkers we support, and information they might
2222
/// need out of the shared crate context before we get rid of it.
23+
#[derive(RustcEncodable, RustcDecodable)]
2324
pub struct LinkerInfo {
2425
exports: FxHashMap<CrateType, Vec<String>>,
2526
}

src/librustc_codegen_ssa/lib.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ impl<M> ModuleCodegen<M> {
8787
}
8888
}
8989

90-
#[derive(Debug)]
90+
#[derive(Debug, RustcEncodable, RustcDecodable)]
9191
pub struct CompiledModule {
9292
pub name: String,
9393
pub kind: ModuleKind,
@@ -101,7 +101,7 @@ pub struct CachedModuleCodegen {
101101
pub source: WorkProduct,
102102
}
103103

104-
#[derive(Copy, Clone, Debug, PartialEq)]
104+
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
105105
pub enum ModuleKind {
106106
Regular,
107107
Metadata,
@@ -117,7 +117,13 @@ bitflags::bitflags! {
117117
}
118118

119119
/// Misc info we load from metadata to persist beyond the tcx.
120-
#[derive(Debug)]
120+
/// Note: though `CrateNum` is only meaningful within the same tcx, information within `CrateInfo`
121+
/// is self-contained. `CrateNum` can be viewed as a unique identifier within a `CrateInfo`, where
122+
/// `used_crate_source` contains all `CrateSource` of the dependents, and maintains a mapping from
123+
/// identifiers (`CrateNum`) to `CrateSource`. The other fields map `CrateNum` to the crate's own
124+
/// additional properties, so that effectively we can retrieve each dependent crate's `CrateSource`
125+
/// and the corresponding properties without referencing information outside of a `CrateInfo`.
126+
#[derive(Debug, RustcEncodable, RustcDecodable)]
121127
pub struct CrateInfo {
122128
pub panic_runtime: Option<CrateNum>,
123129
pub compiler_builtins: Option<CrateNum>,
@@ -135,6 +141,7 @@ pub struct CrateInfo {
135141
pub dependency_formats: Lrc<Dependencies>,
136142
}
137143

144+
#[derive(RustcEncodable, RustcDecodable)]
138145
pub struct CodegenResults {
139146
pub crate_name: Symbol,
140147
pub modules: Vec<CompiledModule>,

src/librustc_hir/def_id.rs

+29-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use rustc_data_structures::AtomicRef;
22
use rustc_index::vec::Idx;
3+
use rustc_serialize::{Decoder, Encoder};
34
use std::fmt;
4-
use std::u32;
5+
use std::{u32, u64};
56

67
rustc_index::newtype_index! {
78
pub struct CrateId {
@@ -86,8 +87,18 @@ impl fmt::Display for CrateNum {
8687
}
8788
}
8889

89-
impl rustc_serialize::UseSpecializedEncodable for CrateNum {}
90-
impl rustc_serialize::UseSpecializedDecodable for CrateNum {}
90+
/// As a local identifier, a `CrateNum` is only meaningful within its context, e.g. within a tcx.
91+
/// Therefore, make sure to include the context when encode a `CrateNum`.
92+
impl rustc_serialize::UseSpecializedEncodable for CrateNum {
93+
fn default_encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
94+
e.emit_u32(self.as_u32())
95+
}
96+
}
97+
impl rustc_serialize::UseSpecializedDecodable for CrateNum {
98+
fn default_decode<D: Decoder>(d: &mut D) -> Result<CrateNum, D::Error> {
99+
Ok(CrateNum::from_u32(d.read_u32()?))
100+
}
101+
}
91102

92103
rustc_index::newtype_index! {
93104
/// A DefIndex is an index into the hir-map for a crate, identifying a
@@ -135,8 +146,21 @@ impl DefId {
135146
}
136147
}
137148

138-
impl rustc_serialize::UseSpecializedEncodable for DefId {}
139-
impl rustc_serialize::UseSpecializedDecodable for DefId {}
149+
impl rustc_serialize::UseSpecializedEncodable for DefId {
150+
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
151+
let krate = u64::from(self.krate.as_u32());
152+
let index = u64::from(self.index.as_u32());
153+
s.emit_u64((krate << 32) | index)
154+
}
155+
}
156+
impl rustc_serialize::UseSpecializedDecodable for DefId {
157+
fn default_decode<D: Decoder>(d: &mut D) -> Result<DefId, D::Error> {
158+
let def_id = d.read_u64()?;
159+
let krate = CrateNum::from_u32((def_id >> 32) as u32);
160+
let index = DefIndex::from_u32((def_id & 0xffffffff) as u32);
161+
Ok(DefId { krate, index })
162+
}
163+
}
140164

141165
pub fn default_def_id_debug(def_id: DefId, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142166
f.debug_struct("DefId").field("krate", &def_id.krate).field("index", &def_id.index).finish()

src/librustc_session/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ pub enum EntryFnType {
619619

620620
impl_stable_hash_via_hash!(EntryFnType);
621621

622-
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
622+
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, RustcEncodable, RustcDecodable)]
623623
pub enum CrateType {
624624
Executable,
625625
Dylib,

src/librustc_session/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -950,4 +950,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
950950
(such as entering an empty infinite loop) by inserting llvm.sideeffect"),
951951
deduplicate_diagnostics: Option<bool> = (None, parse_opt_bool, [UNTRACKED],
952952
"deduplicate identical diagnostics"),
953+
no_link: bool = (false, parse_bool, [TRACKED],
954+
"compile without linking"),
953955
}

src/librustc_session/search_paths.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub struct SearchPath {
99
pub files: Vec<PathBuf>,
1010
}
1111

12-
#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq)]
12+
#[derive(PartialEq, Clone, Copy, Debug, Hash, Eq, RustcEncodable, RustcDecodable)]
1313
pub enum PathKind {
1414
Native,
1515
Crate,

0 commit comments

Comments
 (0)