about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_llvm/src/mono_item.rs25
-rw-r--r--compiler/rustc_interface/src/tests.rs1
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_session/src/session.rs7
-rw-r--r--compiler/rustc_target/src/spec/mod.rs11
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs1
-rw-r--r--src/doc/unstable-book/src/compiler-flags/direct-access-external-data.md16
-rw-r--r--tests/codegen/direct-access-external-data.rs21
8 files changed, 74 insertions, 10 deletions
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index f796ce0990f..f7630719368 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -123,6 +123,17 @@ 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);
@@ -130,18 +141,12 @@ impl CodegenCx<'_, '_> {
             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
     }
 }
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 588139a303c..948db6a6ea1 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -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);
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index c97b18ebd66..ff8c5f4b356 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -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],
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 720599f6095..392485e2238 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -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)
     }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 8e26327196a..7979be7b5d6 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -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.
@@ -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,
@@ -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()) {
@@ -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);
@@ -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);
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
index 0f05e7c475a..234270c999b 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
@@ -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()
         },
     }
diff --git a/src/doc/unstable-book/src/compiler-flags/direct-access-external-data.md b/src/doc/unstable-book/src/compiler-flags/direct-access-external-data.md
new file mode 100644
index 00000000000..c72df437960
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/direct-access-external-data.md
@@ -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.
diff --git a/tests/codegen/direct-access-external-data.rs b/tests/codegen/direct-access-external-data.rs
new file mode 100644
index 00000000000..ec4bfc33518
--- /dev/null
+++ b/tests/codegen/direct-access-external-data.rs
@@ -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 }
+}