Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -729,6 +729,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())) { @@ -755,6 +758,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/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