Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

LLVM Bitcode Linker: A self contained linker for nvptx and other targets #117458

Merged
merged 6 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
LLVM Bitcode Linker: Add as a linker known to the compiler
  • Loading branch information
Kjetil Kjeka committed Mar 11, 2024
commit 43f2055af5a0897876f25b6bdfa821dea8d5e4aa
23 changes: 19 additions & 4 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use rustc_span::symbol::Symbol;
use rustc_target::spec::crt_objects::CrtObjects;
use rustc_target::spec::LinkSelfContainedComponents;
use rustc_target::spec::LinkSelfContainedDefault;
use rustc_target::spec::LinkerFlavorCli;
use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld, PanicStrategy};
use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo};

Expand Down Expand Up @@ -1350,6 +1351,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
}
}
LinkerFlavor::Bpf => "bpf-linker",
LinkerFlavor::Llbc => "llvm-bitcode-linker",
LinkerFlavor::Ptx => "rust-ptx-linker",
}),
flavor,
Expand All @@ -1367,8 +1369,17 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {

// linker and linker flavor specified via command line have precedence over what the target
// specification specifies
let linker_flavor =
sess.opts.cg.linker_flavor.map(|flavor| sess.target.linker_flavor.with_cli_hints(flavor));
let linker_flavor = match sess.opts.cg.linker_flavor {
// The linker flavors that are non-target specific can be directly translated to LinkerFlavor
Some(LinkerFlavorCli::Llbc) => Some(LinkerFlavor::Llbc),
Some(LinkerFlavorCli::Ptx) => Some(LinkerFlavor::Ptx),
// The linker flavors that corresponds to targets needs logic that keeps the base LinkerFlavor
_ => sess
.opts
.cg
.linker_flavor
.map(|flavor| sess.target.linker_flavor.with_cli_hints(flavor)),
};
if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), linker_flavor) {
return ret;
}
Expand Down Expand Up @@ -2338,8 +2349,12 @@ fn add_order_independent_options(
});
}

if flavor == LinkerFlavor::Ptx {
// Provide the linker with fallback to internal `target-cpu`.
if flavor == LinkerFlavor::Llbc {
cmd.arg("--target");
cmd.arg(sess.target.llvm_target.as_ref());
cmd.arg("--target-cpu");
cmd.arg(&codegen_results.crate_info.target_cpu);
} else if flavor == LinkerFlavor::Ptx {
cmd.arg("--fallback-arch");
cmd.arg(&codegen_results.crate_info.target_cpu);
} else if flavor == LinkerFlavor::Bpf {
Expand Down
101 changes: 100 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ pub fn get_linker<'a>(
LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>,
LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
LinkerFlavor::Llbc => Box::new(LlbcLinker { cmd, sess }) as Box<dyn Linker>,
LinkerFlavor::Ptx => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
}
}
Expand Down Expand Up @@ -1824,7 +1825,7 @@ impl<'a> Linker for PtxLinker<'a> {
}

Lto::No => {}
};
}
}

fn output_filename(&mut self, path: &Path) {
Expand Down Expand Up @@ -1862,6 +1863,104 @@ impl<'a> Linker for PtxLinker<'a> {
fn linker_plugin_lto(&mut self) {}
}

/// The `self-contained` LLVM bitcode linker
pub struct LlbcLinker<'a> {
cmd: Command,
sess: &'a Session,
}

impl<'a> Linker for LlbcLinker<'a> {
fn cmd(&mut self) -> &mut Command {
&mut self.cmd
}

fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}

fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
panic!("external dylibs not supported")
}

fn link_staticlib_by_name(
&mut self,
_name: &str,
_verbatim: bool,
_whole_archive: bool,
_search_paths: &SearchPaths,
) {
panic!("staticlibs not supported")
}

fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
self.cmd.arg(path);
}

fn include_path(&mut self, path: &Path) {
self.cmd.arg("-L").arg(path);
}

fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
self.cmd.arg("--debug");
}

fn add_object(&mut self, path: &Path) {
self.cmd.arg(path);
}

