Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -730,6 +730,9 @@ GV.getName() == "llvm.global_dtors")) { Check(!GV.hasInitializer() || GV.hasAppendingLinkage(), "invalid linkage for intrinsic global variable", &GV); + Check(GV.materialized_use_empty(), + "invalid uses of intrinsic global variable", &GV); + // Don't worry about emitting an error for it not being an array, // visitGlobalValue will complain on appending non-array. if (ArrayType *ATy = dyn_cast(GV.getValueType())) { @@ -756,6 +759,9 @@ GV.getName() == "llvm.compiler.used")) { Check(!GV.hasInitializer() || GV.hasAppendingLinkage(), "invalid linkage for intrinsic global variable", &GV); + Check(GV.materialized_use_empty(), + "invalid uses of intrinsic global variable", &GV); + Type *GVType = GV.getValueType(); if (ArrayType *ATy = dyn_cast(GVType)) { PointerType *PTy = dyn_cast(ATy->getElementType()); Index: llvm/lib/Linker/IRMover.cpp =================================================================== --- llvm/lib/Linker/IRMover.cpp +++ llvm/lib/Linker/IRMover.cpp @@ -962,21 +962,19 @@ NG->copyAttributesFrom(SrcGV); forceRenaming(NG, SrcGV->getName()); - Constant *Ret = ConstantExpr::getBitCast(NG, TypeMap.get(SrcGV->getType())); - Mapper.scheduleMapAppendingVariable( *NG, (DstGV && !DstGV->isDeclaration()) ? DstGV->getInitializer() : nullptr, IsOldStructor, SrcElements); // Replace any uses of the two global variables with uses of the new - // global. - if (DstGV) { - RAUWWorklist.push_back( - std::make_pair(DstGV, ConstantExpr::getBitCast(NG, DstGV->getType()))); + // global. No replacement occurs for appending linkage. + if (DstGV && !DstGV->hasAppendingLinkage()) { + Constant *Ret = ConstantExpr::getBitCast(NG, DstGV->getType()); + RAUWWorklist.push_back(std::make_pair(DstGV, Ret)); } - return Ret; + return NG; } bool IRLinker::shouldLink(GlobalValue *DGV, GlobalValue &SGV) { Index: llvm/test/Linker/Inputs/funcimport_appending_global_used.ll =================================================================== --- /dev/null +++ llvm/test/Linker/Inputs/funcimport_appending_global_used.ll @@ -0,0 +1,6 @@ +@v = weak global i8 1 +@llvm.used = appending global [2 x ptr] [ptr @foo, ptr @v] + +define void @foo() { + ret void +} Index: llvm/test/Linker/funcimport_appending_global_used.ll =================================================================== --- /dev/null +++ llvm/test/Linker/funcimport_appending_global_used.ll @@ -0,0 +1,22 @@ +; RUN: opt -module-summary %s -o %t.bc +; RUN: opt -module-summary %p/Inputs/funcimport_appending_global_used.ll -o %t2.bc +; RUN: llvm-lto -thinlto -o %t3 %t.bc %t2.bc + +; Do the import now +; RUN: llvm-link %t.bc -summary-index=%t3.thinlto.bc -import=foo:%t2.bc -S | FileCheck %s + +; Test case where the verifier would fail if checking use_empty +; instead of materialized_use_empty on llvm.used. + +; CHECK: @llvm.used = appending global [1 x ptr] [ptr @f] + +declare void @f() +@llvm.used = appending global [1 x ptr] [ptr @f] + +define i32 @main() { +entry: + call void @foo() + ret i32 0 +} + +declare void @foo() Index: llvm/test/Verifier/global-ctors-dtors-uses.ll =================================================================== --- /dev/null +++ llvm/test/Verifier/global-ctors-dtors-uses.ll @@ -0,0 +1,16 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +; CHECK: invalid uses of intrinsic global variable +; CHECK-NEXT: ptr @llvm.global_ctors +@llvm.global_ctors = appending global [1 x { i32, ptr, ptr } ] [ + { i32, ptr, ptr } { i32 65535, ptr null, ptr null } +] + +; CHECK: invalid uses of intrinsic global variable +; CHECK-NEXT: ptr @llvm.global_dtors +@llvm.global_dtors = appending global [1 x { i32, ptr, ptr } ] [ + { i32, ptr, ptr } { i32 65535, ptr null, ptr null } +] + +@ctor_user = global ptr @llvm.global_ctors +@dtor_user = global ptr @llvm.global_dtors Index: llvm/test/Verifier/used-uses.ll =================================================================== --- /dev/null +++ llvm/test/Verifier/used-uses.ll @@ -0,0 +1,20 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +; CHECK: invalid uses of intrinsic global variable +; CHECK-NEXT: ptr @llvm.used +@llvm.used = appending global [1 x ptr] [ptr @foo] + +; CHECK: invalid uses of intrinsic global variable +; CHECK-NEXT: ptr @llvm.compiler.used +@llvm.compiler.used = appending global [1 x ptr] [ptr @bar] + +define void @foo() { + ret void +} + +define void @bar() { + ret void +} + +@used_user = global ptr @llvm.used +@compiler_used_user = global ptr @llvm.compiler.used