Skip to content

Commit

Permalink
Verifier: Disallow uses of intrinsic global variables
Browse files Browse the repository at this point in the history
appendToGlobalCtors implicitly assumes this is the case, since it
deletes and recreates without trying to update any uses.

This ran into an interesting problem in a few linker tests. During the
link, ConstantExpr casts were speculatively created to replace any
uses that might need them for replacement. These unused ConstantExprs
would hang around and still appear on the use list. It seems like a
bug that those stick around, but I'm not sure where those are supposed
to be cleaned up. Avoid this by not creating the casts for appending
linkage.

Delete one of the casts entirely as it breaks no tests. The verifier
has enforced a specific type for these since 2011, so I don't see why
we would need to handle linking modules with a wrong types. One test
does fail without the second cast (Linker/appending-global-proto.ll,
added by D95126). This test looks contrived; it's using appending
linkage with a regular variable. The LangRef suggests this is illegal
(and suggests another missing verifier check).
  • Loading branch information
arsenm committed Jan 5, 2023
1 parent b4993be commit b67c16f
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 0 deletions.
6 changes: 6 additions & 0 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -729,6 +729,9 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
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<ArrayType>(GV.getValueType())) {
Expand All @@ -755,6 +758,9 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
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<ArrayType>(GVType)) {
PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType());
Expand Down
6 changes: 6 additions & 0 deletions llvm/test/Linker/Inputs/funcimport_appending_global_used.ll
Original file line number Diff line number Diff line change
@@ -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
}
22 changes: 22 additions & 0 deletions llvm/test/Linker/funcimport_appending_global_used.ll
Original file line number Diff line number Diff line change
@@ -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()
16 changes: 16 additions & 0 deletions llvm/test/Verifier/global-ctors-dtors-uses.ll
Original file line number Diff line number Diff line change
@@ -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
20 changes: 20 additions & 0 deletions llvm/test/Verifier/used-uses.ll
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit b67c16f

Please sign in to comment.