[llvm] WIP snapshot: BBAddrMap COFF YAML (PR #202521)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 9 00:13:17 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-objectyaml

Author: Haohai Wen (HaohaiWen)

<details>
<summary>Changes</summary>



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


4 Files Affected:

- (modified) llvm/include/llvm/ObjectYAML/BBAddrMapYAML.h (+32) 
- (modified) llvm/lib/ObjectYAML/BBAddrMapYAML.cpp (+127) 
- (modified) llvm/lib/ObjectYAML/ELFEmitter.cpp (+7-113) 
- (modified) llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml (+1-1) 


``````````diff
diff --git a/llvm/include/llvm/ObjectYAML/BBAddrMapYAML.h b/llvm/include/llvm/ObjectYAML/BBAddrMapYAML.h
index ddf139b025015..89b62ea1a5a99 100644
--- a/llvm/include/llvm/ObjectYAML/BBAddrMapYAML.h
+++ b/llvm/include/llvm/ObjectYAML/BBAddrMapYAML.h
@@ -16,6 +16,9 @@
 #ifndef LLVM_OBJECTYAML_BBADDRMAPYAML_H
 #define LLVM_OBJECTYAML_BBADDRMAPYAML_H
 
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/bit.h"
+#include "llvm/Support/EndianStream.h"
 #include "llvm/Support/YAMLTraits.h"
 #include <cstdint>
 #include <optional>
@@ -81,6 +84,35 @@ struct PGOAnalysisMapEntry {
   std::optional<std::vector<PGOBBEntry>> PGOBBEntries;
 };
 
+/// Byte sink for encoding a BB address map section body.
+class Encoder {
+  raw_ostream &OS;
+  llvm::endianness Endian;
+  unsigned AddressSize;
+  uint64_t NumBytes = 0;
+
+public:
+  Encoder(raw_ostream &OS, llvm::endianness Endian, unsigned AddressSize)
+      : OS(OS), Endian(Endian), AddressSize(AddressSize) {
+    assert((AddressSize == 4 || AddressSize == 8) && "invalid address size");
+  }
+
+  /// Total bytes written so far.
+  uint64_t getNumBytes() const { return NumBytes; }
+
+  template <typename T> void writeInteger(T Value) {
+    support::endian::write<T>(OS, Value, Endian);
+    NumBytes += sizeof(T);
+  }
+  void writeAddress(uint64_t Address);
+  void writeULEB128(uint64_t Value);
+};
+
+/// Shared ELF/COFF yaml2obj encoder. Warns and continues on malformed YAML.
+uint64_t encodePayload(ArrayRef<BBAddrMapEntry> Entries,
+                       const std::vector<PGOAnalysisMapEntry> *PGOAnalyses,
+                       Encoder &E);
+
 } // end namespace BBAddrMapYAML
 } // end namespace llvm
 
diff --git a/llvm/lib/ObjectYAML/BBAddrMapYAML.cpp b/llvm/lib/ObjectYAML/BBAddrMapYAML.cpp
index fbeda0d7f4ef5..94066872ebcf9 100644
--- a/llvm/lib/ObjectYAML/BBAddrMapYAML.cpp
+++ b/llvm/lib/ObjectYAML/BBAddrMapYAML.cpp
@@ -13,8 +13,135 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ObjectYAML/BBAddrMapYAML.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Object/BBAddrMap.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/WithColor.h"
 
 namespace llvm {
+
+void BBAddrMapYAML::Encoder::writeAddress(uint64_t Address) {
+  if (AddressSize == 8)
+    writeInteger<uint64_t>(Address);
+  else
+    writeInteger<uint32_t>(static_cast<uint32_t>(Address));
+}
+
+void BBAddrMapYAML::Encoder::writeULEB128(uint64_t Value) {
+  NumBytes += encodeULEB128(Value, OS);
+}
+
+uint64_t BBAddrMapYAML::encodePayload(
+    ArrayRef<BBAddrMapYAML::BBAddrMapEntry> Entries,
+    const std::vector<BBAddrMapYAML::PGOAnalysisMapEntry> *PGOAnalyses,
+    BBAddrMapYAML::Encoder &E) {
+  uint64_t StartBytes = E.getNumBytes();
+
+  for (const auto &[Idx, Entry] : llvm::enumerate(Entries)) {
+    if (Entry.Version > 5)
+      WithColor::warning() << "unsupported BB address map version: "
+                           << static_cast<int>(Entry.Version)
+                           << "; encoding using the most recent version";
+    E.writeInteger<uint8_t>(Entry.Version);
+    if (Entry.Version < 5)
+      E.writeInteger<uint8_t>(static_cast<uint8_t>(Entry.Feature));
+    else
+      E.writeInteger<uint16_t>(Entry.Feature);
+
+    auto FeatureOrErr = object::BBAddrMap::Features::decode(Entry.Feature);
+    bool MultiBBRangeFeatureEnabled = false;
+    if (!FeatureOrErr)
+      WithColor::warning() << toString(FeatureOrErr.takeError());
+    else
+      MultiBBRangeFeatureEnabled = FeatureOrErr->MultiBBRange;
+    bool MultiBBRange =
+        MultiBBRangeFeatureEnabled ||
+        (Entry.NumBBRanges.has_value() && Entry.NumBBRanges.value() != 1) ||
+        (Entry.BBRanges && Entry.BBRanges->size() != 1);
+    if (MultiBBRange && !MultiBBRangeFeatureEnabled)
+      WithColor::warning() << "feature value(" << Entry.Feature
+                           << ") does not support multiple BB ranges.";
+    if (MultiBBRange) {
+      // Write the number of basic block ranges, which is overridden by the
+      // 'NumBBRanges' field when specified.
+      E.writeULEB128(Entry.NumBBRanges.value_or(
+          Entry.BBRanges ? Entry.BBRanges->size() : 0));
+    }
+    if (!Entry.BBRanges)
+      continue;
+    uint64_t TotalNumBlocks = 0;
+    bool EmitCallsiteEndOffsets =
+        FeatureOrErr->CallsiteEndOffsets || Entry.hasAnyCallsiteEndOffsets();
+    for (const BBAddrMapYAML::BBAddrMapEntry::BBRangeEntry &BBR :
+         *Entry.BBRanges) {
+      // Write the base address of the range.
+      E.writeAddress(BBR.BaseAddress);
+      // Write number of BBEntries (number of basic blocks in this basic block
+      // range). This is overridden by the 'NumBlocks' YAML field when
+      // specified.
+      E.writeULEB128(
+          BBR.NumBlocks.value_or(BBR.BBEntries ? BBR.BBEntries->size() : 0));
+      if (!BBR.BBEntries || FeatureOrErr->OmitBBEntries)
+        continue;
+      for (const BBAddrMapYAML::BBAddrMapEntry::BBEntry &BBE : *BBR.BBEntries) {
+        ++TotalNumBlocks;
+        if (Entry.Version > 1)
+          E.writeULEB128(BBE.ID);
+        E.writeULEB128(BBE.AddressOffset);
+        if (EmitCallsiteEndOffsets) {
+          size_t NumCallsiteEndOffsets =
+              BBE.CallsiteEndOffsets ? BBE.CallsiteEndOffsets->size() : 0;
+          E.writeULEB128(NumCallsiteEndOffsets);
+          if (BBE.CallsiteEndOffsets) {
+            for (uint32_t Offset : *BBE.CallsiteEndOffsets)
+              E.writeULEB128(Offset);
+          }
+        }
+        E.writeULEB128(BBE.Size);
+        E.writeULEB128(BBE.Metadata);
+        if (FeatureOrErr->BBHash || BBE.Hash.has_value())
+          E.writeInteger<uint64_t>(BBE.Hash.has_value() ? BBE.Hash.value()
+                                                        : llvm::yaml::Hex64(0));
+      }
+    }
+    if (!PGOAnalyses)
+      continue;
+    const BBAddrMapYAML::PGOAnalysisMapEntry &PGOEntry = PGOAnalyses->at(Idx);
+
+    if (PGOEntry.FuncEntryCount)
+      E.writeULEB128(*PGOEntry.FuncEntryCount);
+
+    if (!PGOEntry.PGOBBEntries)
+      continue;
+
+    const auto &PGOBBEntries = PGOEntry.PGOBBEntries.value();
+    if (TotalNumBlocks != PGOBBEntries.size()) {
+      WithColor::warning() << "PGOBBEntries must be the same length as "
+                              "BBEntries in the BB address map.\n"
+                           << "Mismatch on function with address: "
+                           << Entry.getFunctionAddress();
+      continue;
+    }
+
+    for (const auto &PGOBBE : PGOBBEntries) {
+      if (PGOBBE.BBFreq)
+        E.writeULEB128(*PGOBBE.BBFreq);
+      if (FeatureOrErr->PostLinkCfg || PGOBBE.PostLinkBBFreq.has_value())
+        E.writeULEB128(PGOBBE.PostLinkBBFreq.value_or(0));
+      if (PGOBBE.Successors) {
+        E.writeULEB128(PGOBBE.Successors->size());
+        for (const auto &[ID, BrProb, PostLinkBrFreq] : *PGOBBE.Successors) {
+          E.writeULEB128(ID);
+          E.writeULEB128(BrProb);
+          if (FeatureOrErr->PostLinkCfg || PostLinkBrFreq.has_value())
+            E.writeULEB128(PostLinkBrFreq.value_or(0));
+        }
+      }
+    }
+  }
+  return E.getNumBytes() - StartBytes;
+}
+
 namespace yaml {
 
 void MappingTraits<BBAddrMapYAML::BBAddrMapEntry>::mapping(
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index b60b27ff6f082..9e94a5f02fb9e 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -1462,119 +1462,13 @@ void ELFState<ELFT>::writeSectionContent(
       PGOAnalyses = &Section.PGOAnalyses.value();
   }
 
-  for (const auto &[Idx, E] : llvm::enumerate(*Section.Entries)) {
-    // Write version and feature values.
-    if (Section.Type == llvm::ELF::SHT_LLVM_BB_ADDR_MAP) {
-      if (E.Version > 5)
-        WithColor::warning() << "unsupported SHT_LLVM_BB_ADDR_MAP version: "
-                             << static_cast<int>(E.Version)
-                             << "; encoding using the most recent version";
-      CBA.write(E.Version);
-      SHeader.sh_size += 1;
-      if (E.Version < 5) {
-        CBA.write(static_cast<uint8_t>(E.Feature));
-        SHeader.sh_size += 1;
-      } else {
-        CBA.write<uint16_t>(E.Feature, ELFT::Endianness);
-        SHeader.sh_size += 2;
-      }
-    }
-    auto FeatureOrErr = llvm::object::BBAddrMap::Features::decode(E.Feature);
-    bool MultiBBRangeFeatureEnabled = false;
-    if (!FeatureOrErr)
-      WithColor::warning() << toString(FeatureOrErr.takeError());
-    else
-      MultiBBRangeFeatureEnabled = FeatureOrErr->MultiBBRange;
-    bool MultiBBRange =
-        MultiBBRangeFeatureEnabled ||
-        (E.NumBBRanges.has_value() && E.NumBBRanges.value() != 1) ||
-        (E.BBRanges && E.BBRanges->size() != 1);
-    if (MultiBBRange && !MultiBBRangeFeatureEnabled)
-      WithColor::warning() << "feature value(" << E.Feature
-                           << ") does not support multiple BB ranges.";
-    if (MultiBBRange) {
-      // Write the number of basic block ranges, which is overridden by the
-      // 'NumBBRanges' field when specified.
-      uint64_t NumBBRanges =
-          E.NumBBRanges.value_or(E.BBRanges ? E.BBRanges->size() : 0);
-      SHeader.sh_size += CBA.writeULEB128(NumBBRanges);
-    }
-    if (!E.BBRanges)
-      continue;
-    uint64_t TotalNumBlocks = 0;
-    bool EmitCallsiteEndOffsets =
-        FeatureOrErr->CallsiteEndOffsets || E.hasAnyCallsiteEndOffsets();
-    for (const BBAddrMapYAML::BBAddrMapEntry::BBRangeEntry &BBR : *E.BBRanges) {
-      // Write the base address of the range.
-      CBA.write<uintX_t>(BBR.BaseAddress, ELFT::Endianness);
-      // Write number of BBEntries (number of basic blocks in this basic block
-      // range). This is overridden by the 'NumBlocks' YAML field when
-      // specified.
-      uint64_t NumBlocks =
-          BBR.NumBlocks.value_or(BBR.BBEntries ? BBR.BBEntries->size() : 0);
-      SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(NumBlocks);
-      // Write all BBEntries in this BBRange.
-      if (!BBR.BBEntries || FeatureOrErr->OmitBBEntries)
-        continue;
-      for (const BBAddrMapYAML::BBAddrMapEntry::BBEntry &BBE : *BBR.BBEntries) {
-        ++TotalNumBlocks;
-        if (Section.Type == llvm::ELF::SHT_LLVM_BB_ADDR_MAP && E.Version > 1)
-          SHeader.sh_size += CBA.writeULEB128(BBE.ID);
-        SHeader.sh_size += CBA.writeULEB128(BBE.AddressOffset);
-        if (EmitCallsiteEndOffsets) {
-          size_t NumCallsiteEndOffsets =
-              BBE.CallsiteEndOffsets ? BBE.CallsiteEndOffsets->size() : 0;
-          SHeader.sh_size += CBA.writeULEB128(NumCallsiteEndOffsets);
-          if (BBE.CallsiteEndOffsets) {
-            for (uint32_t Offset : *BBE.CallsiteEndOffsets)
-              SHeader.sh_size += CBA.writeULEB128(Offset);
-          }
-        }
-        SHeader.sh_size += CBA.writeULEB128(BBE.Size);
-        SHeader.sh_size += CBA.writeULEB128(BBE.Metadata);
-        if (FeatureOrErr->BBHash || BBE.Hash.has_value()) {
-          uint64_t Hash =
-              BBE.Hash.has_value() ? BBE.Hash.value() : llvm::yaml::Hex64(0);
-          CBA.write<uint64_t>(Hash, ELFT::Endianness);
-          SHeader.sh_size += 8;
-        }
-      }
-    }
-    if (!PGOAnalyses)
-      continue;
-    const BBAddrMapYAML::PGOAnalysisMapEntry &PGOEntry = PGOAnalyses->at(Idx);
-
-    if (PGOEntry.FuncEntryCount)
-      SHeader.sh_size += CBA.writeULEB128(*PGOEntry.FuncEntryCount);
-
-    if (!PGOEntry.PGOBBEntries)
-      continue;
-
-    const auto &PGOBBEntries = PGOEntry.PGOBBEntries.value();
-    if (TotalNumBlocks != PGOBBEntries.size()) {
-      WithColor::warning() << "PBOBBEntries must be the same length as "
-                              "BBEntries in SHT_LLVM_BB_ADDR_MAP.\n"
-                           << "Mismatch on function with address: "
-                           << E.getFunctionAddress();
-      continue;
-    }
-
-    for (const auto &PGOBBE : PGOBBEntries) {
-      if (PGOBBE.BBFreq)
-        SHeader.sh_size += CBA.writeULEB128(*PGOBBE.BBFreq);
-      if (FeatureOrErr->PostLinkCfg || PGOBBE.PostLinkBBFreq.has_value())
-        SHeader.sh_size += CBA.writeULEB128(PGOBBE.PostLinkBBFreq.value_or(0));
-      if (PGOBBE.Successors) {
-        SHeader.sh_size += CBA.writeULEB128(PGOBBE.Successors->size());
-        for (const auto &[ID, BrProb, PostLinkBrFreq] : *PGOBBE.Successors) {
-          SHeader.sh_size += CBA.writeULEB128(ID);
-          SHeader.sh_size += CBA.writeULEB128(BrProb);
-          if (FeatureOrErr->PostLinkCfg || PostLinkBrFreq.has_value())
-            SHeader.sh_size += CBA.writeULEB128(PostLinkBrFreq.value_or(0));
-        }
-      }
-    }
-  }
+  // The payload encoder is format-neutral and shared with the COFF emitter.
+  SmallString<128> Buf;
+  raw_svector_ostream OS(Buf);
+  BBAddrMapYAML::Encoder E{OS, ELFT::Endianness, sizeof(uintX_t)};
+  SHeader.sh_size +=
+      BBAddrMapYAML::encodePayload(*Section.Entries, PGOAnalyses, E);
+  CBA.write(Buf.data(), Buf.size());
 }
 
 template <class ELFT>
diff --git a/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml b/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml
index 05d77d67e4468..2b2fd43b243d9 100644
--- a/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml
@@ -220,7 +220,7 @@ Sections:
 
 ## Check that yaml2obj generates a warning when we use unsupported versions.
 # RUN: yaml2obj --docnum=3  %s 2>&1 | FileCheck %s --check-prefix=INVALID-VERSION
-# INVALID-VERSION: warning: unsupported SHT_LLVM_BB_ADDR_MAP version: 6; encoding using the most recent version
+# INVALID-VERSION: warning: unsupported BB address map version: 6; encoding using the most recent version
 
 --- !ELF
 FileHeader:

``````````

</details>


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


More information about the llvm-commits mailing list