diff --git a/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h b/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h --- a/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h +++ b/llvm/include/llvm/CodeGen/DwarfStringPoolEntry.h @@ -9,7 +9,7 @@ #ifndef LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H #define LLVM_CODEGEN_DWARFSTRINGPOOLENTRY_H -#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringMap.h" namespace llvm { @@ -20,45 +20,76 @@ struct DwarfStringPoolEntry { static constexpr unsigned NotIndexed = -1; - MCSymbol *Symbol; - uint64_t Offset; - unsigned Index; + MCSymbol *Symbol = nullptr; + uint64_t Offset = 0; + unsigned Index = 0; bool isIndexed() const { return Index != NotIndexed; } }; /// String pool entry reference. class DwarfStringPoolEntryRef { - const StringMapEntry<DwarfStringPoolEntry> *MapEntry = nullptr; + /// Full DwarfStringPoolEntry stored in the StringMapEntry. + using StringEntryPtr = const StringMapEntry<DwarfStringPoolEntry> *; - const StringMapEntry<DwarfStringPoolEntry> *getMapEntry() const { - return MapEntry; - } + /// Pointer to DwarfStringPoolEntry stored in the StringMapEntry. + using ShortStringEntryPtr = const StringMapEntry<DwarfStringPoolEntry *> *; + + /// Pointer to the string pool Entry. + PointerUnion<StringEntryPtr, ShortStringEntryPtr> MapEntry = nullptr; public: DwarfStringPoolEntryRef() = default; + + // ASSUMPTION: \p Entry mustn`t be reallocated. DwarfStringPoolEntryRef(const StringMapEntry<DwarfStringPoolEntry> &Entry) : MapEntry(&Entry) {} - explicit operator bool() const { return getMapEntry(); } + // ASSUMPTION: \p Entry mustn`t be reallocated. + DwarfStringPoolEntryRef(const StringMapEntry<DwarfStringPoolEntry *> &Entry) + : MapEntry(&Entry) { + assert(MapEntry.get<ShortStringEntryPtr>()->second != nullptr); + } + + explicit operator bool() const { return !MapEntry.isNull(); } + + /// \returns symbol for the dwarf string. MCSymbol *getSymbol() const { - assert(getMapEntry()->second.Symbol && "No symbol available!"); - return getMapEntry()->second.Symbol; + assert(getEntry().Symbol && "No symbol available!"); + return getEntry().Symbol; } - uint64_t getOffset() const { return getMapEntry()->second.Offset; } + + /// \returns offset for the dwarf string. + uint64_t getOffset() const { return getEntry().Offset; } + + /// \returns index for the dwarf string. unsigned getIndex() const { - assert(getMapEntry()->getValue().isIndexed()); - return getMapEntry()->second.Index; + assert(getEntry().isIndexed() && "Index is not set!"); + return getEntry().Index; + } + + /// \returns string. + StringRef getString() const { + if (MapEntry.is<StringEntryPtr>()) + return MapEntry.get<StringEntryPtr>()->first(); + else + return MapEntry.get<ShortStringEntryPtr>()->first(); + } + + /// \returns the entire string pool entry for convenience. + const DwarfStringPoolEntry &getEntry() const { + if (MapEntry.is<StringEntryPtr>()) + return MapEntry.get<StringEntryPtr>()->second; + else + return *MapEntry.get<ShortStringEntryPtr>()->second; } - StringRef getString() const { return getMapEntry()->first(); } - /// Return the entire string pool entry for convenience. - DwarfStringPoolEntry getEntry() const { return getMapEntry()->getValue(); } bool operator==(const DwarfStringPoolEntryRef &X) const { - return getMapEntry() == X.getMapEntry(); + return MapEntry.getOpaqueValue() == X.MapEntry.getOpaqueValue(); } + bool operator!=(const DwarfStringPoolEntryRef &X) const { - return getMapEntry() != X.getMapEntry(); + return MapEntry.getOpaqueValue() != X.MapEntry.getOpaqueValue(); } }; diff --git a/llvm/unittests/CodeGen/CMakeLists.txt b/llvm/unittests/CodeGen/CMakeLists.txt --- a/llvm/unittests/CodeGen/CMakeLists.txt +++ b/llvm/unittests/CodeGen/CMakeLists.txt @@ -21,6 +21,7 @@ AsmPrinterDwarfTest.cpp DIEHashTest.cpp DIETest.cpp + DwarfStringPoolEntryRefTest.cpp InstrRefLDVTest.cpp LowLevelTypeTest.cpp LexicalScopesTest.cpp diff --git a/llvm/unittests/CodeGen/DwarfStringPoolEntryRefTest.cpp b/llvm/unittests/CodeGen/DwarfStringPoolEntryRefTest.cpp new file mode 100644 --- /dev/null +++ b/llvm/unittests/CodeGen/DwarfStringPoolEntryRefTest.cpp @@ -0,0 +1,117 @@ +//===- llvm/unittest/CodeGen/DwarfStringPoolEntryRefTest.cpp --------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/DwarfStringPoolEntry.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Testing/Support/Error.h" + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include <string> + +using namespace llvm; + +TEST(DwarfStringPoolEntryRefTest, TestFullEntry) { + BumpPtrAllocator Allocator; + StringMapEntry<DwarfStringPoolEntry> *StringEntry1 = + StringMapEntry<DwarfStringPoolEntry>::Create( + "Key1", Allocator, DwarfStringPoolEntry{nullptr, 0, 0}); + + EXPECT_TRUE(StringEntry1->getKey() == "Key1"); + EXPECT_TRUE(StringEntry1->second.Symbol == nullptr); + EXPECT_TRUE(StringEntry1->second.Offset == 0); + EXPECT_TRUE(StringEntry1->second.Index == 0); + + DwarfStringPoolEntryRef Ref1(*StringEntry1); + EXPECT_TRUE(Ref1.getString() == "Key1"); + EXPECT_TRUE(Ref1.getOffset() == 0); + EXPECT_TRUE(Ref1.getIndex() == 0); + + DwarfStringPoolEntryRef Ref2(*StringEntry1); + EXPECT_TRUE(Ref2.getString() == "Key1"); + EXPECT_TRUE(Ref2.getOffset() == 0); + EXPECT_TRUE(Ref2.getIndex() == 0); + EXPECT_TRUE(Ref1 == Ref2); + EXPECT_FALSE(Ref1 != Ref2); + + StringMapEntry<DwarfStringPoolEntry> *StringEntry2 = + StringMapEntry<DwarfStringPoolEntry>::Create( + "Key2", Allocator, DwarfStringPoolEntry{nullptr, 0x1000, 1}); + EXPECT_TRUE(StringEntry2->getKey() == "Key2"); + EXPECT_TRUE(StringEntry2->second.Symbol == nullptr); + EXPECT_TRUE(StringEntry2->second.Offset == 0x1000); + EXPECT_TRUE(StringEntry2->second.Index == 1); + + DwarfStringPoolEntryRef Ref3(*StringEntry2); + EXPECT_TRUE(Ref3.getString() == "Key2"); + EXPECT_TRUE(Ref3.getOffset() == 0x1000); + EXPECT_TRUE(Ref3.getIndex() == 1); + EXPECT_TRUE(Ref1 != Ref3); +} + +TEST(DwarfStringPoolEntryRefTest, TestShortEntry) { + BumpPtrAllocator Allocator; + DwarfStringPoolEntry DwarfEntry1 = {nullptr, 0, 0}; + StringMapEntry<DwarfStringPoolEntry *> *StringEntry1 = + StringMapEntry<DwarfStringPoolEntry *>::Create("Key1", Allocator, + &DwarfEntry1); + + EXPECT_TRUE(StringEntry1->getKey() == "Key1"); + EXPECT_TRUE(StringEntry1->second->Symbol == nullptr); + EXPECT_TRUE(StringEntry1->second->Offset == 0); + EXPECT_TRUE(StringEntry1->second->Index == 0); + + DwarfStringPoolEntryRef Ref1(*StringEntry1); + EXPECT_TRUE(Ref1.getString() == "Key1"); + EXPECT_TRUE(Ref1.getOffset() == 0); + EXPECT_TRUE(Ref1.getIndex() == 0); + EXPECT_TRUE(memcmp(&Ref1.getEntry(), &DwarfEntry1, + sizeof(DwarfStringPoolEntry)) == 0); + + DwarfStringPoolEntryRef Ref2(*StringEntry1); + EXPECT_TRUE(Ref2.getString() == "Key1"); + EXPECT_TRUE(Ref2.getOffset() == 0); + EXPECT_TRUE(memcmp(&Ref2.getEntry(), &DwarfEntry1, + sizeof(DwarfStringPoolEntry)) == 0); + EXPECT_TRUE(Ref1 == Ref2); + EXPECT_FALSE(Ref1 != Ref2); + + DwarfStringPoolEntry DwarfEntry2 = {nullptr, 0x1000, 1}; + StringMapEntry<DwarfStringPoolEntry *> *StringEntry2 = + StringMapEntry<DwarfStringPoolEntry *>::Create("Key2", Allocator, + &DwarfEntry2); + EXPECT_TRUE(StringEntry2->getKey() == "Key2"); + EXPECT_TRUE(StringEntry2->second->Symbol == nullptr); + EXPECT_TRUE(StringEntry2->second->Offset == 0x1000); + EXPECT_TRUE(StringEntry2->second->Index == 1); + + DwarfStringPoolEntryRef Ref3(*StringEntry2); + EXPECT_TRUE(Ref3.getString() == "Key2"); + EXPECT_TRUE(Ref3.getOffset() == 0x1000); + EXPECT_TRUE(Ref3.getIndex() == 1); + EXPECT_TRUE(memcmp(&Ref3.getEntry(), &DwarfEntry2, + sizeof(DwarfStringPoolEntry)) == 0); + EXPECT_TRUE(Ref1 != Ref3); +} + +TEST(DwarfStringPoolEntryRefTest, CompareFullAndShort) { + BumpPtrAllocator Allocator; + + DwarfStringPoolEntry DwarfEntry1 = {nullptr, 0, 0}; + StringMapEntry<DwarfStringPoolEntry *> *StringEntry1 = + StringMapEntry<DwarfStringPoolEntry *>::Create("Key1", Allocator, + &DwarfEntry1); + DwarfStringPoolEntryRef Ref1(*StringEntry1); + + StringMapEntry<DwarfStringPoolEntry> *StringEntry2 = + StringMapEntry<DwarfStringPoolEntry>::Create( + "Key1", Allocator, DwarfStringPoolEntry{nullptr, 0, 0}); + DwarfStringPoolEntryRef Ref2(*StringEntry2); + + EXPECT_FALSE(Ref1 == Ref2); +}