Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 16, 2025

Conversation

PiJoules
Copy link
Contributor

@PiJoules PiJoules commented May 14, 2025

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 change the comdat name since symbol and comdat resolution occurs before LTO, so we already know which symbols are prevailing.

@PiJoules PiJoules requested review from pcc and ilovepi May 14, 2025 21:01
@llvmbot
Copy link
Member

llvmbot commented May 14, 2025

@llvm/pr-subscribers-llvm-transforms

Author: None (PiJoules)

Changes

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 --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
+
+@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"}

Copy link
Contributor

@pcc pcc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would break taking the address of a function outside of the linkage unit without LTO, which is something that normally requires opting into.

// 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the name of the comdat should matter at this point, LTO happens after comdat resolution.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I didn't know that. So I guess as long as the key function was chosen as the prevailing symbol for the symbol table passed to LTO, then it should be fine to rename the comdat.

@PiJoules PiJoules force-pushed the coff-cfi-fix branch 2 times, most recently from 60886e8 to 9e6f797 Compare May 15, 2025 19:17
@PiJoules
Copy link
Contributor Author

Updated to rename the comdat

@PiJoules PiJoules requested a review from pcc May 15, 2025 19:19
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.
@PiJoules PiJoules requested a review from pcc May 16, 2025 20:55
@PiJoules PiJoules merged commit 33684ac into llvm:main May 16, 2025
8 of 11 checks passed
@PiJoules PiJoules deleted the coff-cfi-fix branch May 16, 2025 21:54
@llvm-ci
Copy link
Collaborator

llvm-ci commented May 16, 2025

LLVM Buildbot has detected a new failure on builder clang-aarch64-quick running on linaro-clang-aarch64-quick while building llvm at step 5 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/65/builds/16741

Here is the relevant piece of the build log for the reference
Step 5 (ninja check 1) failure: stage 1 checked (failure)
******************** TEST 'LLVM :: Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/opt -S -passes=lowertypetests /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll | /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/FileCheck /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll # RUN: at line 1
+ /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/opt -S -passes=lowertypetests /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll
+ /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/FileCheck /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll
/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/opt: WARNING: failed to create target machine for 'x86_64-pc-windows-msvc': unable to get target for 'x86_64-pc-windows-msvc', see --version and --triple.
/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/opt -S -passes=lowertypetests /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll | /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/llc -asm-verbose=false # RUN: at line 8
+ /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/opt -S -passes=lowertypetests /home/tcwg-buildbot/worker/clang-aarch64-quick/llvm/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll
+ /home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/llc -asm-verbose=false
/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/opt: WARNING: failed to create target machine for 'x86_64-pc-windows-msvc': unable to get target for 'x86_64-pc-windows-msvc', see --version and --triple.
/home/tcwg-buildbot/worker/clang-aarch64-quick/stage1/bin/llc: error: unable to get target for 'x86_64-pc-windows-msvc', see --version and --triple.

--

********************


@llvm-ci
Copy link
Collaborator

llvm-ci commented May 16, 2025

LLVM Buildbot has detected a new failure on builder llvm-clang-aarch64-darwin running on doug-worker-4 while building llvm at step 6 "test-build-unified-tree-check-all".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/190/builds/20125

Here is the relevant piece of the build log for the reference
Step 6 (test-build-unified-tree-check-all) failure: test (failure)
******************** TEST 'LLVM :: Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/opt -S -passes=lowertypetests /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll | /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll # RUN: at line 1
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/opt -S -passes=lowertypetests /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/FileCheck /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll
/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/opt: WARNING: failed to create target machine for 'x86_64-pc-windows-msvc': unable to get target for 'x86_64-pc-windows-msvc', see --version and --triple.
/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/opt -S -passes=lowertypetests /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll | /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/llc -asm-verbose=false # RUN: at line 8
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/opt -S -passes=lowertypetests /Users/buildbot/buildbot-root/aarch64-darwin/llvm-project/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll
+ /Users/buildbot/buildbot-root/aarch64-darwin/build/bin/llc -asm-verbose=false
/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/opt: WARNING: failed to create target machine for 'x86_64-pc-windows-msvc': unable to get target for 'x86_64-pc-windows-msvc', see --version and --triple.
/Users/buildbot/buildbot-root/aarch64-darwin/build/bin/llc: error: unable to get target for 'x86_64-pc-windows-msvc', see --version and --triple.

--

********************


@llvm-ci
Copy link
Collaborator

llvm-ci commented May 16, 2025

LLVM Buildbot has detected a new failure on builder clang-armv8-quick running on linaro-clang-armv8-quick while building llvm at step 5 "ninja check 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/154/builds/16186

Here is the relevant piece of the build log for the reference
Step 5 (ninja check 1) failure: stage 1 checked (failure)
******************** TEST 'LLVM :: Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll' FAILED ********************
Exit Code: 1

Command Output (stderr):
--
/home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/opt -S -passes=lowertypetests /home/tcwg-buildbot/worker/clang-armv8-quick/llvm/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll | /home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/FileCheck /home/tcwg-buildbot/worker/clang-armv8-quick/llvm/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll # RUN: at line 1
+ /home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/opt -S -passes=lowertypetests /home/tcwg-buildbot/worker/clang-armv8-quick/llvm/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll
+ /home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/FileCheck /home/tcwg-buildbot/worker/clang-armv8-quick/llvm/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll
/home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/opt: WARNING: failed to create target machine for 'x86_64-pc-windows-msvc': unable to get target for 'x86_64-pc-windows-msvc', see --version and --triple.
/home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/opt -S -passes=lowertypetests /home/tcwg-buildbot/worker/clang-armv8-quick/llvm/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll | /home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/llc -asm-verbose=false # RUN: at line 8
+ /home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/opt -S -passes=lowertypetests /home/tcwg-buildbot/worker/clang-armv8-quick/llvm/llvm/test/Transforms/LowerTypeTests/cfi-coff-comdat-rename.ll
+ /home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/llc -asm-verbose=false
/home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/opt: WARNING: failed to create target machine for 'x86_64-pc-windows-msvc': unable to get target for 'x86_64-pc-windows-msvc', see --version and --triple.
/home/tcwg-buildbot/worker/clang-armv8-quick/stage1/bin/llc: error: unable to get target for 'x86_64-pc-windows-msvc', see --version and --triple.

--

********************


PiJoules added a commit that referenced this pull request May 16, 2025
…139962)"

This reverts commit 33684ac.

Reverting since this is breaking a bunch of builders. See the llvm-ci
messages on #139962.
PiJoules added a commit that referenced this pull request May 16, 2025
…139962)"

This reapplies 33684ac with appropriate
requires on tests.

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 change the comdat name since symbol and
comdat resolution occurs before LTO, so we already know which symbols
are prevailing.
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request May 16, 2025
…a comdat (#139962)"

This reverts commit 33684ac.

Reverting since this is breaking a bunch of builders. See the llvm-ci
messages on llvm/llvm-project#139962.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants