Skip to content

Commit

Permalink
codegen(feat): Allow forced use of platform linker.
Browse files Browse the repository at this point in the history
bench(feat): Allow forced use of platform linker in benchmarks.
  • Loading branch information
c272 committed May 9, 2024
1 parent 273e5df commit cca6a75
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 10 deletions.
6 changes: 6 additions & 0 deletions crates/bench/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ pub struct Cli {
#[arg(short = 'C', long, default_value_t = 3)]
pub cobc_opt_level: u8,

/// Whether to force usage of the platform linker over other available
/// linkers when compiling with Cobalt.
#[arg(long, short = 'f', action)]
pub force_platform_linker: bool,

/// Whether to disable generation of hardware security instructions by
/// Cobalt when generating benchmarking binaries.
#[arg(long, short = 'h', action)]
Expand Down Expand Up @@ -215,6 +220,7 @@ impl TryInto<Cfg> for Cli {
compiler: cobalt_bin,
cobalt_opt_level: opt_level,
cobc_opt_level: self.cobc_opt_level,
cobc_force_platform_linker: self.force_platform_linker,
disable_hw_security: self.disable_hw_security,
run_comparative: self.run_comparative,
build_only: self.build_only,
Expand Down
8 changes: 7 additions & 1 deletion crates/bench/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ pub(crate) struct Cfg {
/// The optimisation level to run `cobc` at when compiling.
pub cobc_opt_level: u8,

/// Whether to force use of the platform linker when using `cobc`.
pub cobc_force_platform_linker: bool,

/// Whether to disable generating hardware security instructions
/// when compiling sources with Cobalt.
pub disable_hw_security: bool,
Expand Down Expand Up @@ -90,6 +93,9 @@ fn run_cobalt(cfg: &Cfg, benchmark: &Benchmark) -> Result<BenchmarkResult> {
.args(["--opt-level", &cfg.cobalt_opt_level])
.args(["--output-dir", cfg.output_dir.to_str().unwrap()])
.args(["--output-name", BENCH_BIN_NAME]);
if cfg.cobc_force_platform_linker {
cobalt.arg("--prefer-platform-linker");
}
if cfg.disable_hw_security {
cobalt.arg("--disable-security-features");
}
Expand Down Expand Up @@ -167,7 +173,7 @@ fn run_cobc(cfg: &Cfg, benchmark: &Benchmark) -> Result<BenchmarkResult> {
} else {
(None, None)
};

Ok(BenchmarkResult {
compile_time_total: elapsed,
compile_time_avg: elapsed / 100,
Expand Down
4 changes: 4 additions & 0 deletions crates/compiler/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ pub struct BuildCommand {
#[arg(short = 'O', long, value_parser = clap::builder::PossibleValuesParser::new(&["none", "speed", "speed_and_size"]))]
pub opt_level: Option<String>,

/// Actively selects the platform linker over other available linkers.
#[arg(short = 'p', long, action)]
pub prefer_platform_linker: bool,

/// Disables the generation of instructions utilising hardware security
/// features within output binaries (e.g. PAC/BTI on aarch64).
#[arg(long, action)]
Expand Down
4 changes: 4 additions & 0 deletions crates/compiler/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ pub(crate) struct BuildConfig {
/// The output linked executable file for this build.
pub out_file: PathBuf,

/// Whether to use the platform linker over all others.
pub use_platform_linker: bool,

/// Whether to generate code with security features enabled.
pub gen_security_features: bool,

Expand Down Expand Up @@ -82,6 +85,7 @@ impl TryFrom<BuildCommand> for BuildConfig {
input_file: cli.input.clone(),
out_dir,
out_file,
use_platform_linker: cli.prefer_platform_linker,
gen_security_features: !cli.disable_security_features,
opt_level,
#[cfg(debug_assertions)]
Expand Down
2 changes: 1 addition & 1 deletion crates/compiler/src/linker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl<'cfg> Linker<'cfg> {
Ok(Linker {
cfg,
user_objects: Vec::new(),
platform_config: PlatformConfig::new()?,
platform_config: PlatformConfig::new(cfg)?,
})
}

Expand Down
23 changes: 15 additions & 8 deletions crates/compiler/src/linker/platform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use std::process::Command;

use miette::Result;

use crate::config::BuildConfig;

/// Platform-specific linker configuration options.
/// Typically auto-detected from the host machine.
pub(super) struct PlatformConfig {
Expand Down Expand Up @@ -42,11 +44,11 @@ impl LinkerType {

impl PlatformConfig {
/// Auto-detects the platform linker configuration from the host machine's setup.
pub(super) fn new() -> Result<Self> {
pub(super) fn new(cfg: &BuildConfig) -> Result<Self> {
if env::consts::ARCH == "x86_64" && env::consts::OS == "linux" {
Self::detect_linux_x64()
Self::detect_linux_x64(cfg)
} else if env::consts::ARCH == "aarch64" && env::consts::OS == "linux" {
Self::detect_linux_aarch64()
Self::detect_linux_aarch64(cfg)
} else {
miette::bail!(
"Unsupported platform/architecture ({}, {}) for linker.",
Expand All @@ -73,7 +75,7 @@ impl PlatformConfig {
}

/// Detects the linker configuration for an x86_64 Linux host.
fn detect_linux_x64() -> Result<Self> {
fn detect_linux_x64(cfg: &BuildConfig) -> Result<Self> {
// Sanity check that the crt, loader exist.
let crt = PathBuf::from("/usr/lib/x86_64-linux-gnu/crt1.o");
let loader = PathBuf::from("/lib64/ld-linux-x86-64.so.2");
Expand All @@ -91,15 +93,15 @@ impl PlatformConfig {
}

Ok(PlatformConfig {
linker_type: Self::detect_best_linker(),
linker_type: Self::detect_best_linker(cfg),
crt1_o: crt,
dyn_linker: Some(loader),
lib_paths: Vec::new(),
})
}

/// Detects the linker configuration for an aarch64 Linux host.
fn detect_linux_aarch64() -> Result<Self> {
fn detect_linux_aarch64(cfg: &BuildConfig) -> Result<Self> {
// Sanity check that the crt, loader exist.
let crt = PathBuf::from("/usr/lib64/crt1.o");
let loader = PathBuf::from("/usr/lib/ld-linux-aarch64.so.1");
Expand All @@ -117,15 +119,20 @@ impl PlatformConfig {
}

Ok(PlatformConfig {
linker_type: Self::detect_best_linker(),
linker_type: Self::detect_best_linker(cfg),
crt1_o: crt,
dyn_linker: Some(loader),
lib_paths: Vec::new(),
})
}

/// Detects the best linker for use on the host system.
fn detect_best_linker() -> LinkerType {
fn detect_best_linker(cfg: &BuildConfig) -> LinkerType {
// If we need to always prefer the platform linker, we're done.
if cfg.use_platform_linker {
return LinkerType::GnuLd;
}

// If `mold` is present, use that instead for increased performance.
if Command::new("mold").spawn().is_ok() {
LinkerType::Mold
Expand Down
1 change: 1 addition & 0 deletions crates/compiler/src/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ impl CommonTestRunner {
input_file: PathBuf::from_str(&self.name).unwrap(),
out_dir: out_dir.clone(),
out_file,
use_platform_linker: false,
gen_security_features: true,
opt_level: "none".into(),
output_ast: false,
Expand Down

0 comments on commit cca6a75

Please sign in to comment.