Auto merge of #86911 - bjorn3:crate_info_refactor, r=petrochenkov
Refactor linker code This merges `LinkerInfo` into `CrateInfo` as there is no reason to keep them separate. `LinkerInfo::to_linker` is merged into `get_linker` as both have different logic for each linker type and `to_linker` is directly called after `get_linker`. Also contains a couple of small cleanups. See the individual commits for all changes.
This commit is contained in:
commit
b20e3ff2af
10 changed files with 169 additions and 204 deletions
|
@ -4,7 +4,6 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
use rustc_codegen_ssa::back::linker::LinkerInfo;
|
|
||||||
use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
|
use rustc_codegen_ssa::{CodegenResults, CompiledModule, CrateInfo, ModuleKind};
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
|
||||||
|
@ -296,8 +295,7 @@ pub(crate) fn run_aot(
|
||||||
allocator_module,
|
allocator_module,
|
||||||
metadata_module,
|
metadata_module,
|
||||||
metadata,
|
metadata,
|
||||||
linker_info: LinkerInfo::new(tcx, crate::target_triple(tcx.sess).to_string()),
|
crate_info: CrateInfo::new(tcx, crate::target_triple(tcx.sess).to_string()),
|
||||||
crate_info: CrateInfo::new(tcx),
|
|
||||||
},
|
},
|
||||||
work_products,
|
work_products,
|
||||||
))
|
))
|
||||||
|
|
|
@ -178,7 +178,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
|
||||||
|
|
||||||
let mut dylib_paths = Vec::new();
|
let mut dylib_paths = Vec::new();
|
||||||
|
|
||||||
let crate_info = CrateInfo::new(tcx);
|
let crate_info = CrateInfo::new(tcx, "dummy_target_cpu".to_string());
|
||||||
let formats = tcx.dependency_formats(());
|
let formats = tcx.dependency_formats(());
|
||||||
let data = &formats
|
let data = &formats
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -219,7 +219,6 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
||||||
sess,
|
sess,
|
||||||
&codegen_results,
|
&codegen_results,
|
||||||
outputs,
|
outputs,
|
||||||
&codegen_results.crate_info.local_crate_name.as_str(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -292,12 +292,7 @@ impl CodegenBackend for LlvmCodegenBackend {
|
||||||
|
|
||||||
// Run the linker on any artifacts that resulted from the LLVM run.
|
// Run the linker on any artifacts that resulted from the LLVM run.
|
||||||
// This should produce either a finished executable or library.
|
// This should produce either a finished executable or library.
|
||||||
link_binary::<LlvmArchiveBuilder<'_>>(
|
link_binary::<LlvmArchiveBuilder<'_>>(sess, &codegen_results, outputs);
|
||||||
sess,
|
|
||||||
&codegen_results,
|
|
||||||
outputs,
|
|
||||||
&codegen_results.crate_info.local_crate_name.as_str(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
crate_name: &str,
|
|
||||||
) {
|
) {
|
||||||
let _timer = sess.timer("link_binary");
|
let _timer = sess.timer("link_binary");
|
||||||
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
|
let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
|
||||||
|
@ -87,7 +86,12 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
|
||||||
.tempdir()
|
.tempdir()
|
||||||
.unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err)));
|
.unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err)));
|
||||||
let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps);
|
let path = MaybeTempDir::new(tmpdir, sess.opts.cg.save_temps);
|
||||||
let out_filename = out_filename(sess, crate_type, outputs, crate_name);
|
let out_filename = out_filename(
|
||||||
|
sess,
|
||||||
|
crate_type,
|
||||||
|
outputs,
|
||||||
|
&codegen_results.crate_info.local_crate_name.as_str(),
|
||||||
|
);
|
||||||
match crate_type {
|
match crate_type {
|
||||||
CrateType::Rlib => {
|
CrateType::Rlib => {
|
||||||
let _timer = sess.timer("link_rlib");
|
let _timer = sess.timer("link_rlib");
|
||||||
|
@ -143,97 +147,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// The third parameter is for env vars, used on windows to set up the
|
|
||||||
// path for MSVC to find its DLLs, and gcc to find its bundled
|
|
||||||
// toolchain
|
|
||||||
fn get_linker(
|
|
||||||
sess: &Session,
|
|
||||||
linker: &Path,
|
|
||||||
flavor: LinkerFlavor,
|
|
||||||
self_contained: bool,
|
|
||||||
) -> Command {
|
|
||||||
let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
|
|
||||||
|
|
||||||
// If our linker looks like a batch script on Windows then to execute this
|
|
||||||
// we'll need to spawn `cmd` explicitly. This is primarily done to handle
|
|
||||||
// emscripten where the linker is `emcc.bat` and needs to be spawned as
|
|
||||||
// `cmd /c emcc.bat ...`.
|
|
||||||
//
|
|
||||||
// This worked historically but is needed manually since #42436 (regression
|
|
||||||
// was tagged as #42791) and some more info can be found on #44443 for
|
|
||||||
// emscripten itself.
|
|
||||||
let mut cmd = match linker.to_str() {
|
|
||||||
Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
|
|
||||||
_ => match flavor {
|
|
||||||
LinkerFlavor::Lld(f) => Command::lld(linker, f),
|
|
||||||
LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => {
|
|
||||||
Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
|
|
||||||
}
|
|
||||||
_ => Command::new(linker),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// UWP apps have API restrictions enforced during Store submissions.
|
|
||||||
// To comply with the Windows App Certification Kit,
|
|
||||||
// MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
|
|
||||||
let t = &sess.target;
|
|
||||||
if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
|
|
||||||
&& t.vendor == "uwp"
|
|
||||||
{
|
|
||||||
if let Some(ref tool) = msvc_tool {
|
|
||||||
let original_path = tool.path();
|
|
||||||
if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
|
|
||||||
let arch = match t.arch.as_str() {
|
|
||||||
"x86_64" => Some("x64"),
|
|
||||||
"x86" => Some("x86"),
|
|
||||||
"aarch64" => Some("arm64"),
|
|
||||||
"arm" => Some("arm"),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
if let Some(ref a) = arch {
|
|
||||||
// FIXME: Move this to `fn linker_with_args`.
|
|
||||||
let mut arg = OsString::from("/LIBPATH:");
|
|
||||||
arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a));
|
|
||||||
cmd.arg(&arg);
|
|
||||||
} else {
|
|
||||||
warn!("arch is not supported");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn!("MSVC root path lib location not found");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
warn!("link.exe not found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The compiler's sysroot often has some bundled tools, so add it to the
|
|
||||||
// PATH for the child.
|
|
||||||
let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
|
|
||||||
let mut msvc_changed_path = false;
|
|
||||||
if sess.target.is_like_msvc {
|
|
||||||
if let Some(ref tool) = msvc_tool {
|
|
||||||
cmd.args(tool.args());
|
|
||||||
for &(ref k, ref v) in tool.env() {
|
|
||||||
if k == "PATH" {
|
|
||||||
new_path.extend(env::split_paths(v));
|
|
||||||
msvc_changed_path = true;
|
|
||||||
} else {
|
|
||||||
cmd.env(k, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !msvc_changed_path {
|
|
||||||
if let Some(path) = env::var_os("PATH") {
|
|
||||||
new_path.extend(env::split_paths(&path));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cmd.env("PATH", env::join_paths(new_path).unwrap());
|
|
||||||
|
|
||||||
cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn each_linked_rlib(
|
pub fn each_linked_rlib(
|
||||||
info: &CrateInfo,
|
info: &CrateInfo,
|
||||||
f: &mut dyn FnMut(CrateNum, &Path),
|
f: &mut dyn FnMut(CrateNum, &Path),
|
||||||
|
@ -1800,11 +1713,13 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
) -> Command {
|
) -> Command {
|
||||||
let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
|
let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
|
||||||
let base_cmd = get_linker(sess, path, flavor, crt_objects_fallback);
|
let cmd = &mut *super::linker::get_linker(
|
||||||
// FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
|
sess,
|
||||||
// to the linker args construction.
|
path,
|
||||||
assert!(base_cmd.get_args().is_empty() || sess.target.vendor == "uwp");
|
flavor,
|
||||||
let cmd = &mut *codegen_results.linker_info.to_linker(base_cmd, &sess, flavor);
|
crt_objects_fallback,
|
||||||
|
&codegen_results.crate_info.target_cpu,
|
||||||
|
);
|
||||||
let link_output_kind = link_output_kind(sess, crate_type);
|
let link_output_kind = link_output_kind(sess, crate_type);
|
||||||
|
|
||||||
// ------------ Early order-dependent options ------------
|
// ------------ Early order-dependent options ------------
|
||||||
|
@ -1814,7 +1729,11 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
|
||||||
// dynamic library.
|
// dynamic library.
|
||||||
// Must be passed before any libraries to prevent the symbols to export from being thrown away,
|
// Must be passed before any libraries to prevent the symbols to export from being thrown away,
|
||||||
// at least on some platforms (e.g. windows-gnu).
|
// at least on some platforms (e.g. windows-gnu).
|
||||||
cmd.export_symbols(tmpdir, crate_type);
|
cmd.export_symbols(
|
||||||
|
tmpdir,
|
||||||
|
crate_type,
|
||||||
|
&codegen_results.crate_info.exported_symbols[&crate_type],
|
||||||
|
);
|
||||||
|
|
||||||
// Can be used for adding custom CRT objects or overriding order-dependent options above.
|
// Can be used for adding custom CRT objects or overriding order-dependent options above.
|
||||||
// FIXME: In practice built-in target specs use this for arbitrary order-independent options,
|
// FIXME: In practice built-in target specs use this for arbitrary order-independent options,
|
||||||
|
@ -1986,10 +1905,10 @@ fn add_order_independent_options(
|
||||||
if flavor == LinkerFlavor::PtxLinker {
|
if flavor == LinkerFlavor::PtxLinker {
|
||||||
// Provide the linker with fallback to internal `target-cpu`.
|
// Provide the linker with fallback to internal `target-cpu`.
|
||||||
cmd.arg("--fallback-arch");
|
cmd.arg("--fallback-arch");
|
||||||
cmd.arg(&codegen_results.linker_info.target_cpu);
|
cmd.arg(&codegen_results.crate_info.target_cpu);
|
||||||
} else if flavor == LinkerFlavor::BpfLinker {
|
} else if flavor == LinkerFlavor::BpfLinker {
|
||||||
cmd.arg("--cpu");
|
cmd.arg("--cpu");
|
||||||
cmd.arg(&codegen_results.linker_info.target_cpu);
|
cmd.arg(&codegen_results.crate_info.target_cpu);
|
||||||
cmd.arg("--cpu-features");
|
cmd.arg("--cpu-features");
|
||||||
cmd.arg(match &sess.opts.cg.target_feature {
|
cmd.arg(match &sess.opts.cg.target_feature {
|
||||||
feat if !feat.is_empty() => feat,
|
feat if !feat.is_empty() => feat,
|
||||||
|
|
|
@ -7,19 +7,21 @@ use std::ffi::{OsStr, OsString};
|
||||||
use std::fs::{self, File};
|
use std::fs::{self, File};
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::io::{self, BufWriter};
|
use std::io::{self, BufWriter};
|
||||||
use std::mem;
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::{env, mem, str};
|
||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
|
||||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||||
use rustc_middle::middle::dependency_format::Linkage;
|
use rustc_middle::middle::dependency_format::Linkage;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_serialize::{json, Encoder};
|
use rustc_serialize::{json, Encoder};
|
||||||
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
|
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
|
||||||
|
use rustc_session::search_paths::PathKind;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
|
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
|
||||||
|
|
||||||
|
use cc::windows_registry;
|
||||||
|
|
||||||
/// Disables non-English messages from localized linkers.
|
/// Disables non-English messages from localized linkers.
|
||||||
/// Such messages may cause issues with text encoding on Windows (#35785)
|
/// Such messages may cause issues with text encoding on Windows (#35785)
|
||||||
/// and prevent inspection of linker output in case of errors, which we occasionally do.
|
/// and prevent inspection of linker output in case of errors, which we occasionally do.
|
||||||
|
@ -33,61 +35,122 @@ pub fn disable_localization(linker: &mut Command) {
|
||||||
linker.env("VSLANG", "1033");
|
linker.env("VSLANG", "1033");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For all the linkers we support, and information they might
|
// The third parameter is for env vars, used on windows to set up the
|
||||||
/// need out of the shared crate context before we get rid of it.
|
// path for MSVC to find its DLLs, and gcc to find its bundled
|
||||||
#[derive(Encodable, Decodable)]
|
// toolchain
|
||||||
pub struct LinkerInfo {
|
pub fn get_linker<'a>(
|
||||||
pub(super) target_cpu: String,
|
sess: &'a Session,
|
||||||
exports: FxHashMap<CrateType, Vec<String>>,
|
linker: &Path,
|
||||||
}
|
flavor: LinkerFlavor,
|
||||||
|
self_contained: bool,
|
||||||
|
target_cpu: &'a str,
|
||||||
|
) -> Box<dyn Linker + 'a> {
|
||||||
|
let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
|
||||||
|
|
||||||
impl LinkerInfo {
|
// If our linker looks like a batch script on Windows then to execute this
|
||||||
pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> LinkerInfo {
|
// we'll need to spawn `cmd` explicitly. This is primarily done to handle
|
||||||
LinkerInfo {
|
// emscripten where the linker is `emcc.bat` and needs to be spawned as
|
||||||
target_cpu,
|
// `cmd /c emcc.bat ...`.
|
||||||
exports: tcx
|
//
|
||||||
.sess
|
// This worked historically but is needed manually since #42436 (regression
|
||||||
.crate_types()
|
// was tagged as #42791) and some more info can be found on #44443 for
|
||||||
.iter()
|
// emscripten itself.
|
||||||
.map(|&c| (c, exported_symbols(tcx, c)))
|
let mut cmd = match linker.to_str() {
|
||||||
.collect(),
|
Some(linker) if cfg!(windows) && linker.ends_with(".bat") => Command::bat_script(linker),
|
||||||
|
_ => match flavor {
|
||||||
|
LinkerFlavor::Lld(f) => Command::lld(linker, f),
|
||||||
|
LinkerFlavor::Msvc if sess.opts.cg.linker.is_none() && sess.target.linker.is_none() => {
|
||||||
|
Command::new(msvc_tool.as_ref().map_or(linker, |t| t.path()))
|
||||||
|
}
|
||||||
|
_ => Command::new(linker),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// UWP apps have API restrictions enforced during Store submissions.
|
||||||
|
// To comply with the Windows App Certification Kit,
|
||||||
|
// MSVC needs to link with the Store versions of the runtime libraries (vcruntime, msvcrt, etc).
|
||||||
|
let t = &sess.target;
|
||||||
|
if (flavor == LinkerFlavor::Msvc || flavor == LinkerFlavor::Lld(LldFlavor::Link))
|
||||||
|
&& t.vendor == "uwp"
|
||||||
|
{
|
||||||
|
if let Some(ref tool) = msvc_tool {
|
||||||
|
let original_path = tool.path();
|
||||||
|
if let Some(ref root_lib_path) = original_path.ancestors().nth(4) {
|
||||||
|
let arch = match t.arch.as_str() {
|
||||||
|
"x86_64" => Some("x64"),
|
||||||
|
"x86" => Some("x86"),
|
||||||
|
"aarch64" => Some("arm64"),
|
||||||
|
"arm" => Some("arm"),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
if let Some(ref a) = arch {
|
||||||
|
// FIXME: Move this to `fn linker_with_args`.
|
||||||
|
let mut arg = OsString::from("/LIBPATH:");
|
||||||
|
arg.push(format!("{}\\lib\\{}\\store", root_lib_path.display(), a));
|
||||||
|
cmd.arg(&arg);
|
||||||
|
} else {
|
||||||
|
warn!("arch is not supported");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("MSVC root path lib location not found");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("link.exe not found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_linker<'a>(
|
// The compiler's sysroot often has some bundled tools, so add it to the
|
||||||
&'a self,
|
// PATH for the child.
|
||||||
cmd: Command,
|
let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
|
||||||
sess: &'a Session,
|
let mut msvc_changed_path = false;
|
||||||
flavor: LinkerFlavor,
|
if sess.target.is_like_msvc {
|
||||||
) -> Box<dyn Linker + 'a> {
|
if let Some(ref tool) = msvc_tool {
|
||||||
match flavor {
|
cmd.args(tool.args());
|
||||||
LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
|
for &(ref k, ref v) in tool.env() {
|
||||||
Box::new(MsvcLinker { cmd, sess, info: self }) as Box<dyn Linker>
|
if k == "PATH" {
|
||||||
}
|
new_path.extend(env::split_paths(v));
|
||||||
LinkerFlavor::Em => Box::new(EmLinker { cmd, sess, info: self }) as Box<dyn Linker>,
|
msvc_changed_path = true;
|
||||||
LinkerFlavor::Gcc => {
|
} else {
|
||||||
Box::new(GccLinker { cmd, sess, info: self, hinted_static: false, is_ld: false })
|
cmd.env(k, v);
|
||||||
as Box<dyn Linker>
|
}
|
||||||
}
|
|
||||||
|
|
||||||
LinkerFlavor::Lld(LldFlavor::Ld)
|
|
||||||
| LinkerFlavor::Lld(LldFlavor::Ld64)
|
|
||||||
| LinkerFlavor::Ld => {
|
|
||||||
Box::new(GccLinker { cmd, sess, info: self, hinted_static: false, is_ld: true })
|
|
||||||
as Box<dyn Linker>
|
|
||||||
}
|
|
||||||
|
|
||||||
LinkerFlavor::Lld(LldFlavor::Wasm) => {
|
|
||||||
Box::new(WasmLd::new(cmd, sess, self)) as Box<dyn Linker>
|
|
||||||
}
|
|
||||||
|
|
||||||
LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
|
|
||||||
|
|
||||||
LinkerFlavor::BpfLinker => {
|
|
||||||
Box::new(BpfLinker { cmd, sess, info: self }) as Box<dyn Linker>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !msvc_changed_path {
|
||||||
|
if let Some(path) = env::var_os("PATH") {
|
||||||
|
new_path.extend(env::split_paths(&path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmd.env("PATH", env::join_paths(new_path).unwrap());
|
||||||
|
|
||||||
|
// FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
|
||||||
|
// to the linker args construction.
|
||||||
|
assert!(cmd.get_args().is_empty() || sess.target.vendor == "uwp");
|
||||||
|
|
||||||
|
match flavor {
|
||||||
|
LinkerFlavor::Lld(LldFlavor::Link) | LinkerFlavor::Msvc => {
|
||||||
|
Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>
|
||||||
|
}
|
||||||
|
LinkerFlavor::Em => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
|
||||||
|
LinkerFlavor::Gcc => {
|
||||||
|
Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: false })
|
||||||
|
as Box<dyn Linker>
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkerFlavor::Lld(LldFlavor::Ld)
|
||||||
|
| LinkerFlavor::Lld(LldFlavor::Ld64)
|
||||||
|
| LinkerFlavor::Ld => {
|
||||||
|
Box::new(GccLinker { cmd, sess, target_cpu, hinted_static: false, is_ld: true })
|
||||||
|
as Box<dyn Linker>
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkerFlavor::Lld(LldFlavor::Wasm) => Box::new(WasmLd::new(cmd, sess)) as Box<dyn Linker>,
|
||||||
|
|
||||||
|
LinkerFlavor::PtxLinker => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
|
||||||
|
|
||||||
|
LinkerFlavor::BpfLinker => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Linker abstraction used by `back::link` to build up the command to invoke a
|
/// Linker abstraction used by `back::link` to build up the command to invoke a
|
||||||
|
@ -122,7 +185,7 @@ pub trait Linker {
|
||||||
fn debuginfo(&mut self, strip: Strip);
|
fn debuginfo(&mut self, strip: Strip);
|
||||||
fn no_crt_objects(&mut self);
|
fn no_crt_objects(&mut self);
|
||||||
fn no_default_libraries(&mut self);
|
fn no_default_libraries(&mut self);
|
||||||
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
|
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]);
|
||||||
fn subsystem(&mut self, subsystem: &str);
|
fn subsystem(&mut self, subsystem: &str);
|
||||||
fn group_start(&mut self);
|
fn group_start(&mut self);
|
||||||
fn group_end(&mut self);
|
fn group_end(&mut self);
|
||||||
|
@ -150,7 +213,7 @@ impl dyn Linker + '_ {
|
||||||
pub struct GccLinker<'a> {
|
pub struct GccLinker<'a> {
|
||||||
cmd: Command,
|
cmd: Command,
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
info: &'a LinkerInfo,
|
target_cpu: &'a str,
|
||||||
hinted_static: bool, // Keeps track of the current hinting mode.
|
hinted_static: bool, // Keeps track of the current hinting mode.
|
||||||
// Link as ld
|
// Link as ld
|
||||||
is_ld: bool,
|
is_ld: bool,
|
||||||
|
@ -225,7 +288,7 @@ impl<'a> GccLinker<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
self.linker_arg(&format!("-plugin-opt={}", opt_level));
|
self.linker_arg(&format!("-plugin-opt={}", opt_level));
|
||||||
self.linker_arg(&format!("-plugin-opt=mcpu={}", self.info.target_cpu));
|
self.linker_arg(&format!("-plugin-opt=mcpu={}", self.target_cpu));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_dylib(&mut self, out_filename: &Path) {
|
fn build_dylib(&mut self, out_filename: &Path) {
|
||||||
|
@ -554,7 +617,7 @@ impl<'a> Linker for GccLinker<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
|
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
|
||||||
// Symbol visibility in object files typically takes care of this.
|
// Symbol visibility in object files typically takes care of this.
|
||||||
if crate_type == CrateType::Executable && self.sess.target.override_export_symbols.is_none()
|
if crate_type == CrateType::Executable && self.sess.target.override_export_symbols.is_none()
|
||||||
{
|
{
|
||||||
|
@ -583,7 +646,7 @@ impl<'a> Linker for GccLinker<'a> {
|
||||||
// Write a plain, newline-separated list of symbols
|
// Write a plain, newline-separated list of symbols
|
||||||
let res: io::Result<()> = try {
|
let res: io::Result<()> = try {
|
||||||
let mut f = BufWriter::new(File::create(&path)?);
|
let mut f = BufWriter::new(File::create(&path)?);
|
||||||
for sym in self.info.exports[&crate_type].iter() {
|
for sym in symbols {
|
||||||
debug!(" _{}", sym);
|
debug!(" _{}", sym);
|
||||||
writeln!(f, "_{}", sym)?;
|
writeln!(f, "_{}", sym)?;
|
||||||
}
|
}
|
||||||
|
@ -598,7 +661,7 @@ impl<'a> Linker for GccLinker<'a> {
|
||||||
// .def file similar to MSVC one but without LIBRARY section
|
// .def file similar to MSVC one but without LIBRARY section
|
||||||
// because LD doesn't like when it's empty
|
// because LD doesn't like when it's empty
|
||||||
writeln!(f, "EXPORTS")?;
|
writeln!(f, "EXPORTS")?;
|
||||||
for symbol in self.info.exports[&crate_type].iter() {
|
for symbol in symbols {
|
||||||
debug!(" _{}", symbol);
|
debug!(" _{}", symbol);
|
||||||
writeln!(f, " {}", symbol)?;
|
writeln!(f, " {}", symbol)?;
|
||||||
}
|
}
|
||||||
|
@ -611,9 +674,9 @@ impl<'a> Linker for GccLinker<'a> {
|
||||||
let res: io::Result<()> = try {
|
let res: io::Result<()> = try {
|
||||||
let mut f = BufWriter::new(File::create(&path)?);
|
let mut f = BufWriter::new(File::create(&path)?);
|
||||||
writeln!(f, "{{")?;
|
writeln!(f, "{{")?;
|
||||||
if !self.info.exports[&crate_type].is_empty() {
|
if !symbols.is_empty() {
|
||||||
writeln!(f, " global:")?;
|
writeln!(f, " global:")?;
|
||||||
for sym in self.info.exports[&crate_type].iter() {
|
for sym in symbols {
|
||||||
debug!(" {};", sym);
|
debug!(" {};", sym);
|
||||||
writeln!(f, " {};", sym)?;
|
writeln!(f, " {};", sym)?;
|
||||||
}
|
}
|
||||||
|
@ -713,7 +776,6 @@ impl<'a> Linker for GccLinker<'a> {
|
||||||
pub struct MsvcLinker<'a> {
|
pub struct MsvcLinker<'a> {
|
||||||
cmd: Command,
|
cmd: Command,
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
info: &'a LinkerInfo,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Linker for MsvcLinker<'a> {
|
impl<'a> Linker for MsvcLinker<'a> {
|
||||||
|
@ -887,7 +949,7 @@ impl<'a> Linker for MsvcLinker<'a> {
|
||||||
// crates. Upstream rlibs may be linked statically to this dynamic library,
|
// crates. Upstream rlibs may be linked statically to this dynamic library,
|
||||||
// in which case they may continue to transitively be used and hence need
|
// in which case they may continue to transitively be used and hence need
|
||||||
// their symbols exported.
|
// their symbols exported.
|
||||||
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
|
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType, symbols: &[String]) {
|
||||||
// Symbol visibility takes care of this typically
|
// Symbol visibility takes care of this typically
|
||||||
if crate_type == CrateType::Executable {
|
if crate_type == CrateType::Executable {
|
||||||
return;
|
return;
|
||||||
|
@ -901,7 +963,7 @@ impl<'a> Linker for MsvcLinker<'a> {
|
||||||
// straight to exports.
|
// straight to exports.
|
||||||
writeln!(f, "LIBRARY")?;
|
writeln!(f, "LIBRARY")?;
|
||||||
writeln!(f, "EXPORTS")?;
|
writeln!(f, "EXPORTS")?;
|
||||||
for symbol in self.info.exports[&crate_type].iter() {
|
for symbol in symbols {
|
||||||
debug!(" _{}", symbol);
|
debug!(" _{}", symbol);
|
||||||
writeln!(f, " {}", symbol)?;
|
writeln!(f, " {}", symbol)?;
|
||||||
}
|
}
|
||||||
|
@ -954,7 +1016,6 @@ impl<'a> Linker for MsvcLinker<'a> {
|
||||||
pub struct EmLinker<'a> {
|
pub struct EmLinker<'a> {
|
||||||
cmd: Command,
|
cmd: Command,
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
info: &'a LinkerInfo,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Linker for EmLinker<'a> {
|
impl<'a> Linker for EmLinker<'a> {
|
||||||
|
@ -1066,9 +1127,7 @@ impl<'a> Linker for EmLinker<'a> {
|
||||||
self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]);
|
self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
|
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||||
let symbols = &self.info.exports[&crate_type];
|
|
||||||
|
|
||||||
debug!("EXPORTED SYMBOLS:");
|
debug!("EXPORTED SYMBOLS:");
|
||||||
|
|
||||||
self.cmd.arg("-s");
|
self.cmd.arg("-s");
|
||||||
|
@ -1110,11 +1169,10 @@ impl<'a> Linker for EmLinker<'a> {
|
||||||
pub struct WasmLd<'a> {
|
pub struct WasmLd<'a> {
|
||||||
cmd: Command,
|
cmd: Command,
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
info: &'a LinkerInfo,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WasmLd<'a> {
|
impl<'a> WasmLd<'a> {
|
||||||
fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> {
|
fn new(mut cmd: Command, sess: &'a Session) -> WasmLd<'a> {
|
||||||
// If the atomics feature is enabled for wasm then we need a whole bunch
|
// If the atomics feature is enabled for wasm then we need a whole bunch
|
||||||
// of flags:
|
// of flags:
|
||||||
//
|
//
|
||||||
|
@ -1147,7 +1205,7 @@ impl<'a> WasmLd<'a> {
|
||||||
cmd.arg("--export=__tls_align");
|
cmd.arg("--export=__tls_align");
|
||||||
cmd.arg("--export=__tls_base");
|
cmd.arg("--export=__tls_base");
|
||||||
}
|
}
|
||||||
WasmLd { cmd, sess, info }
|
WasmLd { cmd, sess }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1263,8 +1321,8 @@ impl<'a> Linker for WasmLd<'a> {
|
||||||
|
|
||||||
fn no_default_libraries(&mut self) {}
|
fn no_default_libraries(&mut self) {}
|
||||||
|
|
||||||
fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
|
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||||
for sym in self.info.exports[&crate_type].iter() {
|
for sym in symbols {
|
||||||
self.cmd.arg("--export").arg(&sym);
|
self.cmd.arg("--export").arg(&sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1287,7 +1345,7 @@ impl<'a> Linker for WasmLd<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
|
pub(crate) fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
|
||||||
if let Some(ref exports) = tcx.sess.target.override_export_symbols {
|
if let Some(ref exports) = tcx.sess.target.override_export_symbols {
|
||||||
return exports.clone();
|
return exports.clone();
|
||||||
}
|
}
|
||||||
|
@ -1416,7 +1474,7 @@ impl<'a> Linker for PtxLinker<'a> {
|
||||||
|
|
||||||
fn control_flow_guard(&mut self) {}
|
fn control_flow_guard(&mut self) {}
|
||||||
|
|
||||||
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {}
|
fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, _symbols: &[String]) {}
|
||||||
|
|
||||||
fn subsystem(&mut self, _subsystem: &str) {}
|
fn subsystem(&mut self, _subsystem: &str) {}
|
||||||
|
|
||||||
|
@ -1430,7 +1488,6 @@ impl<'a> Linker for PtxLinker<'a> {
|
||||||
pub struct BpfLinker<'a> {
|
pub struct BpfLinker<'a> {
|
||||||
cmd: Command,
|
cmd: Command,
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
info: &'a LinkerInfo,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Linker for BpfLinker<'a> {
|
impl<'a> Linker for BpfLinker<'a> {
|
||||||
|
@ -1517,11 +1574,11 @@ impl<'a> Linker for BpfLinker<'a> {
|
||||||
|
|
||||||
fn control_flow_guard(&mut self) {}
|
fn control_flow_guard(&mut self) {}
|
||||||
|
|
||||||
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
|
fn export_symbols(&mut self, tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
|
||||||
let path = tmpdir.join("symbols");
|
let path = tmpdir.join("symbols");
|
||||||
let res: io::Result<()> = try {
|
let res: io::Result<()> = try {
|
||||||
let mut f = BufWriter::new(File::create(&path)?);
|
let mut f = BufWriter::new(File::create(&path)?);
|
||||||
for sym in self.info.exports[&crate_type].iter() {
|
for sym in symbols {
|
||||||
writeln!(f, "{}", sym)?;
|
writeln!(f, "{}", sym)?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use super::link::{self, ensure_removed};
|
use super::link::{self, ensure_removed};
|
||||||
use super::linker::LinkerInfo;
|
|
||||||
use super::lto::{self, SerializedModule};
|
use super::lto::{self, SerializedModule};
|
||||||
use super::symbol_export::symbol_name_for_instance_in_crate;
|
use super::symbol_export::symbol_name_for_instance_in_crate;
|
||||||
|
|
||||||
|
@ -430,8 +429,7 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
|
||||||
let no_builtins = tcx.sess.contains_name(crate_attrs, sym::no_builtins);
|
let no_builtins = tcx.sess.contains_name(crate_attrs, sym::no_builtins);
|
||||||
let is_compiler_builtins = tcx.sess.contains_name(crate_attrs, sym::compiler_builtins);
|
let is_compiler_builtins = tcx.sess.contains_name(crate_attrs, sym::compiler_builtins);
|
||||||
|
|
||||||
let linker_info = LinkerInfo::new(tcx, target_cpu);
|
let crate_info = CrateInfo::new(tcx, target_cpu);
|
||||||
let crate_info = CrateInfo::new(tcx);
|
|
||||||
|
|
||||||
let regular_config =
|
let regular_config =
|
||||||
ModuleConfig::new(ModuleKind::Regular, sess, no_builtins, is_compiler_builtins);
|
ModuleConfig::new(ModuleKind::Regular, sess, no_builtins, is_compiler_builtins);
|
||||||
|
@ -461,7 +459,6 @@ pub fn start_async_codegen<B: ExtraBackendMethods>(
|
||||||
OngoingCodegen {
|
OngoingCodegen {
|
||||||
backend,
|
backend,
|
||||||
metadata,
|
metadata,
|
||||||
linker_info,
|
|
||||||
crate_info,
|
crate_info,
|
||||||
|
|
||||||
coordinator_send,
|
coordinator_send,
|
||||||
|
@ -1799,7 +1796,6 @@ impl SharedEmitterMain {
|
||||||
pub struct OngoingCodegen<B: ExtraBackendMethods> {
|
pub struct OngoingCodegen<B: ExtraBackendMethods> {
|
||||||
pub backend: B,
|
pub backend: B,
|
||||||
pub metadata: EncodedMetadata,
|
pub metadata: EncodedMetadata,
|
||||||
pub linker_info: LinkerInfo,
|
|
||||||
pub crate_info: CrateInfo,
|
pub crate_info: CrateInfo,
|
||||||
pub coordinator_send: Sender<Box<dyn Any + Send>>,
|
pub coordinator_send: Sender<Box<dyn Any + Send>>,
|
||||||
pub codegen_worker_receive: Receiver<Message<B>>,
|
pub codegen_worker_receive: Receiver<Message<B>>,
|
||||||
|
@ -1842,7 +1838,6 @@ impl<B: ExtraBackendMethods> OngoingCodegen<B> {
|
||||||
(
|
(
|
||||||
CodegenResults {
|
CodegenResults {
|
||||||
metadata: self.metadata,
|
metadata: self.metadata,
|
||||||
linker_info: self.linker_info,
|
|
||||||
crate_info: self.crate_info,
|
crate_info: self.crate_info,
|
||||||
|
|
||||||
modules: compiled_modules.modules,
|
modules: compiled_modules.modules,
|
||||||
|
|
|
@ -754,7 +754,13 @@ impl<B: ExtraBackendMethods> Drop for AbortCodegenOnDrop<B> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CrateInfo {
|
impl CrateInfo {
|
||||||
pub fn new(tcx: TyCtxt<'_>) -> CrateInfo {
|
pub fn new(tcx: TyCtxt<'_>, target_cpu: String) -> CrateInfo {
|
||||||
|
let exported_symbols = tcx
|
||||||
|
.sess
|
||||||
|
.crate_types()
|
||||||
|
.iter()
|
||||||
|
.map(|&c| (c, crate::back::linker::exported_symbols(tcx, c)))
|
||||||
|
.collect();
|
||||||
let local_crate_name = tcx.crate_name(LOCAL_CRATE);
|
let local_crate_name = tcx.crate_name(LOCAL_CRATE);
|
||||||
let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
|
let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
|
||||||
let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
|
let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
|
||||||
|
@ -770,8 +776,9 @@ impl CrateInfo {
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut info = CrateInfo {
|
let mut info = CrateInfo {
|
||||||
|
target_cpu,
|
||||||
|
exported_symbols,
|
||||||
local_crate_name,
|
local_crate_name,
|
||||||
panic_runtime: None,
|
|
||||||
compiler_builtins: None,
|
compiler_builtins: None,
|
||||||
profiler_runtime: None,
|
profiler_runtime: None,
|
||||||
is_no_builtins: Default::default(),
|
is_no_builtins: Default::default(),
|
||||||
|
@ -800,9 +807,6 @@ impl CrateInfo {
|
||||||
.insert(cnum, tcx.native_libraries(cnum).iter().map(Into::into).collect());
|
.insert(cnum, tcx.native_libraries(cnum).iter().map(Into::into).collect());
|
||||||
info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
|
info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
|
||||||
info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
|
info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
|
||||||
if tcx.is_panic_runtime(cnum) {
|
|
||||||
info.panic_runtime = Some(cnum);
|
|
||||||
}
|
|
||||||
if tcx.is_compiler_builtins(cnum) {
|
if tcx.is_compiler_builtins(cnum) {
|
||||||
info.compiler_builtins = Some(cnum);
|
info.compiler_builtins = Some(cnum);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ use rustc_middle::dep_graph::WorkProduct;
|
||||||
use rustc_middle::middle::cstore::{self, CrateSource};
|
use rustc_middle::middle::cstore::{self, CrateSource};
|
||||||
use rustc_middle::middle::dependency_format::Dependencies;
|
use rustc_middle::middle::dependency_format::Dependencies;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_session::config::{OutputFilenames, OutputType, RUST_CGU_EXT};
|
use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
|
||||||
use rustc_session::utils::NativeLibKind;
|
use rustc_session::utils::NativeLibKind;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
@ -135,8 +135,9 @@ impl From<&cstore::NativeLib> for NativeLib {
|
||||||
/// and the corresponding properties without referencing information outside of a `CrateInfo`.
|
/// and the corresponding properties without referencing information outside of a `CrateInfo`.
|
||||||
#[derive(Debug, Encodable, Decodable)]
|
#[derive(Debug, Encodable, Decodable)]
|
||||||
pub struct CrateInfo {
|
pub struct CrateInfo {
|
||||||
|
pub target_cpu: String,
|
||||||
|
pub exported_symbols: FxHashMap<CrateType, Vec<String>>,
|
||||||
pub local_crate_name: Symbol,
|
pub local_crate_name: Symbol,
|
||||||
pub panic_runtime: Option<CrateNum>,
|
|
||||||
pub compiler_builtins: Option<CrateNum>,
|
pub compiler_builtins: Option<CrateNum>,
|
||||||
pub profiler_runtime: Option<CrateNum>,
|
pub profiler_runtime: Option<CrateNum>,
|
||||||
pub is_no_builtins: FxHashSet<CrateNum>,
|
pub is_no_builtins: FxHashSet<CrateNum>,
|
||||||
|
@ -157,7 +158,6 @@ pub struct CodegenResults {
|
||||||
pub allocator_module: Option<CompiledModule>,
|
pub allocator_module: Option<CompiledModule>,
|
||||||
pub metadata_module: Option<CompiledModule>,
|
pub metadata_module: Option<CompiledModule>,
|
||||||
pub metadata: rustc_middle::middle::cstore::EncodedMetadata,
|
pub metadata: rustc_middle::middle::cstore::EncodedMetadata,
|
||||||
pub linker_info: back::linker::LinkerInfo,
|
|
||||||
pub crate_info: CrateInfo,
|
pub crate_info: CrateInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@ extern crate rustc_span;
|
||||||
extern crate rustc_symbol_mangling;
|
extern crate rustc_symbol_mangling;
|
||||||
extern crate rustc_target;
|
extern crate rustc_target;
|
||||||
|
|
||||||
use rustc_codegen_ssa::back::linker::LinkerInfo;
|
|
||||||
use rustc_codegen_ssa::traits::CodegenBackend;
|
use rustc_codegen_ssa::traits::CodegenBackend;
|
||||||
use rustc_codegen_ssa::{CodegenResults, CrateInfo};
|
use rustc_codegen_ssa::{CodegenResults, CrateInfo};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
@ -38,8 +37,7 @@ impl CodegenBackend for TheBackend {
|
||||||
allocator_module: None,
|
allocator_module: None,
|
||||||
metadata_module: None,
|
metadata_module: None,
|
||||||
metadata,
|
metadata,
|
||||||
linker_info: LinkerInfo::new(tcx, "fake_target_cpu".to_string()),
|
crate_info: CrateInfo::new(tcx, "fake_target_cpu".to_string()),
|
||||||
crate_info: CrateInfo::new(tcx),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue