[llvm] WIP snapshot: BBAddrMap COFF YAML (PR #202521)
Haohai Wen via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 9 00:12:39 PDT 2026
https://github.com/HaohaiWen created https://github.com/llvm/llvm-project/pull/202521
None
>From 18cfe473d6ba489daada259c51ae43e09fdaf106 Mon Sep 17 00:00:00 2001
From: Haohai Wen <haohai.wen at intel.com>
Date: Tue, 9 Jun 2026 14:59:27 +0800
Subject: [PATCH] WIP snapshot: BBAddrMap COFF YAML
---
llvm/include/llvm/ObjectYAML/BBAddrMapYAML.h | 32 +++++
llvm/lib/ObjectYAML/BBAddrMapYAML.cpp | 127 ++++++++++++++++++
llvm/lib/ObjectYAML/ELFEmitter.cpp | 120 +----------------
llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml | 2 +-
4 files changed, 167 insertions(+), 114 deletions(-)
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:
More information about the llvm-commits
mailing list