https://github.com/HaohaiWen created 
https://github.com/llvm/llvm-project/pull/191347

Enable -fbasic-block-address-map fo X86 COFF.
Add COFF section creation for .llvm_bb_addr_map.

>From ad2ca2b69e5ba4ba7b6808d9b716fdb269e6f2eb Mon Sep 17 00:00:00 2001
From: Haohai Wen <[email protected]>
Date: Tue, 7 Apr 2026 15:44:11 +0800
Subject: [PATCH] [X86][COFF] Enable basic-block-address-map emission

Enable -fbasic-block-address-map fo X86 COFF.
Add COFF section creation for .llvm_bb_addr_map.
---
 clang/lib/Driver/ToolChains/Clang.cpp         |  3 +-
 clang/test/Driver/basic-block-address-map.c   |  1 +
 llvm/include/llvm/Object/BBAddrMap.h          |  3 ++
 llvm/lib/MC/MCObjectFileInfo.cpp              | 45 +++++++++++++------
 ...sic-block-address-map-function-sections.ll | 32 +++++++++----
 .../CodeGen/X86/basic-block-address-map.ll    | 13 ++++--
 6 files changed, 70 insertions(+), 27 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 0d5722cd536f2..57f342273fef6 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6280,7 +6280,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
 
   if (Arg *A = Args.getLastArg(options::OPT_fbasic_block_address_map,
                                options::OPT_fno_basic_block_address_map)) {
-    if ((Triple.isX86() || Triple.isAArch64()) && Triple.isOSBinFormatELF()) {
+    if (((Triple.isX86() || Triple.isAArch64()) && Triple.isOSBinFormatELF()) 
||
+        (Triple.isX86() && Triple.isOSBinFormatCOFF())) {
       if (A->getOption().matches(options::OPT_fbasic_block_address_map))
         A->render(Args, CmdArgs);
     } else {
diff --git a/clang/test/Driver/basic-block-address-map.c 
b/clang/test/Driver/basic-block-address-map.c
index 12393e8ebfd54..b11dbb3c65548 100644
--- a/clang/test/Driver/basic-block-address-map.c
+++ b/clang/test/Driver/basic-block-address-map.c
@@ -1,5 +1,6 @@
 // RUN: %clang -### --target=x86_64 -fbasic-block-address-map %s -S 2>&1 | 
FileCheck -check-prefix=CHECK-PRESENT %s
 // RUN: %clang -### --target=aarch64 -fbasic-block-address-map %s -S 2>&1 | 
FileCheck -check-prefix=CHECK-PRESENT %s
+// RUN: %clang -### --target=x86_64-pc-windows-msvc -fbasic-block-address-map 
%s -S 2>&1 | FileCheck -check-prefix=CHECK-PRESENT %s
 // CHECK-PRESENT: -fbasic-block-address-map
 
 // RUN: %clang -### --target=x86_64 -fno-basic-block-address-map %s -S 2>&1 | 
FileCheck %s --check-prefix=CHECK-ABSENT
diff --git a/llvm/include/llvm/Object/BBAddrMap.h 
b/llvm/include/llvm/Object/BBAddrMap.h
index 49c9b431822e0..4f710bc19951e 100644
--- a/llvm/include/llvm/Object/BBAddrMap.h
+++ b/llvm/include/llvm/Object/BBAddrMap.h
@@ -15,6 +15,7 @@
 #define LLVM_OBJECT_BBADDRMAP_H
 
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/BlockFrequency.h"
 #include "llvm/Support/BranchProbability.h"
 #include "llvm/Support/DataExtractor.h"
@@ -24,6 +25,8 @@
 namespace llvm {
 namespace object {
 
+inline constexpr StringLiteral BBAddrMapSectionName = ".llvm_bb_addr_map";
+
 // Struct representing the BBAddrMap for one function.
 struct BBAddrMap {
 
diff --git a/llvm/lib/MC/MCObjectFileInfo.cpp b/llvm/lib/MC/MCObjectFileInfo.cpp
index 56a22241ae5d3..1e78e5fe2cc49 100644
--- a/llvm/lib/MC/MCObjectFileInfo.cpp
+++ b/llvm/lib/MC/MCObjectFileInfo.cpp
@@ -27,6 +27,7 @@
 #include "llvm/MC/MCSectionXCOFF.h"
 #include "llvm/MC/MCSymbolGOFF.h"
 #include "llvm/MC/SectionKind.h"
+#include "llvm/Object/BBAddrMap.h"
 #include "llvm/TargetParser/Triple.h"
 
 using namespace llvm;
@@ -1266,23 +1267,39 @@ MCObjectFileInfo::getStackSizesSection(const MCSection 
&TextSec) const {
 
 MCSection *
 MCObjectFileInfo::getBBAddrMapSection(const MCSection &TextSec) const {
-  if (Ctx->getObjectFileType() != MCContext::IsELF)
-    return nullptr;
+  StringRef Name = object::BBAddrMapSectionName;
+  if (Ctx->getObjectFileType() == MCContext::IsELF) {
+    const MCSectionELF &ElfSec = static_cast<const MCSectionELF &>(TextSec);
+    unsigned Flags = ELF::SHF_LINK_ORDER;
+    StringRef GroupName;
+    if (const MCSymbol *Group = ElfSec.getGroup()) {
+      GroupName = Group->getName();
+      Flags |= ELF::SHF_GROUP;
+    }
 
-  const MCSectionELF &ElfSec = static_cast<const MCSectionELF &>(TextSec);
-  unsigned Flags = ELF::SHF_LINK_ORDER;
-  StringRef GroupName;
-  if (const MCSymbol *Group = ElfSec.getGroup()) {
-    GroupName = Group->getName();
-    Flags |= ELF::SHF_GROUP;
+    // Use the text section's begin symbol and unique ID to create a separate
+    // .llvm_bb_addr_map section associated with every unique text section.
+    return Ctx->getELFSection(
+        Name, ELF::SHT_LLVM_BB_ADDR_MAP, Flags, 0, GroupName, true,
+        ElfSec.getUniqueID(),
+        static_cast<const MCSymbolELF *>(TextSec.getBeginSymbol()));
+  } else if (Ctx->getObjectFileType() == MCContext::IsCOFF) {
+    StringRef COMDATSymName = "";
+    int Selection = 0;
+    unsigned Characteristics = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+                               COFF::IMAGE_SCN_MEM_DISCARDABLE |
+                               COFF::IMAGE_SCN_MEM_READ;
+    const auto &COFFSec = static_cast<const MCSectionCOFF &>(TextSec);
+    if (const MCSymbol *COMDATSym = COFFSec.getCOMDATSymbol()) {
+      COMDATSymName = COMDATSym->getName();
+      Characteristics |= COFF::IMAGE_SCN_LNK_COMDAT;
+      Selection = COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
+    }
+    return Ctx->getCOFFSection(Name, Characteristics, COMDATSymName, Selection,
+                               COFFSec.getUniqueID());
   }
 
-  // Use the text section's begin symbol and unique ID to create a separate
-  // .llvm_bb_addr_map section associated with every unique text section.
-  return Ctx->getELFSection(
-      ".llvm_bb_addr_map", ELF::SHT_LLVM_BB_ADDR_MAP, Flags, 0, GroupName, 
true,
-      ElfSec.getUniqueID(),
-      static_cast<const MCSymbolELF *>(TextSec.getBeginSymbol()));
+  return nullptr;
 }
 
 MCSection *
diff --git a/llvm/test/CodeGen/X86/basic-block-address-map-function-sections.ll 
b/llvm/test/CodeGen/X86/basic-block-address-map-function-sections.ll
index 892fa009935d2..2f4be8ab9fd06 100644
--- a/llvm/test/CodeGen/X86/basic-block-address-map-function-sections.ll
+++ b/llvm/test/CodeGen/X86/basic-block-address-map-function-sections.ll
@@ -1,15 +1,23 @@
-; RUN: llc < %s -mtriple=x86_64 -function-sections -basic-block-address-map | 
FileCheck %s
+; RUN: llc < %s -mtriple=x86_64 -function-sections -basic-block-address-map | 
FileCheck %s --check-prefixes=CHECK,ELF,ELF-FS
+; RUN: llc < %s -mtriple=x86_64 -basic-block-address-map | FileCheck %s 
--check-prefixes=CHECK,ELF,ELF-NOFS
+; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc -function-sections 
-basic-block-address-map | FileCheck %s --check-prefixes=CHECK,COFF-FS
+; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc -basic-block-address-map | 
FileCheck %s --check-prefixes=CHECK,COFF-NOFS
 
 $_Z4fooTIiET_v = comdat any
 
 define dso_local i32 @_Z3barv() {
   ret i32 0
 }
-;; Check we add SHF_LINK_ORDER for .llvm_bb_addr_map and link it with the 
corresponding .text sections.
-; CHECK:               .section .text._Z3barv,"ax",@progbits
+;; For ELF, check we add SHF_LINK_ORDER for .llvm_bb_addr_map and link it with 
the corresponding .text sections.
+;; For COFF, it does not have SHF_LINK_ORDER like mechanism, we use function 
symbol to "link" them.
+; ELF-FS:              .section .text._Z3barv,"ax",@progbits
+; COFF-FS:             .section .text,"xr",one_only,_Z3barv
 ; CHECK-LABEL: _Z3barv:
 ; CHECK-NEXT:  [[BAR_BEGIN:.Lfunc_begin[0-9]+]]:
-; CHECK:               .section 
.llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3barv{{$}}
+; ELF-FS:              .section 
.llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3barv{{$}}
+; ELF-NOFS:            .section 
.llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text{{$}}
+; COFF-FS:             .section 
.llvm_bb_addr_map,"drD",associative,_Z3barv,unique,0{{$}}
+; COFF-NOFS:           .section .llvm_bb_addr_map,"drD"{{$}}
 ; CHECK-NEXT:          .byte  5                        # version
 ; CHECK-NEXT:          .short 0                        # feature
 ; CHECK-NEXT:          .quad [[BAR_BEGIN]]     # function address
@@ -19,10 +27,14 @@ define dso_local i32 @_Z3foov() {
   %1 = call i32 @_Z4fooTIiET_v()
   ret i32 %1
 }
-; CHECK:               .section .text._Z3foov,"ax",@progbits
+; ELF-FS:              .section .text._Z3foov,"ax",@progbits
+; COFF-FS:             .section .text,"xr",one_only,_Z3foov
 ; CHECK-LABEL: _Z3foov:
 ; CHECK-NEXT:  [[FOO_BEGIN:.Lfunc_begin[0-9]+]]:
-; CHECK:               .section  
.llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3foov{{$}}
+; ELF-FS:              .section 
.llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3foov{{$}}
+; ELF-NOFS:            .section 
.llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text{{$}}
+; COFF-FS:             .section 
.llvm_bb_addr_map,"drD",associative,_Z3foov,unique,1{{$}}
+; COFF-NOFS:           .section .llvm_bb_addr_map,"drD"{{$}}
 ; CHECK-NEXT:          .byte  5                        # version
 ; CHECK-NEXT:          .short 32                # feature
 ; CHECK-NEXT:          .quad [[FOO_BEGIN]]     # function address
@@ -32,10 +44,14 @@ define linkonce_odr dso_local i32 @_Z4fooTIiET_v() comdat {
   ret i32 0
 }
 ;; Check we add .llvm_bb_addr_map section to a COMDAT group with the 
corresponding .text section if such a COMDAT exists.
-; CHECK:               .section 
.text._Z4fooTIiET_v,"axG",@progbits,_Z4fooTIiET_v,comdat
+; ELF:                 .section 
.text._Z4fooTIiET_v,"axG",@progbits,_Z4fooTIiET_v,comdat
+; COFF-FS:             .section .text,"xr",discard,_Z4fooTIiET_v,unique,2{{$}}
+; COFF-NOFS:           .section .text,"xr",discard,_Z4fooTIiET_v{{$}}
 ; CHECK-LABEL: _Z4fooTIiET_v:
 ; CHECK-NEXT:  [[FOOCOMDAT_BEGIN:.Lfunc_begin[0-9]+]]:
-; CHECK:               .section 
.llvm_bb_addr_map,"oG",@llvm_bb_addr_map,.text._Z4fooTIiET_v,_Z4fooTIiET_v,comdat{{$}}
+; ELF:                 .section 
.llvm_bb_addr_map,"oG",@llvm_bb_addr_map,.text._Z4fooTIiET_v,_Z4fooTIiET_v,comdat{{$}}
+; COFF-FS:             .section 
.llvm_bb_addr_map,"drD",associative,_Z4fooTIiET_v,unique,2{{$}}
+; COFF-NOFS:           .section 
.llvm_bb_addr_map,"drD",associative,_Z4fooTIiET_v{{$}}
 ; CHECK-NEXT:          .byte  5                                # version
 ; CHECK-NEXT:          .short 0                                # feature
 ; CHECK-NEXT:          .quad [[FOOCOMDAT_BEGIN]]       # function address
diff --git a/llvm/test/CodeGen/X86/basic-block-address-map.ll 
b/llvm/test/CodeGen/X86/basic-block-address-map.ll
index 5567ccd4f9e75..c716e12a57646 100644
--- a/llvm/test/CodeGen/X86/basic-block-address-map.ll
+++ b/llvm/test/CodeGen/X86/basic-block-address-map.ll
@@ -1,7 +1,8 @@
 ; Check the basic block sections labels option
-; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=true 
-basic-block-address-map | FileCheck %s --check-prefixes=CHECK,UNIQ
-; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=false 
-basic-block-address-map | FileCheck %s --check-prefixes=CHECK,NOUNIQ
-; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=true 
-basic-block-address-map -split-machine-functions | FileCheck %s 
--check-prefixes=CHECK,UNIQ
+; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=true 
-basic-block-address-map | FileCheck %s --check-prefixes=CHECK,ELF,UNIQ
+; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=false 
-basic-block-address-map | FileCheck %s --check-prefixes=CHECK,ELF,NOUNIQ
+; RUN: llc < %s -mtriple=x86_64 -function-sections -unique-section-names=true 
-basic-block-address-map -split-machine-functions | FileCheck %s 
--check-prefixes=CHECK,ELF,UNIQ
+; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc -function-sections 
-basic-block-address-map | FileCheck %s --check-prefixes=CHECK,COFF
 
 define void @_Z3bazb(i1 zeroext, i1 zeroext) personality ptr 
@__gxx_personality_v0 {
   br i1 %0, label %3, label %8
@@ -52,6 +53,7 @@ declare i32 @__gxx_personality_v0(...)
 ; UNIQ:                        .section        
.llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text._Z3bazb{{$}}
 ;; Verify that with -unique-section-names=false, the unique id of the text 
section gets assigned to the llvm_bb_addr_map section.
 ; NOUNIQ:              .section        
.llvm_bb_addr_map,"o",@llvm_bb_addr_map,.text,unique,1
+; COFF:                        .section        
.llvm_bb_addr_map,"drD",associative,_Z3bazb,unique,0{{$}}
 ; CHECK-NEXT:   .byte   5              # version
 ; CHECK-NEXT:   .short  32             # feature
 ; CHECK-NEXT:  .quad   .Lfunc_begin0   # function address
@@ -87,4 +89,7 @@ declare i32 @__gxx_personality_v0(...)
 ; CHECK-NEXT:  .uleb128 .LBB0_5-.LBB_END0_4
 ; CHECK-NEXT:   .byte  0               # number of callsites
 ; CHECK-NEXT:  .uleb128 .LBB_END0_5-.LBB0_5
-; CHECK-NEXT:  .byte   5
+;; The landingpad block metadata differs: ELF uses eh_frame (HasReturn set),
+;; COFF uses SEH (HasReturn not set).
+; ELF-NEXT:    .byte   5
+; COFF-NEXT:   .byte   4

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to