Skip to content

Commit c338170

Browse files
committed
Add -Z small-data-threshold
This flag allows specifying the threshold size above which LLVM should not consider placing small objects in a .sdata or .sbss section. Support is indicated in the target options via the small-data-threshold-support, which can be either via an LLVM argument or an LLVM module flag.
1 parent c2f74c3 commit c338170

File tree

55 files changed

+467
-55
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+467
-55
lines changed

compiler/rustc_codegen_llvm/src/context.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use rustc_span::source_map::Spanned;
2727
use rustc_span::{Span, DUMMY_SP};
2828
use rustc_target::abi::call::FnAbi;
2929
use rustc_target::abi::{HasDataLayout, TargetDataLayout, VariantIdx};
30-
use rustc_target::spec::{HasTargetSpec, RelocModel, Target, TlsModel};
30+
use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel};
3131
use smallvec::SmallVec;
3232

3333
use crate::back::write::to_llvm_code_model;
@@ -387,6 +387,26 @@ pub(crate) unsafe fn create_module<'ll>(
387387
}
388388
}
389389

390+
match (
391+
sess.opts.unstable_opts.small_data_threshold,
392+
&sess.target.options.small_data_threshold_support,
393+
) {
394+
// Set up the small-data optimization limit for architectures that use
395+
// an LLVM module flag to control this.
396+
(Some(threshold), SmallDataThresholdSupport::LlvmModuleFlag(flag)) => {
397+
let flag = format!("{flag}\0");
398+
unsafe {
399+
llvm::LLVMRustAddModuleFlagU32(
400+
llmod,
401+
llvm::LLVMModFlagBehavior::Error,
402+
flag.as_str().as_ptr().cast(),
403+
threshold as u32,
404+
)
405+
}
406+
}
407+
_ => (),
408+
};
409+
390410
// Insert `llvm.ident` metadata.
391411
//
392412
// On the wasm targets it will get hooked up to the "producer" sections

compiler/rustc_codegen_llvm/src/llvm_util.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_middle::bug;
1414
use rustc_session::config::{PrintKind, PrintRequest};
1515
use rustc_session::Session;
1616
use rustc_span::symbol::Symbol;
17-
use rustc_target::spec::{MergeFunctions, PanicStrategy};
17+
use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
1818
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
1919

2020
use crate::back::write::create_informational_target_machine;
@@ -125,6 +125,18 @@ unsafe fn configure_llvm(sess: &Session) {
125125
for arg in sess_args {
126126
add(&(*arg), true);
127127
}
128+
129+
match (
130+
sess.opts.unstable_opts.small_data_threshold,
131+
&sess.target.options.small_data_threshold_support,
132+
) {
133+
// Set up the small-data optimization limit for architectures that use
134+
// an LLVM argument to control this.
135+
(Some(threshold), SmallDataThresholdSupport::LlvmArg(arg)) => {
136+
add(&format!("--{arg}={threshold}"), false)
137+
}
138+
_ => (),
139+
};
128140
}
129141

130142
if sess.opts.unstable_opts.llvm_time_trace {

compiler/rustc_interface/src/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,7 @@ fn test_unstable_options_tracking_hash() {
847847
tracked!(share_generics, Some(true));
848848
tracked!(show_span, Some(String::from("abc")));
849849
tracked!(simulate_remapped_rust_src_base, Some(PathBuf::from("/rustc/abc")));
850+
tracked!(small_data_threshold, Some(16));
850851
tracked!(split_lto_unit, Some(true));
851852
tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1));
852853
tracked!(stack_protector, StackProtector::All);

