Index: llvm/trunk/lib/Linker/IRMover.cpp =================================================================== --- llvm/trunk/lib/Linker/IRMover.cpp +++ llvm/trunk/lib/Linker/IRMover.cpp @@ -402,6 +402,7 @@ DenseSet ValuesToLink; std::vector Worklist; + std::vector> RAUWWorklist; void maybeAdd(GlobalValue *GV) { if (ValuesToLink.insert(GV).second) @@ -494,6 +495,14 @@ 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 @@ // 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 @@ } 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 @@ 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 @@ Mapper.mapValue(*GV); if (FoundError) return std::move(*FoundError); + flushRAUWWorklist(); } // Note that we are done linking global value bodies. This prevents Index: llvm/trunk/test/LTO/Resolution/X86/Inputs/appending-var-2.ll =================================================================== --- llvm/trunk/test/LTO/Resolution/X86/Inputs/appending-var-2.ll +++ llvm/trunk/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"} Index: llvm/trunk/test/LTO/Resolution/X86/appending-var.ll =================================================================== --- llvm/trunk/test/LTO/Resolution/X86/appending-var.ll +++ llvm/trunk/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"