about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2021-11-21 09:55:14 +0100
committerGitHub <noreply@github.com>2021-11-21 09:55:14 +0100
commitdf552b3c24ac364802aaea6e77025110c074ddc7 (patch)
tree3a6027ca5b4a96af5fab4fc014350218c2d1f7e9 /src
parent789d168e132d3db976394a5d82490c4763c97626 (diff)
parent3aa1954b0bfc3f10917d5ff8fa315ac3cae5c45a (diff)
Rollup merge of #91070 - cuviper:insert-global, r=nagisa
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.

Fixes #91050, fixes #87933, fixes #87813.
Diffstat (limited to 'src')
-rw-r--r--src/test/ui/statics/issue-91050-1.rs34
-rw-r--r--src/test/ui/statics/issue-91050-2.rs24
2 files changed, 58 insertions, 0 deletions
diff --git a/src/test/ui/statics/issue-91050-1.rs b/src/test/ui/statics/issue-91050-1.rs
new file mode 100644
index 00000000000..403a41462ef
--- /dev/null
+++ b/src/test/ui/statics/issue-91050-1.rs
@@ -0,0 +1,34 @@
+// build-pass
+// compile-flags: --crate-type=rlib --emit=llvm-ir -Cno-prepopulate-passes
+
+// 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];
+}
diff --git a/src/test/ui/statics/issue-91050-2.rs b/src/test/ui/statics/issue-91050-2.rs
new file mode 100644
index 00000000000..2ff954d15ca
--- /dev/null
+++ b/src/test/ui/statics/issue-91050-2.rs
@@ -0,0 +1,24 @@
+// build-pass
+// compile-flags: --crate-type=rlib --emit=llvm-ir -Cno-prepopulate-passes
+
+// This is a variant of issue-91050-1.rs -- see there for an explanation.
+
+pub mod before {
+    extern "C" {
+        pub static GLOBAL1: [u8; 1];
+    }
+
+    pub unsafe fn do_something_with_array() -> u8 {
+        GLOBAL1[0]
+    }
+}
+
+pub mod inner {
+    extern "C" {
+        pub static GLOBAL1: u8;
+    }
+
+    pub unsafe fn call() -> u8 {
+        GLOBAL1 + 42
+    }
+}