Skip to content

Commit

Permalink
Add unstable -Z direct-access-external-data cmdline flag for rustc
Browse files Browse the repository at this point in the history
The new flag has been described in the Major Change Proposal at
rust-lang/compiler-team#707
  • Loading branch information
heiher committed Jan 16, 2024
1 parent 9480767 commit 06a4168
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 10 deletions.
25 changes: 15 additions & 10 deletions compiler/rustc_codegen_llvm/src/mono_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,25 +123,30 @@ impl CodegenCx<'_, '_> {
return false;
}

// Match clang by only supporting COFF and ELF for now.
if self.tcx.sess.target.is_like_osx {
return false;
}

// With pie relocation model calls of functions defined in the translation
// unit can use copy relocations.
if self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration {
return true;
}

// Thread-local variables generally don't support copy relocations.
let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval)
.is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True);
if is_thread_local_var {
return false;
}

// Match clang by only supporting COFF and ELF for now.
if self.tcx.sess.target.is_like_osx {
return false;
// Respect the direct-access-external-data to override default behavior if present.
if let Some(direct) = self.tcx.sess.direct_access_external_data() {
return direct;
}

// Static relocation model should force copy relocations everywhere.
if self.tcx.sess.relocation_model() == RelocModel::Static {
return true;
}

// With pie relocation model calls of functions defined in the translation
// unit can use copy relocations.
self.tcx.sess.relocation_model() == RelocModel::Pie && !is_declaration
self.tcx.sess.relocation_model() == RelocModel::Static
}
}
1 change: 1 addition & 0 deletions compiler/rustc_interface/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,7 @@ fn test_unstable_options_tracking_hash() {
tracked!(debug_macros, true);
tracked!(default_hidden_visibility, Some(true));
tracked!(dep_info_omit_d_target, true);
tracked!(direct_access_external_data, Some(true));
tracked!(dual_proc_macros, true);
tracked!(dwarf_version, Some(5));
tracked!(emit_thin_lto, false);
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_session/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1553,6 +1553,8 @@ options! {
dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],
"in dep-info output, omit targets for tracking dependencies of the dep-info files \
themselves (default: no)"),
direct_access_external_data: Option<bool> = (None, parse_opt_bool, [TRACKED],
"Direct or use GOT indirect to reference external data symbols"),
dual_proc_macros: bool = (false, parse_bool, [TRACKED],
"load proc macros for both target and host, but only link to the target (default: no)"),
dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,13 @@ impl Session {
self.opts.unstable_opts.tls_model.unwrap_or(self.target.tls_model)
}

pub fn direct_access_external_data(&self) -> Option<bool> {
self.opts
.unstable_opts
.direct_access_external_data
.or(self.target.direct_access_external_data)
}

pub fn split_debuginfo(&self) -> SplitDebuginfo {
self.opts.cg.split_debuginfo.unwrap_or(self.target.split_debuginfo)
}
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1885,6 +1885,8 @@ pub struct TargetOptions {
/// passed, and cannot be disabled even via `-C`. Corresponds to `llc
/// -mattr=$features`.
pub features: StaticCow<str>,
/// Direct or use GOT indirect to reference external data symbols
pub direct_access_external_data: Option<bool>,
/// Whether dynamic linking is available on this target. Defaults to false.
pub dynamic_linking: bool,
/// Whether dynamic linking can export TLS globals. Defaults to true.
Expand Down Expand Up @@ -2279,6 +2281,7 @@ impl Default for TargetOptions {
asm_args: cvs![],
cpu: "generic".into(),
features: "".into(),
direct_access_external_data: None,
dynamic_linking: false,
dll_tls_export: true,
only_cdylib: false,
Expand Down Expand Up @@ -2575,6 +2578,12 @@ impl Target {
base.$key_name = s as u32;
}
} );
($key_name:ident, Option<bool>) => ( {
let name = (stringify!($key_name)).replace("_", "-");
if let Some(s) = obj.remove(&name).and_then(|b| b.as_bool()) {
base.$key_name = Some(s);
}
} );
($key_name:ident, Option<u64>) => ( {
let name = (stringify!($key_name)).replace("_", "-");
if let Some(s) = obj.remove(&name).and_then(|b| b.as_u64()) {
Expand Down Expand Up @@ -3003,6 +3012,7 @@ impl Target {
key!(cpu);
key!(features);
key!(dynamic_linking, bool);
key!(direct_access_external_data, Option<bool>);
key!(dll_tls_export, bool);
key!(only_cdylib, bool);
key!(executables, bool);
Expand Down Expand Up @@ -3257,6 +3267,7 @@ impl ToJson for Target {
target_option_val!(cpu);
target_option_val!(features);
target_option_val!(dynamic_linking);
target_option_val!(direct_access_external_data);
target_option_val!(dll_tls_export);
target_option_val!(only_cdylib);
target_option_val!(executables);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub fn target() -> Target {
features: "+f,+d".into(),
llvm_abiname: "lp64d".into(),
max_atomic_width: Some(64),
direct_access_external_data: Some(false),
..base::linux_gnu::opts()
},
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# `direct_access_external_data`

The tracking issue for this feature is: https://github.com/rust-lang/compiler-team/issues/707

------------------------

Option `-Z direct-access-external-data` controls how to access symbols of
external data.

Supported values for this option are:

- `yes` - Don't use GOT indirection to reference external data symbols.
- `no` - Use GOT indirection to reference external data symbols.

If the option is not explicitly specified, different targets have different
default values.
21 changes: 21 additions & 0 deletions tests/codegen/direct-access-external-data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// only-loongarch64-unknown-linux-gnu

// revisions: DEFAULT DIRECT INDIRECT
// [DEFAULT] compile-flags: -C relocation-model=static
// [DIRECT] compile-flags: -C relocation-model=static -Z direct-access-external-data=yes
// [INDIRECT] compile-flags: -C relocation-model=static -Z direct-access-external-data=no

#![crate_type = "rlib"]

// DEFAULT: @VAR = external {{.*}} global i32
// DIRECT: @VAR = external dso_local {{.*}} global i32
// INDIRECT: @VAR = external {{.*}} global i32

extern "C" {
static VAR: i32;
}

#[no_mangle]
pub fn get() -> i32 {
unsafe { VAR }
}

0 comments on commit 06a4168

Please sign in to comment.