From 1f848b5e8b943df9ae769ea366533ae42832e8b8 Mon Sep 17 00:00:00 2001 From: Rahman Lavaee 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 | 15 +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 7 +- llvm/lib/Object/ELF.cpp | 31 +++++- 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, 222 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(BBFreq) << 1) | (static_cast(BrProb) << 2) | (static_cast(MultiBBRange) << 3) | - (static_cast(OmitBBEntries) << 4); + (static_cast(OmitBBEntries) << 4) | + (static_cast(CallsiteOffsets) << 5); } // Decodes from minimum bit width representation and validates no @@ -851,7 +853,7 @@ struct BBAddrMap { Features Feat{ static_cast(Val & (1 << 0)), static_cast(Val & (1 << 1)), static_cast(Val & (1 << 2)), static_cast(Val & (1 << 3)), - static_cast(Val & (1 << 4))}; + static_cast(Val & (1 << 4)), static_cast(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 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 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..e883f2f3e1447 100644 --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -162,6 +162,7 @@ struct BBAddrMapEntry { llvm::yaml::Hex64 AddressOffset; llvm::yaml::Hex64 Size; llvm::yaml::Hex64 Metadata; + std::optional> CallsiteOffsets; }; uint8_t Version; llvm::yaml::Hex8 Feature; @@ -180,6 +181,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(BBAddrMapSkipEmitBBEntries)}; + static_cast(BBAddrMapSkipEmitBBEntries), + false}; } void AsmPrinter::emitBBAddrMapSection(const MachineFunction &MF) { diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp index e6864ca508a54..6ee33d94ee861 100644 --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -837,7 +837,7 @@ decodeBBAddrMapImpl(const ELFFile &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(Version))); Feature = Data.getU8(Cur); // Feature byte @@ -847,12 +847,18 @@ decodeBBAddrMapImpl(const ELFFile &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(Version)) + " feature = " + Twine(static_cast(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(Version)) + + " feature = " + Twine(static_cast(Feature))); } uint32_t NumBlocksInBBRange = 0; uint32_t NumBBRanges = 1; @@ -893,7 +899,23 @@ decodeBBAddrMapImpl(const ELFFile &EF, ? readULEB128As(Data, Cur, ULEBSizeErr) : BlockIndex; uint32_t Offset = readULEB128As(Data, Cur, ULEBSizeErr); - uint32_t Size = readULEB128As(Data, Cur, ULEBSizeErr); + // Read the callsite offsets. + uint32_t LastCallsiteOffset = 0; + SmallVector CallsiteOffsets; + if (FeatEnable.CallsiteOffsets) { + uint32_t NumCallsites = + readULEB128As(Data, Cur, ULEBSizeErr); + CallsiteOffsets.reserve(NumCallsites); + for (uint32_t CallsiteIndex = 0; + !ULEBSizeErr && Cur && (CallsiteIndex < NumCallsites); + ++CallsiteIndex) { + LastCallsiteOffset += + readULEB128As(Data, Cur, ULEBSizeErr); + CallsiteOffsets.push_back(LastCallsiteOffset); + } + } + uint32_t Size = readULEB128As(Data, Cur, ULEBSizeErr) + + LastCallsiteOffset; uint32_t MD = readULEB128As(Data, Cur, ULEBSizeErr); if (Version >= 1) { // Offset is calculated relative to the end of the previous BB. @@ -906,7 +928,8 @@ decodeBBAddrMapImpl(const ELFFile &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::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(E.Version) << "; encoding using the most recent version"; @@ -1483,6 +1483,8 @@ void ELFState::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(BBR.BaseAddress, ELFT::Endianness); @@ -1500,6 +1502,15 @@ void ELFState::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::mapping( IO.mapRequired("AddressOffset", E.AddressOffset); IO.mapRequired("Size", E.Size); IO.mapRequired("Metadata", E.Metadata); + IO.mapOptional("CallsiteOffsets", E.CallsiteOffsets); } void MappingTraits::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=]] 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=]] 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=]] BBRanges: - BaseAddress: 0xFFFFFFFFFFFFFF20 NumBlocks: [[NUMBLOCKS=]] 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::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::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::dumpBBAddrMapSection(const Elf_Shdr *Shdr) { ++BlockIndex) { uint32_t ID = Version >= 2 ? Data.getULEB128(Cur) : BlockIndex; uint64_t Offset = Data.getULEB128(Cur); + std::optional> CallsiteOffsets; + if (FeatureOrErr->CallsiteOffsets) { + uint32_t NumCallsites = Data.getULEB128(Cur); + CallsiteOffsets = std::vector(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 Section0BBAddrMaps = {E4}; std::vector 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 Section0BBAddrMaps = {E4, E5, E6}; std::vector 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 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 Encoded = { - {0b0000, 0b0001, 0b0010, 0b0100, 0b1000, 0b0011, 0b0110, 0b1110, 0b1111}}; + const std::array 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 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 Errors = { - "invalid encoding for BBAddrMap::Features: 0x20", + "invalid encoding for BBAddrMap::Features: 0x40", "invalid encoding for BBAddrMap::Features: 0xf0"}; - const std::array Values = {{0b10'0000, 0b1111'0000}}; + const std::array Values = {{0b100'0000, 0b1111'0000}}; for (const auto &[Val, Error] : llvm::zip(Values, Errors)) { EXPECT_THAT_ERROR(BBAddrMap::Features::decode(Val).takeError(), FailedWithMessage(Error));