diff options
| author | Josh Stone <jistone@redhat.com> | 2021-11-19 19:33:29 -0800 |
|---|---|---|
| committer | Josh Stone <jistone@redhat.com> | 2021-11-19 19:33:29 -0800 |
| commit | 023cc968e1295994ed8039da43b0f2f4ea4e9390 (patch) | |
| tree | 4bc92bd38d5dc3ff7f8f157eee092cd69dcd3a1f /compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | |
| parent | a77da2d454e6caa227a85b16410b95f93495e7e0 (diff) | |
| download | rust-023cc968e1295994ed8039da43b0f2f4ea4e9390.tar.gz rust-023cc968e1295994ed8039da43b0f2f4ea4e9390.zip | |
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 'compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp')
| -rw-r--r-- | compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index e77d29bed71..f3d8eb2602a 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -124,8 +124,18 @@ extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, extern "C" LLVMValueRef LLVMRustGetOrInsertGlobal(LLVMModuleRef M, const char *Name, size_t NameLen, LLVMTypeRef Ty) { + Module *Mod = unwrap(M); StringRef NameRef(Name, NameLen); - return wrap(unwrap(M)->getOrInsertGlobal(NameRef, unwrap(Ty))); + + // We don't use Module::getOrInsertGlobal because that returns a Constant*, + // which may either be the real GlobalVariable*, or a constant bitcast of it + // if our type doesn't match the original declaration. We always want the + // GlobalVariable* so we can access linkage, visibility, etc. + GlobalVariable *GV = Mod->getGlobalVariable(NameRef, true); + if (!GV) + GV = new GlobalVariable(*Mod, unwrap(Ty), false, + GlobalValue::ExternalLinkage, nullptr, NameRef); + return wrap(GV); } extern "C" LLVMValueRef |
