| //===----------------------------------------------------------------------===// |
| // |
| // 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/AccelTable.h" |
| #include "TestAsmPrinter.h" |
| #include "llvm/CodeGen/DwarfStringPoolEntry.h" |
| #include "llvm/Testing/Support/Error.h" |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| |
| using namespace llvm; |
| |
| namespace { |
| |
| class AccelTableTest : public testing::Test { |
| protected: |
| void SetUp() override { |
| auto ExpectedTestPrinter = TestAsmPrinter::create( |
| "x86_64-pc-linux", /*DwarfVersion=*/5, dwarf::DWARF32); |
| ASSERT_THAT_EXPECTED(ExpectedTestPrinter, Succeeded()); |
| TestPrinter = std::move(*ExpectedTestPrinter); |
| if (!TestPrinter) |
| GTEST_SKIP(); |
| } |
| |
| /// Builds a table holding \p Names and returns each bucket's contents in the |
| /// order they would be emitted in. |
| std::vector<std::vector<StringRef>> |
| bucketOrder(ArrayRef<const DwarfStringPoolEntryWithExtString *> Names) { |
| DWARF5AccelTable Table; |
| for (const DwarfStringPoolEntryWithExtString *Name : Names) |
| Table.addName(DwarfStringPoolEntryRef(*Name), /*DieOffset=*/0x11, |
| /*DefiningParentOffset=*/std::nullopt, |
| /*DieTag=*/dwarf::DW_TAG_variable, /*UnitID=*/0, |
| /*IsTU=*/false); |
| Table.finalize(TestPrinter->getAP(), "names"); |
| |
| std::vector<std::vector<StringRef>> Order; |
| for (const AccelTableBase::HashList &Bucket : Table.getBuckets()) { |
| Order.emplace_back(); |
| for (const AccelTableBase::HashData *Hash : Bucket) |
| Order.back().push_back(Hash->Name.getString()); |
| } |
| return Order; |
| } |
| |
| std::unique_ptr<TestAsmPrinter> TestPrinter; |
| }; |
| |
| TEST_F(AccelTableTest, CollidingNamesOrderedIndependentlyOfInsertion) { |
| // The DWARF v5 hash folds case, so these three names always collide. |
| DwarfStringPoolEntryWithExtString Lower = {{}, "fixups"}; |
| DwarfStringPoolEntryWithExtString Mixed = {{}, "Fixups"}; |
| DwarfStringPoolEntryWithExtString Upper = {{}, "FIXUPS"}; |
| DwarfStringPoolEntryWithExtString Other = {{}, "gamma"}; |
| |
| const uint32_t Hash = DWARF5AccelTableData::hash(Lower.String); |
| ASSERT_EQ(Hash, DWARF5AccelTableData::hash(Mixed.String)); |
| ASSERT_EQ(Hash, DWARF5AccelTableData::hash(Upper.String)); |
| ASSERT_LT(DWARF5AccelTableData::hash(Other.String), Hash); |
| |
| const std::vector<std::vector<StringRef>> Order = |
| bucketOrder({&Lower, &Mixed, &Upper, &Other}); |
| EXPECT_EQ(bucketOrder({&Other, &Upper, &Mixed, &Lower}), Order); |
| EXPECT_EQ(bucketOrder({&Mixed, &Other, &Lower, &Upper}), Order); |
| |
| // The hash value orders before the name, so "gamma" comes first even though |
| // it sorts after the names it shares a bucket with. |
| EXPECT_THAT(Order, testing::Contains(testing::ElementsAre( |
| "gamma", "FIXUPS", "Fixups", "fixups"))); |
| } |
| |
| } // end namespace |