Skip to content

Commit 60886e8

Browse files
committed
[llvm][CFI] Do not canonicalize COFF functions in a comdat
COFF requires that a function exists with the same name as a comdat. Not having this key function results in `LLVM ERROR: Associative COMDAT symbol '...' does not exist.` CFI by default will attempt to canonicalize a function by appending `.cfi` to its name which allows external references to refer to the new canonical alias, but it does not change the comdat name. We can just change the comdat name since symbol resolution has already happened before LTO.
1 parent a6385a8 commit 60886e8

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

llvm/lib/Transforms/IPO/LowerTypeTests.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,18 @@ void ByteArrayBuilder::allocate(const std::set<uint64_t> &Bits,
246246
bool lowertypetests::isJumpTableCanonical(Function *F) {
247247
if (F->isDeclarationForLinker())
248248
return false;
249+
250+
// Do not canonicalize a comdat'd COFF function because this could end up
251+
// renaming the comdat key function without renaming the comdat key. We cannot
252+
// rename the key in this LTO unit because other TUs may reference the
253+
// original key name. To prevent this, just ignore canonicalization for
254+
// comdat'd COFF functions.
255+
// if (F->hasComdat()) {
256+
// Triple TargetTriple(F->getParent()->getTargetTriple());
257+
// if (TargetTriple.isOSBinFormatCOFF())
258+
// return false;
259+
//}
260+
249261
auto *CI = mdconst::extract_or_null<ConstantInt>(
250262
F->getParent()->getModuleFlag("CFI Canonical Jump Tables"));
251263
if (!CI || !CI->isZero())
@@ -1715,8 +1727,18 @@ void LowerTypeTestsModule::buildBitSetsFromFunctionsNative(
17151727
F->getValueType(), 0, F->getLinkage(), "", CombinedGlobalElemPtr, &M);
17161728
FAlias->setVisibility(F->getVisibility());
17171729
FAlias->takeName(F);
1718-
if (FAlias->hasName())
1730+
if (FAlias->hasName()) {
17191731
F->setName(FAlias->getName() + ".cfi");
1732+
// For COFF we should also rename the comdat if this function also
1733+
// happens to be the key function. Even if the comdat name changes, this
1734+
// should still be fine since comdat and symbol resolution happens
1735+
// before LTO, so all symbols which would prevail have been selected.
1736+
if (F->hasComdat() && ObjectFormat == Triple::COFF &&
1737+
F->getComdat()->getName() == FAlias->getName()) {
1738+
Comdat *NewComdat = M.getOrInsertComdat(F->getName());
1739+
F->setComdat(NewComdat);
1740+
}
1741+
}
17201742
replaceCfiUses(F, FAlias, IsJumpTableCanonical);
17211743
if (!F->hasLocalLinkage())
17221744
F->setVisibility(GlobalVariable::HiddenVisibility);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
; RUN: opt -S -passes=lowertypetests %s | FileCheck %s
2+
3+
;; This is a check to assert we don't crash with:
4+
;;
5+
;; LLVM ERROR: Associative COMDAT symbol '...' does not exist.
6+
;;
7+
;; So this just needs to exit normally.
8+
; RUN: opt -S -passes=lowertypetests %s | llc -asm-verbose=false
9+
10+
target datalayout = "e-p:64:64"
11+
target triple = "x86_64-pc-windows-msvc"
12+
13+
@a = global ptr @f3
14+
15+
$f3 = comdat any
16+
17+
; CHECK: @f3.cfi() comdat !type !0
18+
define void @f3() comdat !type !0 {
19+
ret void
20+
}
21+
22+
declare i1 @llvm.type.test(ptr %ptr, metadata %bitset) nounwind readnone
23+
24+
define i1 @foo(ptr %p) {
25+
%x = call i1 @llvm.type.test(ptr %p, metadata !"typeid1")
26+
ret i1 %x
27+
}
28+
29+
!0 = !{i32 0, !"typeid1"}

0 commit comments

Comments
 (0)