fn optimize(&mut self) {
match self.sess.opts.optimize {
OptLevel::No => "-O0",
OptLevel::Less => "-O1",
OptLevel::Default => "-O2",
OptLevel::Aggressive => "-O3",
OptLevel::Size => "-Os",
OptLevel::SizeMin => "-Oz",
};
}

fn output_filename(&mut self, path: &Path) {
self.cmd.arg("-o").arg(path);
}

fn framework_path(&mut self, _path: &Path) {
panic!("frameworks not supported")
}

fn full_relro(&mut self) {}

fn partial_relro(&mut self) {}

fn no_relro(&mut self) {}

fn gc_sections(&mut self, _keep_metadata: bool) {}

fn no_gc_sections(&mut self) {}

fn pgo_gen(&mut self) {}

fn no_crt_objects(&mut self) {}

fn no_default_libraries(&mut self) {}

fn control_flow_guard(&mut self) {}

fn ehcont_guard(&mut self) {}

fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
match _crate_type {
CrateType::Cdylib => {
for sym in symbols {
self.cmd.arg("--export-symbol").arg(sym);
}
}
_ => (),
}
}

fn subsystem(&mut self, _subsystem: &str) {}

fn linker_plugin_lto(&mut self) {}
}

pub struct BpfLinker<'a> {
cmd: Command,
sess: &'a Session,
Expand Down
22 changes: 19 additions & 3 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ pub enum LinkerFlavor {
Bpf,
/// Linker tool for Nvidia PTX.
Ptx,
/// LLVM bitcode linker that can be used as a `self-contained` linker
Llbc,
}

