-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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.
- Loading branch information
Showing
2 changed files
with
45 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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]; | ||
} |