[llvm] [SHT_LLVM_BB_ADDR_MAP] Encode and decode callsite offsets in a newly-introduced SHT_LLVM_BB_ADDR_MAP version. (PR #144426)
Rahman Lavaee via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 17 16:51:39 PDT 2025
https://github.com/rlavaee updated https://github.com/llvm/llvm-project/pull/144426
>From 0b2502822555c9ea7a7b0fff3976553bf0d87f39 Mon Sep 17 00:00:00 2001
From: Rahman Lavaee <rahmanl at google.com>
Date: Mon, 16 Jun 2025 18:59:42 +0000
Subject: [PATCH] Introduce the new SHT_LLVM_BB_ADDR_MAP version 3, to allow
encoding callsite offsets.
---
llvm/include/llvm/Object/ELFTypes.h | 22 +++--
llvm/include/llvm/ObjectYAML/ELFYAML.h | 21 +++++
llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 7 +-
llvm/lib/Object/ELF.cpp | 33 ++++++-
llvm/lib/ObjectYAML/ELFEmitter.cpp | 13 ++-
llvm/lib/ObjectYAML/ELFYAML.cpp | 1 +
.../tools/llvm-readobj/ELF/bb-addr-map.test | 10 +-
llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml | 30 +++---
llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml | 48 +++++++---
llvm/tools/llvm-readobj/ELFDumper.cpp | 2 +
llvm/tools/obj2yaml/elf2yaml.cpp | 14 ++-
llvm/unittests/Object/ELFObjectFileTest.cpp | 94 ++++++++++++-------
llvm/unittests/Object/ELFTypesTest.cpp | 31 +++---
13 files changed, 230 insertions(+), 96 deletions(-)
diff --git a/llvm/include/llvm/Object/ELFTypes.h b/llvm/include/llvm/Object/ELFTypes.h
index 87e4dbe448091..d7a468f1116d7 100644
--- a/llvm/include/llvm/Object/ELFTypes.h
+++ b/llvm/include/llvm/Object/ELFTypes.h
@@ -831,6 +831,7 @@ struct BBAddrMap {
bool BrProb : 1;
bool MultiBBRange : 1;
bool OmitBBEntries : 1;
+ bool CallsiteOffsets : 1;
bool hasPGOAnalysis() const { return FuncEntryCount || BBFreq || BrProb; }
@@ -842,7 +843,8 @@ struct BBAddrMap {
(static_cast<uint8_t>(BBFreq) << 1) |
(static_cast<uint8_t>(BrProb) << 2) |
(static_cast<uint8_t>(MultiBBRange) << 3) |
- (static_cast<uint8_t>(OmitBBEntries) << 4);
+ (static_cast<uint8_t>(OmitBBEntries) << 4) |
+ (static_cast<uint8_t>(CallsiteOffsets) << 5);
}
// Decodes from minimum bit width representation and validates no
@@ -851,7 +853,7 @@ struct BBAddrMap {
Features Feat{
static_cast<bool>(Val & (1 << 0)), static_cast<bool>(Val & (1 << 1)),
static_cast<bool>(Val & (1 << 2)), static_cast<bool>(Val & (1 << 3)),
- static_cast<bool>(Val & (1 << 4))};
+ static_cast<bool>(Val & (1 << 4)), static_cast<bool>(Val & (1 << 5))};
if (Feat.encode() != Val)
return createStringError(
std::error_code(), "invalid encoding for BBAddrMap::Features: 0x%x",
@@ -861,9 +863,10 @@ struct BBAddrMap {
bool operator==(const Features &Other) const {
return std::tie(FuncEntryCount, BBFreq, BrProb, MultiBBRange,
- OmitBBEntries) ==
+ OmitBBEntries, CallsiteOffsets) ==
std::tie(Other.FuncEntryCount, Other.BBFreq, Other.BrProb,
- Other.MultiBBRange, Other.OmitBBEntries);
+ Other.MultiBBRange, Other.OmitBBEntries,
+ Other.CallsiteOffsets);
}
};
@@ -914,13 +917,18 @@ struct BBAddrMap {
uint32_t Size = 0; // Size of the basic block.
Metadata MD = {false, false, false, false,
false}; // Metdata for this basic block.
+ // Offsets of callsites (end of call instructions), relative to the basic
+ // block start.
+ SmallVector<uint32_t, 1> CallsiteOffsets;
- BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, Metadata MD)
- : ID(ID), Offset(Offset), Size(Size), MD(MD){};
+ BBEntry(uint32_t ID, uint32_t Offset, uint32_t Size, Metadata MD,
+ SmallVector<uint32_t, 1> CallsiteOffsets)
+ : ID(ID), Offset(Offset), Size(Size), MD(MD),
+ CallsiteOffsets(std::move(CallsiteOffsets)) {}
bool operator==(const BBEntry &Other) const {
return ID == Other.ID && Offset == Other.Offset && Size == Other.Size &&
- MD == Other.MD;
+ MD == Other.MD && CallsiteOffsets == Other.CallsiteOffsets;
}
bool hasReturn() const { return MD.HasReturn; }
diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h
index dfdfa055d65fa..27feb9a3eb892 100644
--- a/llvm/include/llvm/ObjectYAML/ELFYAML.h
+++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h
@@ -162,6 +162,13 @@ struct BBAddrMapEntry {
llvm::yaml::Hex64 AddressOffset;
llvm::yaml::Hex64 Size;
llvm::yaml::Hex64 Metadata;
+ std::optional<std::vector<llvm::yaml::Hex64>> CallsiteOffsets;
+
+ bool NumCallsiteOffsets() const {
+ if (!CallsiteOffsets.has_value())
+ return 0;
+ return CallsiteOffsets->size();
+ }
};
uint8_t Version;
llvm::yaml::Hex8 Feature;
@@ -180,6 +187,20 @@ struct BBAddrMapEntry {
return 0;
return BBRanges->front().BaseAddress;
}
+
+ // Returns if any BB entries have non-empty callsite offsets.
+ bool hasAnyCallsiteOffsets() const {
+ if (!BBRanges)
+ return false;
+ for (const ELFYAML::BBAddrMapEntry::BBRangeEntry &BBR : *BBRanges) {
+ if (!BBR.BBEntries)
+ continue;
+ for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *BBR.BBEntries)
+ if (BBE.CallsiteOffsets && !BBE.CallsiteOffsets->empty())
+ return true;
+ }
+ return false;
+ }
};
struct PGOAnalysisMapEntry {
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index a2c3b50b24670..107be4ea5324d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1426,9 +1426,12 @@ getBBAddrMapFeature(const MachineFunction &MF, int NumMBBSectionRanges) {
"BB entries info is required for BBFreq and BrProb "
"features");
}
- return {FuncEntryCountEnabled, BBFreqEnabled, BrProbEnabled,
+ return {FuncEntryCountEnabled,
+ BBFreqEnabled,
+ BrProbEnabled,
MF.hasBBSections() && NumMBBSectionRanges > 1,
- static_cast<bool>(BBAddrMapSkipEmitBBEntries)};
+ static_cast<bool>(BBAddrMapSkipEmitBBEntries),
+ false};
}
void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) {
diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp
index e6864ca508a54..753f9d38b919f 100644
--- a/llvm/lib/Object/ELF.cpp
+++ b/llvm/lib/Object/ELF.cpp
@@ -837,7 +837,7 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
Version = Data.getU8(Cur);
if (!Cur)
break;
- if (Version > 2)
+ if (Version > 3)
return createError("unsupported SHT_LLVM_BB_ADDR_MAP version: " +
Twine(static_cast<int>(Version)));
Feature = Data.getU8(Cur); // Feature byte
@@ -847,12 +847,18 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
if (!FeatEnableOrErr)
return FeatEnableOrErr.takeError();
FeatEnable = *FeatEnableOrErr;
- if (Feature != 0 && Version < 2 && Cur)
+ if (FeatEnable.hasPGOAnalysis() && Version < 2)
return createError(
"version should be >= 2 for SHT_LLVM_BB_ADDR_MAP when "
"PGO features are enabled: version = " +
Twine(static_cast<int>(Version)) +
" feature = " + Twine(static_cast<int>(Feature)));
+ if (FeatEnable.CallsiteOffsets && Version < 3)
+ return createError(
+ "version should be >= 3 for SHT_LLVM_BB_ADDR_MAP when "
+ "callsite offsets feature is enabled: version = " +
+ Twine(static_cast<int>(Version)) +
+ " feature = " + Twine(static_cast<int>(Feature)));
}
uint32_t NumBlocksInBBRange = 0;
uint32_t NumBBRanges = 1;
@@ -893,7 +899,25 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
? readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr)
: BlockIndex;
uint32_t Offset = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
- uint32_t Size = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
+ // Read the callsite offsets.
+ uint32_t LastCallsiteOffset = 0;
+ SmallVector<uint32_t, 1> CallsiteOffsets;
+ if (FeatEnable.CallsiteOffsets) {
+ uint32_t NumCallsites =
+ readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
+ CallsiteOffsets.reserve(NumCallsites);
+ for (uint32_t CallsiteIndex = 0;
+ !ULEBSizeErr && Cur && (CallsiteIndex < NumCallsites);
+ ++CallsiteIndex) {
+ LastCallsiteOffset +=
+ readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
+ CallsiteOffsets.push_back(LastCallsiteOffset);
+ }
+ if (!Cur || ULEBSizeErr)
+ break;
+ }
+ uint32_t Size = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr) +
+ LastCallsiteOffset;
uint32_t MD = readULEB128As<uint32_t>(Data, Cur, ULEBSizeErr);
if (Version >= 1) {
// Offset is calculated relative to the end of the previous BB.
@@ -906,7 +930,8 @@ decodeBBAddrMapImpl(const ELFFile<ELFT> &EF,
MetadataDecodeErr = MetadataOrErr.takeError();
break;
}
- BBEntries.push_back({ID, Offset, Size, *MetadataOrErr});
+ BBEntries.push_back(
+ {ID, Offset, Size, *MetadataOrErr, CallsiteOffsets});
}
TotalNumBlocks += BBEntries.size();
}
diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp
index 9ae76a71ede5e..6de87a88d0060 100644
--- a/llvm/lib/ObjectYAML/ELFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp
@@ -1452,7 +1452,7 @@ void ELFState<ELFT>::writeSectionContent(
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 > 2)
+ if (E.Version > 3)
WithColor::warning() << "unsupported SHT_LLVM_BB_ADDR_MAP version: "
<< static_cast<int>(E.Version)
<< "; encoding using the most recent version";
@@ -1483,6 +1483,8 @@ void ELFState<ELFT>::writeSectionContent(
if (!E.BBRanges)
continue;
uint64_t TotalNumBlocks = 0;
+ bool EmitCallsiteOffsets =
+ FeatureOrErr->CallsiteOffsets || E.hasAnyCallsiteOffsets();
for (const ELFYAML::BBAddrMapEntry::BBRangeEntry &BBR : *E.BBRanges) {
// Write the base address of the range.
CBA.write<uintX_t>(BBR.BaseAddress, ELFT::Endianness);
@@ -1500,6 +1502,15 @@ void ELFState<ELFT>::writeSectionContent(
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 (EmitCallsiteOffsets) {
+ size_t NumCallsiteOffsets =
+ BBE.CallsiteOffsets ? BBE.CallsiteOffsets->size() : 0;
+ SHeader.sh_size += CBA.writeULEB128(NumCallsiteOffsets);
+ if (BBE.CallsiteOffsets) {
+ for (uint32_t Offset : *BBE.CallsiteOffsets)
+ SHeader.sh_size += CBA.writeULEB128(Offset);
+ }
+ }
SHeader.sh_size += CBA.writeULEB128(BBE.Size);
SHeader.sh_size += CBA.writeULEB128(BBE.Metadata);
}
diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp
index 520e956fdab9f..c38f86e4f4f1b 100644
--- a/llvm/lib/ObjectYAML/ELFYAML.cpp
+++ b/llvm/lib/ObjectYAML/ELFYAML.cpp
@@ -1882,6 +1882,7 @@ void MappingTraits<ELFYAML::BBAddrMapEntry::BBEntry>::mapping(
IO.mapRequired("AddressOffset", E.AddressOffset);
IO.mapRequired("Size", E.Size);
IO.mapRequired("Metadata", E.Metadata);
+ IO.mapOptional("CallsiteOffsets", E.CallsiteOffsets);
}
void MappingTraits<ELFYAML::PGOAnalysisMapEntry>::mapping(
diff --git a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test
index c5d071c11d1de..5d7bc8baa9b25 100644
--- a/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test
+++ b/llvm/test/tools/llvm-readobj/ELF/bb-addr-map.test
@@ -49,7 +49,8 @@
# CHECK-NEXT: {
# CHECK-NEXT: ID: 2
# CHECK-NEXT: Offset: 0x3
-# CHECK-NEXT: Size: 0x4
+# CHECK-NEXT: Callsite Offsets: [1, 3]
+# CHECK-NEXT: Size: 0x7
# CHECK-NEXT: HasReturn: Yes
# CHECK-NEXT: HasTailCall: No
# CHECK-NEXT: IsEHPad: Yes
@@ -75,7 +76,7 @@
# CHECK-NEXT: HasTailCall: No
# CHECK-NEXT: IsEHPad: No
# CHECK-NEXT: CanFallThrough: Yes
-# CHECK-NEXT: HasIndirectBranch: No
+# CHECK-NEXT: HasIndirectBranch: No
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
@@ -143,8 +144,8 @@ Sections:
ShSize: [[SIZE=<none>]]
Link: .text
Entries:
- - Version: 2
- Feature: 0x8
+ - Version: 3
+ Feature: 0x28
BBRanges:
- BaseAddress: [[ADDR=0x11111]]
BBEntries:
@@ -158,6 +159,7 @@ Sections:
AddressOffset: 0x3
Size: 0x4
Metadata: 0x15
+ CallsiteOffsets: [ 0x1 , 0x2 ]
- Version: 2
BBRanges:
- BaseAddress: 0x22222
diff --git a/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml b/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml
index 8dbf97ef2bc12..861cb94692947 100644
--- a/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml
+++ b/llvm/test/tools/obj2yaml/ELF/bb-addr-map.yaml
@@ -14,7 +14,7 @@
# VALID-NEXT: - Name: .llvm_bb_addr_map
# VALID-NEXT: Type: SHT_LLVM_BB_ADDR_MAP
# VALID-NEXT: Entries:
-# VALID-NEXT: - Version: 2
+# VALID-NEXT: - Version: 3
# VALID-NEXT: BBRanges:
## The 'BaseAddress' field is omitted when it's zero.
# VALID-NEXT: - BBEntries:
@@ -30,15 +30,16 @@
# VALID-NEXT: AddressOffset: 0xFFFFFFFFFFFFFFF7
# VALID-NEXT: Size: 0xFFFFFFFFFFFFFFF8
# VALID-NEXT: Metadata: 0xFFFFFFFFFFFFFFF9
-# VALID-NEXT: - Version: 2
-# VALID-NEXT: Feature: 0x8
+# VALID-NEXT: - Version: 3
+# VALID-NEXT: Feature: 0x28
# VALID-NEXT: BBRanges:
# VALID-NEXT: - BaseAddress: 0xFFFFFFFFFFFFFF20
# VALID-NEXT: BBEntries:
-# VALID-NEXT: - ID: 6
-# VALID-NEXT: AddressOffset: 0xA
-# VALID-NEXT: Size: 0xB
-# VALID-NEXT: Metadata: 0xC
+# VALID-NEXT: - ID: 6
+# VALID-NEXT: AddressOffset: 0xA
+# VALID-NEXT: Size: 0xB
+# VALID-NEXT: Metadata: 0xC
+# VALID-NEXT: CallsiteOffsets: [ 0x1, 0x2 ]
--- !ELF
FileHeader:
@@ -50,7 +51,7 @@ Sections:
Type: SHT_LLVM_BB_ADDR_MAP
ShSize: [[SIZE=<none>]]
Entries:
- - Version: 2
+ - Version: 3
Feature: 0x0
BBRanges:
- BaseAddress: 0x0
@@ -67,17 +68,18 @@ Sections:
AddressOffset: 0xFFFFFFFFFFFFFFF7
Size: 0xFFFFFFFFFFFFFFF8
Metadata: 0xFFFFFFFFFFFFFFF9
- - Version: 2
- Feature: 0x8
+ - Version: 3
+ Feature: 0x28
NumBBRanges: [[NUMBBRANGES=<none>]]
BBRanges:
- BaseAddress: 0xFFFFFFFFFFFFFF20
NumBlocks: [[NUMBLOCKS=<none>]]
BBEntries:
- - ID: 6
- AddressOffset: 0xA
- Size: 0xB
- Metadata: 0xC
+ - ID: 6
+ AddressOffset: 0xA
+ Size: 0xB
+ Metadata: 0xC
+ CallsiteOffsets: [ 0x1, 0x2 ]
## Check obj2yaml can dump empty .llvm_bb_addr_map sections.
diff --git a/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml b/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml
index 709938babffbf..9fd0577b1e0fd 100644
--- a/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml
+++ b/llvm/test/tools/yaml2obj/ELF/bb-addr-map.yaml
@@ -36,7 +36,8 @@
# Case 4: Specify Entries.
# CHECK: Name: .llvm_bb_addr_map (1)
# CHECK: SectionData (
-# CHECK-NEXT: 0000: 02002000 00000000 0000010B 010203
+# CHECK-NEXT: 0000: 03002000 00000000 0000010B 01020102
+# CHECK-NEXT: 0010: 0203
# CHECK-NEXT: )
# Case 5: Specify Entries and omit the Address field.
@@ -44,28 +45,32 @@
# CHECK: Address:
# CHECK-SAME: {{^ 0x0$}}
# CHECK: SectionData (
-# CHECK-NEXT: 0000: 02000000 00000000 0000010C 010203
+# CHECK-NEXT: 0000: 03000000 00000000 0000010C 010203
# CHECK-NEXT: )
# Case 6: Override the NumBlocks field.
# CHECK: Name: .llvm_bb_addr_map (1)
# CHECK: SectionData (
-# CHECK-NEXT: 0000: 02002000 00000000 0000020D 010203
+# CHECK-NEXT: 0000: 03002000 00000000 0000020D 010203
# CHECK-NEXT: )
# Case 7: Specify empty BBRanges.
# CHECK: Name: .llvm_bb_addr_map (1)
# CHECK: SectionData (
-# CHECK-NEXT: 0000: 020000
+# CHECK-NEXT: 0000: 030000
# CHECK-NEXT: )
# Case 8: Specify empty BBRanges with multi-bb-range.
# CHECK: Name: .llvm_bb_addr_map (1)
# CHECK: SectionData (
-# CHECK-NEXT: 0000: 020800
+# CHECK-NEXT: 0000: 030800
# CHECK-NEXT: )
-
+# Case 9: Specify empty CallsiteOffsets.
+# CHECK: Name: .llvm_bb_addr_map (1)
+# CHECK: SectionData (
+# CHECK-NEXT: 0000: 03202000 00000000 0000010E 01000203
+# CHECK-NEXT: )
--- !ELF
@@ -100,7 +105,7 @@ Sections:
- Name: '.llvm_bb_addr_map (4)'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
- - Version: 2
+ - Version: 3
BBRanges:
- BaseAddress: 0x0000000000000020
BBEntries:
@@ -108,13 +113,14 @@ Sections:
AddressOffset: 0x00000001
Size: 0x00000002
Metadata: 0x00000003
+ CallsiteOffsets: [0x1, 0x2]
## 5) When specifying the description with Entries, the 'Address' field will be
## zero when omitted.
- Name: '.llvm_bb_addr_map (5)'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
- - Version: 2
+ - Version: 3
BBRanges:
- BBEntries:
- ID: 12
@@ -127,7 +133,7 @@ Sections:
- Name: '.llvm_bb_addr_map (6)'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
- - Version: 2
+ - Version: 3
BBRanges:
- BaseAddress: 0x0000000000000020
NumBlocks: 2
@@ -142,7 +148,7 @@ Sections:
- Name: '.llvm_bb_addr_map (7)'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
- - Version: 2
+ - Version: 3
BBRanges: []
## 8) We can produce a SHT_LLVM_BB_ADDR_MAP section from a multi-bb-range
@@ -150,10 +156,26 @@ Sections:
- Name: '.llvm_bb_addr_map (8)'
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
- - Version: 2
+ - Version: 3
Feature: 0x8
BBRanges: []
+## 9) We can produce a SHT_LLVM_BB_ADDR_MAP section from a description
+## with empty callsite offsets.
+ - Name: '.llvm_bb_addr_map (9)'
+ Type: SHT_LLVM_BB_ADDR_MAP
+ Entries:
+ - Version: 3
+ Feature: 0x20
+ BBRanges:
+ - BaseAddress: 0x0000000000000020
+ BBEntries:
+ - ID: 14
+ AddressOffset: 0x00000001
+ Size: 0x00000002
+ Metadata: 0x00000003
+ CallsiteOffsets: []
+
## Check we can't use Entries at the same time as either Content or Size.
# RUN: not yaml2obj --docnum=2 -DCONTENT="00" %s 2>&1 | FileCheck %s --check-prefix=INVALID
# RUN: not yaml2obj --docnum=2 -DSIZE="0" %s 2>&1 | FileCheck %s --check-prefix=INVALID
@@ -175,7 +197,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: 3; encoding using the most recent version
+# INVALID-VERSION: warning: unsupported SHT_LLVM_BB_ADDR_MAP version: 4; encoding using the most recent version
--- !ELF
FileHeader:
@@ -187,4 +209,4 @@ Sections:
Type: SHT_LLVM_BB_ADDR_MAP
Entries:
## Specify unsupported version
- - Version: 3
+ - Version: 4
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index abaf6077ba9e7..7250d0a129cf5 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -7878,6 +7878,8 @@ void LLVMELFDumper<ELFT>::printBBAddrMaps(bool PrettyPGOAnalysis) {
DictScope BBED(W);
W.printNumber("ID", BBE.ID);
W.printHex("Offset", BBE.Offset);
+ if (!BBE.CallsiteOffsets.empty())
+ W.printList("Callsite Offsets", BBE.CallsiteOffsets);
W.printHex("Size", BBE.Size);
W.printBoolean("HasReturn", BBE.hasReturn());
W.printBoolean("HasTailCall", BBE.hasTailCall());
diff --git a/llvm/tools/obj2yaml/elf2yaml.cpp b/llvm/tools/obj2yaml/elf2yaml.cpp
index c56ed15501b40..53455b8c7580a 100644
--- a/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -899,7 +899,7 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
while (Cur && Cur.tell() < Content.size()) {
if (Shdr->sh_type == ELF::SHT_LLVM_BB_ADDR_MAP) {
Version = Data.getU8(Cur);
- if (Cur && Version > 2)
+ if (Cur && Version > 3)
return createStringError(
errc::invalid_argument,
"invalid SHT_LLVM_BB_ADDR_MAP section version: " +
@@ -934,9 +934,19 @@ ELFDumper<ELFT>::dumpBBAddrMapSection(const Elf_Shdr *Shdr) {
++BlockIndex) {
uint32_t ID = Version >= 2 ? Data.getULEB128(Cur) : BlockIndex;
uint64_t Offset = Data.getULEB128(Cur);
+ std::optional<std::vector<llvm::yaml::Hex64>> CallsiteOffsets;
+ if (FeatureOrErr->CallsiteOffsets) {
+ uint32_t NumCallsites = Data.getULEB128(Cur);
+ CallsiteOffsets = std::vector<llvm::yaml::Hex64>(NumCallsites, 0);
+ for (uint32_t CallsiteIndex = 0; Cur && CallsiteIndex < NumCallsites;
+ ++CallsiteIndex) {
+ (*CallsiteOffsets)[CallsiteIndex] = Data.getULEB128(Cur);
+ }
+ }
uint64_t Size = Data.getULEB128(Cur);
uint64_t Metadata = Data.getULEB128(Cur);
- BBEntries.push_back({ID, Offset, Size, Metadata});
+ BBEntries.push_back(
+ {ID, Offset, Size, Metadata, std::move(CallsiteOffsets)});
}
TotalNumBlocks += BBEntries.size();
BBRanges.push_back({BaseAddress, /*NumBlocks=*/{}, BBEntries});
diff --git a/llvm/unittests/Object/ELFObjectFileTest.cpp b/llvm/unittests/Object/ELFObjectFileTest.cpp
index 1073df95c379a..423f92ea07b39 100644
--- a/llvm/unittests/Object/ELFObjectFileTest.cpp
+++ b/llvm/unittests/Object/ELFObjectFileTest.cpp
@@ -531,7 +531,7 @@ TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
// Check that we can detect unsupported versions.
SmallString<128> UnsupportedVersionYamlString(CommonYamlString);
UnsupportedVersionYamlString += R"(
- - Version: 3
+ - Version: 4
BBRanges:
- BaseAddress: 0x11111
BBEntries:
@@ -543,12 +543,12 @@ TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
{
SCOPED_TRACE("unsupported version");
DoCheck(UnsupportedVersionYamlString,
- "unsupported SHT_LLVM_BB_ADDR_MAP version: 3");
+ "unsupported SHT_LLVM_BB_ADDR_MAP version: 4");
}
SmallString<128> ZeroBBRangesYamlString(CommonYamlString);
ZeroBBRangesYamlString += R"(
- - Version: 2
+ - Version: 3
Feature: 0x8
BBRanges: []
)";
@@ -561,7 +561,7 @@ TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
SmallString<128> CommonVersionedYamlString(CommonYamlString);
CommonVersionedYamlString += R"(
- - Version: 2
+ - Version: 3
BBRanges:
- BaseAddress: 0x11111
BBEntries:
@@ -669,6 +669,26 @@ TEST(ELFObjectFileTest, InvalidDecodeBBAddrMap) {
)";
DoCheck(OverLimitNumBBRanges,
"ULEB128 value at offset 0x2 exceeds UINT32_MAX (0x100000000)");
+
+ // Check that we can detect unsupported version for callsite offsets.
+ SmallString<128> UnsupportedLowVersionYamlString(CommonYamlString);
+ UnsupportedLowVersionYamlString += R"(
+ - Version: 2
+ Feature: 0x20
+ BBRanges:
+ - BBEntries:
+ - AddressOffset: 0x0
+ Size: 0x1
+ Metadata: 0x2
+ CallsiteOffsets: [ 0x1 ]
+)";
+
+ {
+ SCOPED_TRACE("unsupported version");
+ DoCheck(UnsupportedLowVersionYamlString,
+ "version should be >= 3 for SHT_LLVM_BB_ADDR_MAP when callsite"
+ " offsets feature is enabled: version = 2 feature = 32");
+ }
}
// Test for the ELFObjectFile::readBBAddrMap API.
@@ -684,19 +704,21 @@ TEST(ELFObjectFileTest, ReadBBAddrMap) {
Type: SHT_LLVM_BB_ADDR_MAP
Link: 1
Entries:
- - Version: 2
+ - Version: 3
+ Feature: 0x20
BBRanges:
- BaseAddress: 0x11111
BBEntries:
- - ID: 1
- AddressOffset: 0x0
- Size: 0x1
- Metadata: 0x2
+ - ID: 1
+ AddressOffset: 0x0
+ Size: 0x1
+ Metadata: 0x2
+ CallsiteOffsets: [ 0x1 , 0x1 ]
- Name: .llvm_bb_addr_map_2
Type: SHT_LLVM_BB_ADDR_MAP
Link: 1
Entries:
- - Version: 2
+ - Version: 3
Feature: 0x8
BBRanges:
- BaseAddress: 0x22222
@@ -738,14 +760,15 @@ TEST(ELFObjectFileTest, ReadBBAddrMap) {
)");
BBAddrMap E1 = {
- {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}}}};
+ {{0x11111,
+ {{1, 0x0, 0x3, {false, true, false, false, false}, {0x1, 0x2}}}}}};
BBAddrMap E2 = {
- {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}},
- {0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}}}}}};
+ {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}}}},
+ {0xFFFFF, {{15, 0xF0, 0xF1, {true, true, true, true, true}, {}}}}}};
BBAddrMap E3 = {
- {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}}}}}};
+ {{0x33333, {{0, 0x0, 0x3, {false, true, true, false, false}, {}}}}}};
BBAddrMap E4 = {
- {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}}}}}};
+ {{0x44444, {{0, 0x0, 0x4, {false, false, false, true, true}, {}}}}}};
std::vector<BBAddrMap> Section0BBAddrMaps = {E4};
std::vector<BBAddrMap> Section1BBAddrMaps = {E3};
@@ -1137,28 +1160,29 @@ TEST(ELFObjectFileTest, ReadPGOAnalysisMap) {
)");
BBAddrMap E1 = {
- {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}}}}}};
- PGOAnalysisMap P1 = {892, {}, {true, false, false, false, false}};
+ {{0x11111, {{1, 0x0, 0x1, {false, true, false, false, false}, {}}}}}};
+ PGOAnalysisMap P1 = {892, {}, {true, false, false, false, false, false}};
BBAddrMap E2 = {
- {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}}}}}};
- PGOAnalysisMap P2 = {
- {}, {{BlockFrequency(343), {}}}, {false, true, false, false, false}};
+ {{0x22222, {{2, 0x0, 0x2, {false, false, true, false, false}, {}}}}}};
+ PGOAnalysisMap P2 = {{},
+ {{BlockFrequency(343), {}}},
+ {false, true, false, false, false, false}};
BBAddrMap E3 = {{{0x33333,
- {{0, 0x0, 0x3, {false, true, true, false, false}},
- {1, 0x3, 0x3, {false, false, true, false, false}},
- {2, 0x6, 0x3, {false, false, false, false, false}}}}}};
+ {{0, 0x0, 0x3, {false, true, true, false, false}, {}},
+ {1, 0x3, 0x3, {false, false, true, false, false}, {}},
+ {2, 0x6, 0x3, {false, false, false, false, false}, {}}}}}};
PGOAnalysisMap P3 = {{},
{{{},
{{1, BranchProbability::getRaw(0x1111'1111)},
{2, BranchProbability::getRaw(0xeeee'eeee)}}},
{{}, {{2, BranchProbability::getRaw(0xffff'ffff)}}},
{{}, {}}},
- {false, false, true, false, false}};
+ {false, false, true, false, false, false}};
BBAddrMap E4 = {{{0x44444,
- {{0, 0x0, 0x4, {false, false, false, true, true}},
- {1, 0x4, 0x4, {false, false, false, false, false}},
- {2, 0x8, 0x4, {false, false, false, false, false}},
- {3, 0xc, 0x4, {false, false, false, false, false}}}}}};
+ {{0, 0x0, 0x4, {false, false, false, true, true}, {}},
+ {1, 0x4, 0x4, {false, false, false, false, false}, {}},
+ {2, 0x8, 0x4, {false, false, false, false, false}, {}},
+ {3, 0xc, 0x4, {false, false, false, false, false}, {}}}}}};
PGOAnalysisMap P4 = {
1000,
{{BlockFrequency(1000),
@@ -1170,22 +1194,22 @@ TEST(ELFObjectFileTest, ReadPGOAnalysisMap) {
{3, BranchProbability::getRaw(0xeeee'eeee)}}},
{BlockFrequency(18), {{3, BranchProbability::getRaw(0xffff'ffff)}}},
{BlockFrequency(1000), {}}},
- {true, true, true, false, false}};
+ {true, true, true, false, false, false}};
BBAddrMap E5 = {
- {{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}}}}}};
- PGOAnalysisMap P5 = {{}, {}, {false, false, false, false, false}};
+ {{0x55555, {{2, 0x0, 0x2, {false, false, true, false, false}, {}}}}}};
+ PGOAnalysisMap P5 = {{}, {}, {false, false, false, false, false, false}};
BBAddrMap E6 = {
{{0x66666,
- {{0, 0x0, 0x6, {false, true, true, false, false}},
- {1, 0x6, 0x6, {false, false, true, false, false}}}},
- {0x666661, {{2, 0x0, 0x6, {false, false, false, false, false}}}}}};
+ {{0, 0x0, 0x6, {false, true, true, false, false}, {}},
+ {1, 0x6, 0x6, {false, false, true, false, false}, {}}}},
+ {0x666661, {{2, 0x0, 0x6, {false, false, false, false, false}, {}}}}}};
PGOAnalysisMap P6 = {{},
{{{},
{{1, BranchProbability::getRaw(0x2222'2222)},
{2, BranchProbability::getRaw(0xcccc'cccc)}}},
{{}, {{2, BranchProbability::getRaw(0x8888'8888)}}},
{{}, {}}},
- {false, false, true, true, false}};
+ {false, false, true, true, false, false}};
std::vector<BBAddrMap> Section0BBAddrMaps = {E4, E5, E6};
std::vector<BBAddrMap> Section1BBAddrMaps = {E3};
diff --git a/llvm/unittests/Object/ELFTypesTest.cpp b/llvm/unittests/Object/ELFTypesTest.cpp
index 13130dde80ef1..f88931b5f544c 100644
--- a/llvm/unittests/Object/ELFTypesTest.cpp
+++ b/llvm/unittests/Object/ELFTypesTest.cpp
@@ -101,18 +101,21 @@ static_assert(
"PGOAnalysisMap should use the same type for basic block ID as BBAddrMap");
TEST(ELFTypesTest, BBAddrMapFeaturesEncodingTest) {
- const std::array<BBAddrMap::Features, 9> Decoded = {
- {{false, false, false, false, false},
- {true, false, false, false, false},
- {false, true, false, false, false},
- {false, false, true, false, false},
- {false, false, false, true, false},
- {true, true, false, false, false},
- {false, true, true, false, false},
- {false, true, true, true, false},
- {true, true, true, true, false}}};
- const std::array<uint8_t, 9> Encoded = {
- {0b0000, 0b0001, 0b0010, 0b0100, 0b1000, 0b0011, 0b0110, 0b1110, 0b1111}};
+ const std::array<BBAddrMap::Features, 11> Decoded = {
+ {{false, false, false, false, false, false},
+ {true, false, false, false, false, false},
+ {false, true, false, false, false, false},
+ {false, false, true, false, false, false},
+ {false, false, false, true, false, false},
+ {true, true, false, false, false, false},
+ {false, true, true, false, false, false},
+ {false, true, true, true, false, false},
+ {true, true, true, true, false, false},
+ {false, false, false, false, true, false},
+ {false, false, false, false, false, true}}};
+ const std::array<uint8_t, 11> Encoded = {{0b0000, 0b0001, 0b0010, 0b0100,
+ 0b1000, 0b0011, 0b0110, 0b1110,
+ 0b1111, 0b1'0000, 0b10'0000}};
for (const auto &[Feat, EncodedVal] : llvm::zip(Decoded, Encoded))
EXPECT_EQ(Feat.encode(), EncodedVal);
for (const auto &[Feat, EncodedVal] : llvm::zip(Decoded, Encoded)) {
@@ -125,9 +128,9 @@ TEST(ELFTypesTest, BBAddrMapFeaturesEncodingTest) {
TEST(ELFTypesTest, BBAddrMapFeaturesInvalidEncodingTest) {
const std::array<std::string, 2> Errors = {
- "invalid encoding for BBAddrMap::Features: 0x20",
+ "invalid encoding for BBAddrMap::Features: 0x40",
"invalid encoding for BBAddrMap::Features: 0xf0"};
- const std::array<uint8_t, 2> Values = {{0b10'0000, 0b1111'0000}};
+ const std::array<uint8_t, 2> Values = {{0b100'0000, 0b1111'0000}};
for (const auto &[Val, Error] : llvm::zip(Values, Errors)) {
EXPECT_THAT_ERROR(BBAddrMap::Features::decode(Val).takeError(),
FailedWithMessage(Error));
More information about the llvm-commits
mailing list