/// Linker flavors available externally through command line (`-Clinker-flavor`)
Expand All @@ -141,6 +143,7 @@ pub enum LinkerFlavorCli {
EmCc,
Bpf,
Ptx,
Llbc,

// Legacy stable values
Gcc,
Expand All @@ -160,6 +163,7 @@ impl LinkerFlavorCli {
| LinkerFlavorCli::Msvc(Lld::Yes)
| LinkerFlavorCli::EmCc
| LinkerFlavorCli::Bpf
| LinkerFlavorCli::Llbc
| LinkerFlavorCli::Ptx => true,
LinkerFlavorCli::Gcc
| LinkerFlavorCli::Ld
Expand Down Expand Up @@ -219,6 +223,7 @@ impl LinkerFlavor {
LinkerFlavorCli::Msvc(lld) => LinkerFlavor::Msvc(lld),
LinkerFlavorCli::EmCc => LinkerFlavor::EmCc,
LinkerFlavorCli::Bpf => LinkerFlavor::Bpf,
LinkerFlavorCli::Llbc => LinkerFlavor::Llbc,
LinkerFlavorCli::Ptx => LinkerFlavor::Ptx,

// Below: legacy stable values
Expand Down Expand Up @@ -258,6 +263,7 @@ impl LinkerFlavor {
LinkerFlavor::Msvc(..) => LinkerFlavorCli::Msvc(Lld::No),
LinkerFlavor::EmCc => LinkerFlavorCli::Em,
LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
}
}
Expand All @@ -272,6 +278,7 @@ impl LinkerFlavor {
LinkerFlavor::Msvc(lld) => LinkerFlavorCli::Msvc(lld),
LinkerFlavor::EmCc => LinkerFlavorCli::EmCc,
LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
}
}
Expand All @@ -286,6 +293,7 @@ impl LinkerFlavor {
LinkerFlavorCli::Msvc(lld) => (Some(Cc::No), Some(lld)),
LinkerFlavorCli::EmCc => (Some(Cc::Yes), Some(Lld::Yes)),
LinkerFlavorCli::Bpf | LinkerFlavorCli::Ptx => (None, None),
LinkerFlavorCli::Llbc => (None, None),

// Below: legacy stable values
LinkerFlavorCli::Gcc => (Some(Cc::Yes), None),
Expand Down Expand Up @@ -340,7 +348,7 @@ impl LinkerFlavor {
LinkerFlavor::WasmLld(cc) => LinkerFlavor::WasmLld(cc_hint.unwrap_or(cc)),
LinkerFlavor::Unix(cc) => LinkerFlavor::Unix(cc_hint.unwrap_or(cc)),
LinkerFlavor::Msvc(lld) => LinkerFlavor::Msvc(lld_hint.unwrap_or(lld)),
LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Ptx => self,
LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc | LinkerFlavor::Ptx => self,
}
}

Expand All @@ -355,20 +363,23 @@ impl LinkerFlavor {
pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option<String> {
let compatible = |cli| {
// The CLI flavor should be compatible with the target if:
// 1. they are counterparts: they have the same principal flavor.
match (self, cli) {
// 1. they are counterparts: they have the same principal flavor.
(LinkerFlavor::Gnu(..), LinkerFlavorCli::Gnu(..))
| (LinkerFlavor::Darwin(..), LinkerFlavorCli::Darwin(..))
| (LinkerFlavor::WasmLld(..), LinkerFlavorCli::WasmLld(..))
| (LinkerFlavor::Unix(..), LinkerFlavorCli::Unix(..))
| (LinkerFlavor::Msvc(..), LinkerFlavorCli::Msvc(..))
| (LinkerFlavor::EmCc, LinkerFlavorCli::EmCc)
| (LinkerFlavor::Bpf, LinkerFlavorCli::Bpf)
| (LinkerFlavor::Llbc, LinkerFlavorCli::Llbc)
| (LinkerFlavor::Ptx, LinkerFlavorCli::Ptx) => return true,
// 2. The linker flavor is independent of target and compatible
(LinkerFlavor::Ptx, LinkerFlavorCli::Llbc) => return true,
_ => {}
}

// 2. or, the flavor is legacy and survives this roundtrip.
// 3. or, the flavor is legacy and survives this roundtrip.
cli == self.with_cli_hints(cli).to_cli()
};
(!compatible(cli)).then(|| {
Expand All @@ -387,6 +398,7 @@ impl LinkerFlavor {
| LinkerFlavor::Unix(..)
| LinkerFlavor::EmCc
| LinkerFlavor::Bpf
| LinkerFlavor::Llbc
| LinkerFlavor::Ptx => LldFlavor::Ld,
LinkerFlavor::Darwin(..) => LldFlavor::Ld64,
LinkerFlavor::WasmLld(..) => LldFlavor::Wasm,
Expand All @@ -412,6 +424,7 @@ impl LinkerFlavor {
| LinkerFlavor::Msvc(_)
| LinkerFlavor::Unix(_)
| LinkerFlavor::Bpf
| LinkerFlavor::Llbc
| LinkerFlavor::Ptx => false,
}
}
Expand All @@ -431,6 +444,7 @@ impl LinkerFlavor {
| LinkerFlavor::Msvc(_)
| LinkerFlavor::Unix(_)
| LinkerFlavor::Bpf
| LinkerFlavor::Llbc
| LinkerFlavor::Ptx => false,
}
}
Expand Down Expand Up @@ -480,6 +494,7 @@ linker_flavor_cli_impls! {
(LinkerFlavorCli::Msvc(Lld::No)) "msvc"
(LinkerFlavorCli::EmCc) "em-cc"
(LinkerFlavorCli::Bpf) "bpf"
(LinkerFlavorCli::Llbc) "llbc"
petrochenkov marked this conversation as resolved.
Show resolved Hide resolved
(LinkerFlavorCli::Ptx) "ptx"

// Legacy stable flavors
Expand Down Expand Up @@ -2205,6 +2220,7 @@ fn add_link_args_iter(
| LinkerFlavor::Unix(..)
| LinkerFlavor::EmCc
| LinkerFlavor::Bpf
| LinkerFlavor::Llbc
| LinkerFlavor::Ptx => {}
}
}
Expand Down
5 changes: 4 additions & 1 deletion compiler/rustc_target/src/spec/tests/tests_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,10 @@ impl Target {
LinkerFlavor::Msvc(..) => {
assert_matches!(flavor, LinkerFlavor::Msvc(..))
}
LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Ptx => {
LinkerFlavor::EmCc
| LinkerFlavor::Bpf
| LinkerFlavor::Ptx
| LinkerFlavor::Llbc => {
assert_eq!(flavor, self.linker_flavor)
}
}
Expand Down