compiler/rustc_session/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ session_split_lto_unit_requires_lto = `-Zsplit-lto-unit` requires `-Clto`, `-Clt
113113
114114
session_target_requires_unwind_tables = target requires unwind tables, they cannot be disabled with `-C force-unwind-tables=no`
115115
116+
session_target_small_data_threshold_not_supported = `-Z small-data-threshold` is not supported for target {$target_triple} and will be ignored
117+
116118
session_target_stack_protector_not_supported = `-Z stack-protector={$stack_protector}` is not supported for target {$target_triple} and will be ignored
117119
118120
session_unleashed_feature_help_named = skipping check for `{$gate}` feature

compiler/rustc_session/src/errors.rs

+6
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,12 @@ pub(crate) struct StackProtectorNotSupportedForTarget<'a> {
182182
pub(crate) target_triple: &'a TargetTriple,
183183
}
184184

185+
#[derive(Diagnostic)]
186+
#[diag(session_target_small_data_threshold_not_supported)]
187+
pub(crate) struct SmallDataThresholdNotSupportedForTarget<'a> {
188+
pub(crate) target_triple: &'a TargetTriple,
189+
}
190+
185191
#[derive(Diagnostic)]
186192
#[diag(session_branch_protection_requires_aarch64)]
187193
pub(crate) struct BranchProtectionRequiresAArch64;

compiler/rustc_session/src/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2014,6 +2014,8 @@ written to standard error output)"),
20142014
simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
20152015
"simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
20162016
to rust's source base directory. only meant for testing purposes"),
2017+
small_data_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
2018+
"Set the threshold for objects to be stored in a \"small data\" section"),
20172019
span_debug: bool = (false, parse_bool, [UNTRACKED],
20182020
"forward proc_macro::Span's `Debug` impl to `Span`"),
20192021
/// o/w tests have closure@path

compiler/rustc_session/src/session.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ use rustc_span::source_map::{FilePathMapping, SourceMap};
3030
use rustc_span::{FileNameDisplayPreference, RealFileName, Span, Symbol};
3131
use rustc_target::asm::InlineAsmArch;
3232
use rustc_target::spec::{
33-
CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo,
34-
StackProtector, Target, TargetTriple, TlsModel,
33+
CodeModel, DebuginfoKind, PanicStrategy, RelocModel, RelroLevel, SanitizerSet,
34+
SmallDataThresholdSupport, SplitDebuginfo, StackProtector, Target, TargetTriple, TlsModel,
3535
};
3636

3737
use crate::code_stats::CodeStats;
@@ -1278,6 +1278,14 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
12781278
}
12791279
}
12801280

1281+
if sess.opts.unstable_opts.small_data_threshold.is_some() {
1282+
if sess.target.options.small_data_threshold_support == SmallDataThresholdSupport::None {
1283+
sess.dcx().emit_warn(errors::SmallDataThresholdNotSupportedForTarget {
1284+
target_triple: &sess.opts.target_triple,
1285+
})
1286+
}
1287+
}
1288+
12811289
if sess.opts.unstable_opts.branch_protection.is_some() && sess.target.arch != "aarch64" {
12821290
sess.dcx().emit_err(errors::BranchProtectionRequiresAArch64);
12831291
}

compiler/rustc_target/src/spec/mod.rs

+48
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,39 @@ impl ToJson for RelroLevel {
855855
}
856856
}
857857

858+
#[derive(Clone, Debug, PartialEq, Hash)]
859+
pub enum SmallDataThresholdSupport {
860+
None,
861+
LlvmModuleFlag(StaticCow<str>),
862+
LlvmArg(StaticCow<str>),
863+
}
864+
865+
impl FromStr for SmallDataThresholdSupport {
866+
type Err = ();
867+
868+
fn from_str(s: &str) -> Result<Self, Self::Err> {
869+
if s == "none" {
870+
Ok(Self::None)
871+
} else if let Some(flag) = s.strip_prefix("llvm-module-flag=") {
872+
Ok(Self::LlvmModuleFlag(flag.to_string().into()))
873+
} else if let Some(arg) = s.strip_prefix("llvm-arg=") {
874+
Ok(Self::LlvmArg(arg.to_string().into()))
875+
} else {
876+
Err(())
877+
}
878+
}
879+
}
880+
881+
impl ToJson for SmallDataThresholdSupport {
882+
fn to_json(&self) -> Value {
883+
match self {
884+
Self::None => "none".to_json(),
885+
Self::LlvmModuleFlag(flag) => format!("llvm-module-flag={flag}").to_json(),
886+
Self::LlvmArg(arg) => format!("llvm-arg={arg}").to_json(),
887+
}
888+
}
889+
}
890+
858891
#[derive(Clone, Copy, Debug, PartialEq, Hash)]
859892
pub enum MergeFunctions {
860893
Disabled,
@@ -2392,6 +2425,9 @@ pub struct TargetOptions {
23922425

23932426
/// Whether the target supports XRay instrumentation.
23942427
pub supports_xray: bool,
2428+
2429+
/// Whether the targets supports -Z small-data-threshold
2430+
pub small_data_threshold_support: SmallDataThresholdSupport,
23952431
}
23962432

23972433
/// Add arguments for the given flavor and also for its "twin" flavors
@@ -2609,6 +2645,7 @@ impl Default for TargetOptions {
26092645
entry_name: "main".into(),
26102646
entry_abi: Conv::C,
26112647
supports_xray: false,
2648+
small_data_threshold_support: SmallDataThresholdSupport::None,
26122649
}
26132650
}
26142651
}
@@ -2884,6 +2921,15 @@ impl Target {
28842921
Some(Ok(()))
28852922
})).unwrap_or(Ok(()))
28862923
} );
2924+
($key_name:ident, SmallDataThresholdSupport) => ( {
2925+
obj.remove("small-data-threshold-support").and_then(|o| o.as_str().and_then(|s| {
2926+
match s.parse::<SmallDataThresholdSupport>() {
2927+
Ok(support) => base.small_data_threshold_support = support,
2928+
_ => return Some(Err(format!("'{s}' is not a valid value for small-data-threshold-support."))),
2929+
}
2930+
Some(Ok(()))
2931+
})).unwrap_or(Ok(()))
2932+
} );
28872933
($key_name:ident, PanicStrategy) => ( {
28882934
let name = (stringify!($key_name)).replace("_", "-");
28892935
obj.remove(&name).and_then(|o| o.as_str().and_then(|s| {
@@ -3321,6 +3367,7 @@ impl Target {
33213367
key!(supported_sanitizers, SanitizerSet)?;
33223368
key!(generate_arange_section, bool);
33233369
key!(supports_stack_protector, bool);
3370+
key!(small_data_threshold_support, SmallDataThresholdSupport)?;
33243371
key!(entry_name);
33253372
key!(entry_abi, Conv)?;
33263373
key!(supports_xray, bool);
@@ -3577,6 +3624,7 @@ impl ToJson for Target {
35773624
target_option_val!(c_enum_min_bits);
35783625
target_option_val!(generate_arange_section);
35793626
target_option_val!(supports_stack_protector);
3627+
target_option_val!(small_data_threshold_support);
35803628
target_option_val!(entry_name);
35813629
target_option_val!(entry_abi);
35823630
target_option_val!(supports_xray);

compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{base, Cc, LinkerFlavor, Target};
1+
use crate::spec::{base, Cc, LinkerFlavor, SmallDataThresholdSupport, Target};
22

33
pub(crate) fn target() -> Target {
44
let mut base = base::linux_musl::opts();
@@ -13,6 +13,9 @@ pub(crate) fn target() -> Target {
1313

1414
base.c_enum_min_bits = Some(8);
1515

16+
base.small_data_threshold_support =
17+
SmallDataThresholdSupport::LlvmArg("hexagon-small-data-threshold".into());
18+
1619
Target {
1720
llvm_target: "hexagon-unknown-linux-musl".into(),
1821
metadata: crate::spec::TargetMetadata {

compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{PanicStrategy, Target, TargetOptions};
1+
use crate::spec::{PanicStrategy, SmallDataThresholdSupport, Target, TargetOptions};
22

33
pub(crate) fn target() -> Target {
44
Target {
@@ -27,6 +27,9 @@ pub(crate) fn target() -> Target {
2727
max_atomic_width: Some(32),
2828
emit_debug_gdb_scripts: false,
2929
c_enum_min_bits: Some(8),
30+
small_data_threshold_support: SmallDataThresholdSupport::LlvmArg(
31+
"hexagon-small-data-threshold".into(),
32+
),
3033
..Default::default()
3134
},
3235
}

compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::abi::Endian;
2-
use crate::spec::{base, Target, TargetOptions};
2+
use crate::spec::{base, SmallDataThresholdSupport, Target, TargetOptions};
33

44
pub(crate) fn target() -> Target {
55
let mut base = base::linux_gnu::opts();
@@ -17,6 +17,13 @@ pub(crate) fn target() -> Target {
1717
pointer_width: 32,
1818
data_layout: "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16".into(),
1919
arch: "m68k".into(),
20-
options: TargetOptions { endian: Endian::Big, mcount: "_mcount".into(), ..base },
20+
options: TargetOptions {
21+
endian: Endian::Big,
22+
mcount: "_mcount".into(),
23+
small_data_threshold_support: SmallDataThresholdSupport::LlvmArg(
24+
"m68k-ssection-threshold".into(),
25+
),
26+
..base
27+
},
2128
}
2229
}

compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! A target tuple for OpenWrt MIPS64 targets.
22
33
use crate::abi::Endian;
4-
use crate::spec::{base, Target, TargetOptions};
4+
use crate::spec::{base, SmallDataThresholdSupport, Target, TargetOptions};
55

66
pub(crate) fn target() -> Target {
77
let mut base = base::linux_musl::opts();
@@ -26,6 +26,9 @@ pub(crate) fn target() -> Target {
2626
abi: "abi64".into(),
2727
endian: Endian::Big,
2828
mcount: "_mcount".into(),
29+
small_data_threshold_support: SmallDataThresholdSupport::LlvmArg(
30+
"mips-ssection-threshold".into(),
31+
),
2932
..base
3033
},
3134
}

compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::abi::Endian;
2-
use crate::spec::{base, Target, TargetOptions};
2+
use crate::spec::{base, SmallDataThresholdSupport, Target, TargetOptions};
33

44
pub(crate) fn target() -> Target {
55
Target {
@@ -21,6 +21,9 @@ pub(crate) fn target() -> Target {
2121
features: "+mips64r2,+xgot".into(),
2222
max_atomic_width: Some(64),
2323
mcount: "_mcount".into(),
24+
small_data_threshold_support: SmallDataThresholdSupport::LlvmArg(
25+
"mips-ssection-threshold".into(),
26+
),
2427

2528
..base::linux_gnu::opts()
2629
},

compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::abi::Endian;
2-
use crate::spec::{base, Target, TargetOptions};
2+
use crate::spec::{base, SmallDataThresholdSupport, Target, TargetOptions};
33

44
pub(crate) fn target() -> Target {
55
let mut base = base::linux_musl::opts();
@@ -22,6 +22,9 @@ pub(crate) fn target() -> Target {
2222
abi: "abi64".into(),
2323
endian: Endian::Big,
2424
mcount: "_mcount".into(),
25+
small_data_threshold_support: SmallDataThresholdSupport::LlvmArg(
26+
"mips-ssection-threshold".into(),
27+
),
2528
..base
2629
},
2730
}

compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{base, Target, TargetOptions};
1+
use crate::spec::{base, SmallDataThresholdSupport, Target, TargetOptions};
22

33
pub(crate) fn target() -> Target {
44
Target {
@@ -19,6 +19,9 @@ pub(crate) fn target() -> Target {
1919
features: "+mips64r2,+xgot".into(),
2020
max_atomic_width: Some(64),
2121
mcount: "_mcount".into(),
22+
small_data_threshold_support: SmallDataThresholdSupport::LlvmArg(
23+
"mips-ssection-threshold".into(),
24+
),
2225

2326
..base::linux_gnu::opts()
2427
},

compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::spec::{base, Target, TargetOptions};
1+
use crate::spec::{base, SmallDataThresholdSupport, Target, TargetOptions};
22

33
pub(crate) fn target() -> Target {
44
let mut base = base::linux_musl::opts();
@@ -17,6 +17,13 @@ pub(crate) fn target() -> Target {
1717
pointer_width: 64,
1818
data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
1919
arch: "mips64".into(),
20-
options: TargetOptions { abi: "abi64".into(), mcount: "_mcount".into(), ..base },
20+
options: TargetOptions {
21+
abi: "abi64".into(),
22+
mcount: "_mcount".into(),
23+
small_data_threshold_support: SmallDataThresholdSupport::LlvmArg(
24+
"mips-ssection-threshold".into(),
25+
),
26+
..base
27+
},
2128
}
2229
}

compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::abi::Endian;
2-
use crate::spec::{base, Target, TargetOptions};
2+
use crate::spec::{base, SmallDataThresholdSupport, Target, TargetOptions};
33

44
pub(crate) fn target() -> Target {
55
Target {
@@ -19,6 +19,9 @@ pub(crate) fn target() -> Target {
1919
features: "+mips32r2,+fpxx,+nooddspreg".into(),
2020
max_atomic_width: Some(32),
2121
mcount: "_mcount".into(),
22+
small_data_threshold_support: SmallDataThresholdSupport::LlvmArg(
23+
"mips-ssection-threshold".into(),
24+
),
2225

2326
..base::linux_gnu::opts()
2427
},

0 commit comments

Comments
 (0)