[llvm] [llvm][CFI] Do not canonicalize COFF functions in a comdat (PR #139962)

via llvm-commits llvm-commits at lists.llvm.org
Wed May 14 14:01:57 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: None (PiJoules)

<details>
<summary>Changes</summary>

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 cannot change the comdat name in case the same comdat is used by other TUs outside this LTO unit. To prevent this, we can just not canonicalize COFF comdat'd functions.

---
Full diff: https://github.com/llvm/llvm-project/pull/139962.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/IPO/LowerTypeTests.cpp (+12) 
- (added) llvm/test/Transforms/LowerTypeTests/cfi-canonical-jump-tables-coff.ll (+30) 


``````````diff
diff --git a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
index d855647095550..b9e83565497c4 100644
--- a/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
+++ b/llvm/lib/Transforms/IPO/LowerTypeTests.cpp
@@ -246,6 +246,18 @@ void ByteArrayBuilder::allocate(const std::set<uint64_t> &Bits,
 bool lowertypetests::isJumpTableCanonical(Function *F) {
   if (F->isDeclarationForLinker())
     return false;
+
+  // Do not canonicalize a comdat'd COFF function because this could end up
+  // renaming the comdat key function without renaming the comdat key. We cannot
+  // rename the key in this LTO unit because other TUs may reference the
+  // original key name. To prevent this, just ignore canonicalization for
+  // comdat'd COFF functions.
+  if (F->hasComdat()) {
+    Triple TargetTriple(F->getParent()->getTargetTriple());
+    if (TargetTriple.isOSBinFormatCOFF())
+      return false;
+  }
+
   auto *CI = mdconst::extract_or_null<ConstantInt>(
       F->getParent()->getModuleFlag("CFI Canonical Jump Tables"));
   if (!CI || !CI->isZero())
diff --git a/llvm/test/Transforms/LowerTypeTests/cfi-canonical-jump-tables-coff.ll b/llvm/test/Transforms/LowerTypeTests/cfi-canonical-jump-tables-coff.ll
new file mode 100644
index 0000000000000..8ad5099874226
--- /dev/null
+++ b/llvm/test/Transforms/LowerTypeTests/cfi-canonical-jump-tables-coff.ll
@@ -0,0 +1,30 @@
+; RUN: opt -S -passes=lowertypetests %s -mtriple=x86_64-pc-windows-msvc | llc -asm-verbose=false | FileCheck %s --check-prefixes=COFF,CHECK
+; RUN: opt -S -passes=lowertypetests %s -mtriple=x86_64-unknown-linux-gnu | llc -asm-verbose=false | FileCheck %s --check-prefixes=ELF,CHECK
+
+target datalayout = "e-p:64:64"
+
+; COFF-LABEL: f3:
+; ELF-LABEL:  f3.cfi:
+
+; CHECK-LABEL: a:
+; COFF:          .quad   .L.cfi.jumptable
+; ELF:           .quad   f3
+
+; ELF:  .set f3, .L.cfi.jumptable
+
+ at a = global ptr @f3
+
+$f3 = comdat any
+
+define void @f3() comdat !type !0 {
+  ret void
+}
+
+declare i1 @llvm.type.test(ptr %ptr, metadata %bitset) nounwind readnone
+
+define i1 @foo(ptr %p) {
+  %x = call i1 @llvm.type.test(ptr %p, metadata !"typeid1")
+  ret i1 %x
+}
+
+!0 = !{i32 0, !"typeid1"}

``````````

</details>


https://github.com/llvm/llvm-project/pull/139962


More information about the llvm-commits mailing list