about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJosh Stone <jistone@redhat.com>2021-11-19 19:33:29 -0800
committerJosh Stone <jistone@redhat.com>2021-11-19 19:33:29 -0800
commit023cc968e1295994ed8039da43b0f2f4ea4e9390 (patch)
tree4bc92bd38d5dc3ff7f8f157eee092cd69dcd3a1f /src
parenta77da2d454e6caa227a85b16410b95f93495e7e0 (diff)
Make `LLVMRustGetOrInsertGlobal` always return a `GlobalVariable`
`Module::getOrInsertGlobal` returns a `Constant*`, which is a super
class of `GlobalVariable`, but if the given type doesn't match an
existing declaration, it returns a bitcast of that global instead.
This causes UB when we pass that to `LLVMGetVisibility` which
unconditionally casts the opaque argument to a `GlobalValue*`.

Instead, we can do our own get-or-insert without worrying whether
existing types match exactly. It's not relevant when we're just trying
to get/set the linkage and visibility, and if types are needed we can
bitcast or error nicely from `rustc_codegen_llvm` instead.
Diffstat (limited to 'src')
-rw-r--r--src/test/ui/issues/issue-91050.rs34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/test/ui/issues/issue-91050.rs b/src/test/ui/issues/issue-91050.rs
new file mode 100644
index 00000000000..50763d30931
--- /dev/null
+++ b/src/test/ui/issues/issue-91050.rs
@@ -0,0 +1,34 @@
+// build-pass
+// compile-flags: --crate-type lib -Ccodegen-units=1
+
+// This test declares globals by the same name with different types, which
+// caused problems because Module::getOrInsertGlobal would return a Constant*
+// bitcast instead of a GlobalVariable* that could access linkage/visibility.
+// In alt builds with LLVM assertions this would fail:
+//
+// rustc: /checkout/src/llvm-project/llvm/include/llvm/Support/Casting.h:269:
+// typename cast_retty<X, Y *>::ret_type llvm::cast(Y *) [X = llvm::GlobalValue, Y = llvm::Value]:
+// Assertion `isa<X>(Val) && "cast<Ty>() argument of incompatible type!"' failed.
+//
+// In regular builds, the bad cast was UB, like "Invalid LLVMRustVisibility value!"
+
+pub mod before {
+    #[no_mangle]
+    pub static GLOBAL1: [u8; 1] = [1];
+}
+
+pub mod inner {
+    extern "C" {
+        pub static GLOBAL1: u8;
+        pub static GLOBAL2: u8;
+    }
+
+    pub fn call() {
+        drop(unsafe { (GLOBAL1, GLOBAL2) });
+    }
+}
+
+pub mod after {
+    #[no_mangle]
+    pub static GLOBAL2: [u8; 1] = [2];
+}