summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Linker/IRMover.cpp35
-rw-r--r--llvm/test/LTO/Resolution/X86/Inputs/appending-var-2.ll14
-rw-r--r--llvm/test/LTO/Resolution/X86/appending-var.ll16
3 files changed, 60 insertions, 5 deletions
diff --git a/llvm/lib/Linker/IRMover.cpp b/llvm/lib/Linker/IRMover.cpp
index 70d5262fd61..b21b8f33ab4 100644
--- a/llvm/lib/Linker/IRMover.cpp
+++ b/llvm/lib/Linker/IRMover.cpp
@@ -402,6 +402,7 @@ class IRLinker {
DenseSet<GlobalValue *> ValuesToLink;
std::vector<GlobalValue *> Worklist;
+ std::vector<std::pair<GlobalValue *, Value*>> RAUWWorklist;
void maybeAdd(GlobalValue *GV) {
if (ValuesToLink.insert(GV).second)
@@ -494,6 +495,14 @@ class IRLinker {
Function *copyFunctionProto(const Function *SF);
GlobalValue *copyGlobalAliasProto(const GlobalAlias *SGA);
+ /// Perform "replace all uses with" operations. These work items need to be
+ /// performed as part of materialization, but we postpone them to happen after
+ /// materialization is done. The materializer called by ValueMapper is not
+ /// expected to delete constants, as ValueMapper is holding pointers to some
+ /// of them, but constant destruction may be indirectly triggered by RAUW.
+ /// Hence, the need to move this out of the materialization call chain.
+ void flushRAUWWorklist();
+
/// When importing for ThinLTO, prevent importing of types listed on
/// the DICompileUnit that we don't need a copy of in the importing
/// module.
@@ -883,8 +892,8 @@ IRLinker::linkAppendingVarProto(GlobalVariable *DstGV,
// Replace any uses of the two global variables with uses of the new
// global.
if (DstGV) {
- DstGV->replaceAllUsesWith(ConstantExpr::getBitCast(NG, DstGV->getType()));
- DstGV->eraseFromParent();
+ RAUWWorklist.push_back(
+ std::make_pair(DstGV, ConstantExpr::getBitCast(NG, DstGV->getType())));
}
return Ret;
@@ -983,9 +992,12 @@ Expected<Constant *> IRLinker::linkGlobalValueProto(GlobalValue *SGV,
}
if (DGV && NewGV != DGV) {
- DGV->replaceAllUsesWith(
- ConstantExpr::getPointerBitCastOrAddrSpaceCast(NewGV, DGV->getType()));
- DGV->eraseFromParent();
+ // Schedule "replace all uses with" to happen after materializing is
+ // done. It is not safe to do it now, since ValueMapper may be holding
+ // pointers to constants that will get deleted if RAUW runs.
+ RAUWWorklist.push_back(std::make_pair(
+ DGV,
+ ConstantExpr::getPointerBitCastOrAddrSpaceCast(NewGV, DGV->getType())));
}
return C;
@@ -1043,6 +1055,18 @@ Error IRLinker::linkGlobalValueBody(GlobalValue &Dst, GlobalValue &Src) {
return Error::success();
}
+void IRLinker::flushRAUWWorklist() {
+ for (const auto Elem : RAUWWorklist) {
+ GlobalValue *Old;
+ Value *New;
+ std::tie(Old, New) = Elem;
+
+ Old->replaceAllUsesWith(New);
+ Old->eraseFromParent();
+ }
+ RAUWWorklist.clear();
+}
+
void IRLinker::prepareCompileUnitsForImport() {
NamedMDNode *SrcCompileUnits = SrcM->getNamedMetadata("llvm.dbg.cu");
if (!SrcCompileUnits)
@@ -1368,6 +1392,7 @@ Error IRLinker::run() {
Mapper.mapValue(*GV);
if (FoundError)
return std::move(*FoundError);
+ flushRAUWWorklist();
}
// Note that we are done linking global value bodies. This prevents
diff --git a/llvm/test/LTO/Resolution/X86/Inputs/appending-var-2.ll b/llvm/test/LTO/Resolution/X86/Inputs/appending-var-2.ll
new file mode 100644
index 00000000000..29bc8433d3e
--- /dev/null
+++ b/llvm/test/LTO/Resolution/X86/Inputs/appending-var-2.ll
@@ -0,0 +1,14 @@
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%"foo" = type { i8 }
+
+@llvm.used = appending global [1 x i8*] [i8* bitcast (i32 (%"foo"*)* @bar to i8*)], section "llvm.metadata"
+
+; Function Attrs: norecurse nounwind readnone uwtable
+define dso_local i32 @bar(%"foo"* nocapture readnone %this) align 2 !type !0 {
+entry:
+ ret i32 0
+}
+
+!0 = !{i64 0, !"typeid1"}
diff --git a/llvm/test/LTO/Resolution/X86/appending-var.ll b/llvm/test/LTO/Resolution/X86/appending-var.ll
new file mode 100644
index 00000000000..4d259d7f8db
--- /dev/null
+++ b/llvm/test/LTO/Resolution/X86/appending-var.ll
@@ -0,0 +1,16 @@
+; Check we don't crash when linking a global variable with appending linkage
+; if the types in their elements don't have a straightforward mapping, forcing
+; us to use bitcasts.
+
+; RUN: opt %s -o %t1.o
+; RUN: opt %p/Inputs/appending-var-2.ll -o %t2.o
+
+; RUN: llvm-lto2 run -o %t3.o %t1.o %t2.o -r %t1.o,bar, -r %t2.o,bar,px
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+%"foo.1" = type { i8, i8 }
+declare dso_local i32 @bar(%"foo.1"* nocapture readnone %this) local_unnamed_addr
+
+@llvm.used = appending global [1 x i8*] [i8* bitcast (i32 (%"foo.1"*)* @bar to i8*)], section "llvm.metadata"
OpenPOWER on IntegriCloud