Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1760,12 +1760,20 @@ void Verifier::visitDIImportedEntity(const DIImportedEntity &N) {
}

void Verifier::visitComdat(const Comdat &C) {
// In COFF the Module is invalid if the GlobalValue has private linkage.
// Entities with private linkage don't have entries in the symbol table.
if (TT.isOSBinFormatCOFF())
if (const GlobalValue *GV = M.getNamedValue(C.getName()))
// Comdats in COFF modules must have a corresponding global that is not
// private. If the global is private, there will be no symbol table entry.
// We consider unused or dead comdat entries to be valid, since they won't
// make it into the COFF object file.
if (TT.isOSBinFormatCOFF()) {
const GlobalValue *GV = M.getNamedValue(C.getName());
bool IsDefined = GV != nullptr && !GV->isDeclarationForLinker();
Check(IsDefined || C.getUsers().empty(),
"COFF comdats must have a defined global value with the same name",
GV);
if (IsDefined)
Check(!GV->hasPrivateLinkage(), "comdat global value has private linkage",
GV);
}
}

void Verifier::visitModuleIdents() {
Expand Down
40 changes: 38 additions & 2 deletions llvm/test/Verifier/comdat.ll
Original file line number Diff line number Diff line change
@@ -1,5 +1,41 @@
; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s
; RUN: split-file %s %t

;--- common.ll
; RUN: not llvm-as %t/common.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-COMMON
$v = comdat any
@v = common global i32 0, comdat($v)
; CHECK: 'common' global may not be in a Comdat!
; CHECK-COMMON: 'common' global may not be in a Comdat!

;--- private.ll
; RUN: llvm-as %t/private.ll -o /dev/null
; RUN: opt -mtriple=x86_64-unknown-linux %t/private.ll -o /dev/null
; RUN: not opt -mtriple=x86_64-pc-win32 %t/private.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-PRIVATE
$v = comdat any
@v = private global i32 0, comdat($v)
; CHECK-PRIVATE: comdat global value has private linkage

;--- noleader.ll
; RUN: llvm-as %t/noleader.ll -o /dev/null
; RUN: opt -mtriple=x86_64-unknown-linux %t/noleader.ll -o /dev/null
; RUN: not opt -mtriple=x86_64-pc-win32 %t/noleader.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-NOLEADER

$v = comdat any
@unrelated = internal global i32 0, comdat($v)
; CHECK-NOLEADER: COFF comdats must have a defined global value with the same name

;--- undefined.ll
; RUN: llvm-as %t/undefined.ll -o /dev/null
; RUN: opt -mtriple=x86_64-unknown-linux %t/undefined.ll -o /dev/null
; RUN: not opt -mtriple=x86_64-pc-win32 %t/undefined.ll -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED

$v = comdat any
@v = external global i32
@unrelated = internal global i32 0, comdat($v)
; CHECK-UNDEFINED: COFF comdats must have a defined global value with the same name

;--- largest.ll
; RUN: llvm-as %t/largest.ll -o /dev/null
; This used to be invalid, but now it's valid. Ensure the verifier
; doesn't reject it.

$v = comdat largest
7 changes: 0 additions & 7 deletions llvm/test/Verifier/comdat2.ll

This file was deleted.

5 changes: 0 additions & 5 deletions llvm/test/Verifier/comdat3.ll

This file was deleted.

Loading