Skip to content

[experiment] Add -Z no-link flag #67195

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 1 commit into from
Jan 23, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -3428,6 +3428,7 @@ dependencies = [
"rustc_session",
"rustc_span",
"rustc_target",
"serialize",
"smallvec 1.0.0",
"syntax",
]
5 changes: 3 additions & 2 deletions src/librustc/middle/cstore.rs
Original file line number Diff line number Diff line change
@@ -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)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to save this in a binary file rather than escaped binary in a json string.

That said, I'm okay with doing this later, especially since this is an experimental feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agreed, a binary file is definitely the proper way. I chose JSON in this PR purely because I don't want the file format details hold the feature, especially the proposed approach has not been reviewed yet.

pub struct EncodedMetadata {
pub raw_data: Vec<u8>,
}
2 changes: 1 addition & 1 deletion src/librustc/middle/dependency_format.rs
Original file line number Diff line number Diff line change
@@ -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,
1 change: 1 addition & 0 deletions src/librustc_codegen_llvm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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" }
14 changes: 14 additions & 0 deletions src/librustc_codegen_llvm/lib.rs
Original file line number Diff line number Diff line change
@@ -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(());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed that finalize_session_directory is never called in this case, which means that incremental compilation won't work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should it have been called for Exe and Metadata output types, too?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current condition says return if neither exe, nor metadata is emitted.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just realized that codegen_backend.join_codegen_and_link needs to be called to actually emit all object files. Maybe split rename it to join_codegen and return CodegenResults from it, leaving the linker part to rustc_driver?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion. In fact, I think it is a good refactoring even without this -Z no-link change.

}

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", || {
1 change: 1 addition & 0 deletions src/librustc_codegen_ssa/back/linker.rs
Original file line number Diff line number Diff line change
@@ -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>>,
}
14 changes: 11 additions & 3 deletions src/librustc_codegen_ssa/lib.rs
Original file line number Diff line number Diff line change
@@ -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>,
34 changes: 29 additions & 5 deletions src/librustc_hir/def_id.rs
Original file line number Diff line number Diff line change
@@ -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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we decided to stick with this approach (#67516 (comment)), we may want to add a comment (here or on CrateNum) saying which conditions have to hold when using this.

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()
2 changes: 1 addition & 1 deletion src/librustc_session/config.rs
Original file line number Diff line number Diff line change
@@ -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,
2 changes: 2 additions & 0 deletions src/librustc_session/options.rs
Original file line number Diff line number Diff line change
@@ -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"),
}
2 changes: 1 addition & 1 deletion src/librustc_session/search_paths.rs
Original file line number Diff line number Diff line change
@@ -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,