diff options
author | Stephen Hines <srhines@google.com> | 2015-03-23 12:10:34 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2015-03-23 12:10:34 -0700 |
commit | ebe69fe11e48d322045d5949c83283927a0d790b (patch) | |
tree | c92f1907a6b8006628a4b01615f38264d29834ea /unittests | |
parent | b7d2e72b02a4cb8034f32f8247a2558d2434e121 (diff) | |
download | external_llvm-ebe69fe11e48d322045d5949c83283927a0d790b.zip external_llvm-ebe69fe11e48d322045d5949c83283927a0d790b.tar.gz external_llvm-ebe69fe11e48d322045d5949c83283927a0d790b.tar.bz2 |
Update aosp/master LLVM for rebase to r230699.
Change-Id: I2b5be30509658cb8266be782de0ab24f9099f9b9
Diffstat (limited to 'unittests')
88 files changed, 4325 insertions, 622 deletions
diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index c7ec16b..8b82fb2 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -475,6 +475,47 @@ TEST(APFloatTest, FMA) { EXPECT_EQ(12.0f, f1.convertToFloat()); } + // Test for correct zero sign when answer is exactly zero. + // fma(1.0, -1.0, 1.0) -> +ve 0. + { + APFloat f1(1.0); + APFloat f2(-1.0); + APFloat f3(1.0); + f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); + EXPECT_TRUE(!f1.isNegative() && f1.isZero()); + } + + // Test for correct zero sign when answer is exactly zero and rounding towards + // negative. + // fma(1.0, -1.0, 1.0) -> +ve 0. + { + APFloat f1(1.0); + APFloat f2(-1.0); + APFloat f3(1.0); + f1.fusedMultiplyAdd(f2, f3, APFloat::rmTowardNegative); + EXPECT_TRUE(f1.isNegative() && f1.isZero()); + } + + // Test for correct (in this case -ve) sign when adding like signed zeros. + // Test fma(0.0, -0.0, -0.0) -> -ve 0. + { + APFloat f1(0.0); + APFloat f2(-0.0); + APFloat f3(-0.0); + f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); + EXPECT_TRUE(f1.isNegative() && f1.isZero()); + } + + // Test -ve sign preservation when small negative results underflow. + { + APFloat f1(APFloat::IEEEdouble, "-0x1p-1074"); + APFloat f2(APFloat::IEEEdouble, "+0x1p-1074"); + APFloat f3(0.0); + f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); + EXPECT_TRUE(f1.isNegative() && f1.isZero()); + } + + // Test x87 extended precision case from http://llvm.org/PR20728. { APFloat M1(APFloat::x87DoubleExtended, 1.0); APFloat M2(APFloat::x87DoubleExtended, 1.0); diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 8198c71..3b7ac5b 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -678,6 +678,14 @@ TEST(APIntTest, nearestLogBase2) { EXPECT_EQ(A9.nearestLogBase2(), UINT32_MAX); } +#if defined(__clang__) +// Disable the pragma warning from versions of Clang without -Wself-move +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunknown-pragmas" +// Disable the warning that triggers on exactly what is being tested. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wself-move" +#endif TEST(APIntTest, SelfMoveAssignment) { APInt X(32, 0xdeadbeef); X = std::move(X); @@ -694,5 +702,8 @@ TEST(APIntTest, SelfMoveAssignment) { EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[0]); EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[1]); } - +#if defined(__clang__) +#pragma clang diagnostic pop +#pragma clang diagnostic pop +#endif } diff --git a/unittests/ADT/APSIntTest.cpp b/unittests/ADT/APSIntTest.cpp index eef9c8a..5e4e874 100644 --- a/unittests/ADT/APSIntTest.cpp +++ b/unittests/ADT/APSIntTest.cpp @@ -41,4 +41,106 @@ TEST(APSIntTest, MoveTest) { EXPECT_EQ(Bits, A.getRawData()); // Verify that "Wide" was really moved. } +TEST(APSIntTest, get) { + EXPECT_TRUE(APSInt::get(7).isSigned()); + EXPECT_EQ(64u, APSInt::get(7).getBitWidth()); + EXPECT_EQ(7u, APSInt::get(7).getZExtValue()); + EXPECT_EQ(7, APSInt::get(7).getSExtValue()); + EXPECT_TRUE(APSInt::get(-7).isSigned()); + EXPECT_EQ(64u, APSInt::get(-7).getBitWidth()); + EXPECT_EQ(-7, APSInt::get(-7).getSExtValue()); + EXPECT_EQ(UINT64_C(0) - 7, APSInt::get(-7).getZExtValue()); +} + +TEST(APSIntTest, getUnsigned) { + EXPECT_TRUE(APSInt::getUnsigned(7).isUnsigned()); + EXPECT_EQ(64u, APSInt::getUnsigned(7).getBitWidth()); + EXPECT_EQ(7u, APSInt::getUnsigned(7).getZExtValue()); + EXPECT_EQ(7, APSInt::getUnsigned(7).getSExtValue()); + EXPECT_TRUE(APSInt::getUnsigned(-7).isUnsigned()); + EXPECT_EQ(64u, APSInt::getUnsigned(-7).getBitWidth()); + EXPECT_EQ(-7, APSInt::getUnsigned(-7).getSExtValue()); + EXPECT_EQ(UINT64_C(0) - 7, APSInt::getUnsigned(-7).getZExtValue()); +} + +TEST(APSIntTest, getExtValue) { + EXPECT_TRUE(APSInt(APInt(3, 7), true).isUnsigned()); + EXPECT_TRUE(APSInt(APInt(3, 7), false).isSigned()); + EXPECT_TRUE(APSInt(APInt(4, 7), true).isUnsigned()); + EXPECT_TRUE(APSInt(APInt(4, 7), false).isSigned()); + EXPECT_TRUE(APSInt(APInt(4, -7), true).isUnsigned()); + EXPECT_TRUE(APSInt(APInt(4, -7), false).isSigned()); + EXPECT_EQ(7, APSInt(APInt(3, 7), true).getExtValue()); + EXPECT_EQ(-1, APSInt(APInt(3, 7), false).getExtValue()); + EXPECT_EQ(7, APSInt(APInt(4, 7), true).getExtValue()); + EXPECT_EQ(7, APSInt(APInt(4, 7), false).getExtValue()); + EXPECT_EQ(9, APSInt(APInt(4, -7), true).getExtValue()); + EXPECT_EQ(-7, APSInt(APInt(4, -7), false).getExtValue()); +} + +TEST(APSIntTest, compareValues) { + auto U = [](uint64_t V) { return APSInt::getUnsigned(V); }; + auto S = [](int64_t V) { return APSInt::get(V); }; + + // Bit-width matches and is-signed. + EXPECT_TRUE(APSInt::compareValues(S(7), S(8)) < 0); + EXPECT_TRUE(APSInt::compareValues(S(8), S(7)) > 0); + EXPECT_TRUE(APSInt::compareValues(S(7), S(7)) == 0); + EXPECT_TRUE(APSInt::compareValues(S(-7), S(8)) < 0); + EXPECT_TRUE(APSInt::compareValues(S(8), S(-7)) > 0); + EXPECT_TRUE(APSInt::compareValues(S(-7), S(-7)) == 0); + EXPECT_TRUE(APSInt::compareValues(S(-7), S(-8)) > 0); + EXPECT_TRUE(APSInt::compareValues(S(-8), S(-7)) < 0); + EXPECT_TRUE(APSInt::compareValues(S(-7), S(-7)) == 0); + + // Bit-width matches and not is-signed. + EXPECT_TRUE(APSInt::compareValues(U(7), U(8)) < 0); + EXPECT_TRUE(APSInt::compareValues(U(8), U(7)) > 0); + EXPECT_TRUE(APSInt::compareValues(U(7), U(7)) == 0); + + // Bit-width matches and mixed signs. + EXPECT_TRUE(APSInt::compareValues(U(7), S(8)) < 0); + EXPECT_TRUE(APSInt::compareValues(U(8), S(7)) > 0); + EXPECT_TRUE(APSInt::compareValues(U(7), S(7)) == 0); + EXPECT_TRUE(APSInt::compareValues(U(8), S(-7)) > 0); + + // Bit-width mismatch and is-signed. + EXPECT_TRUE(APSInt::compareValues(S(7).trunc(32), S(8)) < 0); + EXPECT_TRUE(APSInt::compareValues(S(8).trunc(32), S(7)) > 0); + EXPECT_TRUE(APSInt::compareValues(S(7).trunc(32), S(7)) == 0); + EXPECT_TRUE(APSInt::compareValues(S(-7).trunc(32), S(8)) < 0); + EXPECT_TRUE(APSInt::compareValues(S(8).trunc(32), S(-7)) > 0); + EXPECT_TRUE(APSInt::compareValues(S(-7).trunc(32), S(-7)) == 0); + EXPECT_TRUE(APSInt::compareValues(S(-7).trunc(32), S(-8)) > 0); + EXPECT_TRUE(APSInt::compareValues(S(-8).trunc(32), S(-7)) < 0); + EXPECT_TRUE(APSInt::compareValues(S(-7).trunc(32), S(-7)) == 0); + EXPECT_TRUE(APSInt::compareValues(S(7), S(8).trunc(32)) < 0); + EXPECT_TRUE(APSInt::compareValues(S(8), S(7).trunc(32)) > 0); + EXPECT_TRUE(APSInt::compareValues(S(7), S(7).trunc(32)) == 0); + EXPECT_TRUE(APSInt::compareValues(S(-7), S(8).trunc(32)) < 0); + EXPECT_TRUE(APSInt::compareValues(S(8), S(-7).trunc(32)) > 0); + EXPECT_TRUE(APSInt::compareValues(S(-7), S(-7).trunc(32)) == 0); + EXPECT_TRUE(APSInt::compareValues(S(-7), S(-8).trunc(32)) > 0); + EXPECT_TRUE(APSInt::compareValues(S(-8), S(-7).trunc(32)) < 0); + EXPECT_TRUE(APSInt::compareValues(S(-7), S(-7).trunc(32)) == 0); + + // Bit-width mismatch and not is-signed. + EXPECT_TRUE(APSInt::compareValues(U(7), U(8).trunc(32)) < 0); + EXPECT_TRUE(APSInt::compareValues(U(8), U(7).trunc(32)) > 0); + EXPECT_TRUE(APSInt::compareValues(U(7), U(7).trunc(32)) == 0); + EXPECT_TRUE(APSInt::compareValues(U(7).trunc(32), U(8)) < 0); + EXPECT_TRUE(APSInt::compareValues(U(8).trunc(32), U(7)) > 0); + EXPECT_TRUE(APSInt::compareValues(U(7).trunc(32), U(7)) == 0); + + // Bit-width mismatch and mixed signs. + EXPECT_TRUE(APSInt::compareValues(U(7).trunc(32), S(8)) < 0); + EXPECT_TRUE(APSInt::compareValues(U(8).trunc(32), S(7)) > 0); + EXPECT_TRUE(APSInt::compareValues(U(7).trunc(32), S(7)) == 0); + EXPECT_TRUE(APSInt::compareValues(U(8).trunc(32), S(-7)) > 0); + EXPECT_TRUE(APSInt::compareValues(U(7), S(8).trunc(32)) < 0); + EXPECT_TRUE(APSInt::compareValues(U(8), S(7).trunc(32)) > 0); + EXPECT_TRUE(APSInt::compareValues(U(7), S(7).trunc(32)) == 0); + EXPECT_TRUE(APSInt::compareValues(U(8), S(-7).trunc(32)) > 0); +} + } diff --git a/unittests/ADT/ArrayRefTest.cpp b/unittests/ADT/ArrayRefTest.cpp index f9c98a5..70f8208 100644 --- a/unittests/ADT/ArrayRefTest.cpp +++ b/unittests/ADT/ArrayRefTest.cpp @@ -11,6 +11,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" +#include <vector> using namespace llvm; // Check that the ArrayRef-of-pointer converting constructor only allows adding @@ -90,4 +91,24 @@ TEST(ArrayRefTest, ConstConvert) { a = ArrayRef<int *>(A); } +static std::vector<int> ReturnTest12() { return {1, 2}; } +static void ArgTest12(ArrayRef<int> A) { + EXPECT_EQ(2U, A.size()); + EXPECT_EQ(1, A[0]); + EXPECT_EQ(2, A[1]); +} + +TEST(ArrayRefTest, InitializerList) { + ArrayRef<int> A = { 0, 1, 2, 3, 4 }; + for (int i = 0; i < 5; ++i) + EXPECT_EQ(i, A[i]); + + std::vector<int> B = ReturnTest12(); + A = B; + EXPECT_EQ(1, A[0]); + EXPECT_EQ(2, A[1]); + + ArgTest12({1, 2}); +} + } // end anonymous namespace diff --git a/unittests/ADT/HashingTest.cpp b/unittests/ADT/HashingTest.cpp index acaa83c..34eb5a5 100644 --- a/unittests/ADT/HashingTest.cpp +++ b/unittests/ADT/HashingTest.cpp @@ -421,4 +421,29 @@ TEST(HashingTest, HashCombineBasicTest) { hash_combine(bigarr[0], l2, bigarr[9], l3, bigarr[18], bigarr[19])); } +TEST(HashingTest, HashCombineArgs18) { + // This tests that we can pass in up to 18 args. +#define CHECK_SAME(...) \ + EXPECT_EQ(hash_combine(__VA_ARGS__), hash_combine(__VA_ARGS__)) + CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18); + CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17); + CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); + CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14); + CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13); + CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); + CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11); + CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); + CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9); + CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8); + CHECK_SAME(1, 2, 3, 4, 5, 6, 7); + CHECK_SAME(1, 2, 3, 4, 5, 6); + CHECK_SAME(1, 2, 3, 4, 5); + CHECK_SAME(1, 2, 3, 4); + CHECK_SAME(1, 2, 3); + CHECK_SAME(1, 2); + CHECK_SAME(1); +#undef CHECK_SAME +} + } diff --git a/unittests/ADT/MapVectorTest.cpp b/unittests/ADT/MapVectorTest.cpp index 8919799..2caa8c7 100644 --- a/unittests/ADT/MapVectorTest.cpp +++ b/unittests/ADT/MapVectorTest.cpp @@ -122,3 +122,221 @@ TEST(MapVectorTest, iteration_test) { count--; } } + +TEST(SmallMapVectorSmallTest, insert_pop) { + SmallMapVector<int, int, 32> MV; + std::pair<SmallMapVector<int, int, 32>::iterator, bool> R; + + R = MV.insert(std::make_pair(1, 2)); + ASSERT_EQ(R.first, MV.begin()); + EXPECT_EQ(R.first->first, 1); + EXPECT_EQ(R.first->second, 2); + EXPECT_TRUE(R.second); + + R = MV.insert(std::make_pair(1, 3)); + ASSERT_EQ(R.first, MV.begin()); + EXPECT_EQ(R.first->first, 1); + EXPECT_EQ(R.first->second, 2); + EXPECT_FALSE(R.second); + + R = MV.insert(std::make_pair(4, 5)); + ASSERT_NE(R.first, MV.end()); + EXPECT_EQ(R.first->first, 4); + EXPECT_EQ(R.first->second, 5); + EXPECT_TRUE(R.second); + + EXPECT_EQ(MV.size(), 2u); + EXPECT_EQ(MV[1], 2); + EXPECT_EQ(MV[4], 5); + + MV.pop_back(); + EXPECT_EQ(MV.size(), 1u); + EXPECT_EQ(MV[1], 2); + + R = MV.insert(std::make_pair(4, 7)); + ASSERT_NE(R.first, MV.end()); + EXPECT_EQ(R.first->first, 4); + EXPECT_EQ(R.first->second, 7); + EXPECT_TRUE(R.second); + + EXPECT_EQ(MV.size(), 2u); + EXPECT_EQ(MV[1], 2); + EXPECT_EQ(MV[4], 7); +} + +TEST(SmallMapVectorSmallTest, erase) { + SmallMapVector<int, int, 32> MV; + + MV.insert(std::make_pair(1, 2)); + MV.insert(std::make_pair(3, 4)); + MV.insert(std::make_pair(5, 6)); + ASSERT_EQ(MV.size(), 3u); + + MV.erase(MV.find(1)); + ASSERT_EQ(MV.size(), 2u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV[3], 4); + ASSERT_EQ(MV[5], 6); + + ASSERT_EQ(MV.erase(3), 1u); + ASSERT_EQ(MV.size(), 1u); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV[5], 6); + + ASSERT_EQ(MV.erase(79), 0u); + ASSERT_EQ(MV.size(), 1u); +} + +TEST(SmallMapVectorSmallTest, remove_if) { + SmallMapVector<int, int, 32> MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + MV.remove_if([](const std::pair<int, int> &Val) { return Val.second % 2; }); + ASSERT_EQ(MV.size(), 3u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV.find(5), MV.end()); + ASSERT_EQ(MV[2], 12); + ASSERT_EQ(MV[4], 14); + ASSERT_EQ(MV[6], 16); +} + +TEST(SmallMapVectorSmallTest, iteration_test) { + SmallMapVector<int, int, 32> MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + int count = 1; + for (auto P : make_range(MV.begin(), MV.end())) { + ASSERT_EQ(P.first, count); + count++; + } + + count = 6; + for (auto P : make_range(MV.rbegin(), MV.rend())) { + ASSERT_EQ(P.first, count); + count--; + } +} + +TEST(SmallMapVectorLargeTest, insert_pop) { + SmallMapVector<int, int, 1> MV; + std::pair<SmallMapVector<int, int, 1>::iterator, bool> R; + + R = MV.insert(std::make_pair(1, 2)); + ASSERT_EQ(R.first, MV.begin()); + EXPECT_EQ(R.first->first, 1); + EXPECT_EQ(R.first->second, 2); + EXPECT_TRUE(R.second); + + R = MV.insert(std::make_pair(1, 3)); + ASSERT_EQ(R.first, MV.begin()); + EXPECT_EQ(R.first->first, 1); + EXPECT_EQ(R.first->second, 2); + EXPECT_FALSE(R.second); + + R = MV.insert(std::make_pair(4, 5)); + ASSERT_NE(R.first, MV.end()); + EXPECT_EQ(R.first->first, 4); + EXPECT_EQ(R.first->second, 5); + EXPECT_TRUE(R.second); + + EXPECT_EQ(MV.size(), 2u); + EXPECT_EQ(MV[1], 2); + EXPECT_EQ(MV[4], 5); + + MV.pop_back(); + EXPECT_EQ(MV.size(), 1u); + EXPECT_EQ(MV[1], 2); + + R = MV.insert(std::make_pair(4, 7)); + ASSERT_NE(R.first, MV.end()); + EXPECT_EQ(R.first->first, 4); + EXPECT_EQ(R.first->second, 7); + EXPECT_TRUE(R.second); + + EXPECT_EQ(MV.size(), 2u); + EXPECT_EQ(MV[1], 2); + EXPECT_EQ(MV[4], 7); +} + +TEST(SmallMapVectorLargeTest, erase) { + SmallMapVector<int, int, 1> MV; + + MV.insert(std::make_pair(1, 2)); + MV.insert(std::make_pair(3, 4)); + MV.insert(std::make_pair(5, 6)); + ASSERT_EQ(MV.size(), 3u); + + MV.erase(MV.find(1)); + ASSERT_EQ(MV.size(), 2u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV[3], 4); + ASSERT_EQ(MV[5], 6); + + ASSERT_EQ(MV.erase(3), 1u); + ASSERT_EQ(MV.size(), 1u); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV[5], 6); + + ASSERT_EQ(MV.erase(79), 0u); + ASSERT_EQ(MV.size(), 1u); +} + +TEST(SmallMapVectorLargeTest, remove_if) { + SmallMapVector<int, int, 1> MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + MV.remove_if([](const std::pair<int, int> &Val) { return Val.second % 2; }); + ASSERT_EQ(MV.size(), 3u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV.find(5), MV.end()); + ASSERT_EQ(MV[2], 12); + ASSERT_EQ(MV[4], 14); + ASSERT_EQ(MV[6], 16); +} + +TEST(SmallMapVectorLargeTest, iteration_test) { + SmallMapVector<int, int, 1> MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + int count = 1; + for (auto P : make_range(MV.begin(), MV.end())) { + ASSERT_EQ(P.first, count); + count++; + } + + count = 6; + for (auto P : make_range(MV.rbegin(), MV.rend())) { + ASSERT_EQ(P.first, count); + count--; + } +} diff --git a/unittests/ADT/OptionalTest.cpp b/unittests/ADT/OptionalTest.cpp index cadadce..92c4eec 100644 --- a/unittests/ADT/OptionalTest.cpp +++ b/unittests/ADT/OptionalTest.cpp @@ -183,10 +183,10 @@ struct MultiArgConstructor { explicit MultiArgConstructor(int x, bool positive) : x(x), y(positive ? x : -x) {} - MultiArgConstructor(const MultiArgConstructor &) LLVM_DELETED_FUNCTION; - MultiArgConstructor(MultiArgConstructor &&) LLVM_DELETED_FUNCTION; - MultiArgConstructor &operator=(const MultiArgConstructor &) LLVM_DELETED_FUNCTION; - MultiArgConstructor &operator=(MultiArgConstructor &&) LLVM_DELETED_FUNCTION; + MultiArgConstructor(const MultiArgConstructor &) = delete; + MultiArgConstructor(MultiArgConstructor &&) = delete; + MultiArgConstructor &operator=(const MultiArgConstructor &) = delete; + MultiArgConstructor &operator=(MultiArgConstructor &&) = delete; static unsigned Destructions; ~MultiArgConstructor() { @@ -340,7 +340,7 @@ struct Immovable { } private: // This should disable all move/copy operations. - Immovable(Immovable&& other) LLVM_DELETED_FUNCTION; + Immovable(Immovable&& other) = delete; }; unsigned Immovable::Constructions = 0; diff --git a/unittests/ADT/PointerIntPairTest.cpp b/unittests/ADT/PointerIntPairTest.cpp index 296d475..0bbcd9f 100644 --- a/unittests/ADT/PointerIntPairTest.cpp +++ b/unittests/ADT/PointerIntPairTest.cpp @@ -42,7 +42,6 @@ TEST_F(PointerIntPairTest, DefaultInitialize) { EXPECT_EQ(0U, Pair.getInt()); } -#if !(defined(_MSC_VER) && _MSC_VER==1700) TEST_F(PointerIntPairTest, ManyUnusedBits) { // In real code this would be a word-sized integer limited to 31 bits. struct Fixnum31 { @@ -71,6 +70,5 @@ TEST_F(PointerIntPairTest, ManyUnusedBits) { EXPECT_EQ(FixnumPointerTraits::NumLowBitsAvailable - 1, PointerLikeTypeTraits<decltype(pair)>::NumLowBitsAvailable); } -#endif } // end anonymous namespace diff --git a/unittests/ADT/SmallVectorTest.cpp b/unittests/ADT/SmallVectorTest.cpp index 95bf33e..2bbb4ed 100644 --- a/unittests/ADT/SmallVectorTest.cpp +++ b/unittests/ADT/SmallVectorTest.cpp @@ -144,8 +144,8 @@ struct NonCopyable { NonCopyable(NonCopyable &&) {} NonCopyable &operator=(NonCopyable &&) { return *this; } private: - NonCopyable(const NonCopyable &) LLVM_DELETED_FUNCTION; - NonCopyable &operator=(const NonCopyable &) LLVM_DELETED_FUNCTION; + NonCopyable(const NonCopyable &) = delete; + NonCopyable &operator=(const NonCopyable &) = delete; }; LLVM_ATTRIBUTE_USED void CompileTest() { @@ -153,17 +153,14 @@ LLVM_ATTRIBUTE_USED void CompileTest() { V.resize(42); } -// Test fixture class -template <typename VectorT> -class SmallVectorTest : public testing::Test { +class SmallVectorTestBase : public testing::Test { protected: - VectorT theVector; - VectorT otherVector; void SetUp() { Constructable::reset(); } + template <typename VectorT> void assertEmpty(VectorT & v) { // Size tests EXPECT_EQ(0u, v.size()); @@ -173,7 +170,8 @@ protected: EXPECT_TRUE(v.begin() == v.end()); } - // Assert that theVector contains the specified values, in order. + // Assert that v contains the specified values, in order. + template <typename VectorT> void assertValuesInOrder(VectorT & v, size_t size, ...) { EXPECT_EQ(size, v.size()); @@ -188,6 +186,7 @@ protected: } // Generate a sequence of values to initialize the vector. + template <typename VectorT> void makeSequence(VectorT & v, int start, int end) { for (int i = start; i <= end; ++i) { v.push_back(Constructable(i)); @@ -195,6 +194,15 @@ protected: } }; +// Test fixture class +template <typename VectorT> +class SmallVectorTest : public SmallVectorTestBase { +protected: + VectorT theVector; + VectorT otherVector; +}; + + typedef ::testing::Types<SmallVector<Constructable, 0>, SmallVector<Constructable, 1>, SmallVector<Constructable, 2>, @@ -664,6 +672,67 @@ TYPED_TEST(SmallVectorTest, IteratorTest) { this->theVector.insert(this->theVector.end(), L.begin(), L.end()); } +template <typename InvalidType> class DualSmallVectorsTest; + +template <typename VectorT1, typename VectorT2> +class DualSmallVectorsTest<std::pair<VectorT1, VectorT2>> : public SmallVectorTestBase { +protected: + VectorT1 theVector; + VectorT2 otherVector; + + template <typename T, unsigned N> + static unsigned NumBuiltinElts(const SmallVector<T, N>&) { return N; } +}; + +typedef ::testing::Types< + // Small mode -> Small mode. + std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 4>>, + // Small mode -> Big mode. + std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 2>>, + // Big mode -> Small mode. + std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 4>>, + // Big mode -> Big mode. + std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 2>> + > DualSmallVectorTestTypes; + +TYPED_TEST_CASE(DualSmallVectorsTest, DualSmallVectorTestTypes); + +TYPED_TEST(DualSmallVectorsTest, MoveAssignment) { + SCOPED_TRACE("MoveAssignTest-DualVectorTypes"); + + // Set up our vector with four elements. + for (unsigned I = 0; I < 4; ++I) + this->otherVector.push_back(Constructable(I)); + + const Constructable *OrigDataPtr = this->otherVector.data(); + + // Move-assign from the other vector. + this->theVector = + std::move(static_cast<SmallVectorImpl<Constructable>&>(this->otherVector)); + + // Make sure we have the right result. + this->assertValuesInOrder(this->theVector, 4u, 0, 1, 2, 3); + + // Make sure the # of constructor/destructor calls line up. There + // are two live objects after clearing the other vector. + this->otherVector.clear(); + EXPECT_EQ(Constructable::getNumConstructorCalls()-4, + Constructable::getNumDestructorCalls()); + + // If the source vector (otherVector) was in small-mode, assert that we just + // moved the data pointer over. + EXPECT_TRUE(this->NumBuiltinElts(this->otherVector) == 4 || + this->theVector.data() == OrigDataPtr); + + // There shouldn't be any live objects any more. + this->theVector.clear(); + EXPECT_EQ(Constructable::getNumConstructorCalls(), + Constructable::getNumDestructorCalls()); + + // We shouldn't have copied anything in this whole process. + EXPECT_EQ(Constructable::getNumCopyConstructorCalls(), 0); +} + struct notassignable { int &x; notassignable(int &x) : x(x) {} @@ -699,4 +768,142 @@ TEST(SmallVectorTest, MidInsert) { EXPECT_TRUE(m.hasValue); } +enum EmplaceableArgState { + EAS_Defaulted, + EAS_Arg, + EAS_LValue, + EAS_RValue, + EAS_Failure +}; +template <int I> struct EmplaceableArg { + EmplaceableArgState State; + EmplaceableArg() : State(EAS_Defaulted) {} + EmplaceableArg(EmplaceableArg &&X) + : State(X.State == EAS_Arg ? EAS_RValue : EAS_Failure) {} + EmplaceableArg(EmplaceableArg &X) + : State(X.State == EAS_Arg ? EAS_LValue : EAS_Failure) {} + + explicit EmplaceableArg(bool) : State(EAS_Arg) {} + +private: + EmplaceableArg &operator=(EmplaceableArg &&) = delete; + EmplaceableArg &operator=(const EmplaceableArg &) = delete; +}; + +enum EmplaceableState { ES_Emplaced, ES_Moved }; +struct Emplaceable { + EmplaceableArg<0> A0; + EmplaceableArg<1> A1; + EmplaceableArg<2> A2; + EmplaceableArg<3> A3; + EmplaceableState State; + + Emplaceable() : State(ES_Emplaced) {} + + template <class A0Ty> + explicit Emplaceable(A0Ty &&A0) + : A0(std::forward<A0Ty>(A0)), State(ES_Emplaced) {} + + template <class A0Ty, class A1Ty> + Emplaceable(A0Ty &&A0, A1Ty &&A1) + : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)), + State(ES_Emplaced) {} + + template <class A0Ty, class A1Ty, class A2Ty> + Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2) + : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)), + A2(std::forward<A2Ty>(A2)), State(ES_Emplaced) {} + + template <class A0Ty, class A1Ty, class A2Ty, class A3Ty> + Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2, A3Ty &&A3) + : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)), + A2(std::forward<A2Ty>(A2)), A3(std::forward<A3Ty>(A3)), + State(ES_Emplaced) {} + + Emplaceable(Emplaceable &&) : State(ES_Moved) {} + Emplaceable &operator=(Emplaceable &&) { + State = ES_Moved; + return *this; + } + +private: + Emplaceable(const Emplaceable &) = delete; + Emplaceable &operator=(const Emplaceable &) = delete; +}; + +TEST(SmallVectorTest, EmplaceBack) { + EmplaceableArg<0> A0(true); + EmplaceableArg<1> A1(true); + EmplaceableArg<2> A2(true); + EmplaceableArg<3> A3(true); + { + SmallVector<Emplaceable, 3> V; + V.emplace_back(); + EXPECT_TRUE(V.size() == 1); + EXPECT_TRUE(V.back().State == ES_Emplaced); + EXPECT_TRUE(V.back().A0.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A1.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A2.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A3.State == EAS_Defaulted); + } + { + SmallVector<Emplaceable, 3> V; + V.emplace_back(std::move(A0)); + EXPECT_TRUE(V.size() == 1); + EXPECT_TRUE(V.back().State == ES_Emplaced); + EXPECT_TRUE(V.back().A0.State == EAS_RValue); + EXPECT_TRUE(V.back().A1.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A2.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A3.State == EAS_Defaulted); + } + { + SmallVector<Emplaceable, 3> V; + V.emplace_back(A0); + EXPECT_TRUE(V.size() == 1); + EXPECT_TRUE(V.back().State == ES_Emplaced); + EXPECT_TRUE(V.back().A0.State == EAS_LValue); + EXPECT_TRUE(V.back().A1.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A2.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A3.State == EAS_Defaulted); + } + { + SmallVector<Emplaceable, 3> V; + V.emplace_back(A0, A1); + EXPECT_TRUE(V.size() == 1); + EXPECT_TRUE(V.back().State == ES_Emplaced); + EXPECT_TRUE(V.back().A0.State == EAS_LValue); + EXPECT_TRUE(V.back().A1.State == EAS_LValue); + EXPECT_TRUE(V.back().A2.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A3.State == EAS_Defaulted); + } + { + SmallVector<Emplaceable, 3> V; + V.emplace_back(std::move(A0), std::move(A1)); + EXPECT_TRUE(V.size() == 1); + EXPECT_TRUE(V.back().State == ES_Emplaced); + EXPECT_TRUE(V.back().A0.State == EAS_RValue); + EXPECT_TRUE(V.back().A1.State == EAS_RValue); + EXPECT_TRUE(V.back().A2.State == EAS_Defaulted); + EXPECT_TRUE(V.back().A3.State == EAS_Defaulted); + } + { + SmallVector<Emplaceable, 3> V; + V.emplace_back(std::move(A0), A1, std::move(A2), A3); + EXPECT_TRUE(V.size() == 1); + EXPECT_TRUE(V.back().State == ES_Emplaced); + EXPECT_TRUE(V.back().A0.State == EAS_RValue); + EXPECT_TRUE(V.back().A1.State == EAS_LValue); + EXPECT_TRUE(V.back().A2.State == EAS_RValue); + EXPECT_TRUE(V.back().A3.State == EAS_LValue); + } + { + SmallVector<int, 1> V; + V.emplace_back(); + V.emplace_back(42); + EXPECT_EQ(2U, V.size()); + EXPECT_EQ(0, V[0]); + EXPECT_EQ(42, V[1]); + } } + +} // end namespace diff --git a/unittests/ADT/StringMapTest.cpp b/unittests/ADT/StringMapTest.cpp index 33d668f..4ed0b76 100644 --- a/unittests/ADT/StringMapTest.cpp +++ b/unittests/ADT/StringMapTest.cpp @@ -244,7 +244,7 @@ TEST_F(StringMapTest, InsertRehashingPairTest) { // Create a non-default constructable value struct StringMapTestStruct { StringMapTestStruct(int i) : i(i) {} - StringMapTestStruct() LLVM_DELETED_FUNCTION; + StringMapTestStruct() = delete; int i; }; @@ -258,7 +258,7 @@ TEST_F(StringMapTest, NonDefaultConstructable) { struct Immovable { Immovable() {} - Immovable(Immovable&&) LLVM_DELETED_FUNCTION; // will disable the other special members + Immovable(Immovable&&) = delete; // will disable the other special members }; struct MoveOnly { @@ -272,8 +272,8 @@ struct MoveOnly { } private: - MoveOnly(const MoveOnly &) LLVM_DELETED_FUNCTION; - MoveOnly &operator=(const MoveOnly &) LLVM_DELETED_FUNCTION; + MoveOnly(const MoveOnly &) = delete; + MoveOnly &operator=(const MoveOnly &) = delete; }; TEST_F(StringMapTest, MoveOnly) { diff --git a/unittests/ADT/TinyPtrVectorTest.cpp b/unittests/ADT/TinyPtrVectorTest.cpp index ec868d4..294dfac 100644 --- a/unittests/ADT/TinyPtrVectorTest.cpp +++ b/unittests/ADT/TinyPtrVectorTest.cpp @@ -412,3 +412,50 @@ TYPED_TEST(TinyPtrVectorTest, InsertRange) { } } + +TEST(TinyPtrVectorTest, SingleEltCtorTest) { + int v = 55; + TinyPtrVector<int *> V(&v); + + EXPECT_TRUE(V.size() == 1); + EXPECT_FALSE(V.empty()); + EXPECT_TRUE(V.front() == &v); +} + +TEST(TinyPtrVectorTest, ArrayRefCtorTest) { + int data_array[128]; + std::vector<int *> data; + + for (unsigned i = 0, e = 128; i != e; ++i) { + data_array[i] = 324 - int(i); + data.push_back(&data_array[i]); + } + + TinyPtrVector<int *> V(data); + EXPECT_TRUE(V.size() == 128); + EXPECT_FALSE(V.empty()); + for (unsigned i = 0, e = 128; i != e; ++i) { + EXPECT_TRUE(V[i] == data[i]); + } +} + +TEST(TinyPtrVectorTest, MutableArrayRefTest) { + int data_array[128]; + std::vector<int *> data; + + for (unsigned i = 0, e = 128; i != e; ++i) { + data_array[i] = 324 - int(i); + data.push_back(&data_array[i]); + } + + TinyPtrVector<int *> V(data); + EXPECT_TRUE(V.size() == 128); + EXPECT_FALSE(V.empty()); + + MutableArrayRef<int *> mut_array = V; + for (unsigned i = 0, e = 128; i != e; ++i) { + EXPECT_TRUE(mut_array[i] == data[i]); + mut_array[i] = 324 + mut_array[i]; + EXPECT_TRUE(mut_array[i] == (324 + data[i])); + } +} diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index cacbde6..1f9aa32 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -665,3 +665,20 @@ TEST(TripleTest, getARMCPUForArch) { } } } + +TEST(TripleTest, NormalizeARM) { + EXPECT_EQ("armv6--netbsd-eabi", Triple::normalize("armv6-netbsd-eabi")); + EXPECT_EQ("armv7--netbsd-eabi", Triple::normalize("armv7-netbsd-eabi")); + EXPECT_EQ("armv6eb--netbsd-eabi", Triple::normalize("armv6eb-netbsd-eabi")); + EXPECT_EQ("armv7eb--netbsd-eabi", Triple::normalize("armv7eb-netbsd-eabi")); + EXPECT_EQ("armv6--netbsd-eabihf", Triple::normalize("armv6-netbsd-eabihf")); + EXPECT_EQ("armv7--netbsd-eabihf", Triple::normalize("armv7-netbsd-eabihf")); + EXPECT_EQ("armv6eb--netbsd-eabihf", Triple::normalize("armv6eb-netbsd-eabihf")); + EXPECT_EQ("armv7eb--netbsd-eabihf", Triple::normalize("armv7eb-netbsd-eabihf")); + + Triple T; + T = Triple("armv6--netbsd-eabi"); + EXPECT_EQ(Triple::arm, T.getArch()); + T = Triple("armv6eb--netbsd-eabi"); + EXPECT_EQ(Triple::armeb, T.getArch()); +} diff --git a/unittests/Analysis/CFGTest.cpp b/unittests/Analysis/CFGTest.cpp index dba9d49..4b4ebb6 100644 --- a/unittests/Analysis/CFGTest.cpp +++ b/unittests/Analysis/CFGTest.cpp @@ -16,7 +16,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Pass.h" -#include "llvm/PassManager.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" @@ -72,7 +72,7 @@ protected: PassInfo *PI = new PassInfo("isPotentiallyReachable testing pass", "", &ID, nullptr, true, true); PassRegistry::getPassRegistry()->registerPass(*PI, false); - initializeLoopInfoPass(*PassRegistry::getPassRegistry()); + initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry()); initializeDominatorTreeWrapperPassPass( *PassRegistry::getPassRegistry()); return 0; @@ -80,7 +80,7 @@ protected: void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); - AU.addRequired<LoopInfo>(); + AU.addRequired<LoopInfoWrapperPass>(); AU.addRequired<DominatorTreeWrapperPass>(); } @@ -88,7 +88,7 @@ protected: if (!F.hasName() || F.getName() != "test") return false; - LoopInfo *LI = &getAnalysis<LoopInfo>(); + LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo(); DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, nullptr), @@ -107,7 +107,7 @@ protected: IsPotentiallyReachableTestPass *P = new IsPotentiallyReachableTestPass(ExpectedResult, A, B); - PassManager PM; + legacy::PassManager PM; PM.add(P); PM.run(*M); } diff --git a/unittests/Analysis/MixedTBAATest.cpp b/unittests/Analysis/MixedTBAATest.cpp index d7935e3..7b8a25c 100644 --- a/unittests/Analysis/MixedTBAATest.cpp +++ b/unittests/Analysis/MixedTBAATest.cpp @@ -13,7 +13,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" -#include "llvm/PassManager.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/Support/CommandLine.h" #include "gtest/gtest.h" @@ -27,7 +27,7 @@ protected: LLVMContext C; Module M; MDBuilder MD; - PassManager PM; + legacy::PassManager PM; }; TEST_F(MixedTBAATest, MixedTBAA) { diff --git a/unittests/Analysis/ScalarEvolutionTest.cpp b/unittests/Analysis/ScalarEvolutionTest.cpp index 90f6997..876a264 100644 --- a/unittests/Analysis/ScalarEvolutionTest.cpp +++ b/unittests/Analysis/ScalarEvolutionTest.cpp @@ -14,7 +14,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" -#include "llvm/PassManager.h" +#include "llvm/IR/LegacyPassManager.h" #include "gtest/gtest.h" namespace llvm { @@ -32,7 +32,7 @@ protected: } LLVMContext Context; Module M; - PassManager PM; + legacy::PassManager PM; ScalarEvolution &SE; }; diff --git a/unittests/Bitcode/BitReaderTest.cpp b/unittests/Bitcode/BitReaderTest.cpp index 6eb40d6..1f28ec6 100644 --- a/unittests/Bitcode/BitReaderTest.cpp +++ b/unittests/Bitcode/BitReaderTest.cpp @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/SmallString.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index 65930b5..a1272ed 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -4,7 +4,7 @@ set_target_properties(UnitTests PROPERTIES FOLDER "Tests") if (APPLE) set(CMAKE_INSTALL_RPATH "@executable_path/../../lib") else(UNIX) - set(CMAKE_INSTALL_RPATH "\$ORIGIN/../../lib") + set(CMAKE_INSTALL_RPATH "\$ORIGIN/../../lib${LLVM_LIBDIR_SUFFIX}") endif() function(add_llvm_unittest test_dirname) @@ -22,5 +22,6 @@ add_subdirectory(LineEditor) add_subdirectory(Linker) add_subdirectory(MC) add_subdirectory(Option) +add_subdirectory(ProfileData) add_subdirectory(Support) add_subdirectory(Transforms) diff --git a/unittests/CodeGen/DIEHashTest.cpp b/unittests/CodeGen/DIEHashTest.cpp index 04c5a8a..efb0920 100644 --- a/unittests/CodeGen/DIEHashTest.cpp +++ b/unittests/CodeGen/DIEHashTest.cpp @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// -#include "../lib/CodeGen/AsmPrinter/DIE.h" +#include "llvm/CodeGen/DIE.h" #include "../lib/CodeGen/AsmPrinter/DIEHash.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" -#include "llvm/ADT/STLExtras.h" #include "gtest/gtest.h" using namespace llvm; diff --git a/unittests/DebugInfo/CMakeLists.txt b/unittests/DebugInfo/CMakeLists.txt index e844e95..dae472b 100644 --- a/unittests/DebugInfo/CMakeLists.txt +++ b/unittests/DebugInfo/CMakeLists.txt @@ -1,11 +1,3 @@ -set(LLVM_LINK_COMPONENTS - DebugInfo - ) -set(DebugInfoSources - DWARFFormValueTest.cpp - ) - -add_llvm_unittest(DebugInfoTests - ${DebugInfoSources} - ) +add_subdirectory(DWARF) +add_subdirectory(PDB) diff --git a/unittests/DebugInfo/DWARF/CMakeLists.txt b/unittests/DebugInfo/DWARF/CMakeLists.txt new file mode 100644 index 0000000..4bec17c --- /dev/null +++ b/unittests/DebugInfo/DWARF/CMakeLists.txt @@ -0,0 +1,11 @@ +set(LLVM_LINK_COMPONENTS + DebugInfoDWARF + ) + +set(DebugInfoSources + DWARFFormValueTest.cpp + ) + +add_llvm_unittest(DebugInfoDWARFTests + ${DebugInfoSources} + ) diff --git a/unittests/DebugInfo/DWARFFormValueTest.cpp b/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp index 38b932e..4521132 100644 --- a/unittests/DebugInfo/DWARFFormValueTest.cpp +++ b/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/DWARFFormValue.h" +#include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/Support/Dwarf.h" #include "gtest/gtest.h" using namespace llvm; diff --git a/unittests/DebugInfo/DWARF/Makefile b/unittests/DebugInfo/DWARF/Makefile new file mode 100644 index 0000000..b0f40e1 --- /dev/null +++ b/unittests/DebugInfo/DWARF/Makefile @@ -0,0 +1,16 @@ +##===- unittests/DebugInfo/Makefile ------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +TESTNAME = DebugInfoDWARF +LINK_COMPONENTS := DebugInfoDWARF object support + +include $(LEVEL)/Makefile.config + +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/DebugInfo/Makefile b/unittests/DebugInfo/Makefile index 999ded9..1889ad2 100644 --- a/unittests/DebugInfo/Makefile +++ b/unittests/DebugInfo/Makefile @@ -6,11 +6,10 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## - LEVEL = ../.. -TESTNAME = DebugInfo -LINK_COMPONENTS := debuginfo object support include $(LEVEL)/Makefile.config +PARALLEL_DIRS := DWARF PDB + include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/DebugInfo/PDB/CMakeLists.txt b/unittests/DebugInfo/PDB/CMakeLists.txt new file mode 100644 index 0000000..91924a5 --- /dev/null +++ b/unittests/DebugInfo/PDB/CMakeLists.txt @@ -0,0 +1,11 @@ +set(LLVM_LINK_COMPONENTS + DebugInfoPDB + ) + +set(DebugInfoPDBSources + PDBApiTest.cpp + ) + +add_llvm_unittest(DebugInfoPDBTests + ${DebugInfoPDBSources} + ) diff --git a/unittests/DebugInfo/PDB/Makefile b/unittests/DebugInfo/PDB/Makefile new file mode 100644 index 0000000..eb118a3 --- /dev/null +++ b/unittests/DebugInfo/PDB/Makefile @@ -0,0 +1,16 @@ +##===- unittests/DebugInfo/PDB/Makefile -------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +TESTNAME = DebugInfoPDB +LINK_COMPONENTS := DebugInfoPDB support + +include $(LEVEL)/Makefile.config + +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/DebugInfo/PDB/PDBApiTest.cpp b/unittests/DebugInfo/PDB/PDBApiTest.cpp new file mode 100644 index 0000000..629c5f8 --- /dev/null +++ b/unittests/DebugInfo/PDB/PDBApiTest.cpp @@ -0,0 +1,387 @@ +//===- llvm/unittest/DebugInfo/PDB/PDBApiTest.cpp -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <unordered_map> + +#include "llvm/ADT/STLExtras.h" +#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" +#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" +#include "llvm/DebugInfo/PDB/IPDBSession.h" +#include "llvm/DebugInfo/PDB/IPDBSourceFile.h" + +#include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolAnnotation.h" +#include "llvm/DebugInfo/PDB/PDBSymbolBlock.h" +#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" +#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h" +#include "llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h" +#include "llvm/DebugInfo/PDB/PDBSymbolCustom.h" +#include "llvm/DebugInfo/PDB/PDBSymbolData.h" +#include "llvm/DebugInfo/PDB/PDBSymbolExe.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" +#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" +#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h" +#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" +#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h" +#include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h" +#include "llvm/DebugInfo/PDB/PDBTypes.h" +#include "gtest/gtest.h" +using namespace llvm; + +namespace { + +#define MOCK_SYMBOL_ACCESSOR(Func) \ + decltype(std::declval<IPDBRawSymbol>().Func()) Func() const override { \ + typedef decltype(IPDBRawSymbol::Func()) ReturnType; \ + return ReturnType(); \ + } + +class MockSession : public IPDBSession { + uint64_t getLoadAddress() const override { return 0; } + void setLoadAddress(uint64_t Address) override {} + std::unique_ptr<PDBSymbolExe> getGlobalScope() const override { + return nullptr; + } + std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override { + return nullptr; + } + std::unique_ptr<IPDBSourceFile> + getSourceFileById(uint32_t SymbolId) const override { + return nullptr; + } + std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const override { + return nullptr; + } + std::unique_ptr<IPDBEnumSourceFiles> getSourceFilesForCompiland( + const PDBSymbolCompiland &Compiland) const override { + return nullptr; + } + + std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override { + return nullptr; + } +}; + +class MockRawSymbol : public IPDBRawSymbol { +public: + MockRawSymbol(PDB_SymType SymType) + : Type(SymType) {} + + void dump(raw_ostream &OS, int Indent) const override {} + + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type) const override { + return nullptr; + } + std::unique_ptr<IPDBEnumSymbols> + findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const override { + return nullptr; + } + std::unique_ptr<IPDBEnumSymbols> + findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags, + uint32_t RVA) const override { + return nullptr; + } + std::unique_ptr<IPDBEnumSymbols> + findInlineFramesByRVA(uint32_t RVA) const override { + return nullptr; + } + + void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const override {} + void getFrontEndVersion(VersionInfo &Version) const override {} + void getBackEndVersion(VersionInfo &Version) const override {} + + PDB_SymType getSymTag() const override { return Type; } + + MOCK_SYMBOL_ACCESSOR(getAccess) + MOCK_SYMBOL_ACCESSOR(getAddressOffset) + MOCK_SYMBOL_ACCESSOR(getAddressSection) + MOCK_SYMBOL_ACCESSOR(getAge) + MOCK_SYMBOL_ACCESSOR(getArrayIndexTypeId) + MOCK_SYMBOL_ACCESSOR(getBaseDataOffset) + MOCK_SYMBOL_ACCESSOR(getBaseDataSlot) + MOCK_SYMBOL_ACCESSOR(getBaseSymbolId) + MOCK_SYMBOL_ACCESSOR(getBuiltinType) + MOCK_SYMBOL_ACCESSOR(getBitPosition) + MOCK_SYMBOL_ACCESSOR(getCallingConvention) + MOCK_SYMBOL_ACCESSOR(getClassParentId) + MOCK_SYMBOL_ACCESSOR(getCompilerName) + MOCK_SYMBOL_ACCESSOR(getCount) + MOCK_SYMBOL_ACCESSOR(getCountLiveRanges) + MOCK_SYMBOL_ACCESSOR(getLanguage) + MOCK_SYMBOL_ACCESSOR(getLexicalParentId) + MOCK_SYMBOL_ACCESSOR(getLibraryName) + MOCK_SYMBOL_ACCESSOR(getLiveRangeStartAddressOffset) + MOCK_SYMBOL_ACCESSOR(getLiveRangeStartAddressSection) + MOCK_SYMBOL_ACCESSOR(getLiveRangeStartRelativeVirtualAddress) + MOCK_SYMBOL_ACCESSOR(getLocalBasePointerRegisterId) + MOCK_SYMBOL_ACCESSOR(getLowerBoundId) + MOCK_SYMBOL_ACCESSOR(getMemorySpaceKind) + MOCK_SYMBOL_ACCESSOR(getName) + MOCK_SYMBOL_ACCESSOR(getNumberOfAcceleratorPointerTags) + MOCK_SYMBOL_ACCESSOR(getNumberOfColumns) + MOCK_SYMBOL_ACCESSOR(getNumberOfModifiers) + MOCK_SYMBOL_ACCESSOR(getNumberOfRegisterIndices) + MOCK_SYMBOL_ACCESSOR(getNumberOfRows) + MOCK_SYMBOL_ACCESSOR(getObjectFileName) + MOCK_SYMBOL_ACCESSOR(getOemId) + MOCK_SYMBOL_ACCESSOR(getOemSymbolId) + MOCK_SYMBOL_ACCESSOR(getOffsetInUdt) + MOCK_SYMBOL_ACCESSOR(getPlatform) + MOCK_SYMBOL_ACCESSOR(getRank) + MOCK_SYMBOL_ACCESSOR(getRegisterId) + MOCK_SYMBOL_ACCESSOR(getRegisterType) + MOCK_SYMBOL_ACCESSOR(getRelativeVirtualAddress) + MOCK_SYMBOL_ACCESSOR(getSamplerSlot) + MOCK_SYMBOL_ACCESSOR(getSignature) + MOCK_SYMBOL_ACCESSOR(getSizeInUdt) + MOCK_SYMBOL_ACCESSOR(getSlot) + MOCK_SYMBOL_ACCESSOR(getSourceFileName) + MOCK_SYMBOL_ACCESSOR(getStride) + MOCK_SYMBOL_ACCESSOR(getSubTypeId) + MOCK_SYMBOL_ACCESSOR(getSymbolsFileName) + MOCK_SYMBOL_ACCESSOR(getSymIndexId) + MOCK_SYMBOL_ACCESSOR(getTargetOffset) + MOCK_SYMBOL_ACCESSOR(getTargetRelativeVirtualAddress) + MOCK_SYMBOL_ACCESSOR(getTargetVirtualAddress) + MOCK_SYMBOL_ACCESSOR(getTargetSection) + MOCK_SYMBOL_ACCESSOR(getTextureSlot) + MOCK_SYMBOL_ACCESSOR(getTimeStamp) + MOCK_SYMBOL_ACCESSOR(getToken) + MOCK_SYMBOL_ACCESSOR(getTypeId) + MOCK_SYMBOL_ACCESSOR(getUavSlot) + MOCK_SYMBOL_ACCESSOR(getUndecoratedName) + MOCK_SYMBOL_ACCESSOR(getUnmodifiedTypeId) + MOCK_SYMBOL_ACCESSOR(getUpperBoundId) + MOCK_SYMBOL_ACCESSOR(getVirtualBaseDispIndex) + MOCK_SYMBOL_ACCESSOR(getVirtualBaseOffset) + MOCK_SYMBOL_ACCESSOR(getVirtualTableShapeId) + MOCK_SYMBOL_ACCESSOR(getDataKind) + MOCK_SYMBOL_ACCESSOR(getGuid) + MOCK_SYMBOL_ACCESSOR(getOffset) + MOCK_SYMBOL_ACCESSOR(getThisAdjust) + MOCK_SYMBOL_ACCESSOR(getVirtualBasePointerOffset) + MOCK_SYMBOL_ACCESSOR(getLocationType) + MOCK_SYMBOL_ACCESSOR(getMachineType) + MOCK_SYMBOL_ACCESSOR(getThunkOrdinal) + MOCK_SYMBOL_ACCESSOR(getLength) + MOCK_SYMBOL_ACCESSOR(getLiveRangeLength) + MOCK_SYMBOL_ACCESSOR(getVirtualAddress) + MOCK_SYMBOL_ACCESSOR(getUdtKind) + MOCK_SYMBOL_ACCESSOR(hasConstructor) + MOCK_SYMBOL_ACCESSOR(hasCustomCallingConvention) + MOCK_SYMBOL_ACCESSOR(hasFarReturn) + MOCK_SYMBOL_ACCESSOR(isCode) + MOCK_SYMBOL_ACCESSOR(isCompilerGenerated) + MOCK_SYMBOL_ACCESSOR(isConstType) + MOCK_SYMBOL_ACCESSOR(isEditAndContinueEnabled) + MOCK_SYMBOL_ACCESSOR(isFunction) + MOCK_SYMBOL_ACCESSOR(getAddressTaken) + MOCK_SYMBOL_ACCESSOR(getNoStackOrdering) + MOCK_SYMBOL_ACCESSOR(hasAlloca) + MOCK_SYMBOL_ACCESSOR(hasAssignmentOperator) + MOCK_SYMBOL_ACCESSOR(hasCTypes) + MOCK_SYMBOL_ACCESSOR(hasCastOperator) + MOCK_SYMBOL_ACCESSOR(hasDebugInfo) + MOCK_SYMBOL_ACCESSOR(hasEH) + MOCK_SYMBOL_ACCESSOR(hasEHa) + MOCK_SYMBOL_ACCESSOR(hasFramePointer) + MOCK_SYMBOL_ACCESSOR(hasInlAsm) + MOCK_SYMBOL_ACCESSOR(hasInlineAttribute) + MOCK_SYMBOL_ACCESSOR(hasInterruptReturn) + MOCK_SYMBOL_ACCESSOR(hasLongJump) + MOCK_SYMBOL_ACCESSOR(hasManagedCode) + MOCK_SYMBOL_ACCESSOR(hasNestedTypes) + MOCK_SYMBOL_ACCESSOR(hasNoInlineAttribute) + MOCK_SYMBOL_ACCESSOR(hasNoReturnAttribute) + MOCK_SYMBOL_ACCESSOR(hasOptimizedCodeDebugInfo) + MOCK_SYMBOL_ACCESSOR(hasOverloadedOperator) + MOCK_SYMBOL_ACCESSOR(hasSEH) + MOCK_SYMBOL_ACCESSOR(hasSecurityChecks) + MOCK_SYMBOL_ACCESSOR(hasSetJump) + MOCK_SYMBOL_ACCESSOR(hasStrictGSCheck) + MOCK_SYMBOL_ACCESSOR(isAcceleratorGroupSharedLocal) + MOCK_SYMBOL_ACCESSOR(isAcceleratorPointerTagLiveRange) + MOCK_SYMBOL_ACCESSOR(isAcceleratorStubFunction) + MOCK_SYMBOL_ACCESSOR(isAggregated) + MOCK_SYMBOL_ACCESSOR(isIntroVirtualFunction) + MOCK_SYMBOL_ACCESSOR(isCVTCIL) + MOCK_SYMBOL_ACCESSOR(isConstructorVirtualBase) + MOCK_SYMBOL_ACCESSOR(isCxxReturnUdt) + MOCK_SYMBOL_ACCESSOR(isDataAligned) + MOCK_SYMBOL_ACCESSOR(isHLSLData) + MOCK_SYMBOL_ACCESSOR(isHotpatchable) + MOCK_SYMBOL_ACCESSOR(isIndirectVirtualBaseClass) + MOCK_SYMBOL_ACCESSOR(isInterfaceUdt) + MOCK_SYMBOL_ACCESSOR(isIntrinsic) + MOCK_SYMBOL_ACCESSOR(isLTCG) + MOCK_SYMBOL_ACCESSOR(isLocationControlFlowDependent) + MOCK_SYMBOL_ACCESSOR(isMSILNetmodule) + MOCK_SYMBOL_ACCESSOR(isMatrixRowMajor) + MOCK_SYMBOL_ACCESSOR(isManagedCode) + MOCK_SYMBOL_ACCESSOR(isMSILCode) + MOCK_SYMBOL_ACCESSOR(isMultipleInheritance) + MOCK_SYMBOL_ACCESSOR(isNaked) + MOCK_SYMBOL_ACCESSOR(isNested) + MOCK_SYMBOL_ACCESSOR(isOptimizedAway) + MOCK_SYMBOL_ACCESSOR(isPacked) + MOCK_SYMBOL_ACCESSOR(isPointerBasedOnSymbolValue) + MOCK_SYMBOL_ACCESSOR(isPointerToDataMember) + MOCK_SYMBOL_ACCESSOR(isPointerToMemberFunction) + MOCK_SYMBOL_ACCESSOR(isPureVirtual) + MOCK_SYMBOL_ACCESSOR(isRValueReference) + MOCK_SYMBOL_ACCESSOR(isRefUdt) + MOCK_SYMBOL_ACCESSOR(isReference) + MOCK_SYMBOL_ACCESSOR(isRestrictedType) + MOCK_SYMBOL_ACCESSOR(isReturnValue) + MOCK_SYMBOL_ACCESSOR(isSafeBuffers) + MOCK_SYMBOL_ACCESSOR(isScoped) + MOCK_SYMBOL_ACCESSOR(isSdl) + MOCK_SYMBOL_ACCESSOR(isSingleInheritance) + MOCK_SYMBOL_ACCESSOR(isSplitted) + MOCK_SYMBOL_ACCESSOR(isStatic) + MOCK_SYMBOL_ACCESSOR(hasPrivateSymbols) + MOCK_SYMBOL_ACCESSOR(isUnalignedType) + MOCK_SYMBOL_ACCESSOR(isUnreached) + MOCK_SYMBOL_ACCESSOR(isValueUdt) + MOCK_SYMBOL_ACCESSOR(isVirtual) + MOCK_SYMBOL_ACCESSOR(isVirtualBaseClass) + MOCK_SYMBOL_ACCESSOR(isVirtualInheritance) + MOCK_SYMBOL_ACCESSOR(isVolatileType) + MOCK_SYMBOL_ACCESSOR(getValue) + MOCK_SYMBOL_ACCESSOR(wasInlined) + MOCK_SYMBOL_ACCESSOR(getUnused) + +private: + PDB_SymType Type; +}; + +class PDBApiTest : public testing::Test { +public: + std::unordered_map<PDB_SymType, std::unique_ptr<PDBSymbol>> SymbolMap; + + void SetUp() override { + Session.reset(new MockSession()); + + InsertItemWithTag(PDB_SymType::None); + InsertItemWithTag(PDB_SymType::Exe); + InsertItemWithTag(PDB_SymType::Compiland); + InsertItemWithTag(PDB_SymType::CompilandDetails); + InsertItemWithTag(PDB_SymType::CompilandEnv); + InsertItemWithTag(PDB_SymType::Function); + InsertItemWithTag(PDB_SymType::Block); + InsertItemWithTag(PDB_SymType::Data); + InsertItemWithTag(PDB_SymType::Annotation); + InsertItemWithTag(PDB_SymType::Label); + InsertItemWithTag(PDB_SymType::PublicSymbol); + InsertItemWithTag(PDB_SymType::UDT); + InsertItemWithTag(PDB_SymType::Enum); + InsertItemWithTag(PDB_SymType::FunctionSig); + InsertItemWithTag(PDB_SymType::PointerType); + InsertItemWithTag(PDB_SymType::ArrayType); + InsertItemWithTag(PDB_SymType::BuiltinType); + InsertItemWithTag(PDB_SymType::Typedef); + InsertItemWithTag(PDB_SymType::BaseClass); + InsertItemWithTag(PDB_SymType::Friend); + InsertItemWithTag(PDB_SymType::FunctionArg); + InsertItemWithTag(PDB_SymType::FuncDebugStart); + InsertItemWithTag(PDB_SymType::FuncDebugEnd); + InsertItemWithTag(PDB_SymType::UsingNamespace); + InsertItemWithTag(PDB_SymType::VTableShape); + InsertItemWithTag(PDB_SymType::VTable); + InsertItemWithTag(PDB_SymType::Custom); + InsertItemWithTag(PDB_SymType::Thunk); + InsertItemWithTag(PDB_SymType::CustomType); + InsertItemWithTag(PDB_SymType::ManagedType); + InsertItemWithTag(PDB_SymType::Dimension); + InsertItemWithTag(PDB_SymType::Max); + } + + template <class ExpectedType> void VerifyDyncast(PDB_SymType Tag) { + for (auto item = SymbolMap.begin(); item != SymbolMap.end(); ++item) { + EXPECT_EQ(item->first == Tag, llvm::isa<ExpectedType>(*item->second)); + } + } + + void VerifyUnknownDyncasts() { + for (auto item = SymbolMap.begin(); item != SymbolMap.end(); ++item) { + bool should_match = false; + if (item->first == PDB_SymType::None || item->first >= PDB_SymType::Max) + should_match = true; + + EXPECT_EQ(should_match, llvm::isa<PDBSymbolUnknown>(*item->second)); + } + } + +private: + std::unique_ptr<IPDBSession> Session; + + void InsertItemWithTag(PDB_SymType Tag) { + auto RawSymbol = llvm::make_unique<MockRawSymbol>(Tag); + auto Symbol = PDBSymbol::create(*Session, std::move(RawSymbol)); + SymbolMap.insert(std::make_pair(Tag, std::move(Symbol))); + } +}; + +TEST_F(PDBApiTest, Dyncast) { + + // Most of the types have a one-to-one mapping between Tag and concrete type. + VerifyDyncast<PDBSymbolExe>(PDB_SymType::Exe); + VerifyDyncast<PDBSymbolCompiland>(PDB_SymType::Compiland); + VerifyDyncast<PDBSymbolCompilandDetails>(PDB_SymType::CompilandDetails); + VerifyDyncast<PDBSymbolCompilandEnv>(PDB_SymType::CompilandEnv); + VerifyDyncast<PDBSymbolFunc>(PDB_SymType::Function); + VerifyDyncast<PDBSymbolBlock>(PDB_SymType::Block); + VerifyDyncast<PDBSymbolData>(PDB_SymType::Data); + VerifyDyncast<PDBSymbolAnnotation>(PDB_SymType::Annotation); + VerifyDyncast<PDBSymbolLabel>(PDB_SymType::Label); + VerifyDyncast<PDBSymbolPublicSymbol>(PDB_SymType::PublicSymbol); + VerifyDyncast<PDBSymbolTypeUDT>(PDB_SymType::UDT); + VerifyDyncast<PDBSymbolTypeEnum>(PDB_SymType::Enum); + VerifyDyncast<PDBSymbolTypeFunctionSig>(PDB_SymType::FunctionSig); + VerifyDyncast<PDBSymbolTypePointer>(PDB_SymType::PointerType); + VerifyDyncast<PDBSymbolTypeArray>(PDB_SymType::ArrayType); + VerifyDyncast<PDBSymbolTypeBuiltin>(PDB_SymType::BuiltinType); + VerifyDyncast<PDBSymbolTypeTypedef>(PDB_SymType::Typedef); + VerifyDyncast<PDBSymbolTypeBaseClass>(PDB_SymType::BaseClass); + VerifyDyncast<PDBSymbolTypeFriend>(PDB_SymType::Friend); + VerifyDyncast<PDBSymbolTypeFunctionArg>(PDB_SymType::FunctionArg); + VerifyDyncast<PDBSymbolFuncDebugStart>(PDB_SymType::FuncDebugStart); + VerifyDyncast<PDBSymbolFuncDebugEnd>(PDB_SymType::FuncDebugEnd); + VerifyDyncast<PDBSymbolUsingNamespace>(PDB_SymType::UsingNamespace); + VerifyDyncast<PDBSymbolTypeVTableShape>(PDB_SymType::VTableShape); + VerifyDyncast<PDBSymbolTypeVTable>(PDB_SymType::VTable); + VerifyDyncast<PDBSymbolCustom>(PDB_SymType::Custom); + VerifyDyncast<PDBSymbolThunk>(PDB_SymType::Thunk); + VerifyDyncast<PDBSymbolTypeCustom>(PDB_SymType::CustomType); + VerifyDyncast<PDBSymbolTypeManaged>(PDB_SymType::ManagedType); + VerifyDyncast<PDBSymbolTypeDimension>(PDB_SymType::Dimension); + + VerifyUnknownDyncasts(); +} + +} // end anonymous namespace diff --git a/unittests/ExecutionEngine/CMakeLists.txt b/unittests/ExecutionEngine/CMakeLists.txt index 783c9b5..302de99 100644 --- a/unittests/ExecutionEngine/CMakeLists.txt +++ b/unittests/ExecutionEngine/CMakeLists.txt @@ -3,6 +3,8 @@ set(LLVM_LINK_COMPONENTS ExecutionEngine Interpreter MC + OrcJIT + RuntimeDyld Support ) @@ -10,6 +12,8 @@ add_llvm_unittest(ExecutionEngineTests ExecutionEngineTest.cpp ) +add_subdirectory(Orc) + # Include MCJIT tests only if native arch is a built JIT target. list(FIND LLVM_TARGETS_TO_BUILD "${LLVM_NATIVE_ARCH}" build_idx) list(FIND LLVM_TARGETS_WITH_JIT "${LLVM_NATIVE_ARCH}" jit_idx) diff --git a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt index b10cbb4..e29787f 100644 --- a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS IPO MC MCJIT + RuntimeDyld ScalarOpts Support Target diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp index c80b88b..f2a3000 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -347,6 +347,38 @@ TEST_F(MCJITCAPITest, simple_function) { EXPECT_EQ(42, functionPointer.usable()); } +TEST_F(MCJITCAPITest, gva) { + SKIP_UNSUPPORTED_PLATFORM; + + Module = LLVMModuleCreateWithName("simple_module"); + LLVMSetTarget(Module, HostTriple.c_str()); + LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "simple_value"); + LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0)); + + buildMCJITOptions(); + buildMCJITEngine(); + buildAndRunPasses(); + + uint64_t raw = LLVMGetGlobalValueAddress(Engine, "simple_value"); + int32_t *usable = (int32_t *) raw; + + EXPECT_EQ(42, *usable); +} + +TEST_F(MCJITCAPITest, gfa) { + SKIP_UNSUPPORTED_PLATFORM; + + buildSimpleFunction(); + buildMCJITOptions(); + buildMCJITEngine(); + buildAndRunPasses(); + + uint64_t raw = LLVMGetFunctionAddress(Engine, "simple_function"); + int (*usable)() = (int (*)()) raw; + + EXPECT_EQ(42, usable()); +} + TEST_F(MCJITCAPITest, custom_memory_manager) { SKIP_UNSUPPORTED_PLATFORM; diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp index b0d1bb3..da6e25a 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp @@ -392,4 +392,23 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) { ptr = TheJIT->getFunctionAddress(FB2->getName().str()); checkAccumulate(ptr); } + +// Test that FindFunctionNamed finds the definition of +// a function in the correct module. We check two functions +// in two different modules, to make sure that for at least +// one of them MCJIT had to ignore the extern declaration. +TEST_F(MCJITMultipleModuleTest, FindFunctionNamed_test) { + SKIP_UNSUPPORTED_PLATFORM; + + std::unique_ptr<Module> A, B; + Function *FA, *FB1, *FB2; + createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); + + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); + + EXPECT_EQ(FA, TheJIT->FindFunctionNamed(FA->getName().data())); + EXPECT_EQ(FB1, TheJIT->FindFunctionNamed(FB1->getName().data())); +} + } diff --git a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp index 2736383..2e38dd8 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp @@ -163,7 +163,7 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { TheJIT.reset(); // Create a new memory manager. - MM = new SectionMemoryManager; + MM.reset(new SectionMemoryManager()); // Create a new module and save it. Use a different return code so we can // tell if MCJIT compiled this module or used the cache. @@ -197,7 +197,7 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { TheJIT.reset(); // Create a new memory manager. - MM = new SectionMemoryManager; + MM.reset(new SectionMemoryManager()); // Create a new module and save it. Use a different return code so we can // tell if MCJIT compiled this module or used the cache. Note that we use diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h index eea88bb..35af417 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h @@ -325,7 +325,7 @@ protected: EngineBuilder EB(std::move(M)); std::string Error; TheJIT.reset(EB.setEngineKind(EngineKind::JIT) - .setMCJITMemoryManager(MM) + .setMCJITMemoryManager(std::move(MM)) .setErrorStr(&Error) .setOptLevel(CodeGenOpt::None) .setCodeModel(CodeModel::JITDefault) @@ -344,7 +344,7 @@ protected: StringRef MArch; SmallVector<std::string, 1> MAttrs; std::unique_ptr<ExecutionEngine> TheJIT; - RTDyldMemoryManager *MM; + std::unique_ptr<RTDyldMemoryManager> MM; std::unique_ptr<Module> M; }; diff --git a/unittests/ExecutionEngine/Makefile b/unittests/ExecutionEngine/Makefile index 8ecb883..c19f8d6 100644 --- a/unittests/ExecutionEngine/Makefile +++ b/unittests/ExecutionEngine/Makefile @@ -13,8 +13,10 @@ LINK_COMPONENTS :=interpreter include $(LEVEL)/Makefile.config +PARALLEL_DIRS = Orc + ifeq ($(TARGET_HAS_JIT),1) - PARALLEL_DIRS = MCJIT + PARALLEL_DIRS += MCJIT endif include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/ExecutionEngine/Orc/CMakeLists.txt b/unittests/ExecutionEngine/Orc/CMakeLists.txt new file mode 100644 index 0000000..7bc13a1 --- /dev/null +++ b/unittests/ExecutionEngine/Orc/CMakeLists.txt @@ -0,0 +1,8 @@ +set(LLVM_LINK_COMPONENTS + Core + Support + ) + +add_llvm_unittest(OrcJITTests + LazyEmittingLayerTest.cpp + ) diff --git a/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp b/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp new file mode 100644 index 0000000..b0ff127 --- /dev/null +++ b/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp @@ -0,0 +1,30 @@ +//===- LazyEmittingLayerTest.cpp - Unit tests for the lazy emitting layer -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h" +#include "gtest/gtest.h" + +namespace { + +struct MockBaseLayer { + typedef int ModuleSetHandleT; + ModuleSetHandleT addModuleSet(std::list<std::unique_ptr<llvm::Module>>, + std::unique_ptr<llvm::RTDyldMemoryManager> x) { + EXPECT_FALSE(x); + return 42; + } +}; + +TEST(LazyEmittingLayerTest, Empty) { + MockBaseLayer M; + llvm::orc::LazyEmittingLayer<MockBaseLayer> L(M); + L.addModuleSet(std::list<std::unique_ptr<llvm::Module>>(), nullptr); +} + +} diff --git a/unittests/ExecutionEngine/Orc/Makefile b/unittests/ExecutionEngine/Orc/Makefile new file mode 100644 index 0000000..c899728 --- /dev/null +++ b/unittests/ExecutionEngine/Orc/Makefile @@ -0,0 +1,16 @@ +##===- unittests/ExecutionEngine/Orc/Makefile --------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +TESTNAME = OrcJIT +LINK_COMPONENTS := core ipo mcjit orcjit native support + +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest + diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index a046209..0c29796 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -14,7 +14,6 @@ set(IRSources DominatorTreeTest.cpp IRBuilderTest.cpp InstructionsTest.cpp - LeakDetectorTest.cpp LegacyPassManagerTest.cpp MDBuilderTest.cpp MetadataTest.cpp diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index 5414b25..5d271e2 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -7,12 +7,14 @@ // //===----------------------------------------------------------------------===// +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" namespace llvm { @@ -347,5 +349,19 @@ TEST(ConstantsTest, GEPReplaceWithConstant) { ASSERT_EQ(GEP->getOperand(0), Alias); } +TEST(ConstantsTest, AliasCAPI) { + LLVMContext Context; + SMDiagnostic Error; + std::unique_ptr<Module> M = + parseAssemblyString("@g = global i32 42", Error, Context); + GlobalVariable *G = M->getGlobalVariable("g"); + Type *I16Ty = Type::getInt16Ty(Context); + Type *I16PTy = PointerType::get(I16Ty, 0); + Constant *Aliasee = ConstantExpr::getBitCast(G, I16PTy); + LLVMValueRef AliasRef = + LLVMAddAlias(wrap(M.get()), wrap(I16PTy), wrap(Aliasee), "a"); + ASSERT_EQ(unwrap<GlobalAlias>(AliasRef)->getAliasee(), Aliasee); +} + } // end anonymous namespace } // end namespace llvm diff --git a/unittests/IR/DebugInfoTest.cpp b/unittests/IR/DebugInfoTest.cpp index 1fa851e..3c6c786 100644 --- a/unittests/IR/DebugInfoTest.cpp +++ b/unittests/IR/DebugInfoTest.cpp @@ -65,4 +65,71 @@ TEST(DebugInfoTest, DIHeaderFieldIterator) { ASSERT_EQ("stuff", *++MAKE_FIELD_ITERATOR("\0stuff")); } +TEST(DIDescriptorTest, getFlag) { + // Some valid flags. + EXPECT_EQ(DIDescriptor::FlagPublic, DIDescriptor::getFlag("DIFlagPublic")); + EXPECT_EQ(DIDescriptor::FlagProtected, + DIDescriptor::getFlag("DIFlagProtected")); + EXPECT_EQ(DIDescriptor::FlagPrivate, DIDescriptor::getFlag("DIFlagPrivate")); + EXPECT_EQ(DIDescriptor::FlagVector, DIDescriptor::getFlag("DIFlagVector")); + EXPECT_EQ(DIDescriptor::FlagRValueReference, + DIDescriptor::getFlag("DIFlagRValueReference")); + + // FlagAccessibility shouldn't work. + EXPECT_EQ(0u, DIDescriptor::getFlag("DIFlagAccessibility")); + + // Some other invalid strings. + EXPECT_EQ(0u, DIDescriptor::getFlag("FlagVector")); + EXPECT_EQ(0u, DIDescriptor::getFlag("Vector")); + EXPECT_EQ(0u, DIDescriptor::getFlag("other things")); + EXPECT_EQ(0u, DIDescriptor::getFlag("DIFlagOther")); +} + +TEST(DIDescriptorTest, getFlagString) { + // Some valid flags. + EXPECT_EQ(StringRef("DIFlagPublic"), + DIDescriptor::getFlagString(DIDescriptor::FlagPublic)); + EXPECT_EQ(StringRef("DIFlagProtected"), + DIDescriptor::getFlagString(DIDescriptor::FlagProtected)); + EXPECT_EQ(StringRef("DIFlagPrivate"), + DIDescriptor::getFlagString(DIDescriptor::FlagPrivate)); + EXPECT_EQ(StringRef("DIFlagVector"), + DIDescriptor::getFlagString(DIDescriptor::FlagVector)); + EXPECT_EQ(StringRef("DIFlagRValueReference"), + DIDescriptor::getFlagString(DIDescriptor::FlagRValueReference)); + + // FlagAccessibility actually equals FlagPublic. + EXPECT_EQ(StringRef("DIFlagPublic"), + DIDescriptor::getFlagString(DIDescriptor::FlagAccessibility)); + + // Some other invalid flags. + EXPECT_EQ(StringRef(), DIDescriptor::getFlagString(DIDescriptor::FlagPublic | + DIDescriptor::FlagVector)); + EXPECT_EQ(StringRef(), + DIDescriptor::getFlagString(DIDescriptor::FlagFwdDecl | + DIDescriptor::FlagArtificial)); + EXPECT_EQ(StringRef(), DIDescriptor::getFlagString(0xffff)); +} + +TEST(DIDescriptorTest, splitFlags) { + // Some valid flags. +#define CHECK_SPLIT(FLAGS, VECTOR, REMAINDER) \ + { \ + SmallVector<unsigned, 8> V; \ + EXPECT_EQ(REMAINDER, DIDescriptor::splitFlags(FLAGS, V)); \ + EXPECT_TRUE(makeArrayRef(V).equals VECTOR); \ + } + CHECK_SPLIT(DIDescriptor::FlagPublic, (DIDescriptor::FlagPublic), 0u); + CHECK_SPLIT(DIDescriptor::FlagProtected, (DIDescriptor::FlagProtected), 0u); + CHECK_SPLIT(DIDescriptor::FlagPrivate, (DIDescriptor::FlagPrivate), 0u); + CHECK_SPLIT(DIDescriptor::FlagVector, (DIDescriptor::FlagVector), 0u); + CHECK_SPLIT(DIDescriptor::FlagRValueReference, (DIDescriptor::FlagRValueReference), 0u); + CHECK_SPLIT(DIDescriptor::FlagFwdDecl | DIDescriptor::FlagVector, + (DIDescriptor::FlagFwdDecl, DIDescriptor::FlagVector), 0u); + CHECK_SPLIT(0x100000u, (), 0x100000u); + CHECK_SPLIT(0x100000u | DIDescriptor::FlagVector, (DIDescriptor::FlagVector), + 0x100000u); +#undef CHECK_SPLIT +} + } // end namespace diff --git a/unittests/IR/DominatorTreeTest.cpp b/unittests/IR/DominatorTreeTest.cpp index 6c43d6f..8d2dc41 100644 --- a/unittests/IR/DominatorTreeTest.cpp +++ b/unittests/IR/DominatorTreeTest.cpp @@ -13,7 +13,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" -#include "llvm/PassManager.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" @@ -218,7 +218,7 @@ namespace llvm { TEST(DominatorTree, Unreachable) { DPass *P = new DPass(); std::unique_ptr<Module> M = makeLLVMModule(P); - PassManager Passes; + legacy::PassManager Passes; Passes.add(P); Passes.run(*M); } diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp index df5c840..08a729a 100644 --- a/unittests/IR/IRBuilderTest.cpp +++ b/unittests/IR/IRBuilderTest.cpp @@ -10,6 +10,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/Function.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" @@ -287,5 +288,22 @@ TEST_F(IRBuilderTest, RAIIHelpersTest) { EXPECT_EQ(BB, Builder.GetInsertBlock()); } +TEST_F(IRBuilderTest, DIBuilder) { + IRBuilder<> Builder(BB); + DIBuilder DIB(*M); + auto File = DIB.createFile("F.CBL", "/"); + auto CU = DIB.createCompileUnit(dwarf::DW_LANG_Cobol74, "F.CBL", "/", + "llvm-cobol74", true, "", 0); + auto Type = DIB.createSubroutineType(File, DIB.getOrCreateTypeArray(None)); + auto SP = DIB.createFunction(CU, "foo", "", File, 1, Type, + false, true, 1, 0, true, F); + EXPECT_TRUE(SP.Verify()); + AllocaInst *I = Builder.CreateAlloca(Builder.getInt8Ty()); + auto BadScope = DIB.createLexicalBlockFile(DIDescriptor(), File, 0); + I->setDebugLoc(DebugLoc::get(2, 0, BadScope)); + EXPECT_FALSE(SP.Verify()); + DIB.finalize(); +} + } diff --git a/unittests/IR/LeakDetectorTest.cpp b/unittests/IR/LeakDetectorTest.cpp deleted file mode 100644 index 94eed4c..0000000 --- a/unittests/IR/LeakDetectorTest.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//===- LeakDetectorTest.cpp -----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/IR/LeakDetector.h" -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -#ifdef GTEST_HAS_DEATH_TEST -#ifndef NDEBUG -TEST(LeakDetector, Death1) { - LeakDetector::addGarbageObject((void*) 1); - LeakDetector::addGarbageObject((void*) 2); - - EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 1), - ".*Ts.count\\(o\\) == 0 && \"Object already in set!\""); - EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 2), - "Cache != o && \"Object already in set!\""); -} -#endif -#endif - -} diff --git a/unittests/IR/LegacyPassManagerTest.cpp b/unittests/IR/LegacyPassManagerTest.cpp index 4efc2f5..9cb9414 100644 --- a/unittests/IR/LegacyPassManagerTest.cpp +++ b/unittests/IR/LegacyPassManagerTest.cpp @@ -8,13 +8,12 @@ //===----------------------------------------------------------------------===// // // This unit test exercises the legacy pass manager infrastructure. We use the -// old names as well to ensure that the source-level compatibility wrapper -// works for out-of-tree code that expects to include llvm/PassManager.h and -// subclass the core pass classes. +// old names as well to ensure that the source-level compatibility is preserved +// where possible. // //===----------------------------------------------------------------------===// -#include "llvm/PassManager.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LoopInfo.h" @@ -302,7 +301,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; - PassManager Passes; + legacy::PassManager Passes; Passes.add(new DataLayoutPass()); Passes.add(mNDM2); Passes.add(mNDM); @@ -326,7 +325,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; - PassManager Passes; + legacy::PassManager Passes; Passes.add(new DataLayoutPass()); Passes.add(mNDM); Passes.add(mNDNM); @@ -348,7 +347,7 @@ namespace llvm { void MemoryTestHelper(int run) { std::unique_ptr<Module> M(makeLLVMModule()); T *P = new T(); - PassManager Passes; + legacy::PassManager Passes; Passes.add(new DataLayoutPass()); Passes.add(P); Passes.run(*M); @@ -359,7 +358,7 @@ namespace llvm { void MemoryTestHelper(int run, int N) { Module *M = makeLLVMModule(); T *P = new T(); - PassManager Passes; + legacy::PassManager Passes; Passes.add(new DataLayoutPass()); Passes.add(P); Passes.run(*M); @@ -397,7 +396,7 @@ namespace llvm { { SCOPED_TRACE("Running OnTheFlyTest"); struct OnTheFlyTest *O = new OnTheFlyTest(); - PassManager Passes; + legacy::PassManager Passes; Passes.add(new DataLayoutPass()); Passes.add(O); Passes.run(*M); @@ -554,6 +553,6 @@ INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false) INITIALIZE_PASS(FPass, "fp","fp", false, false) INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false) -INITIALIZE_PASS_DEPENDENCY(LoopInfo) +INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) INITIALIZE_PASS_END(LPass, "lp","lp", false, false) INITIALIZE_PASS(BPass, "bp","bp", false, false) diff --git a/unittests/IR/MDBuilderTest.cpp b/unittests/IR/MDBuilderTest.cpp index fc4674e..ab2d34e 100644 --- a/unittests/IR/MDBuilderTest.cpp +++ b/unittests/IR/MDBuilderTest.cpp @@ -36,10 +36,10 @@ TEST_F(MDBuilderTest, createFPMath) { EXPECT_EQ(MD0, (MDNode *)nullptr); EXPECT_NE(MD1, (MDNode *)nullptr); EXPECT_EQ(MD1->getNumOperands(), 1U); - Value *Op = MD1->getOperand(0); - EXPECT_TRUE(isa<ConstantFP>(Op)); - EXPECT_TRUE(Op->getType()->isFloatingPointTy()); - ConstantFP *Val = cast<ConstantFP>(Op); + Metadata *Op = MD1->getOperand(0); + EXPECT_TRUE(mdconst::hasa<ConstantFP>(Op)); + ConstantFP *Val = mdconst::extract<ConstantFP>(Op); + EXPECT_TRUE(Val->getType()->isFloatingPointTy()); EXPECT_TRUE(Val->isExactlyValue(1.0)); } TEST_F(MDBuilderTest, createRangeMetadata) { @@ -50,10 +50,10 @@ TEST_F(MDBuilderTest, createRangeMetadata) { EXPECT_EQ(R0, (MDNode *)nullptr); EXPECT_NE(R1, (MDNode *)nullptr); EXPECT_EQ(R1->getNumOperands(), 2U); - EXPECT_TRUE(isa<ConstantInt>(R1->getOperand(0))); - EXPECT_TRUE(isa<ConstantInt>(R1->getOperand(1))); - ConstantInt *C0 = cast<ConstantInt>(R1->getOperand(0)); - ConstantInt *C1 = cast<ConstantInt>(R1->getOperand(1)); + EXPECT_TRUE(mdconst::hasa<ConstantInt>(R1->getOperand(0))); + EXPECT_TRUE(mdconst::hasa<ConstantInt>(R1->getOperand(1))); + ConstantInt *C0 = mdconst::extract<ConstantInt>(R1->getOperand(0)); + ConstantInt *C1 = mdconst::extract<ConstantInt>(R1->getOperand(1)); EXPECT_EQ(C0->getValue(), A); EXPECT_EQ(C1->getValue(), B); } @@ -101,7 +101,8 @@ TEST_F(MDBuilderTest, createTBAANode) { EXPECT_EQ(N0->getOperand(1), R); EXPECT_EQ(N1->getOperand(1), R); EXPECT_EQ(N2->getOperand(1), R); - EXPECT_TRUE(isa<ConstantInt>(N2->getOperand(2))); - EXPECT_EQ(cast<ConstantInt>(N2->getOperand(2))->getZExtValue(), 1U); + EXPECT_TRUE(mdconst::hasa<ConstantInt>(N2->getOperand(2))); + EXPECT_EQ(mdconst::extract<ConstantInt>(N2->getOperand(2))->getZExtValue(), + 1U); } } diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index 4f7bd72..6f2372d 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/IR/Metadata.cpp - Metadata unit tests ----------------===// +//===- unittests/IR/MetadataTest.cpp - Metadata unit tests ----------------===// // // The LLVM Compiler Infrastructure // @@ -7,22 +7,67 @@ // //===----------------------------------------------------------------------===// -#include "llvm/IR/Metadata.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" -#include "llvm/IR/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" using namespace llvm; namespace { +TEST(ContextAndReplaceableUsesTest, FromContext) { + LLVMContext Context; + ContextAndReplaceableUses CRU(Context); + EXPECT_EQ(&Context, &CRU.getContext()); + EXPECT_FALSE(CRU.hasReplaceableUses()); + EXPECT_FALSE(CRU.getReplaceableUses()); +} + +TEST(ContextAndReplaceableUsesTest, FromReplaceableUses) { + LLVMContext Context; + ContextAndReplaceableUses CRU(make_unique<ReplaceableMetadataImpl>(Context)); + EXPECT_EQ(&Context, &CRU.getContext()); + EXPECT_TRUE(CRU.hasReplaceableUses()); + EXPECT_TRUE(CRU.getReplaceableUses()); +} + +TEST(ContextAndReplaceableUsesTest, makeReplaceable) { + LLVMContext Context; + ContextAndReplaceableUses CRU(Context); + CRU.makeReplaceable(make_unique<ReplaceableMetadataImpl>(Context)); + EXPECT_EQ(&Context, &CRU.getContext()); + EXPECT_TRUE(CRU.hasReplaceableUses()); + EXPECT_TRUE(CRU.getReplaceableUses()); +} + +TEST(ContextAndReplaceableUsesTest, takeReplaceableUses) { + LLVMContext Context; + auto ReplaceableUses = make_unique<ReplaceableMetadataImpl>(Context); + auto *Ptr = ReplaceableUses.get(); + ContextAndReplaceableUses CRU(std::move(ReplaceableUses)); + ReplaceableUses = CRU.takeReplaceableUses(); + EXPECT_EQ(&Context, &CRU.getContext()); + EXPECT_FALSE(CRU.hasReplaceableUses()); + EXPECT_FALSE(CRU.getReplaceableUses()); + EXPECT_EQ(Ptr, ReplaceableUses.get()); +} + class MetadataTest : public testing::Test { protected: LLVMContext Context; + MDNode *getNode() { return MDNode::get(Context, None); } + MDNode *getNode(Metadata *MD) { return MDNode::get(Context, MD); } + MDNode *getNode(Metadata *MD1, Metadata *MD2) { + Metadata *MDs[] = {MD1, MD2}; + return MDNode::get(Context, MDs); + } }; typedef MetadataTest MDStringTest; @@ -58,7 +103,7 @@ TEST_F(MDStringTest, PrintingSimple) { std::string Str; raw_string_ostream oss(Str); s->print(oss); - EXPECT_STREQ("metadata !\"testing 1 2 3\"", oss.str().c_str()); + EXPECT_STREQ("!\"testing 1 2 3\"", oss.str().c_str()); } // Test printing of MDString with non-printable characters. @@ -68,7 +113,7 @@ TEST_F(MDStringTest, PrintingComplex) { std::string Str; raw_string_ostream oss(Str); s->print(oss); - EXPECT_STREQ("metadata !\"\\00\\0A\\22\\5C\\FF\"", oss.str().c_str()); + EXPECT_STREQ("!\"\\00\\0A\\22\\5C\\FF\"", oss.str().c_str()); } typedef MetadataTest MDNodeTest; @@ -80,30 +125,27 @@ TEST_F(MDNodeTest, Simple) { MDString *s1 = MDString::get(Context, StringRef(&x[0], 3)); MDString *s2 = MDString::get(Context, StringRef(&y[0], 3)); - ConstantInt *CI = ConstantInt::get(getGlobalContext(), APInt(8, 0)); + ConstantAsMetadata *CI = ConstantAsMetadata::get( + ConstantInt::get(getGlobalContext(), APInt(8, 0))); - std::vector<Value *> V; + std::vector<Metadata *> V; V.push_back(s1); V.push_back(CI); V.push_back(s2); MDNode *n1 = MDNode::get(Context, V); - Value *const c1 = n1; + Metadata *const c1 = n1; MDNode *n2 = MDNode::get(Context, c1); - Value *const c2 = n2; + Metadata *const c2 = n2; MDNode *n3 = MDNode::get(Context, V); MDNode *n4 = MDNode::getIfExists(Context, V); MDNode *n5 = MDNode::getIfExists(Context, c1); MDNode *n6 = MDNode::getIfExists(Context, c2); EXPECT_NE(n1, n2); -#ifdef ENABLE_MDNODE_UNIQUING EXPECT_EQ(n1, n3); -#else - (void) n3; -#endif EXPECT_EQ(n4, n1); EXPECT_EQ(n5, n2); - EXPECT_EQ(n6, (Value*)nullptr); + EXPECT_EQ(n6, (Metadata *)nullptr); EXPECT_EQ(3u, n1->getNumOperands()); EXPECT_EQ(s1, n1->getOperand(0)); @@ -118,22 +160,1713 @@ TEST_F(MDNodeTest, Delete) { Constant *C = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 1); Instruction *I = new BitCastInst(C, Type::getInt32Ty(getGlobalContext())); - Value *const V = I; + Metadata *const V = LocalAsMetadata::get(I); MDNode *n = MDNode::get(Context, V); - WeakVH wvh = n; + TrackingMDRef wvh(n); EXPECT_EQ(n, wvh); delete I; } +TEST_F(MDNodeTest, SelfReference) { + // !0 = !{!0} + // !1 = !{!0} + { + auto Temp = MDNode::getTemporary(Context, None); + Metadata *Args[] = {Temp.get()}; + MDNode *Self = MDNode::get(Context, Args); + Self->replaceOperandWith(0, Self); + ASSERT_EQ(Self, Self->getOperand(0)); + + // Self-references should be distinct, so MDNode::get() should grab a + // uniqued node that references Self, not Self. + Args[0] = Self; + MDNode *Ref1 = MDNode::get(Context, Args); + MDNode *Ref2 = MDNode::get(Context, Args); + EXPECT_NE(Self, Ref1); + EXPECT_EQ(Ref1, Ref2); + } + + // !0 = !{!0, !{}} + // !1 = !{!0, !{}} + { + auto Temp = MDNode::getTemporary(Context, None); + Metadata *Args[] = {Temp.get(), MDNode::get(Context, None)}; + MDNode *Self = MDNode::get(Context, Args); + Self->replaceOperandWith(0, Self); + ASSERT_EQ(Self, Self->getOperand(0)); + + // Self-references should be distinct, so MDNode::get() should grab a + // uniqued node that references Self, not Self itself. + Args[0] = Self; + MDNode *Ref1 = MDNode::get(Context, Args); + MDNode *Ref2 = MDNode::get(Context, Args); + EXPECT_NE(Self, Ref1); + EXPECT_EQ(Ref1, Ref2); + } +} + +TEST_F(MDNodeTest, Print) { + Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 7); + MDString *S = MDString::get(Context, "foo"); + MDNode *N0 = getNode(); + MDNode *N1 = getNode(N0); + MDNode *N2 = getNode(N0, N1); + + Metadata *Args[] = {ConstantAsMetadata::get(C), S, nullptr, N0, N1, N2}; + MDNode *N = MDNode::get(Context, Args); + + std::string Expected; + { + raw_string_ostream OS(Expected); + OS << "!{"; + C->printAsOperand(OS); + OS << ", "; + S->printAsOperand(OS); + OS << ", null"; + MDNode *Nodes[] = {N0, N1, N2}; + for (auto *Node : Nodes) + OS << ", <" << (void *)Node << ">"; + OS << "}"; + } + + std::string Actual; + { + raw_string_ostream OS(Actual); + N->print(OS); + } + + EXPECT_EQ(Expected, Actual); +} + +TEST_F(MDNodeTest, NullOperand) { + // metadata !{} + MDNode *Empty = MDNode::get(Context, None); + + // metadata !{metadata !{}} + Metadata *Ops[] = {Empty}; + MDNode *N = MDNode::get(Context, Ops); + ASSERT_EQ(Empty, N->getOperand(0)); + + // metadata !{metadata !{}} => metadata !{null} + N->replaceOperandWith(0, nullptr); + ASSERT_EQ(nullptr, N->getOperand(0)); + + // metadata !{null} + Ops[0] = nullptr; + MDNode *NullOp = MDNode::get(Context, Ops); + ASSERT_EQ(nullptr, NullOp->getOperand(0)); + EXPECT_EQ(N, NullOp); +} + +TEST_F(MDNodeTest, DistinctOnUniquingCollision) { + // !{} + MDNode *Empty = MDNode::get(Context, None); + ASSERT_TRUE(Empty->isResolved()); + EXPECT_FALSE(Empty->isDistinct()); + + // !{!{}} + Metadata *Wrapped1Ops[] = {Empty}; + MDNode *Wrapped1 = MDNode::get(Context, Wrapped1Ops); + ASSERT_EQ(Empty, Wrapped1->getOperand(0)); + ASSERT_TRUE(Wrapped1->isResolved()); + EXPECT_FALSE(Wrapped1->isDistinct()); + + // !{!{!{}}} + Metadata *Wrapped2Ops[] = {Wrapped1}; + MDNode *Wrapped2 = MDNode::get(Context, Wrapped2Ops); + ASSERT_EQ(Wrapped1, Wrapped2->getOperand(0)); + ASSERT_TRUE(Wrapped2->isResolved()); + EXPECT_FALSE(Wrapped2->isDistinct()); + + // !{!{!{}}} => !{!{}} + Wrapped2->replaceOperandWith(0, Empty); + ASSERT_EQ(Empty, Wrapped2->getOperand(0)); + EXPECT_TRUE(Wrapped2->isDistinct()); + EXPECT_FALSE(Wrapped1->isDistinct()); +} + +TEST_F(MDNodeTest, getDistinct) { + // !{} + MDNode *Empty = MDNode::get(Context, None); + ASSERT_TRUE(Empty->isResolved()); + ASSERT_FALSE(Empty->isDistinct()); + ASSERT_EQ(Empty, MDNode::get(Context, None)); + + // distinct !{} + MDNode *Distinct1 = MDNode::getDistinct(Context, None); + MDNode *Distinct2 = MDNode::getDistinct(Context, None); + EXPECT_TRUE(Distinct1->isResolved()); + EXPECT_TRUE(Distinct2->isDistinct()); + EXPECT_NE(Empty, Distinct1); + EXPECT_NE(Empty, Distinct2); + EXPECT_NE(Distinct1, Distinct2); + + // !{} + ASSERT_EQ(Empty, MDNode::get(Context, None)); +} + +TEST_F(MDNodeTest, isUniqued) { + MDNode *U = MDTuple::get(Context, None); + MDNode *D = MDTuple::getDistinct(Context, None); + auto T = MDTuple::getTemporary(Context, None); + EXPECT_TRUE(U->isUniqued()); + EXPECT_FALSE(D->isUniqued()); + EXPECT_FALSE(T->isUniqued()); +} + +TEST_F(MDNodeTest, isDistinct) { + MDNode *U = MDTuple::get(Context, None); + MDNode *D = MDTuple::getDistinct(Context, None); + auto T = MDTuple::getTemporary(Context, None); + EXPECT_FALSE(U->isDistinct()); + EXPECT_TRUE(D->isDistinct()); + EXPECT_FALSE(T->isDistinct()); +} + +TEST_F(MDNodeTest, isTemporary) { + MDNode *U = MDTuple::get(Context, None); + MDNode *D = MDTuple::getDistinct(Context, None); + auto T = MDTuple::getTemporary(Context, None); + EXPECT_FALSE(U->isTemporary()); + EXPECT_FALSE(D->isTemporary()); + EXPECT_TRUE(T->isTemporary()); +} + +TEST_F(MDNodeTest, getDistinctWithUnresolvedOperands) { + // temporary !{} + auto Temp = MDTuple::getTemporary(Context, None); + ASSERT_FALSE(Temp->isResolved()); + + // distinct !{temporary !{}} + Metadata *Ops[] = {Temp.get()}; + MDNode *Distinct = MDNode::getDistinct(Context, Ops); + EXPECT_TRUE(Distinct->isResolved()); + EXPECT_EQ(Temp.get(), Distinct->getOperand(0)); + + // temporary !{} => !{} + MDNode *Empty = MDNode::get(Context, None); + Temp->replaceAllUsesWith(Empty); + EXPECT_EQ(Empty, Distinct->getOperand(0)); +} + +TEST_F(MDNodeTest, handleChangedOperandRecursion) { + // !0 = !{} + MDNode *N0 = MDNode::get(Context, None); + + // !1 = !{!3, null} + auto Temp3 = MDTuple::getTemporary(Context, None); + Metadata *Ops1[] = {Temp3.get(), nullptr}; + MDNode *N1 = MDNode::get(Context, Ops1); + + // !2 = !{!3, !0} + Metadata *Ops2[] = {Temp3.get(), N0}; + MDNode *N2 = MDNode::get(Context, Ops2); + + // !3 = !{!2} + Metadata *Ops3[] = {N2}; + MDNode *N3 = MDNode::get(Context, Ops3); + Temp3->replaceAllUsesWith(N3); + + // !4 = !{!1} + Metadata *Ops4[] = {N1}; + MDNode *N4 = MDNode::get(Context, Ops4); + + // Confirm that the cycle prevented RAUW from getting dropped. + EXPECT_TRUE(N0->isResolved()); + EXPECT_FALSE(N1->isResolved()); + EXPECT_FALSE(N2->isResolved()); + EXPECT_FALSE(N3->isResolved()); + EXPECT_FALSE(N4->isResolved()); + + // Create a couple of distinct nodes to observe what's going on. + // + // !5 = distinct !{!2} + // !6 = distinct !{!3} + Metadata *Ops5[] = {N2}; + MDNode *N5 = MDNode::getDistinct(Context, Ops5); + Metadata *Ops6[] = {N3}; + MDNode *N6 = MDNode::getDistinct(Context, Ops6); + + // Mutate !2 to look like !1, causing a uniquing collision (and an RAUW). + // This will ripple up, with !3 colliding with !4, and RAUWing. Since !2 + // references !3, this can cause a re-entry of handleChangedOperand() when !3 + // is not ready for it. + // + // !2->replaceOperandWith(1, nullptr) + // !2: !{!3, !0} => !{!3, null} + // !2->replaceAllUsesWith(!1) + // !3: !{!2] => !{!1} + // !3->replaceAllUsesWith(!4) + N2->replaceOperandWith(1, nullptr); + + // If all has gone well, N2 and N3 will have been RAUW'ed and deleted from + // under us. Just check that the other nodes are sane. + // + // !1 = !{!4, null} + // !4 = !{!1} + // !5 = distinct !{!1} + // !6 = distinct !{!4} + EXPECT_EQ(N4, N1->getOperand(0)); + EXPECT_EQ(N1, N4->getOperand(0)); + EXPECT_EQ(N1, N5->getOperand(0)); + EXPECT_EQ(N4, N6->getOperand(0)); +} + +TEST_F(MDNodeTest, replaceResolvedOperand) { + // Check code for replacing one resolved operand with another. If doing this + // directly (via replaceOperandWith()) becomes illegal, change the operand to + // a global value that gets RAUW'ed. + // + // Use a temporary node to keep N from being resolved. + auto Temp = MDTuple::getTemporary(Context, None); + Metadata *Ops[] = {nullptr, Temp.get()}; + + MDNode *Empty = MDTuple::get(Context, ArrayRef<Metadata *>()); + MDNode *N = MDTuple::get(Context, Ops); + EXPECT_EQ(nullptr, N->getOperand(0)); + ASSERT_FALSE(N->isResolved()); + + // Check code for replacing resolved nodes. + N->replaceOperandWith(0, Empty); + EXPECT_EQ(Empty, N->getOperand(0)); + + // Check code for adding another unresolved operand. + N->replaceOperandWith(0, Temp.get()); + EXPECT_EQ(Temp.get(), N->getOperand(0)); + + // Remove the references to Temp; required for teardown. + Temp->replaceAllUsesWith(nullptr); +} + +TEST_F(MDNodeTest, replaceWithUniqued) { + auto *Empty = MDTuple::get(Context, None); + MDTuple *FirstUniqued; + { + Metadata *Ops[] = {Empty}; + auto Temp = MDTuple::getTemporary(Context, Ops); + EXPECT_TRUE(Temp->isTemporary()); + + // Don't expect a collision. + auto *Current = Temp.get(); + FirstUniqued = MDNode::replaceWithUniqued(std::move(Temp)); + EXPECT_TRUE(FirstUniqued->isUniqued()); + EXPECT_TRUE(FirstUniqued->isResolved()); + EXPECT_EQ(Current, FirstUniqued); + } + { + Metadata *Ops[] = {Empty}; + auto Temp = MDTuple::getTemporary(Context, Ops); + EXPECT_TRUE(Temp->isTemporary()); + + // Should collide with Uniqued above this time. + auto *Uniqued = MDNode::replaceWithUniqued(std::move(Temp)); + EXPECT_TRUE(Uniqued->isUniqued()); + EXPECT_TRUE(Uniqued->isResolved()); + EXPECT_EQ(FirstUniqued, Uniqued); + } + { + auto Unresolved = MDTuple::getTemporary(Context, None); + Metadata *Ops[] = {Unresolved.get()}; + auto Temp = MDTuple::getTemporary(Context, Ops); + EXPECT_TRUE(Temp->isTemporary()); + + // Shouldn't be resolved. + auto *Uniqued = MDNode::replaceWithUniqued(std::move(Temp)); + EXPECT_TRUE(Uniqued->isUniqued()); + EXPECT_FALSE(Uniqued->isResolved()); + + // Should be a different node. + EXPECT_NE(FirstUniqued, Uniqued); + + // Should resolve when we update its node (note: be careful to avoid a + // collision with any other nodes above). + Uniqued->replaceOperandWith(0, nullptr); + EXPECT_TRUE(Uniqued->isResolved()); + } +} + +TEST_F(MDNodeTest, replaceWithDistinct) { + { + auto *Empty = MDTuple::get(Context, None); + Metadata *Ops[] = {Empty}; + auto Temp = MDTuple::getTemporary(Context, Ops); + EXPECT_TRUE(Temp->isTemporary()); + + // Don't expect a collision. + auto *Current = Temp.get(); + auto *Distinct = MDNode::replaceWithDistinct(std::move(Temp)); + EXPECT_TRUE(Distinct->isDistinct()); + EXPECT_TRUE(Distinct->isResolved()); + EXPECT_EQ(Current, Distinct); + } + { + auto Unresolved = MDTuple::getTemporary(Context, None); + Metadata *Ops[] = {Unresolved.get()}; + auto Temp = MDTuple::getTemporary(Context, Ops); + EXPECT_TRUE(Temp->isTemporary()); + + // Don't expect a collision. + auto *Current = Temp.get(); + auto *Distinct = MDNode::replaceWithDistinct(std::move(Temp)); + EXPECT_TRUE(Distinct->isDistinct()); + EXPECT_TRUE(Distinct->isResolved()); + EXPECT_EQ(Current, Distinct); + + // Cleanup; required for teardown. + Unresolved->replaceAllUsesWith(nullptr); + } +} + +TEST_F(MDNodeTest, replaceWithPermanent) { + Metadata *Ops[] = {nullptr}; + auto Temp = MDTuple::getTemporary(Context, Ops); + auto *T = Temp.get(); + + // U is a normal, uniqued node that references T. + auto *U = MDTuple::get(Context, T); + EXPECT_TRUE(U->isUniqued()); + + // Make Temp self-referencing. + Temp->replaceOperandWith(0, T); + + // Try to uniquify Temp. This should, despite the name in the API, give a + // 'distinct' node, since self-references aren't allowed to be uniqued. + // + // Since it's distinct, N should have the same address as when it was a + // temporary (i.e., be equal to T not U). + auto *N = MDNode::replaceWithPermanent(std::move(Temp)); + EXPECT_EQ(N, T); + EXPECT_TRUE(N->isDistinct()); + + // U should be the canonical unique node with N as the argument. + EXPECT_EQ(U, MDTuple::get(Context, N)); + EXPECT_TRUE(U->isUniqued()); + + // This temporary should collide with U when replaced, but it should still be + // uniqued. + EXPECT_EQ(U, MDNode::replaceWithPermanent(MDTuple::getTemporary(Context, N))); + EXPECT_TRUE(U->isUniqued()); + + // This temporary should become a new uniqued node. + auto Temp2 = MDTuple::getTemporary(Context, U); + auto *V = Temp2.get(); + EXPECT_EQ(V, MDNode::replaceWithPermanent(std::move(Temp2))); + EXPECT_TRUE(V->isUniqued()); + EXPECT_EQ(U, V->getOperand(0)); +} + +TEST_F(MDNodeTest, deleteTemporaryWithTrackingRef) { + TrackingMDRef Ref; + EXPECT_EQ(nullptr, Ref.get()); + { + auto Temp = MDTuple::getTemporary(Context, None); + Ref.reset(Temp.get()); + EXPECT_EQ(Temp.get(), Ref.get()); + } + EXPECT_EQ(nullptr, Ref.get()); +} + +typedef MetadataTest MDLocationTest; + +TEST_F(MDLocationTest, Overflow) { + MDNode *N = MDNode::get(Context, None); + { + MDLocation *L = MDLocation::get(Context, 2, 7, N); + EXPECT_EQ(2u, L->getLine()); + EXPECT_EQ(7u, L->getColumn()); + } + unsigned U16 = 1u << 16; + { + MDLocation *L = MDLocation::get(Context, UINT32_MAX, U16 - 1, N); + EXPECT_EQ(UINT32_MAX, L->getLine()); + EXPECT_EQ(U16 - 1, L->getColumn()); + } + { + MDLocation *L = MDLocation::get(Context, UINT32_MAX, U16, N); + EXPECT_EQ(UINT32_MAX, L->getLine()); + EXPECT_EQ(0u, L->getColumn()); + } + { + MDLocation *L = MDLocation::get(Context, UINT32_MAX, U16 + 1, N); + EXPECT_EQ(UINT32_MAX, L->getLine()); + EXPECT_EQ(0u, L->getColumn()); + } +} + +TEST_F(MDLocationTest, getDistinct) { + MDNode *N = MDNode::get(Context, None); + MDLocation *L0 = MDLocation::getDistinct(Context, 2, 7, N); + EXPECT_TRUE(L0->isDistinct()); + MDLocation *L1 = MDLocation::get(Context, 2, 7, N); + EXPECT_FALSE(L1->isDistinct()); + EXPECT_EQ(L1, MDLocation::get(Context, 2, 7, N)); +} + +TEST_F(MDLocationTest, getTemporary) { + MDNode *N = MDNode::get(Context, None); + auto L = MDLocation::getTemporary(Context, 2, 7, N); + EXPECT_TRUE(L->isTemporary()); + EXPECT_FALSE(L->isResolved()); +} + +typedef MetadataTest GenericDebugNodeTest; + +TEST_F(GenericDebugNodeTest, get) { + StringRef Header = "header"; + auto *Empty = MDNode::get(Context, None); + Metadata *Ops1[] = {Empty}; + auto *N = GenericDebugNode::get(Context, 15, Header, Ops1); + EXPECT_EQ(15u, N->getTag()); + EXPECT_EQ(2u, N->getNumOperands()); + EXPECT_EQ(Header, N->getHeader()); + EXPECT_EQ(MDString::get(Context, Header), N->getOperand(0)); + EXPECT_EQ(1u, N->getNumDwarfOperands()); + EXPECT_EQ(Empty, N->getDwarfOperand(0)); + EXPECT_EQ(Empty, N->getOperand(1)); + ASSERT_TRUE(N->isUniqued()); + + EXPECT_EQ(N, GenericDebugNode::get(Context, 15, Header, Ops1)); + + N->replaceOperandWith(1, nullptr); + EXPECT_EQ(15u, N->getTag()); + EXPECT_EQ(Header, N->getHeader()); + EXPECT_EQ(nullptr, N->getDwarfOperand(0)); + ASSERT_TRUE(N->isUniqued()); + + Metadata *Ops2[] = {nullptr}; + EXPECT_EQ(N, GenericDebugNode::get(Context, 15, Header, Ops2)); + + N->replaceDwarfOperandWith(0, Empty); + EXPECT_EQ(15u, N->getTag()); + EXPECT_EQ(Header, N->getHeader()); + EXPECT_EQ(Empty, N->getDwarfOperand(0)); + ASSERT_TRUE(N->isUniqued()); + EXPECT_EQ(N, GenericDebugNode::get(Context, 15, Header, Ops1)); + + TempGenericDebugNode Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +TEST_F(GenericDebugNodeTest, getEmptyHeader) { + // Canonicalize !"" to null. + auto *N = GenericDebugNode::get(Context, 15, StringRef(), None); + EXPECT_EQ(StringRef(), N->getHeader()); + EXPECT_EQ(nullptr, N->getOperand(0)); +} + +typedef MetadataTest MDSubrangeTest; + +TEST_F(MDSubrangeTest, get) { + auto *N = MDSubrange::get(Context, 5, 7); + EXPECT_EQ(dwarf::DW_TAG_subrange_type, N->getTag()); + EXPECT_EQ(5, N->getCount()); + EXPECT_EQ(7, N->getLo()); + EXPECT_EQ(N, MDSubrange::get(Context, 5, 7)); + EXPECT_EQ(MDSubrange::get(Context, 5, 0), MDSubrange::get(Context, 5)); + + TempMDSubrange Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +TEST_F(MDSubrangeTest, getEmptyArray) { + auto *N = MDSubrange::get(Context, -1, 0); + EXPECT_EQ(dwarf::DW_TAG_subrange_type, N->getTag()); + EXPECT_EQ(-1, N->getCount()); + EXPECT_EQ(0, N->getLo()); + EXPECT_EQ(N, MDSubrange::get(Context, -1, 0)); +} + +typedef MetadataTest MDEnumeratorTest; + +TEST_F(MDEnumeratorTest, get) { + auto *N = MDEnumerator::get(Context, 7, "name"); + EXPECT_EQ(dwarf::DW_TAG_enumerator, N->getTag()); + EXPECT_EQ(7, N->getValue()); + EXPECT_EQ("name", N->getName()); + EXPECT_EQ(N, MDEnumerator::get(Context, 7, "name")); + + EXPECT_NE(N, MDEnumerator::get(Context, 8, "name")); + EXPECT_NE(N, MDEnumerator::get(Context, 7, "nam")); + + TempMDEnumerator Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +typedef MetadataTest MDBasicTypeTest; + +TEST_F(MDBasicTypeTest, get) { + auto *N = + MDBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, 26, 7); + EXPECT_EQ(dwarf::DW_TAG_base_type, N->getTag()); + EXPECT_EQ("special", N->getName()); + EXPECT_EQ(33u, N->getSizeInBits()); + EXPECT_EQ(26u, N->getAlignInBits()); + EXPECT_EQ(7u, N->getEncoding()); + EXPECT_EQ(0u, N->getLine()); + EXPECT_EQ(N, MDBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, + 26, 7)); + + EXPECT_NE(N, MDBasicType::get(Context, dwarf::DW_TAG_unspecified_type, + "special", 33, 26, 7)); + EXPECT_NE(N, + MDBasicType::get(Context, dwarf::DW_TAG_base_type, "s", 33, 26, 7)); + EXPECT_NE(N, MDBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 32, + 26, 7)); + EXPECT_NE(N, MDBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, + 25, 7)); + EXPECT_NE(N, MDBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, + 26, 6)); + + TempMDBasicType Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +TEST_F(MDBasicTypeTest, getWithLargeValues) { + auto *N = MDBasicType::get(Context, dwarf::DW_TAG_base_type, "special", + UINT64_MAX, UINT64_MAX - 1, 7); + EXPECT_EQ(UINT64_MAX, N->getSizeInBits()); + EXPECT_EQ(UINT64_MAX - 1, N->getAlignInBits()); +} + +typedef MetadataTest MDDerivedTypeTest; + +TEST_F(MDDerivedTypeTest, get) { + Metadata *File = MDTuple::getDistinct(Context, None); + Metadata *Scope = MDTuple::getDistinct(Context, None); + Metadata *BaseType = MDTuple::getDistinct(Context, None); + Metadata *ExtraData = MDTuple::getDistinct(Context, None); + + auto *N = MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", + File, 1, Scope, BaseType, 2, 3, 4, 5, ExtraData); + EXPECT_EQ(dwarf::DW_TAG_pointer_type, N->getTag()); + EXPECT_EQ("something", N->getName()); + EXPECT_EQ(File, N->getFile()); + EXPECT_EQ(1u, N->getLine()); + EXPECT_EQ(Scope, N->getScope()); + EXPECT_EQ(BaseType, N->getBaseType()); + EXPECT_EQ(2u, N->getSizeInBits()); + EXPECT_EQ(3u, N->getAlignInBits()); + EXPECT_EQ(4u, N->getOffsetInBits()); + EXPECT_EQ(5u, N->getFlags()); + EXPECT_EQ(ExtraData, N->getExtraData()); + EXPECT_EQ(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, + "something", File, 1, Scope, BaseType, 2, 3, + 4, 5, ExtraData)); + + EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_reference_type, + "something", File, 1, Scope, BaseType, 2, 3, + 4, 5, ExtraData)); + EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "else", + File, 1, Scope, BaseType, 2, 3, 4, 5, + ExtraData)); + EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, + "something", Scope, 1, Scope, BaseType, 2, 3, + 4, 5, ExtraData)); + EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, + "something", File, 2, Scope, BaseType, 2, 3, + 4, 5, ExtraData)); + EXPECT_NE(N, + MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", + File, 1, File, BaseType, 2, 3, 4, 5, ExtraData)); + EXPECT_NE(N, + MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", + File, 1, Scope, File, 2, 3, 4, 5, ExtraData)); + EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, + "something", File, 1, Scope, BaseType, 3, 3, + 4, 5, ExtraData)); + EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, + "something", File, 1, Scope, BaseType, 2, 2, + 4, 5, ExtraData)); + EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, + "something", File, 1, Scope, BaseType, 2, 3, + 5, 5, ExtraData)); + EXPECT_NE(N, MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, + "something", File, 1, Scope, BaseType, 2, 3, + 4, 4, ExtraData)); + EXPECT_NE(N, + MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", + File, 1, Scope, BaseType, 2, 3, 4, 5, File)); + + TempMDDerivedType Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +TEST_F(MDDerivedTypeTest, getWithLargeValues) { + Metadata *File = MDTuple::getDistinct(Context, None); + Metadata *Scope = MDTuple::getDistinct(Context, None); + Metadata *BaseType = MDTuple::getDistinct(Context, None); + Metadata *ExtraData = MDTuple::getDistinct(Context, None); + + auto *N = MDDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something", + File, 1, Scope, BaseType, UINT64_MAX, + UINT64_MAX - 1, UINT64_MAX - 2, 5, ExtraData); + EXPECT_EQ(UINT64_MAX, N->getSizeInBits()); + EXPECT_EQ(UINT64_MAX - 1, N->getAlignInBits()); + EXPECT_EQ(UINT64_MAX - 2, N->getOffsetInBits()); +} + +typedef MetadataTest MDCompositeTypeTest; + +TEST_F(MDCompositeTypeTest, get) { + unsigned Tag = dwarf::DW_TAG_structure_type; + StringRef Name = "some name"; + Metadata *File = MDTuple::getDistinct(Context, None); + unsigned Line = 1; + Metadata *Scope = MDTuple::getDistinct(Context, None); + Metadata *BaseType = MDTuple::getDistinct(Context, None); + uint64_t SizeInBits = 2; + uint64_t AlignInBits = 3; + uint64_t OffsetInBits = 4; + unsigned Flags = 5; + Metadata *Elements = MDTuple::getDistinct(Context, None); + unsigned RuntimeLang = 6; + Metadata *VTableHolder = MDTuple::getDistinct(Context, None); + Metadata *TemplateParams = MDTuple::getDistinct(Context, None); + StringRef Identifier = "some id"; + + auto *N = MDCompositeType::get(Context, Tag, Name, File, Line, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier); + EXPECT_EQ(Tag, N->getTag()); + EXPECT_EQ(Name, N->getName()); + EXPECT_EQ(File, N->getFile()); + EXPECT_EQ(Line, N->getLine()); + EXPECT_EQ(Scope, N->getScope()); + EXPECT_EQ(BaseType, N->getBaseType()); + EXPECT_EQ(SizeInBits, N->getSizeInBits()); + EXPECT_EQ(AlignInBits, N->getAlignInBits()); + EXPECT_EQ(OffsetInBits, N->getOffsetInBits()); + EXPECT_EQ(Flags, N->getFlags()); + EXPECT_EQ(Elements, N->getElements()); + EXPECT_EQ(RuntimeLang, N->getRuntimeLang()); + EXPECT_EQ(VTableHolder, N->getVTableHolder()); + EXPECT_EQ(TemplateParams, N->getTemplateParams()); + EXPECT_EQ(Identifier, N->getIdentifier()); + + EXPECT_EQ(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)); + + EXPECT_NE(N, MDCompositeType::get(Context, Tag + 1, Name, File, Line, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get(Context, Tag, "abc", File, Line, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, Scope, Line, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line + 1, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, File, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, File, + SizeInBits, AlignInBits, OffsetInBits, + Flags, Elements, RuntimeLang, VTableHolder, + TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, + BaseType, SizeInBits + 1, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, + BaseType, SizeInBits, AlignInBits + 1, + OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits + 1, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags + 1, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, File, RuntimeLang, + VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang + 1, + VTableHolder, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, + File, TemplateParams, Identifier)); + EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, File, Identifier)); + EXPECT_NE(N, MDCompositeType::get(Context, Tag, Name, File, Line, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, "other")); + + // Be sure that missing identifiers get null pointers. + EXPECT_FALSE(MDCompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, "")->getRawIdentifier()); + EXPECT_FALSE(MDCompositeType::get( + Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, + AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams)->getRawIdentifier()); + + TempMDCompositeType Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +TEST_F(MDCompositeTypeTest, getWithLargeValues) { + unsigned Tag = dwarf::DW_TAG_structure_type; + StringRef Name = "some name"; + Metadata *File = MDTuple::getDistinct(Context, None); + unsigned Line = 1; + Metadata *Scope = MDTuple::getDistinct(Context, None); + Metadata *BaseType = MDTuple::getDistinct(Context, None); + uint64_t SizeInBits = UINT64_MAX; + uint64_t AlignInBits = UINT64_MAX - 1; + uint64_t OffsetInBits = UINT64_MAX - 2; + unsigned Flags = 5; + Metadata *Elements = MDTuple::getDistinct(Context, None); + unsigned RuntimeLang = 6; + Metadata *VTableHolder = MDTuple::getDistinct(Context, None); + Metadata *TemplateParams = MDTuple::getDistinct(Context, None); + StringRef Identifier = "some id"; + + auto *N = MDCompositeType::get(Context, Tag, Name, File, Line, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, Elements, RuntimeLang, + VTableHolder, TemplateParams, Identifier); + EXPECT_EQ(SizeInBits, N->getSizeInBits()); + EXPECT_EQ(AlignInBits, N->getAlignInBits()); + EXPECT_EQ(OffsetInBits, N->getOffsetInBits()); +} + +TEST_F(MDCompositeTypeTest, replaceOperands) { + unsigned Tag = dwarf::DW_TAG_structure_type; + StringRef Name = "some name"; + Metadata *File = MDTuple::getDistinct(Context, None); + unsigned Line = 1; + Metadata *Scope = MDTuple::getDistinct(Context, None); + Metadata *BaseType = MDTuple::getDistinct(Context, None); + uint64_t SizeInBits = 2; + uint64_t AlignInBits = 3; + uint64_t OffsetInBits = 4; + unsigned Flags = 5; + unsigned RuntimeLang = 6; + StringRef Identifier = "some id"; + + auto *N = MDCompositeType::get(Context, Tag, Name, File, Line, Scope, + BaseType, SizeInBits, AlignInBits, + OffsetInBits, Flags, nullptr, RuntimeLang, + nullptr, nullptr, Identifier); + + auto *Elements = MDTuple::getDistinct(Context, None); + EXPECT_EQ(nullptr, N->getElements()); + N->replaceElements(Elements); + EXPECT_EQ(Elements, N->getElements()); + N->replaceElements(nullptr); + EXPECT_EQ(nullptr, N->getElements()); + + auto *VTableHolder = MDTuple::getDistinct(Context, None); + EXPECT_EQ(nullptr, N->getVTableHolder()); + N->replaceVTableHolder(VTableHolder); + EXPECT_EQ(VTableHolder, N->getVTableHolder()); + N->replaceVTableHolder(nullptr); + EXPECT_EQ(nullptr, N->getVTableHolder()); + + auto *TemplateParams = MDTuple::getDistinct(Context, None); + EXPECT_EQ(nullptr, N->getTemplateParams()); + N->replaceTemplateParams(TemplateParams); + EXPECT_EQ(TemplateParams, N->getTemplateParams()); + N->replaceTemplateParams(nullptr); + EXPECT_EQ(nullptr, N->getTemplateParams()); +} + +typedef MetadataTest MDSubroutineTypeTest; + +TEST_F(MDSubroutineTypeTest, get) { + unsigned Flags = 1; + Metadata *TypeArray = MDTuple::getDistinct(Context, None); + + auto *N = MDSubroutineType::get(Context, Flags, TypeArray); + EXPECT_EQ(dwarf::DW_TAG_subroutine_type, N->getTag()); + EXPECT_EQ(Flags, N->getFlags()); + EXPECT_EQ(TypeArray, N->getTypeArray()); + EXPECT_EQ(N, MDSubroutineType::get(Context, Flags, TypeArray)); + + EXPECT_NE(N, MDSubroutineType::get(Context, Flags + 1, TypeArray)); + EXPECT_NE(N, MDSubroutineType::get(Context, Flags, + MDTuple::getDistinct(Context, None))); + + TempMDSubroutineType Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); + + // Test always-empty operands. + EXPECT_EQ(nullptr, N->getScope()); + EXPECT_EQ(nullptr, N->getFile()); + EXPECT_EQ("", N->getName()); + EXPECT_EQ(nullptr, N->getBaseType()); + EXPECT_EQ(nullptr, N->getVTableHolder()); + EXPECT_EQ(nullptr, N->getTemplateParams()); + EXPECT_EQ("", N->getIdentifier()); +} + +typedef MetadataTest MDFileTest; + +TEST_F(MDFileTest, get) { + StringRef Filename = "file"; + StringRef Directory = "dir"; + auto *N = MDFile::get(Context, Filename, Directory); + + EXPECT_EQ(dwarf::DW_TAG_file_type, N->getTag()); + EXPECT_EQ(Filename, N->getFilename()); + EXPECT_EQ(Directory, N->getDirectory()); + EXPECT_EQ(N, MDFile::get(Context, Filename, Directory)); + + EXPECT_NE(N, MDFile::get(Context, "other", Directory)); + EXPECT_NE(N, MDFile::get(Context, Filename, "other")); + + TempMDFile Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +typedef MetadataTest MDCompileUnitTest; + +TEST_F(MDCompileUnitTest, get) { + unsigned SourceLanguage = 1; + Metadata *File = MDTuple::getDistinct(Context, None); + StringRef Producer = "some producer"; + bool IsOptimized = false; + StringRef Flags = "flag after flag"; + unsigned RuntimeVersion = 2; + StringRef SplitDebugFilename = "another/file"; + unsigned EmissionKind = 3; + Metadata *EnumTypes = MDTuple::getDistinct(Context, None); + Metadata *RetainedTypes = MDTuple::getDistinct(Context, None); + Metadata *Subprograms = MDTuple::getDistinct(Context, None); + Metadata *GlobalVariables = MDTuple::getDistinct(Context, None); + Metadata *ImportedEntities = MDTuple::getDistinct(Context, None); + auto *N = MDCompileUnit::get( + Context, SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, Subprograms, GlobalVariables, ImportedEntities); + + EXPECT_EQ(dwarf::DW_TAG_compile_unit, N->getTag()); + EXPECT_EQ(SourceLanguage, N->getSourceLanguage()); + EXPECT_EQ(File, N->getFile()); + EXPECT_EQ(Producer, N->getProducer()); + EXPECT_EQ(IsOptimized, N->isOptimized()); + EXPECT_EQ(Flags, N->getFlags()); + EXPECT_EQ(RuntimeVersion, N->getRuntimeVersion()); + EXPECT_EQ(SplitDebugFilename, N->getSplitDebugFilename()); + EXPECT_EQ(EmissionKind, N->getEmissionKind()); + EXPECT_EQ(EnumTypes, N->getEnumTypes()); + EXPECT_EQ(RetainedTypes, N->getRetainedTypes()); + EXPECT_EQ(Subprograms, N->getSubprograms()); + EXPECT_EQ(GlobalVariables, N->getGlobalVariables()); + EXPECT_EQ(ImportedEntities, N->getImportedEntities()); + EXPECT_EQ(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer, + IsOptimized, Flags, RuntimeVersion, + SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)); + + EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage + 1, File, Producer, + IsOptimized, Flags, RuntimeVersion, + SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)); + EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, EnumTypes, Producer, + IsOptimized, Flags, RuntimeVersion, + SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)); + EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, "other", + IsOptimized, Flags, RuntimeVersion, + SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)); + EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer, + !IsOptimized, Flags, RuntimeVersion, + SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)); + EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer, + IsOptimized, "other", RuntimeVersion, + SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)); + EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer, + IsOptimized, Flags, RuntimeVersion + 1, + SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)); + EXPECT_NE(N, + MDCompileUnit::get(Context, SourceLanguage, File, Producer, + IsOptimized, Flags, RuntimeVersion, "other", + EmissionKind, EnumTypes, RetainedTypes, + Subprograms, GlobalVariables, ImportedEntities)); + EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer, + IsOptimized, Flags, RuntimeVersion, + SplitDebugFilename, EmissionKind + 1, + EnumTypes, RetainedTypes, Subprograms, + GlobalVariables, ImportedEntities)); + EXPECT_NE(N, MDCompileUnit::get(Context, SourceLanguage, File, Producer, + IsOptimized, Flags, RuntimeVersion, + SplitDebugFilename, EmissionKind, File, + RetainedTypes, Subprograms, GlobalVariables, + ImportedEntities)); + EXPECT_NE(N, MDCompileUnit::get( + Context, SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, + File, Subprograms, GlobalVariables, ImportedEntities)); + EXPECT_NE(N, MDCompileUnit::get( + Context, SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, File, GlobalVariables, ImportedEntities)); + EXPECT_NE(N, MDCompileUnit::get( + Context, SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, Subprograms, File, ImportedEntities)); + EXPECT_NE(N, MDCompileUnit::get( + Context, SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, Subprograms, GlobalVariables, File)); + + TempMDCompileUnit Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +TEST_F(MDCompileUnitTest, replaceArrays) { + unsigned SourceLanguage = 1; + Metadata *File = MDTuple::getDistinct(Context, None); + StringRef Producer = "some producer"; + bool IsOptimized = false; + StringRef Flags = "flag after flag"; + unsigned RuntimeVersion = 2; + StringRef SplitDebugFilename = "another/file"; + unsigned EmissionKind = 3; + Metadata *EnumTypes = MDTuple::getDistinct(Context, None); + Metadata *RetainedTypes = MDTuple::getDistinct(Context, None); + Metadata *ImportedEntities = MDTuple::getDistinct(Context, None); + auto *N = MDCompileUnit::get( + Context, SourceLanguage, File, Producer, IsOptimized, Flags, + RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, + RetainedTypes, nullptr, nullptr, ImportedEntities); + + auto *Subprograms = MDTuple::getDistinct(Context, None); + EXPECT_EQ(nullptr, N->getSubprograms()); + N->replaceSubprograms(Subprograms); + EXPECT_EQ(Subprograms, N->getSubprograms()); + N->replaceSubprograms(nullptr); + EXPECT_EQ(nullptr, N->getSubprograms()); + + auto *GlobalVariables = MDTuple::getDistinct(Context, None); + EXPECT_EQ(nullptr, N->getGlobalVariables()); + N->replaceGlobalVariables(GlobalVariables); + EXPECT_EQ(GlobalVariables, N->getGlobalVariables()); + N->replaceGlobalVariables(nullptr); + EXPECT_EQ(nullptr, N->getGlobalVariables()); +} + +typedef MetadataTest MDSubprogramTest; + +TEST_F(MDSubprogramTest, get) { + Metadata *Scope = MDTuple::getDistinct(Context, None); + StringRef Name = "name"; + StringRef LinkageName = "linkage"; + Metadata *File = MDTuple::getDistinct(Context, None); + unsigned Line = 2; + Metadata *Type = MDTuple::getDistinct(Context, None); + bool IsLocalToUnit = false; + bool IsDefinition = true; + unsigned ScopeLine = 3; + Metadata *ContainingType = MDTuple::getDistinct(Context, None); + unsigned Virtuality = 4; + unsigned VirtualIndex = 5; + unsigned Flags = 6; + bool IsOptimized = false; + Metadata *Function = MDTuple::getDistinct(Context, None); + Metadata *TemplateParams = MDTuple::getDistinct(Context, None); + Metadata *Declaration = MDTuple::getDistinct(Context, None); + Metadata *Variables = MDTuple::getDistinct(Context, None); + + auto *N = MDSubprogram::get( + Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, + IsOptimized, Function, TemplateParams, Declaration, Variables); + + EXPECT_EQ(dwarf::DW_TAG_subprogram, N->getTag()); + EXPECT_EQ(Scope, N->getScope()); + EXPECT_EQ(Name, N->getName()); + EXPECT_EQ(LinkageName, N->getLinkageName()); + EXPECT_EQ(File, N->getFile()); + EXPECT_EQ(Line, N->getLine()); + EXPECT_EQ(Type, N->getType()); + EXPECT_EQ(IsLocalToUnit, N->isLocalToUnit()); + EXPECT_EQ(IsDefinition, N->isDefinition()); + EXPECT_EQ(ScopeLine, N->getScopeLine()); + EXPECT_EQ(ContainingType, N->getContainingType()); + EXPECT_EQ(Virtuality, N->getVirtuality()); + EXPECT_EQ(VirtualIndex, N->getVirtualIndex()); + EXPECT_EQ(Flags, N->getFlags()); + EXPECT_EQ(IsOptimized, N->isOptimized()); + EXPECT_EQ(Function, N->getFunction()); + EXPECT_EQ(TemplateParams, N->getTemplateParams()); + EXPECT_EQ(Declaration, N->getDeclaration()); + EXPECT_EQ(Variables, N->getVariables()); + EXPECT_EQ(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)); + + EXPECT_NE(N, MDSubprogram::get(Context, File, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, "other", LinkageName, File, + Line, Type, IsLocalToUnit, IsDefinition, + ScopeLine, ContainingType, Virtuality, + VirtualIndex, Flags, IsOptimized, Function, + TemplateParams, Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, "other", File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, Scope, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, + Line + 1, Type, IsLocalToUnit, IsDefinition, + ScopeLine, ContainingType, Virtuality, + VirtualIndex, Flags, IsOptimized, Function, + TemplateParams, Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Scope, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, !IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, !IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, + ScopeLine + 1, ContainingType, Virtuality, + VirtualIndex, Flags, IsOptimized, Function, + TemplateParams, Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + Type, Virtuality, VirtualIndex, Flags, + IsOptimized, Function, TemplateParams, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality + 1, VirtualIndex, + Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex + 1, + Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + ~Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + Flags, !IsOptimized, Function, TemplateParams, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + Flags, IsOptimized, Type, TemplateParams, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + Flags, IsOptimized, Function, Type, + Declaration, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + Flags, IsOptimized, Function, TemplateParams, + Type, Variables)); + EXPECT_NE(N, MDSubprogram::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, ScopeLine, + ContainingType, Virtuality, VirtualIndex, + Flags, IsOptimized, Function, TemplateParams, + Declaration, Type)); + + TempMDSubprogram Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +TEST_F(MDSubprogramTest, replaceFunction) { + Metadata *Scope = MDTuple::getDistinct(Context, None); + StringRef Name = "name"; + StringRef LinkageName = "linkage"; + Metadata *File = MDTuple::getDistinct(Context, None); + unsigned Line = 2; + Metadata *Type = MDTuple::getDistinct(Context, None); + bool IsLocalToUnit = false; + bool IsDefinition = true; + unsigned ScopeLine = 3; + Metadata *ContainingType = MDTuple::getDistinct(Context, None); + unsigned Virtuality = 4; + unsigned VirtualIndex = 5; + unsigned Flags = 6; + bool IsOptimized = false; + Metadata *TemplateParams = MDTuple::getDistinct(Context, None); + Metadata *Declaration = MDTuple::getDistinct(Context, None); + Metadata *Variables = MDTuple::getDistinct(Context, None); + + auto *N = MDSubprogram::get( + Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, + IsOptimized, nullptr, TemplateParams, Declaration, Variables); + + EXPECT_EQ(nullptr, N->getFunction()); + + std::unique_ptr<Function> F( + Function::Create(FunctionType::get(Type::getVoidTy(Context), false), + GlobalValue::ExternalLinkage)); + N->replaceFunction(F.get()); + EXPECT_EQ(ConstantAsMetadata::get(F.get()), N->getFunction()); + + N->replaceFunction(nullptr); + EXPECT_EQ(nullptr, N->getFunction()); +} + +typedef MetadataTest MDLexicalBlockTest; + +TEST_F(MDLexicalBlockTest, get) { + Metadata *Scope = MDTuple::getDistinct(Context, None); + Metadata *File = MDTuple::getDistinct(Context, None); + unsigned Line = 5; + unsigned Column = 8; + + auto *N = MDLexicalBlock::get(Context, Scope, File, Line, Column); + + EXPECT_EQ(dwarf::DW_TAG_lexical_block, N->getTag()); + EXPECT_EQ(Scope, N->getScope()); + EXPECT_EQ(File, N->getFile()); + EXPECT_EQ(Line, N->getLine()); + EXPECT_EQ(Column, N->getColumn()); + EXPECT_EQ(N, MDLexicalBlock::get(Context, Scope, File, Line, Column)); + + EXPECT_NE(N, MDLexicalBlock::get(Context, File, File, Line, Column)); + EXPECT_NE(N, MDLexicalBlock::get(Context, Scope, Scope, Line, Column)); + EXPECT_NE(N, MDLexicalBlock::get(Context, Scope, File, Line + 1, Column)); + EXPECT_NE(N, MDLexicalBlock::get(Context, Scope, File, Line, Column + 1)); + + TempMDLexicalBlock Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +typedef MetadataTest MDLexicalBlockFileTest; + +TEST_F(MDLexicalBlockFileTest, get) { + Metadata *Scope = MDTuple::getDistinct(Context, None); + Metadata *File = MDTuple::getDistinct(Context, None); + unsigned Discriminator = 5; + + auto *N = MDLexicalBlockFile::get(Context, Scope, File, Discriminator); + + EXPECT_EQ(dwarf::DW_TAG_lexical_block, N->getTag()); + EXPECT_EQ(Scope, N->getScope()); + EXPECT_EQ(File, N->getFile()); + EXPECT_EQ(Discriminator, N->getDiscriminator()); + EXPECT_EQ(N, MDLexicalBlockFile::get(Context, Scope, File, Discriminator)); + + EXPECT_NE(N, MDLexicalBlockFile::get(Context, File, File, Discriminator)); + EXPECT_NE(N, MDLexicalBlockFile::get(Context, Scope, Scope, Discriminator)); + EXPECT_NE(N, + MDLexicalBlockFile::get(Context, Scope, File, Discriminator + 1)); + + TempMDLexicalBlockFile Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +typedef MetadataTest MDNamespaceTest; + +TEST_F(MDNamespaceTest, get) { + Metadata *Scope = MDTuple::getDistinct(Context, None); + Metadata *File = MDTuple::getDistinct(Context, None); + StringRef Name = "namespace"; + unsigned Line = 5; + + auto *N = MDNamespace::get(Context, Scope, File, Name, Line); + + EXPECT_EQ(dwarf::DW_TAG_namespace, N->getTag()); + EXPECT_EQ(Scope, N->getScope()); + EXPECT_EQ(File, N->getFile()); + EXPECT_EQ(Name, N->getName()); + EXPECT_EQ(Line, N->getLine()); + EXPECT_EQ(N, MDNamespace::get(Context, Scope, File, Name, Line)); + + EXPECT_NE(N, MDNamespace::get(Context, File, File, Name, Line)); + EXPECT_NE(N, MDNamespace::get(Context, Scope, Scope, Name, Line)); + EXPECT_NE(N, MDNamespace::get(Context, Scope, File, "other", Line)); + EXPECT_NE(N, MDNamespace::get(Context, Scope, File, Name, Line + 1)); + + TempMDNamespace Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +typedef MetadataTest MDTemplateTypeParameterTest; + +TEST_F(MDTemplateTypeParameterTest, get) { + StringRef Name = "template"; + Metadata *Type = MDTuple::getDistinct(Context, None); + Metadata *Other = MDTuple::getDistinct(Context, None); + + auto *N = MDTemplateTypeParameter::get(Context, Name, Type); + + EXPECT_EQ(dwarf::DW_TAG_template_type_parameter, N->getTag()); + EXPECT_EQ(Name, N->getName()); + EXPECT_EQ(Type, N->getType()); + EXPECT_EQ(N, MDTemplateTypeParameter::get(Context, Name, Type)); + + EXPECT_NE(N, MDTemplateTypeParameter::get(Context, "other", Type)); + EXPECT_NE(N, MDTemplateTypeParameter::get(Context, Name, Other)); + + TempMDTemplateTypeParameter Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +typedef MetadataTest MDTemplateValueParameterTest; + +TEST_F(MDTemplateValueParameterTest, get) { + unsigned Tag = dwarf::DW_TAG_template_value_parameter; + StringRef Name = "template"; + Metadata *Type = MDTuple::getDistinct(Context, None); + Metadata *Value = MDTuple::getDistinct(Context, None); + Metadata *Other = MDTuple::getDistinct(Context, None); + + auto *N = MDTemplateValueParameter::get(Context, Tag, Name, Type, Value); + EXPECT_EQ(Tag, N->getTag()); + EXPECT_EQ(Name, N->getName()); + EXPECT_EQ(Type, N->getType()); + EXPECT_EQ(Value, N->getValue()); + EXPECT_EQ(N, MDTemplateValueParameter::get(Context, Tag, Name, Type, Value)); + + EXPECT_NE(N, MDTemplateValueParameter::get( + Context, dwarf::DW_TAG_GNU_template_template_param, Name, + Type, Value)); + EXPECT_NE(N, MDTemplateValueParameter::get(Context, Tag, "other", Type, + Value)); + EXPECT_NE(N, MDTemplateValueParameter::get(Context, Tag, Name, Other, + Value)); + EXPECT_NE(N, MDTemplateValueParameter::get(Context, Tag, Name, Type, Other)); + + TempMDTemplateValueParameter Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +typedef MetadataTest MDGlobalVariableTest; + +TEST_F(MDGlobalVariableTest, get) { + Metadata *Scope = MDTuple::getDistinct(Context, None); + StringRef Name = "name"; + StringRef LinkageName = "linkage"; + Metadata *File = MDTuple::getDistinct(Context, None); + unsigned Line = 5; + Metadata *Type = MDTuple::getDistinct(Context, None); + bool IsLocalToUnit = false; + bool IsDefinition = true; + Metadata *Variable = MDTuple::getDistinct(Context, None); + Metadata *StaticDataMemberDeclaration = MDTuple::getDistinct(Context, None); + + auto *N = MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line, + Type, IsLocalToUnit, IsDefinition, Variable, + StaticDataMemberDeclaration); + EXPECT_EQ(dwarf::DW_TAG_variable, N->getTag()); + EXPECT_EQ(Scope, N->getScope()); + EXPECT_EQ(Name, N->getName()); + EXPECT_EQ(LinkageName, N->getLinkageName()); + EXPECT_EQ(File, N->getFile()); + EXPECT_EQ(Line, N->getLine()); + EXPECT_EQ(Type, N->getType()); + EXPECT_EQ(IsLocalToUnit, N->isLocalToUnit()); + EXPECT_EQ(IsDefinition, N->isDefinition()); + EXPECT_EQ(Variable, N->getVariable()); + EXPECT_EQ(StaticDataMemberDeclaration, N->getStaticDataMemberDeclaration()); + EXPECT_EQ(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, + Line, Type, IsLocalToUnit, IsDefinition, + Variable, StaticDataMemberDeclaration)); + + EXPECT_NE(N, MDGlobalVariable::get(Context, File, Name, LinkageName, File, + Line, Type, IsLocalToUnit, IsDefinition, + Variable, StaticDataMemberDeclaration)); + EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, "other", LinkageName, File, + Line, Type, IsLocalToUnit, IsDefinition, + Variable, StaticDataMemberDeclaration)); + EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, "other", File, Line, + Type, IsLocalToUnit, IsDefinition, + Variable, StaticDataMemberDeclaration)); + EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, Scope, + Line, Type, IsLocalToUnit, IsDefinition, + Variable, StaticDataMemberDeclaration)); + EXPECT_NE(N, + MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, + Line + 1, Type, IsLocalToUnit, IsDefinition, + Variable, StaticDataMemberDeclaration)); + EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, + Line, Scope, IsLocalToUnit, IsDefinition, + Variable, StaticDataMemberDeclaration)); + EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, + Line, Type, !IsLocalToUnit, IsDefinition, + Variable, StaticDataMemberDeclaration)); + EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, + Line, Type, IsLocalToUnit, !IsDefinition, + Variable, StaticDataMemberDeclaration)); + EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, + Line, Type, IsLocalToUnit, IsDefinition, + Type, StaticDataMemberDeclaration)); + EXPECT_NE(N, MDGlobalVariable::get(Context, Scope, Name, LinkageName, File, + Line, Type, IsLocalToUnit, IsDefinition, + Variable, Type)); + + TempMDGlobalVariable Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +typedef MetadataTest MDLocalVariableTest; + +TEST_F(MDLocalVariableTest, get) { + unsigned Tag = dwarf::DW_TAG_arg_variable; + Metadata *Scope = MDTuple::getDistinct(Context, None); + StringRef Name = "name"; + Metadata *File = MDTuple::getDistinct(Context, None); + unsigned Line = 5; + Metadata *Type = MDTuple::getDistinct(Context, None); + unsigned Arg = 6; + unsigned Flags = 7; + Metadata *InlinedAt = MDTuple::getDistinct(Context, None); + + auto *N = MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type, + Arg, Flags, InlinedAt); + EXPECT_EQ(Tag, N->getTag()); + EXPECT_EQ(Scope, N->getScope()); + EXPECT_EQ(Name, N->getName()); + EXPECT_EQ(File, N->getFile()); + EXPECT_EQ(Line, N->getLine()); + EXPECT_EQ(Type, N->getType()); + EXPECT_EQ(Arg, N->getArg()); + EXPECT_EQ(Flags, N->getFlags()); + EXPECT_EQ(InlinedAt, N->getInlinedAt()); + EXPECT_EQ(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type, + Arg, Flags, InlinedAt)); + + EXPECT_NE(N, MDLocalVariable::get(Context, dwarf::DW_TAG_auto_variable, Scope, + Name, File, Line, Type, Arg, Flags, + InlinedAt)); + EXPECT_NE(N, MDLocalVariable::get(Context, Tag, File, Name, File, Line, + Type, Arg, Flags, InlinedAt)); + EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, "other", File, Line, + Type, Arg, Flags, InlinedAt)); + EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, Scope, Line, + Type, Arg, Flags, InlinedAt)); + EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line + 1, + Type, Arg, Flags, InlinedAt)); + EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, + Scope, Arg, Flags, InlinedAt)); + EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type, + Arg + 1, Flags, InlinedAt)); + EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type, + Arg, ~Flags, InlinedAt)); + EXPECT_NE(N, MDLocalVariable::get(Context, Tag, Scope, Name, File, Line, Type, + Arg, Flags, Scope)); + + TempMDLocalVariable Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +typedef MetadataTest MDExpressionTest; + +TEST_F(MDExpressionTest, get) { + uint64_t Elements[] = {2, 6, 9, 78, 0}; + auto *N = MDExpression::get(Context, Elements); + EXPECT_EQ(makeArrayRef(Elements), N->getElements()); + EXPECT_EQ(N, MDExpression::get(Context, Elements)); + + EXPECT_EQ(5u, N->getNumElements()); + EXPECT_EQ(2u, N->getElement(0)); + EXPECT_EQ(6u, N->getElement(1)); + EXPECT_EQ(9u, N->getElement(2)); + EXPECT_EQ(78u, N->getElement(3)); + EXPECT_EQ(0u, N->getElement(4)); + + TempMDExpression Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +TEST_F(MDExpressionTest, isValid) { +#define EXPECT_VALID(...) \ + do { \ + uint64_t Elements[] = {__VA_ARGS__}; \ + EXPECT_TRUE(MDExpression::get(Context, Elements)->isValid()); \ + } while (false) +#define EXPECT_INVALID(...) \ + do { \ + uint64_t Elements[] = {__VA_ARGS__}; \ + EXPECT_FALSE(MDExpression::get(Context, Elements)->isValid()); \ + } while (false) + + // Empty expression should be valid. + EXPECT_TRUE(MDExpression::get(Context, None)); + + // Valid constructions. + EXPECT_VALID(dwarf::DW_OP_plus, 6); + EXPECT_VALID(dwarf::DW_OP_deref); + EXPECT_VALID(dwarf::DW_OP_bit_piece, 3, 7); + EXPECT_VALID(dwarf::DW_OP_plus, 6, dwarf::DW_OP_deref); + EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6); + EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_bit_piece, 3, 7); + EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6, dwarf::DW_OP_bit_piece, 3, 7); + + // Invalid constructions. + EXPECT_INVALID(~0u); + EXPECT_INVALID(dwarf::DW_OP_plus); + EXPECT_INVALID(dwarf::DW_OP_bit_piece); + EXPECT_INVALID(dwarf::DW_OP_bit_piece, 3); + EXPECT_INVALID(dwarf::DW_OP_bit_piece, 3, 7, dwarf::DW_OP_plus, 3); + EXPECT_INVALID(dwarf::DW_OP_bit_piece, 3, 7, dwarf::DW_OP_deref); + +#undef EXPECT_VALID +#undef EXPECT_INVALID +} + +typedef MetadataTest MDObjCPropertyTest; + +TEST_F(MDObjCPropertyTest, get) { + StringRef Name = "name"; + Metadata *File = MDTuple::getDistinct(Context, None); + unsigned Line = 5; + StringRef GetterName = "getter"; + StringRef SetterName = "setter"; + unsigned Attributes = 7; + Metadata *Type = MDTuple::getDistinct(Context, None); + + auto *N = MDObjCProperty::get(Context, Name, File, Line, GetterName, + SetterName, Attributes, Type); + + EXPECT_EQ(dwarf::DW_TAG_APPLE_property, N->getTag()); + EXPECT_EQ(Name, N->getName()); + EXPECT_EQ(File, N->getFile()); + EXPECT_EQ(Line, N->getLine()); + EXPECT_EQ(GetterName, N->getGetterName()); + EXPECT_EQ(SetterName, N->getSetterName()); + EXPECT_EQ(Attributes, N->getAttributes()); + EXPECT_EQ(Type, N->getType()); + EXPECT_EQ(N, MDObjCProperty::get(Context, Name, File, Line, GetterName, + SetterName, Attributes, Type)); + + EXPECT_NE(N, MDObjCProperty::get(Context, "other", File, Line, GetterName, + SetterName, Attributes, Type)); + EXPECT_NE(N, MDObjCProperty::get(Context, Name, Type, Line, GetterName, + SetterName, Attributes, Type)); + EXPECT_NE(N, MDObjCProperty::get(Context, Name, File, Line + 1, GetterName, + SetterName, Attributes, Type)); + EXPECT_NE(N, MDObjCProperty::get(Context, Name, File, Line, "other", + SetterName, Attributes, Type)); + EXPECT_NE(N, MDObjCProperty::get(Context, Name, File, Line, GetterName, + "other", Attributes, Type)); + EXPECT_NE(N, MDObjCProperty::get(Context, Name, File, Line, GetterName, + SetterName, Attributes + 1, Type)); + EXPECT_NE(N, MDObjCProperty::get(Context, Name, File, Line, GetterName, + SetterName, Attributes, File)); + + TempMDObjCProperty Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +typedef MetadataTest MDImportedEntityTest; + +TEST_F(MDImportedEntityTest, get) { + unsigned Tag = dwarf::DW_TAG_imported_module; + Metadata *Scope = MDTuple::getDistinct(Context, None); + Metadata *Entity = MDTuple::getDistinct(Context, None); + unsigned Line = 5; + StringRef Name = "name"; + + auto *N = MDImportedEntity::get(Context, Tag, Scope, Entity, Line, Name); + + EXPECT_EQ(Tag, N->getTag()); + EXPECT_EQ(Scope, N->getScope()); + EXPECT_EQ(Entity, N->getEntity()); + EXPECT_EQ(Line, N->getLine()); + EXPECT_EQ(Name, N->getName()); + EXPECT_EQ(N, MDImportedEntity::get(Context, Tag, Scope, Entity, Line, Name)); + + EXPECT_NE(N, + MDImportedEntity::get(Context, dwarf::DW_TAG_imported_declaration, + Scope, Entity, Line, Name)); + EXPECT_NE(N, MDImportedEntity::get(Context, Tag, Entity, Entity, Line, Name)); + EXPECT_NE(N, MDImportedEntity::get(Context, Tag, Scope, Scope, Line, Name)); + EXPECT_NE(N, + MDImportedEntity::get(Context, Tag, Scope, Entity, Line + 1, Name)); + EXPECT_NE(N, + MDImportedEntity::get(Context, Tag, Scope, Entity, Line, "other")); + + TempMDImportedEntity Temp = N->clone(); + EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp))); +} + +typedef MetadataTest MetadataAsValueTest; + +TEST_F(MetadataAsValueTest, MDNode) { + MDNode *N = MDNode::get(Context, None); + auto *V = MetadataAsValue::get(Context, N); + EXPECT_TRUE(V->getType()->isMetadataTy()); + EXPECT_EQ(N, V->getMetadata()); + + auto *V2 = MetadataAsValue::get(Context, N); + EXPECT_EQ(V, V2); +} + +TEST_F(MetadataAsValueTest, MDNodeMDNode) { + MDNode *N = MDNode::get(Context, None); + Metadata *Ops[] = {N}; + MDNode *N2 = MDNode::get(Context, Ops); + auto *V = MetadataAsValue::get(Context, N2); + EXPECT_TRUE(V->getType()->isMetadataTy()); + EXPECT_EQ(N2, V->getMetadata()); + + auto *V2 = MetadataAsValue::get(Context, N2); + EXPECT_EQ(V, V2); + + auto *V3 = MetadataAsValue::get(Context, N); + EXPECT_TRUE(V3->getType()->isMetadataTy()); + EXPECT_NE(V, V3); + EXPECT_EQ(N, V3->getMetadata()); +} + +TEST_F(MetadataAsValueTest, MDNodeConstant) { + auto *C = ConstantInt::getTrue(Context); + auto *MD = ConstantAsMetadata::get(C); + Metadata *Ops[] = {MD}; + auto *N = MDNode::get(Context, Ops); + + auto *V = MetadataAsValue::get(Context, MD); + EXPECT_TRUE(V->getType()->isMetadataTy()); + EXPECT_EQ(MD, V->getMetadata()); + + auto *V2 = MetadataAsValue::get(Context, N); + EXPECT_EQ(MD, V2->getMetadata()); + EXPECT_EQ(V, V2); +} + +typedef MetadataTest ValueAsMetadataTest; + +TEST_F(ValueAsMetadataTest, UpdatesOnRAUW) { + Type *Ty = Type::getInt1PtrTy(Context); + std::unique_ptr<GlobalVariable> GV0( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + auto *MD = ValueAsMetadata::get(GV0.get()); + EXPECT_TRUE(MD->getValue() == GV0.get()); + ASSERT_TRUE(GV0->use_empty()); + + std::unique_ptr<GlobalVariable> GV1( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + GV0->replaceAllUsesWith(GV1.get()); + EXPECT_TRUE(MD->getValue() == GV1.get()); +} + +TEST_F(ValueAsMetadataTest, CollidingDoubleUpdates) { + // Create a constant. + ConstantAsMetadata *CI = ConstantAsMetadata::get( + ConstantInt::get(getGlobalContext(), APInt(8, 0))); + + // Create a temporary to prevent nodes from resolving. + auto Temp = MDTuple::getTemporary(Context, None); + + // When the first operand of N1 gets reset to nullptr, it'll collide with N2. + Metadata *Ops1[] = {CI, CI, Temp.get()}; + Metadata *Ops2[] = {nullptr, CI, Temp.get()}; + + auto *N1 = MDTuple::get(Context, Ops1); + auto *N2 = MDTuple::get(Context, Ops2); + ASSERT_NE(N1, N2); + + // Tell metadata that the constant is getting deleted. + // + // After this, N1 will be invalid, so don't touch it. + ValueAsMetadata::handleDeletion(CI->getValue()); + EXPECT_EQ(nullptr, N2->getOperand(0)); + EXPECT_EQ(nullptr, N2->getOperand(1)); + EXPECT_EQ(Temp.get(), N2->getOperand(2)); + + // Clean up Temp for teardown. + Temp->replaceAllUsesWith(nullptr); +} + +typedef MetadataTest TrackingMDRefTest; + +TEST_F(TrackingMDRefTest, UpdatesOnRAUW) { + Type *Ty = Type::getInt1PtrTy(Context); + std::unique_ptr<GlobalVariable> GV0( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + TypedTrackingMDRef<ValueAsMetadata> MD(ValueAsMetadata::get(GV0.get())); + EXPECT_TRUE(MD->getValue() == GV0.get()); + ASSERT_TRUE(GV0->use_empty()); + + std::unique_ptr<GlobalVariable> GV1( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + GV0->replaceAllUsesWith(GV1.get()); + EXPECT_TRUE(MD->getValue() == GV1.get()); + + // Reset it, so we don't inadvertently test deletion. + MD.reset(); +} + +TEST_F(TrackingMDRefTest, UpdatesOnDeletion) { + Type *Ty = Type::getInt1PtrTy(Context); + std::unique_ptr<GlobalVariable> GV( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + TypedTrackingMDRef<ValueAsMetadata> MD(ValueAsMetadata::get(GV.get())); + EXPECT_TRUE(MD->getValue() == GV.get()); + ASSERT_TRUE(GV->use_empty()); + + GV.reset(); + EXPECT_TRUE(!MD); +} + TEST(NamedMDNodeTest, Search) { LLVMContext Context; - Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 1); - Constant *C2 = ConstantInt::get(Type::getInt32Ty(Context), 2); + ConstantAsMetadata *C = + ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Context), 1)); + ConstantAsMetadata *C2 = + ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Context), 2)); - Value *const V = C; - Value *const V2 = C2; + Metadata *const V = C; + Metadata *const V2 = C2; MDNode *n = MDNode::get(Context, V); MDNode *n2 = MDNode::get(Context, V2); diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp index d493156..41af0b0 100644 --- a/unittests/IR/PassManagerTest.cpp +++ b/unittests/IR/PassManagerTest.cpp @@ -29,13 +29,16 @@ public: /// \brief Returns an opaque, unique ID for this pass type. static void *ID() { return (void *)&PassID; } + /// \brief Returns the name of the analysis. + static StringRef name() { return "TestFunctionAnalysis"; } + TestFunctionAnalysis(int &Runs) : Runs(Runs) {} /// \brief Run the analysis pass over the function and return a result. - Result run(Function *F, FunctionAnalysisManager *AM) { + Result run(Function &F, FunctionAnalysisManager *AM) { ++Runs; int Count = 0; - for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; ++BBI) + for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; ++II) ++Count; @@ -60,12 +63,14 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "TestModuleAnalysis"; } + TestModuleAnalysis(int &Runs) : Runs(Runs) {} - Result run(Module *M, ModuleAnalysisManager *AM) { + Result run(Module &M, ModuleAnalysisManager *AM) { ++Runs; int Count = 0; - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) ++Count; return Result(Count); } @@ -81,7 +86,7 @@ char TestModuleAnalysis::PassID; struct TestModulePass { TestModulePass(int &RunCount) : RunCount(RunCount) {} - PreservedAnalyses run(Module *M) { + PreservedAnalyses run(Module &M) { ++RunCount; return PreservedAnalyses::none(); } @@ -92,13 +97,13 @@ struct TestModulePass { }; struct TestPreservingModulePass { - PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); } + PreservedAnalyses run(Module &M) { return PreservedAnalyses::all(); } static StringRef name() { return "TestPreservingModulePass"; } }; struct TestMinPreservingModulePass { - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) { PreservedAnalyses PA; // Force running an analysis. @@ -119,13 +124,13 @@ struct TestFunctionPass { AnalyzedFunctionCount(AnalyzedFunctionCount), OnlyUseCachedResults(OnlyUseCachedResults) {} - PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM) { + PreservedAnalyses run(Function &F, FunctionAnalysisManager *AM) { ++RunCount; const ModuleAnalysisManager &MAM = AM->getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); if (TestModuleAnalysis::Result *TMA = - MAM.getCachedResult<TestModuleAnalysis>(F->getParent())) + MAM.getCachedResult<TestModuleAnalysis>(*F.getParent())) AnalyzedFunctionCount += TMA->FunctionCount; if (OnlyUseCachedResults) { @@ -155,9 +160,9 @@ struct TestFunctionPass { struct TestInvalidationFunctionPass { TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {} - PreservedAnalyses run(Function *F) { - return F->getName() == Name ? PreservedAnalyses::none() - : PreservedAnalyses::all(); + PreservedAnalyses run(Function &F) { + return F.getName() == Name ? PreservedAnalyses::none() + : PreservedAnalyses::all(); } static StringRef name() { return "TestInvalidationFunctionPass"; } @@ -165,10 +170,10 @@ struct TestInvalidationFunctionPass { StringRef Name; }; -Module *parseIR(const char *IR) { +std::unique_ptr<Module> parseIR(const char *IR) { LLVMContext &C = getGlobalContext(); SMDiagnostic Err; - return parseAssemblyString(IR, Err, C).release(); + return parseAssemblyString(IR, Err, C); } class PassManagerTest : public ::testing::Test { @@ -310,7 +315,7 @@ TEST_F(PassManagerTest, Basic) { MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } - MPM.run(M.get(), &MAM); + MPM.run(*M, &MAM); // Validate module pass counters. EXPECT_EQ(1, ModulePassRunCount); diff --git a/unittests/IR/UseTest.cpp b/unittests/IR/UseTest.cpp index 3f33ca6..d9d20af 100644 --- a/unittests/IR/UseTest.cpp +++ b/unittests/IR/UseTest.cpp @@ -9,10 +9,10 @@ #include "llvm/AsmParser/Parser.h" #include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/User.h" -#include "llvm/IR/Instructions.h" #include "llvm/Support/Format.h" #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" @@ -50,7 +50,7 @@ TEST(UseTest, sort) { }); unsigned I = 0; for (User *U : X.users()) { - snprintf(vnbuf, sizeof(vnbuf), "v%u", I++); + format("v%u", I++).snprint(vnbuf, sizeof(vnbuf)); EXPECT_EQ(vnbuf, U->getName()); } ASSERT_EQ(8u, I); @@ -60,7 +60,7 @@ TEST(UseTest, sort) { }); I = 0; for (User *U : X.users()) { - snprintf(vnbuf, sizeof(vnbuf), "v%u", (7 - I++)); + format("v%u", (7 - I++)).snprint(vnbuf, sizeof(vnbuf)); EXPECT_EQ(vnbuf, U->getName()); } ASSERT_EQ(8u, I); @@ -95,7 +95,7 @@ TEST(UseTest, reverse) { }); unsigned I = 0; for (User *U : X.users()) { - snprintf(vnbuf, sizeof(vnbuf), "v%u", I++); + format("v%u", I++).snprint(vnbuf, sizeof(vnbuf)); EXPECT_EQ(vnbuf, U->getName()); } ASSERT_EQ(8u, I); @@ -103,7 +103,7 @@ TEST(UseTest, reverse) { X.reverseUseList(); I = 0; for (User *U : X.users()) { - snprintf(vnbuf, sizeof(vnbuf), "v%u", (7 - I++)); + format("v%u", (7 - I++)).snprint(vnbuf, sizeof(vnbuf)); EXPECT_EQ(vnbuf, U->getName()); } ASSERT_EQ(8u, I); diff --git a/unittests/IR/UserTest.cpp b/unittests/IR/UserTest.cpp index 5572424..56b054b 100644 --- a/unittests/IR/UserTest.cpp +++ b/unittests/IR/UserTest.cpp @@ -9,10 +9,10 @@ #include "llvm/AsmParser/Parser.h" #include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/User.h" -#include "llvm/IR/Instructions.h" #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" using namespace llvm; diff --git a/unittests/IR/WaymarkTest.cpp b/unittests/IR/WaymarkTest.cpp index 8e3cd45..a8924ef 100644 --- a/unittests/IR/WaymarkTest.cpp +++ b/unittests/IR/WaymarkTest.cpp @@ -29,8 +29,9 @@ TEST(WaymarkTest, NativeArray) { Value * values[22]; std::transform(tail, tail + 22, values, char2constant); FunctionType *FT = FunctionType::get(Type::getVoidTy(getGlobalContext()), true); - Function *F = Function::Create(FT, GlobalValue::ExternalLinkage); - const CallInst *A = CallInst::Create(F, makeArrayRef(values)); + std::unique_ptr<Function> F( + Function::Create(FT, GlobalValue::ExternalLinkage)); + const CallInst *A = CallInst::Create(F.get(), makeArrayRef(values)); ASSERT_NE(A, (const CallInst*)nullptr); ASSERT_EQ(1U + 22, A->getNumOperands()); const Use *U = &A->getOperandUse(0); diff --git a/unittests/Linker/LinkModulesTest.cpp b/unittests/Linker/LinkModulesTest.cpp index b15d180..91f97d7 100644 --- a/unittests/Linker/LinkModulesTest.cpp +++ b/unittests/Linker/LinkModulesTest.cpp @@ -8,12 +8,12 @@ //===----------------------------------------------------------------------===// #include "llvm/AsmParser/Parser.h" -#include "llvm/Linker/Linker.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/Linker/Linker.h" #include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" diff --git a/unittests/MC/CMakeLists.txt b/unittests/MC/CMakeLists.txt index c82bcde..f83eaf4 100644 --- a/unittests/MC/CMakeLists.txt +++ b/unittests/MC/CMakeLists.txt @@ -10,9 +10,3 @@ add_llvm_unittest(MCTests StringTableBuilderTest.cpp YAMLTest.cpp ) - -foreach(t ${LLVM_TARGETS_TO_BUILD}) - if (IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/${t}") - add_subdirectory(${t}) - endif (IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/${t}") -endforeach() diff --git a/unittests/MC/Hexagon/CMakeLists.txt b/unittests/MC/Hexagon/CMakeLists.txt deleted file mode 100644 index 6d4ee93..0000000 --- a/unittests/MC/Hexagon/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -set(LLVM_LINK_COMPONENTS - HexagonCodeGen - HexagonDesc - HexagonInfo - MC - Support - ) - -include_directories (${LLVM_MAIN_SRC_DIR}/lib/Target/Hexagon) -include_directories (${LLVM_BINARY_DIR}/lib/Target/Hexagon) - -add_llvm_unittest(HexagonTests - HexagonMCCodeEmitterTest.cpp - ) diff --git a/unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp b/unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp deleted file mode 100644 index 958a21f..0000000 --- a/unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include "gtest/gtest.h" - -#include <memory> - -#include "llvm/MC/MCCodeEmitter.h" -#include "llvm/MC/MCContext.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" - -#include "MCTargetDesc/HexagonMCInst.h" -#include "MCTargetDesc/HexagonMCTargetDesc.h" - -namespace { -class TestEmitter { -public: - TestEmitter() : Triple("hexagon-unknown-elf") { - LLVMInitializeHexagonTargetInfo(); - LLVMInitializeHexagonTarget(); - LLVMInitializeHexagonTargetMC(); - std::string error; - Target = llvm::TargetRegistry::lookupTarget("hexagon", error); - assert(Target != nullptr && "Expected to find target"); - assert(error.empty() && "Error should be empty if we have a target"); - RegisterInfo = Target->createMCRegInfo(Triple); - assert(RegisterInfo != nullptr && "Expecting to find register info"); - AsmInfo = Target->createMCAsmInfo(*RegisterInfo, Triple); - assert(AsmInfo != nullptr && "Expecting to find asm info"); - Context = new llvm::MCContext(AsmInfo, RegisterInfo, nullptr); - assert(Context != nullptr && "Expecting to create a context"); - Subtarget = Target->createMCSubtargetInfo(Triple, "hexagonv4", ""); - assert(Subtarget != nullptr && "Expecting to find a subtarget"); - InstrInfo = Target->createMCInstrInfo(); - assert(InstrInfo != nullptr && "Expecting to find instr info"); - Emitter = Target->createMCCodeEmitter(*InstrInfo, *RegisterInfo, *Subtarget, - *Context); - assert(Emitter != nullptr); - } - std::string Triple; - llvm::Target const *Target; - llvm::MCRegisterInfo *RegisterInfo; - llvm::MCAsmInfo *AsmInfo; - llvm::MCContext *Context; - llvm::MCSubtargetInfo *Subtarget; - llvm::MCInstrInfo *InstrInfo; - llvm::MCCodeEmitter *Emitter; -}; -TestEmitter Emitter; -} - -TEST(HexagonMCCodeEmitter, emitter_creation) { - ASSERT_NE(nullptr, Emitter.Emitter); -} diff --git a/unittests/MC/StringTableBuilderTest.cpp b/unittests/MC/StringTableBuilderTest.cpp index 6b5185c..716b9c7 100644 --- a/unittests/MC/StringTableBuilderTest.cpp +++ b/unittests/MC/StringTableBuilderTest.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/MC/StringTableBuilder.h" -#include "gtest/gtest.h" #include "llvm/Support/Endian.h" +#include "gtest/gtest.h" #include <string> using namespace llvm; diff --git a/unittests/Makefile b/unittests/Makefile index 603e7d5..fefef07 100644 --- a/unittests/Makefile +++ b/unittests/Makefile @@ -10,7 +10,7 @@ LEVEL = .. PARALLEL_DIRS = ADT Analysis Bitcode CodeGen DebugInfo ExecutionEngine IR \ - LineEditor Linker MC Option Support Transforms + LineEditor Linker MC Option ProfileData Support Transforms include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/ProfileData/CMakeLists.txt b/unittests/ProfileData/CMakeLists.txt new file mode 100644 index 0000000..79137c9 --- /dev/null +++ b/unittests/ProfileData/CMakeLists.txt @@ -0,0 +1,10 @@ +set(LLVM_LINK_COMPONENTS + Core + ProfileData + Support + ) + +add_llvm_unittest(ProfileDataTests + CoverageMappingTest.cpp + InstrProfTest.cpp + ) diff --git a/unittests/ProfileData/CoverageMappingTest.cpp b/unittests/ProfileData/CoverageMappingTest.cpp new file mode 100644 index 0000000..9fceacb --- /dev/null +++ b/unittests/ProfileData/CoverageMappingTest.cpp @@ -0,0 +1,262 @@ +//===- unittest/ProfileData/CoverageMappingTest.cpp -------------------------=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/CoverageMapping.h" +#include "llvm/ProfileData/CoverageMappingReader.h" +#include "llvm/ProfileData/CoverageMappingWriter.h" +#include "llvm/ProfileData/InstrProfReader.h" +#include "llvm/ProfileData/InstrProfWriter.h" +#include "llvm/Support/raw_ostream.h" +#include "gtest/gtest.h" + +#include <sstream> + +using namespace llvm; +using namespace coverage; + +static ::testing::AssertionResult NoError(std::error_code EC) { + if (!EC) + return ::testing::AssertionSuccess(); + return ::testing::AssertionFailure() << "error " << EC.value() + << ": " << EC.message(); +} + +namespace llvm { +namespace coverage { +void PrintTo(const Counter &C, ::std::ostream *os) { + if (C.isZero()) + *os << "Zero"; + else if (C.isExpression()) + *os << "Expression " << C.getExpressionID(); + else + *os << "Counter " << C.getCounterID(); +} + +void PrintTo(const CoverageSegment &S, ::std::ostream *os) { + *os << "CoverageSegment(" << S.Line << ", " << S.Col << ", "; + if (S.HasCount) + *os << S.Count << ", "; + *os << (S.IsRegionEntry ? "true" : "false") << ")"; +} +} +} + +namespace { + +struct OneFunctionCoverageReader : CoverageMappingReader { + StringRef Name; + uint64_t Hash; + std::vector<StringRef> Filenames; + ArrayRef<CounterMappingRegion> Regions; + bool Done; + + OneFunctionCoverageReader(StringRef Name, uint64_t Hash, + ArrayRef<StringRef> Filenames, + ArrayRef<CounterMappingRegion> Regions) + : Name(Name), Hash(Hash), Filenames(Filenames), Regions(Regions), + Done(false) {} + + std::error_code readNextRecord(CoverageMappingRecord &Record) override { + if (Done) + return instrprof_error::eof; + Done = true; + + Record.FunctionName = Name; + Record.FunctionHash = Hash; + Record.Filenames = Filenames; + Record.Expressions = {}; + Record.MappingRegions = Regions; + return instrprof_error::success; + } +}; + +struct CoverageMappingTest : ::testing::Test { + StringMap<unsigned> Files; + unsigned NextFile; + std::vector<CounterMappingRegion> InputCMRs; + + std::vector<StringRef> OutputFiles; + std::vector<CounterExpression> OutputExpressions; + std::vector<CounterMappingRegion> OutputCMRs; + + InstrProfWriter ProfileWriter; + std::unique_ptr<IndexedInstrProfReader> ProfileReader; + + std::unique_ptr<CoverageMapping> LoadedCoverage; + + void SetUp() override { + NextFile = 0; + } + + unsigned getFile(StringRef Name) { + auto R = Files.find(Name); + if (R != Files.end()) + return R->second; + Files[Name] = NextFile; + return NextFile++; + } + + void addCMR(Counter C, StringRef File, unsigned LS, unsigned CS, unsigned LE, + unsigned CE) { + InputCMRs.push_back( + CounterMappingRegion::makeRegion(C, getFile(File), LS, CS, LE, CE)); + } + + void addExpansionCMR(StringRef File, StringRef ExpandedFile, unsigned LS, + unsigned CS, unsigned LE, unsigned CE) { + InputCMRs.push_back(CounterMappingRegion::makeExpansion( + getFile(File), getFile(ExpandedFile), LS, CS, LE, CE)); + } + + std::string writeCoverageRegions() { + SmallVector<unsigned, 8> FileIDs; + for (const auto &E : Files) + FileIDs.push_back(E.getValue()); + std::string Coverage; + llvm::raw_string_ostream OS(Coverage); + CoverageMappingWriter(FileIDs, None, InputCMRs).write(OS); + return OS.str(); + } + + void readCoverageRegions(std::string Coverage) { + SmallVector<StringRef, 8> Filenames; + for (const auto &E : Files) + Filenames.push_back(E.getKey()); + RawCoverageMappingReader Reader(Coverage, Filenames, OutputFiles, + OutputExpressions, OutputCMRs); + ASSERT_TRUE(NoError(Reader.read())); + } + + void readProfCounts() { + auto Profile = ProfileWriter.writeBuffer(); + auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile)); + ASSERT_TRUE(NoError(ReaderOrErr.getError())); + ProfileReader = std::move(ReaderOrErr.get()); + } + + void loadCoverageMapping(StringRef FuncName, uint64_t Hash) { + std::string Regions = writeCoverageRegions(); + readCoverageRegions(Regions); + + SmallVector<StringRef, 8> Filenames; + for (const auto &E : Files) + Filenames.push_back(E.getKey()); + OneFunctionCoverageReader CovReader(FuncName, Hash, Filenames, OutputCMRs); + auto CoverageOrErr = CoverageMapping::load(CovReader, *ProfileReader); + ASSERT_TRUE(NoError(CoverageOrErr.getError())); + LoadedCoverage = std::move(CoverageOrErr.get()); + } +}; + +TEST_F(CoverageMappingTest, basic_write_read) { + addCMR(Counter::getCounter(0), "foo", 1, 1, 1, 1); + addCMR(Counter::getCounter(1), "foo", 2, 1, 2, 2); + addCMR(Counter::getZero(), "foo", 3, 1, 3, 4); + addCMR(Counter::getCounter(2), "foo", 4, 1, 4, 8); + addCMR(Counter::getCounter(3), "bar", 1, 2, 3, 4); + std::string Coverage = writeCoverageRegions(); + readCoverageRegions(Coverage); + + size_t N = makeArrayRef(InputCMRs).size(); + ASSERT_EQ(N, OutputCMRs.size()); + for (size_t I = 0; I < N; ++I) { + ASSERT_EQ(InputCMRs[I].Count, OutputCMRs[I].Count); + ASSERT_EQ(InputCMRs[I].FileID, OutputCMRs[I].FileID); + ASSERT_EQ(InputCMRs[I].startLoc(), OutputCMRs[I].startLoc()); + ASSERT_EQ(InputCMRs[I].endLoc(), OutputCMRs[I].endLoc()); + ASSERT_EQ(InputCMRs[I].Kind, OutputCMRs[I].Kind); + } +} + +TEST_F(CoverageMappingTest, expansion_gets_first_counter) { + addCMR(Counter::getCounter(1), "foo", 10, 1, 10, 2); + // This starts earlier in "foo", so the expansion should get its counter. + addCMR(Counter::getCounter(2), "foo", 1, 1, 20, 1); + addExpansionCMR("bar", "foo", 3, 3, 3, 3); + std::string Coverage = writeCoverageRegions(); + readCoverageRegions(Coverage); + + ASSERT_EQ(CounterMappingRegion::ExpansionRegion, OutputCMRs[2].Kind); + ASSERT_EQ(Counter::getCounter(2), OutputCMRs[2].Count); + ASSERT_EQ(3U, OutputCMRs[2].LineStart); +} + +TEST_F(CoverageMappingTest, basic_coverage_iteration) { + ProfileWriter.addFunctionCounts("func", 0x1234, {30, 20, 10, 0}); + readProfCounts(); + + addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); + addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7); + addCMR(Counter::getCounter(2), "file1", 5, 8, 9, 1); + addCMR(Counter::getCounter(3), "file1", 10, 10, 11, 11); + loadCoverageMapping("func", 0x1234); + + CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); + std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); + ASSERT_EQ(7U, Segments.size()); + ASSERT_EQ(CoverageSegment(1, 1, 20, true), Segments[0]); + ASSERT_EQ(CoverageSegment(4, 7, 30, false), Segments[1]); + ASSERT_EQ(CoverageSegment(5, 8, 10, true), Segments[2]); + ASSERT_EQ(CoverageSegment(9, 1, 30, false), Segments[3]); + ASSERT_EQ(CoverageSegment(9, 9, false), Segments[4]); + ASSERT_EQ(CoverageSegment(10, 10, 0, true), Segments[5]); + ASSERT_EQ(CoverageSegment(11, 11, false), Segments[6]); +} + +TEST_F(CoverageMappingTest, uncovered_function) { + readProfCounts(); + + addCMR(Counter::getZero(), "file1", 1, 2, 3, 4); + loadCoverageMapping("func", 0x1234); + + CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); + std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); + ASSERT_EQ(2U, Segments.size()); + ASSERT_EQ(CoverageSegment(1, 2, 0, true), Segments[0]); + ASSERT_EQ(CoverageSegment(3, 4, false), Segments[1]); +} + +TEST_F(CoverageMappingTest, combine_regions) { + ProfileWriter.addFunctionCounts("func", 0x1234, {10, 20, 30}); + readProfCounts(); + + addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); + addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4); + addCMR(Counter::getCounter(2), "file1", 3, 3, 4, 4); + loadCoverageMapping("func", 0x1234); + + CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); + std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); + ASSERT_EQ(4U, Segments.size()); + ASSERT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]); + ASSERT_EQ(CoverageSegment(3, 3, 50, true), Segments[1]); + ASSERT_EQ(CoverageSegment(4, 4, 10, false), Segments[2]); + ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]); +} + +TEST_F(CoverageMappingTest, dont_combine_expansions) { + ProfileWriter.addFunctionCounts("func", 0x1234, {10, 20}); + readProfCounts(); + + addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9); + addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4); + addCMR(Counter::getCounter(1), "include1", 6, 6, 7, 7); + addExpansionCMR("file1", "include1", 3, 3, 4, 4); + loadCoverageMapping("func", 0x1234); + + CoverageData Data = LoadedCoverage->getCoverageForFile("file1"); + std::vector<CoverageSegment> Segments(Data.begin(), Data.end()); + ASSERT_EQ(4U, Segments.size()); + ASSERT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]); + ASSERT_EQ(CoverageSegment(3, 3, 20, true), Segments[1]); + ASSERT_EQ(CoverageSegment(4, 4, 10, false), Segments[2]); + ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]); +} + +} // end anonymous namespace diff --git a/unittests/ProfileData/InstrProfTest.cpp b/unittests/ProfileData/InstrProfTest.cpp new file mode 100644 index 0000000..26ea0e4 --- /dev/null +++ b/unittests/ProfileData/InstrProfTest.cpp @@ -0,0 +1,98 @@ +//===- unittest/ProfileData/InstrProfTest.cpp -------------------------------=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ProfileData/InstrProfReader.h" +#include "llvm/ProfileData/InstrProfWriter.h" +#include "gtest/gtest.h" + +#include <cstdarg> + +using namespace llvm; + +static ::testing::AssertionResult NoError(std::error_code EC) { + if (!EC) + return ::testing::AssertionSuccess(); + return ::testing::AssertionFailure() << "error " << EC.value() + << ": " << EC.message(); +} + +static ::testing::AssertionResult ErrorEquals(std::error_code Expected, + std::error_code Found) { + if (Expected == Found) + return ::testing::AssertionSuccess(); + return ::testing::AssertionFailure() << "error " << Found.value() + << ": " << Found.message(); +} + +namespace { + +struct InstrProfTest : ::testing::Test { + InstrProfWriter Writer; + std::unique_ptr<IndexedInstrProfReader> Reader; + + void readProfile(std::unique_ptr<MemoryBuffer> Profile) { + auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile)); + ASSERT_TRUE(NoError(ReaderOrErr.getError())); + Reader = std::move(ReaderOrErr.get()); + } +}; + +TEST_F(InstrProfTest, write_and_read_empty_profile) { + auto Profile = Writer.writeBuffer(); + readProfile(std::move(Profile)); + ASSERT_TRUE(Reader->begin() == Reader->end()); +} + +TEST_F(InstrProfTest, write_and_read_one_function) { + Writer.addFunctionCounts("foo", 0x1234, {1, 2, 3, 4}); + auto Profile = Writer.writeBuffer(); + readProfile(std::move(Profile)); + + auto I = Reader->begin(), E = Reader->end(); + ASSERT_TRUE(I != E); + ASSERT_EQ(StringRef("foo"), I->Name); + ASSERT_EQ(0x1234U, I->Hash); + ASSERT_EQ(4U, I->Counts.size()); + ASSERT_EQ(1U, I->Counts[0]); + ASSERT_EQ(2U, I->Counts[1]); + ASSERT_EQ(3U, I->Counts[2]); + ASSERT_EQ(4U, I->Counts[3]); + ASSERT_TRUE(++I == E); +} + +TEST_F(InstrProfTest, get_function_counts) { + Writer.addFunctionCounts("foo", 0x1234, {1, 2}); + auto Profile = Writer.writeBuffer(); + readProfile(std::move(Profile)); + + std::vector<uint64_t> Counts; + ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts))); + ASSERT_EQ(2U, Counts.size()); + ASSERT_EQ(1U, Counts[0]); + ASSERT_EQ(2U, Counts[1]); + + std::error_code EC; + EC = Reader->getFunctionCounts("foo", 0x5678, Counts); + ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, EC)); + + EC = Reader->getFunctionCounts("bar", 0x1234, Counts); + ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, EC)); +} + +TEST_F(InstrProfTest, get_max_function_count) { + Writer.addFunctionCounts("foo", 0x1234, {1ULL << 31, 2}); + Writer.addFunctionCounts("bar", 0, {1ULL << 63}); + Writer.addFunctionCounts("baz", 0x5678, {0, 0, 0, 0}); + auto Profile = Writer.writeBuffer(); + readProfile(std::move(Profile)); + + ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount()); +} + +} // end anonymous namespace diff --git a/unittests/ProfileData/Makefile b/unittests/ProfileData/Makefile new file mode 100644 index 0000000..d017c15 --- /dev/null +++ b/unittests/ProfileData/Makefile @@ -0,0 +1,15 @@ +##===- unittests/ProfileData/Makefile ----------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../.. +TESTNAME = ProfileData +LINK_COMPONENTS := ProfileData Core Support + +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Support/AlignOfTest.cpp b/unittests/Support/AlignOfTest.cpp index 40f7295..1119019 100644 --- a/unittests/Support/AlignOfTest.cpp +++ b/unittests/Support/AlignOfTest.cpp @@ -22,13 +22,13 @@ namespace { // Suppress direct base '{anonymous}::S1' inaccessible in '{anonymous}::D9' // due to ambiguity warning. -// +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wunknown-pragmas" +#pragma clang diagnostic ignored "-Winaccessible-base" +#elif ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402 // Pragma based warning suppression was introduced in GGC 4.2. Additionally // this warning is "enabled by default". The warning still appears if -Wall is // suppressed. Apparently GCC suppresses it when -w is specifed, which is odd. -// At any rate, clang on the other hand gripes about -Wunknown-pragma, so -// leaving it out of this. -#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402 && !defined(__clang__) #pragma GCC diagnostic warning "-w" #endif diff --git a/unittests/Support/BlockFrequencyTest.cpp b/unittests/Support/BlockFrequencyTest.cpp index f6e3537..0eac8bb 100644 --- a/unittests/Support/BlockFrequencyTest.cpp +++ b/unittests/Support/BlockFrequencyTest.cpp @@ -1,3 +1,12 @@ +//===- unittests/Support/BlockFrequencyTest.cpp - BlockFrequency tests ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + #include "llvm/Support/BlockFrequency.h" #include "llvm/Support/BranchProbability.h" #include "llvm/Support/DataTypes.h" diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 7abdd8a..f3b55c3 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -13,6 +13,8 @@ add_llvm_unittest(SupportTests CompressionTest.cpp ConvertUTFTest.cpp DataExtractorTest.cpp + DwarfTest.cpp + EndianStreamTest.cpp EndianTest.cpp ErrorOrTest.cpp FileOutputBufferTest.cpp @@ -32,6 +34,7 @@ add_llvm_unittest(SupportTests ScaledNumberTest.cpp SourceMgrTest.cpp SpecialCaseListTest.cpp + StreamingMemoryObject.cpp StringPool.cpp SwapByteOrderTest.cpp ThreadLocalTest.cpp diff --git a/unittests/Support/Casting.cpp b/unittests/Support/Casting.cpp index 88c7d19..e6c35fc 100644 --- a/unittests/Support/Casting.cpp +++ b/unittests/Support/Casting.cpp @@ -232,3 +232,99 @@ namespace TemporaryCast { struct pod {}; IllegalCast *testIllegalCast() { return cast<foo>(pod()); } } + +namespace { +namespace pointer_wrappers { + +struct Base { + bool IsDerived; + Base(bool IsDerived = false) : IsDerived(IsDerived) {} +}; + +struct Derived : Base { + Derived() : Base(true) {} + static bool classof(const Base *B) { return B->IsDerived; } +}; + +class PTy { + Base *B; +public: + PTy(Base *B) : B(B) {} + explicit operator bool() const { return get(); } + Base *get() const { return B; } +}; + +} // end namespace pointer_wrappers +} // end namespace + +namespace llvm { + +template <> struct simplify_type<pointer_wrappers::PTy> { + typedef pointer_wrappers::Base *SimpleType; + static SimpleType getSimplifiedValue(pointer_wrappers::PTy &P) { + return P.get(); + } +}; +template <> struct simplify_type<const pointer_wrappers::PTy> { + typedef pointer_wrappers::Base *SimpleType; + static SimpleType getSimplifiedValue(const pointer_wrappers::PTy &P) { + return P.get(); + } +}; + +} // end namespace llvm + +namespace { +namespace pointer_wrappers { + +// Some objects. +pointer_wrappers::Base B; +pointer_wrappers::Derived D; + +// Mutable "smart" pointers. +pointer_wrappers::PTy MN(nullptr); +pointer_wrappers::PTy MB(&B); +pointer_wrappers::PTy MD(&D); + +// Const "smart" pointers. +const pointer_wrappers::PTy CN(nullptr); +const pointer_wrappers::PTy CB(&B); +const pointer_wrappers::PTy CD(&D); + +TEST(CastingTest, smart_isa) { + EXPECT_TRUE(!isa<pointer_wrappers::Derived>(MB)); + EXPECT_TRUE(!isa<pointer_wrappers::Derived>(CB)); + EXPECT_TRUE(isa<pointer_wrappers::Derived>(MD)); + EXPECT_TRUE(isa<pointer_wrappers::Derived>(CD)); +} + +TEST(CastingTest, smart_cast) { + EXPECT_TRUE(cast<pointer_wrappers::Derived>(MD) == &D); + EXPECT_TRUE(cast<pointer_wrappers::Derived>(CD) == &D); +} + +TEST(CastingTest, smart_cast_or_null) { + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MN) == nullptr); + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CN) == nullptr); + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MD) == &D); + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CD) == &D); +} + +TEST(CastingTest, smart_dyn_cast) { + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MB) == nullptr); + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CB) == nullptr); + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MD) == &D); + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CD) == &D); +} + +TEST(CastingTest, smart_dyn_cast_or_null) { + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MN) == nullptr); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CN) == nullptr); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MB) == nullptr); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CB) == nullptr); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MD) == &D); + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CD) == &D); +} + +} // end namespace pointer_wrappers +} // end namespace diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index ac8d3d8..9d7679d 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -35,6 +35,8 @@ class TempEnvVar { #if HAVE_SETENV // Assume setenv and unsetenv come together. unsetenv(name); +#else + (void)name; // Suppress -Wunused-private-field. #endif } @@ -70,14 +72,14 @@ public: cl::OptionCategory TestCategory("Test Options", "Description"); -cl::opt<int> TestOption("test-option", cl::desc("old description")); TEST(CommandLineTest, ModifyExisitingOption) { + StackOption<int> TestOption("test-option", cl::desc("old description")); + const char Description[] = "New description"; const char ArgString[] = "new-test-option"; const char ValueString[] = "Integer"; - StringMap<cl::Option*> Map; - cl::getRegisteredOptions(Map); + StringMap<cl::Option *> &Map = cl::getRegisteredOptions(); ASSERT_TRUE(Map.count("test-option") == 1) << "Could not find option in map."; @@ -230,5 +232,44 @@ TEST(CommandLineTest, AliasRequired) { testAliasRequired(array_lengthof(opts2), opts2); } +TEST(CommandLineTest, HideUnrelatedOptions) { + StackOption<int> TestOption1("hide-option-1"); + StackOption<int> TestOption2("hide-option-2", cl::cat(TestCategory)); + + cl::HideUnrelatedOptions(TestCategory); + + ASSERT_EQ(cl::ReallyHidden, TestOption1.getOptionHiddenFlag()) + << "Failed to hide extra option."; + ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag()) + << "Hid extra option that should be visable."; + + StringMap<cl::Option *> &Map = cl::getRegisteredOptions(); + ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag()) + << "Hid default option that should be visable."; +} + +cl::OptionCategory TestCategory2("Test Options set 2", "Description"); + +TEST(CommandLineTest, HideUnrelatedOptionsMulti) { + StackOption<int> TestOption1("multi-hide-option-1"); + StackOption<int> TestOption2("multi-hide-option-2", cl::cat(TestCategory)); + StackOption<int> TestOption3("multi-hide-option-3", cl::cat(TestCategory2)); + + const cl::OptionCategory *VisibleCategories[] = {&TestCategory, + &TestCategory2}; + + cl::HideUnrelatedOptions(makeArrayRef(VisibleCategories)); + + ASSERT_EQ(cl::ReallyHidden, TestOption1.getOptionHiddenFlag()) + << "Failed to hide extra option."; + ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag()) + << "Hid extra option that should be visable."; + ASSERT_EQ(cl::NotHidden, TestOption3.getOptionHiddenFlag()) + << "Hid extra option that should be visable."; + + StringMap<cl::Option *> &Map = cl::getRegisteredOptions(); + ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag()) + << "Hid default option that should be visable."; +} } // anonymous namespace diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp index 698ae3a..36b84d8 100644 --- a/unittests/Support/CompressionTest.cpp +++ b/unittests/Support/CompressionTest.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Compression.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Config/config.h" #include "gtest/gtest.h" diff --git a/unittests/Support/ConvertUTFTest.cpp b/unittests/Support/ConvertUTFTest.cpp index 510b1da..d436fc0 100644 --- a/unittests/Support/ConvertUTFTest.cpp +++ b/unittests/Support/ConvertUTFTest.cpp @@ -8,10 +8,11 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ConvertUTF.h" +#include "llvm/Support/Format.h" #include "gtest/gtest.h" #include <string> -#include <vector> #include <utility> +#include <vector> using namespace llvm; @@ -37,6 +38,19 @@ TEST(ConvertUTFTest, ConvertUTF16BigEndianToUTF8String) { EXPECT_EQ(Expected, Result); } +TEST(ConvertUTFTest, ConvertUTF8ToUTF16String) { + // Src is the look of disapproval. + static const char Src[] = "\xe0\xb2\xa0_\xe0\xb2\xa0"; + StringRef Ref(Src, sizeof(Src) - 1); + SmallVector<UTF16, 5> Result; + bool Success = convertUTF8ToUTF16String(Ref, Result); + EXPECT_TRUE(Success); + static const UTF16 Expected[] = {0x0CA0, 0x005f, 0x0CA0, 0}; + ASSERT_EQ(3u, Result.size()); + for (int I = 0, E = 3; I != E; ++I) + EXPECT_EQ(Expected[I], Result[I]); +} + TEST(ConvertUTFTest, OddLengthInput) { std::string Result; bool Success = convertUTF16ToUTF8String(makeArrayRef("xxxxx", 5), Result); @@ -141,8 +155,8 @@ CheckConvertUTF8ToUnicodeScalars(ConvertUTFResultContainer Expected, if (!Partial) std::tie(ErrorCode, Decoded) = ConvertUTF8ToUnicodeScalarsLenient(S); else - std::tie(ErrorCode, Decoded) = ConvertUTF8ToUnicodeScalarsPartialLenient(S); + if (Expected.ErrorCode != ErrorCode) return ::testing::AssertionFailure() << "Expected error code " << Expected.ErrorCode << ", actual " diff --git a/unittests/Support/DwarfTest.cpp b/unittests/Support/DwarfTest.cpp new file mode 100644 index 0000000..74fcc98 --- /dev/null +++ b/unittests/Support/DwarfTest.cpp @@ -0,0 +1,141 @@ +//===- unittest/Support/DwarfTest.cpp - Dwarf support tests ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Dwarf.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::dwarf; + +namespace { + +TEST(DwarfTest, TagStringOnInvalid) { + // This is invalid, so it shouldn't be stringified. + EXPECT_EQ(nullptr, TagString(DW_TAG_invalid)); + + // These aren't really tags: they describe ranges within tags. They + // shouldn't be stringified either. + EXPECT_EQ(nullptr, TagString(DW_TAG_lo_user)); + EXPECT_EQ(nullptr, TagString(DW_TAG_hi_user)); + EXPECT_EQ(nullptr, TagString(DW_TAG_user_base)); +} + +TEST(DwarfTest, getTag) { + // A couple of valid tags. + EXPECT_EQ(DW_TAG_array_type, getTag("DW_TAG_array_type")); + EXPECT_EQ(DW_TAG_module, getTag("DW_TAG_module")); + + // Invalid tags. + EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_invalid")); + EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_madeuptag")); + EXPECT_EQ(DW_TAG_invalid, getTag("something else")); + + // Tag range markers should not be recognized. + EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_lo_user")); + EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_hi_user")); + EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_user_base")); +} + +TEST(DwarfTest, getOperationEncoding) { + // Some valid ops. + EXPECT_EQ(DW_OP_deref, getOperationEncoding("DW_OP_deref")); + EXPECT_EQ(DW_OP_bit_piece, getOperationEncoding("DW_OP_bit_piece")); + + // Invalid ops. + EXPECT_EQ(0u, getOperationEncoding("DW_OP_otherthings")); + EXPECT_EQ(0u, getOperationEncoding("other")); + + // Markers shouldn't be recognized. + EXPECT_EQ(0u, getOperationEncoding("DW_OP_lo_user")); + EXPECT_EQ(0u, getOperationEncoding("DW_OP_hi_user")); +} + +TEST(DwarfTest, LanguageStringOnInvalid) { + // This is invalid, so it shouldn't be stringified. + EXPECT_EQ(nullptr, LanguageString(0)); + + // These aren't really tags: they describe ranges within tags. They + // shouldn't be stringified either. + EXPECT_EQ(nullptr, LanguageString(DW_LANG_lo_user)); + EXPECT_EQ(nullptr, LanguageString(DW_LANG_hi_user)); +} + +TEST(DwarfTest, getLanguage) { + // A couple of valid languages. + EXPECT_EQ(DW_LANG_C89, getLanguage("DW_LANG_C89")); + EXPECT_EQ(DW_LANG_C_plus_plus_11, getLanguage("DW_LANG_C_plus_plus_11")); + EXPECT_EQ(DW_LANG_OCaml, getLanguage("DW_LANG_OCaml")); + EXPECT_EQ(DW_LANG_Mips_Assembler, getLanguage("DW_LANG_Mips_Assembler")); + + // Invalid languages. + EXPECT_EQ(0u, getLanguage("DW_LANG_invalid")); + EXPECT_EQ(0u, getLanguage("DW_TAG_array_type")); + EXPECT_EQ(0u, getLanguage("something else")); + + // Language range markers should not be recognized. + EXPECT_EQ(0u, getLanguage("DW_LANG_lo_user")); + EXPECT_EQ(0u, getLanguage("DW_LANG_hi_user")); +} + +TEST(DwarfTest, AttributeEncodingStringOnInvalid) { + // This is invalid, so it shouldn't be stringified. + EXPECT_EQ(nullptr, AttributeEncodingString(0)); + + // These aren't really tags: they describe ranges within tags. They + // shouldn't be stringified either. + EXPECT_EQ(nullptr, AttributeEncodingString(DW_ATE_lo_user)); + EXPECT_EQ(nullptr, AttributeEncodingString(DW_ATE_hi_user)); +} + +TEST(DwarfTest, getAttributeEncoding) { + // A couple of valid languages. + EXPECT_EQ(DW_ATE_boolean, getAttributeEncoding("DW_ATE_boolean")); + EXPECT_EQ(DW_ATE_imaginary_float, + getAttributeEncoding("DW_ATE_imaginary_float")); + + // Invalid languages. + EXPECT_EQ(0u, getAttributeEncoding("DW_ATE_invalid")); + EXPECT_EQ(0u, getAttributeEncoding("DW_TAG_array_type")); + EXPECT_EQ(0u, getAttributeEncoding("something else")); + + // AttributeEncoding range markers should not be recognized. + EXPECT_EQ(0u, getAttributeEncoding("DW_ATE_lo_user")); + EXPECT_EQ(0u, getAttributeEncoding("DW_ATE_hi_user")); +} + +TEST(DwarfTest, VirtualityString) { + EXPECT_EQ(StringRef("DW_VIRTUALITY_none"), + VirtualityString(DW_VIRTUALITY_none)); + EXPECT_EQ(StringRef("DW_VIRTUALITY_virtual"), + VirtualityString(DW_VIRTUALITY_virtual)); + EXPECT_EQ(StringRef("DW_VIRTUALITY_pure_virtual"), + VirtualityString(DW_VIRTUALITY_pure_virtual)); + + // DW_VIRTUALITY_max should be pure virtual. + EXPECT_EQ(StringRef("DW_VIRTUALITY_pure_virtual"), + VirtualityString(DW_VIRTUALITY_max)); + + // Invalid numbers shouldn't be stringified. + EXPECT_EQ(nullptr, VirtualityString(DW_VIRTUALITY_max + 1)); + EXPECT_EQ(nullptr, VirtualityString(DW_VIRTUALITY_max + 77)); +} + +TEST(DwarfTest, getVirtuality) { + EXPECT_EQ(DW_VIRTUALITY_none, getVirtuality("DW_VIRTUALITY_none")); + EXPECT_EQ(DW_VIRTUALITY_virtual, getVirtuality("DW_VIRTUALITY_virtual")); + EXPECT_EQ(DW_VIRTUALITY_pure_virtual, + getVirtuality("DW_VIRTUALITY_pure_virtual")); + + // Invalid strings. + EXPECT_EQ(DW_VIRTUALITY_invalid, getVirtuality("DW_VIRTUALITY_invalid")); + EXPECT_EQ(DW_VIRTUALITY_invalid, getVirtuality("DW_VIRTUALITY_max")); + EXPECT_EQ(DW_VIRTUALITY_invalid, getVirtuality("something else")); +} + +} // end namespace diff --git a/unittests/Support/EndianStreamTest.cpp b/unittests/Support/EndianStreamTest.cpp new file mode 100644 index 0000000..6a69be5 --- /dev/null +++ b/unittests/Support/EndianStreamTest.cpp @@ -0,0 +1,157 @@ +//===- unittests/Support/EndianStreamTest.cpp - EndianStream.h tests ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/DataTypes.h" +#include "gtest/gtest.h" +using namespace llvm; +using namespace support; + +namespace { + +TEST(EndianStream, WriteInt32LE) { + SmallString<16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<little> LE(OS); + LE.write(static_cast<int32_t>(-1362446643)); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xCD); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xB6); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xCA); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0xAE); +} + +TEST(EndianStream, WriteInt32BE) { + SmallVector<char, 16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<big> BE(OS); + BE.write(static_cast<int32_t>(-1362446643)); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xAE); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xCA); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xB6); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0xCD); +} + + +TEST(EndianStream, WriteFloatLE) { + SmallString<16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<little> LE(OS); + LE.write(12345.0f); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0x00); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xE4); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0x40); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x46); +} + +TEST(EndianStream, WriteFloatBE) { + SmallVector<char, 16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<big> BE(OS); + BE.write(12345.0f); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0x46); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0x40); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xE4); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x00); +} + +TEST(EndianStream, WriteInt64LE) { + SmallString<16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<little> LE(OS); + LE.write(static_cast<int64_t>(-136244664332342323)); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xCD); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xAB); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xED); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x1B); + EXPECT_EQ(static_cast<uint8_t>(data[4]), 0x33); + EXPECT_EQ(static_cast<uint8_t>(data[5]), 0xF6); + EXPECT_EQ(static_cast<uint8_t>(data[6]), 0x1B); + EXPECT_EQ(static_cast<uint8_t>(data[7]), 0xFE); +} + +TEST(EndianStream, WriteInt64BE) { + SmallVector<char, 16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<big> BE(OS); + BE.write(static_cast<int64_t>(-136244664332342323)); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xFE); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0x1B); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xF6); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x33); + EXPECT_EQ(static_cast<uint8_t>(data[4]), 0x1B); + EXPECT_EQ(static_cast<uint8_t>(data[5]), 0xED); + EXPECT_EQ(static_cast<uint8_t>(data[6]), 0xAB); + EXPECT_EQ(static_cast<uint8_t>(data[7]), 0xCD); +} + +TEST(EndianStream, WriteDoubleLE) { + SmallString<16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<little> LE(OS); + LE.write(-2349214918.58107); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0x20); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0x98); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xD2); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x98); + EXPECT_EQ(static_cast<uint8_t>(data[4]), 0xC5); + EXPECT_EQ(static_cast<uint8_t>(data[5]), 0x80); + EXPECT_EQ(static_cast<uint8_t>(data[6]), 0xE1); + EXPECT_EQ(static_cast<uint8_t>(data[7]), 0xC1); +} + +TEST(EndianStream, WriteDoubleBE) { + SmallVector<char, 16> data; + + { + raw_svector_ostream OS(data); + endian::Writer<big> BE(OS); + BE.write(-2349214918.58107); + } + + EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xC1); + EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xE1); + EXPECT_EQ(static_cast<uint8_t>(data[2]), 0x80); + EXPECT_EQ(static_cast<uint8_t>(data[3]), 0xC5); + EXPECT_EQ(static_cast<uint8_t>(data[4]), 0x98); + EXPECT_EQ(static_cast<uint8_t>(data[5]), 0xD2); + EXPECT_EQ(static_cast<uint8_t>(data[6]), 0x98); + EXPECT_EQ(static_cast<uint8_t>(data[7]), 0x20); +} + + +} // end anon namespace diff --git a/unittests/Support/FileOutputBufferTest.cpp b/unittests/Support/FileOutputBufferTest.cpp index 911d516..c7e1006 100644 --- a/unittests/Support/FileOutputBufferTest.cpp +++ b/unittests/Support/FileOutputBufferTest.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Errc.h" -#include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -80,14 +80,13 @@ TEST(FileOutputBuffer, Test) { memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20); // Write to end of buffer to verify it is writable. memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20); - // Commit buffer, but size down to smaller size - ASSERT_NO_ERROR(Buffer->commit(5000)); + ASSERT_NO_ERROR(Buffer->commit()); } // Verify file is correct size. uint64_t File3Size; ASSERT_NO_ERROR(fs::file_size(Twine(File3), File3Size)); - ASSERT_EQ(File3Size, 5000ULL); + ASSERT_EQ(File3Size, 8192000ULL); ASSERT_NO_ERROR(fs::remove(File3.str())); // TEST 4: Verify file can be made executable. diff --git a/unittests/Support/MathExtrasTest.cpp b/unittests/Support/MathExtrasTest.cpp index 93a38cb..5c95b50 100644 --- a/unittests/Support/MathExtrasTest.cpp +++ b/unittests/Support/MathExtrasTest.cpp @@ -141,21 +141,18 @@ TEST(MathExtras, ByteSwap_64) { EXPECT_EQ(0x1100FFEEDDCCBBAAULL, ByteSwap_64(0xAABBCCDDEEFF0011LL)); } -TEST(MathExtras, CountLeadingOnes_32) { +TEST(MathExtras, countLeadingOnes) { for (int i = 30; i >= 0; --i) { // Start with all ones and unset some bit. - EXPECT_EQ(31u - i, CountLeadingOnes_32(0xFFFFFFFF ^ (1 << i))); + EXPECT_EQ(31u - i, countLeadingOnes(0xFFFFFFFF ^ (1 << i))); } -} - -TEST(MathExtras, CountLeadingOnes_64) { for (int i = 62; i >= 0; --i) { // Start with all ones and unset some bit. - EXPECT_EQ(63u - i, CountLeadingOnes_64(0xFFFFFFFFFFFFFFFFLL ^ (1LL << i))); + EXPECT_EQ(63u - i, countLeadingOnes(0xFFFFFFFFFFFFFFFFULL ^ (1LL << i))); } for (int i = 30; i >= 0; --i) { // Start with all ones and unset some bit. - EXPECT_EQ(31u - i, CountLeadingOnes_32(0xFFFFFFFF ^ (1 << i))); + EXPECT_EQ(31u - i, countLeadingOnes(0xFFFFFFFF ^ (1 << i))); } } diff --git a/unittests/Support/MemoryTest.cpp b/unittests/Support/MemoryTest.cpp index 8ad90e0..f439cb2 100644 --- a/unittests/Support/MemoryTest.cpp +++ b/unittests/Support/MemoryTest.cpp @@ -21,7 +21,7 @@ class MappedMemoryTest : public ::testing::TestWithParam<unsigned> { public: MappedMemoryTest() { Flags = GetParam(); - PageSize = sys::process::get_self()->page_size(); + PageSize = sys::Process::getPageSize(); } protected: diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index 502cda2..00af989 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -557,6 +557,7 @@ const char macho_dynamically_linked_shared_lib[] = const char macho_dynamic_linker[] = "\xfe\xed\xfa\xce..........\x00\x07"; const char macho_bundle[] = "\xfe\xed\xfa\xce..........\x00\x08"; const char macho_dsym_companion[] = "\xfe\xed\xfa\xce..........\x00\x0a"; +const char macho_kext_bundle[] = "\xfe\xed\xfa\xce..........\x00\x0b"; const char windows_resource[] = "\x00\x00\x00\x00\x020\x00\x00\x00\xff"; const char macho_dynamically_linked_shared_lib_stub[] = "\xfe\xed\xfa\xce..........\x00\x09"; @@ -587,6 +588,7 @@ TEST_F(FileSystemTest, Magic) { DEFINE(macho_bundle), DEFINE(macho_dynamically_linked_shared_lib_stub), DEFINE(macho_dsym_companion), + DEFINE(macho_kext_bundle), DEFINE(windows_resource) #undef DEFINE }; @@ -638,22 +640,31 @@ TEST_F(FileSystemTest, CarriageReturn) { } #endif +TEST_F(FileSystemTest, Resize) { + int FD; + SmallString<64> TempPath; + ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath)); + ASSERT_NO_ERROR(fs::resize_file(FD, 123)); + fs::file_status Status; + ASSERT_NO_ERROR(fs::status(FD, Status)); + ASSERT_EQ(Status.getSize(), 123U); +} + TEST_F(FileSystemTest, FileMapping) { // Create a temp file. int FileDescriptor; SmallString<64> TempPath; ASSERT_NO_ERROR( fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); + unsigned Size = 4096; + ASSERT_NO_ERROR(fs::resize_file(FileDescriptor, Size)); + // Map in temp file and add some content std::error_code EC; StringRef Val("hello there"); { fs::mapped_file_region mfr(FileDescriptor, - true, - fs::mapped_file_region::readwrite, - 4096, - 0, - EC); + fs::mapped_file_region::readwrite, Size, 0, EC); ASSERT_NO_ERROR(EC); std::copy(Val.begin(), Val.end(), mfr.data()); // Explicitly add a 0. @@ -662,27 +673,19 @@ TEST_F(FileSystemTest, FileMapping) { } // Map it back in read-only - fs::mapped_file_region mfr(Twine(TempPath), - fs::mapped_file_region::readonly, - 0, - 0, - EC); + int FD; + EC = fs::openFileForRead(Twine(TempPath), FD); + ASSERT_NO_ERROR(EC); + fs::mapped_file_region mfr(FD, fs::mapped_file_region::readonly, Size, 0, EC); ASSERT_NO_ERROR(EC); // Verify content EXPECT_EQ(StringRef(mfr.const_data()), Val); // Unmap temp file - - fs::mapped_file_region m(Twine(TempPath), - fs::mapped_file_region::readonly, - 0, - 0, - EC); + fs::mapped_file_region m(FD, fs::mapped_file_region::readonly, Size, 0, EC); ASSERT_NO_ERROR(EC); - const char *Data = m.const_data(); - fs::mapped_file_region mfrrv(std::move(m)); - EXPECT_EQ(mfrrv.const_data(), Data); + ASSERT_EQ(close(FD), 0); } TEST(Support, NormalizePath) { diff --git a/unittests/Support/ProcessTest.cpp b/unittests/Support/ProcessTest.cpp index 3045c30..298a0a3 100644 --- a/unittests/Support/ProcessTest.cpp +++ b/unittests/Support/ProcessTest.cpp @@ -19,26 +19,6 @@ namespace { using namespace llvm; using namespace sys; -TEST(ProcessTest, SelfProcess) { - EXPECT_TRUE(process::get_self()); - EXPECT_EQ(process::get_self(), process::get_self()); - -#if defined(LLVM_ON_UNIX) - EXPECT_EQ(getpid(), process::get_self()->get_id()); -#elif defined(LLVM_ON_WIN32) - EXPECT_EQ(GetCurrentProcessId(), process::get_self()->get_id()); -#endif - - EXPECT_LT(1u, process::get_self()->page_size()); - - EXPECT_LT(TimeValue::MinTime(), process::get_self()->get_user_time()); - EXPECT_GT(TimeValue::MaxTime(), process::get_self()->get_user_time()); - EXPECT_LT(TimeValue::MinTime(), process::get_self()->get_system_time()); - EXPECT_GT(TimeValue::MaxTime(), process::get_self()->get_system_time()); - EXPECT_LT(TimeValue::MinTime(), process::get_self()->get_wall_time()); - EXPECT_GT(TimeValue::MaxTime(), process::get_self()->get_wall_time()); -} - TEST(ProcessTest, GetRandomNumberTest) { const unsigned r1 = Process::GetRandomNumber(); const unsigned r2 = Process::GetRandomNumber(); diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp index c0e6e80..0feed47 100644 --- a/unittests/Support/ProgramTest.cpp +++ b/unittests/Support/ProgramTest.cpp @@ -70,6 +70,56 @@ static void CopyEnvironment(std::vector<const char *> &out) { } } +#ifdef LLVM_ON_WIN32 +TEST(ProgramTest, CreateProcessLongPath) { + if (getenv("LLVM_PROGRAM_TEST_LONG_PATH")) + exit(0); + + // getMainExecutable returns an absolute path; prepend the long-path prefix. + std::string MyAbsExe = + sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1); + std::string MyExe; + if (!StringRef(MyAbsExe).startswith("\\\\?\\")) + MyExe.append("\\\\?\\"); + MyExe.append(MyAbsExe); + + const char *ArgV[] = { + MyExe.c_str(), + "--gtest_filter=ProgramTest.CreateProcessLongPath", + nullptr + }; + + // Add LLVM_PROGRAM_TEST_LONG_PATH to the environment of the child. + std::vector<const char *> EnvP; + CopyEnvironment(EnvP); + EnvP.push_back("LLVM_PROGRAM_TEST_LONG_PATH=1"); + EnvP.push_back(nullptr); + + // Redirect stdout to a long path. + SmallString<128> TestDirectory; + ASSERT_NO_ERROR( + fs::createUniqueDirectory("program-redirect-test", TestDirectory)); + SmallString<256> LongPath(TestDirectory); + LongPath.push_back('\\'); + // MAX_PATH = 260 + LongPath.append(260 - TestDirectory.size(), 'a'); + StringRef LongPathRef(LongPath); + + std::string Error; + bool ExecutionFailed; + const StringRef *Redirects[] = { nullptr, &LongPathRef, nullptr }; + int RC = ExecuteAndWait(MyExe, ArgV, &EnvP[0], Redirects, + /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &Error, + &ExecutionFailed); + EXPECT_FALSE(ExecutionFailed) << Error; + EXPECT_EQ(0, RC); + + // Remove the long stdout. + ASSERT_NO_ERROR(fs::remove(Twine(LongPath))); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory))); +} +#endif + TEST(ProgramTest, CreateProcessTrailingSlash) { if (getenv("LLVM_PROGRAM_TEST_CHILD")) { if (ProgramTestStringArg1 == "has\\\\ trailing\\" && diff --git a/unittests/Support/ScaledNumberTest.cpp b/unittests/Support/ScaledNumberTest.cpp index 7bbef7e..d8d6e31 100644 --- a/unittests/Support/ScaledNumberTest.cpp +++ b/unittests/Support/ScaledNumberTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ScaledNumber.h" - #include "llvm/Support/DataTypes.h" #include "gtest/gtest.h" diff --git a/unittests/Support/SpecialCaseListTest.cpp b/unittests/Support/SpecialCaseListTest.cpp index 740dbfe..0657f80 100644 --- a/unittests/Support/SpecialCaseListTest.cpp +++ b/unittests/Support/SpecialCaseListTest.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SpecialCaseList.h" #include "gtest/gtest.h" @@ -30,6 +31,16 @@ protected: assert(Error == ""); return SCL; } + + std::string makeSpecialCaseListFile(StringRef Contents) { + int FD; + SmallString<64> Path; + sys::fs::createTemporaryFile("SpecialCaseListTest", "temp", FD, Path); + raw_fd_ostream OF(FD, true, true); + OF << Contents; + OF.close(); + return Path.str(); + } }; TEST_F(SpecialCaseListTest, Basic) { @@ -86,17 +97,18 @@ TEST_F(SpecialCaseListTest, Substring) { TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) { std::string Error; EXPECT_EQ(nullptr, makeSpecialCaseList("badline", Error)); - EXPECT_EQ("Malformed line 1: 'badline'", Error); + EXPECT_EQ("malformed line 1: 'badline'", Error); EXPECT_EQ(nullptr, makeSpecialCaseList("src:bad[a-", Error)); - EXPECT_EQ("Malformed regex in line 1: 'bad[a-': invalid character range", + EXPECT_EQ("malformed regex in line 1: 'bad[a-': invalid character range", Error); EXPECT_EQ(nullptr, makeSpecialCaseList("src:a.c\n" "fun:fun(a\n", Error)); - EXPECT_EQ("Malformed regex in line 2: 'fun(a': parentheses not balanced", + EXPECT_EQ("malformed regex in line 2: 'fun(a': parentheses not balanced", Error); - EXPECT_EQ(nullptr, SpecialCaseList::create("unexisting", Error)); - EXPECT_EQ(0U, Error.find("Can't open file 'unexisting':")); + std::vector<std::string> Files(1, "unexisting"); + EXPECT_EQ(nullptr, SpecialCaseList::create(Files, Error)); + EXPECT_EQ(0U, Error.find("can't open file 'unexisting':")); } TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { @@ -104,6 +116,20 @@ TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { EXPECT_FALSE(SCL->inSection("foo", "bar")); } +TEST_F(SpecialCaseListTest, MultipleBlacklists) { + std::vector<std::string> Files; + Files.push_back(makeSpecialCaseListFile("src:bar\n" + "src:*foo*\n" + "src:ban=init\n")); + Files.push_back(makeSpecialCaseListFile("src:baz\n" + "src:*fog*\n")); + auto SCL = SpecialCaseList::createOrDie(Files); + EXPECT_TRUE(SCL->inSection("src", "bar")); + EXPECT_TRUE(SCL->inSection("src", "baz")); + EXPECT_FALSE(SCL->inSection("src", "ban")); + EXPECT_TRUE(SCL->inSection("src", "ban", "init")); + EXPECT_TRUE(SCL->inSection("src", "tomfoolery")); + EXPECT_TRUE(SCL->inSection("src", "tomfoglery")); } - +} diff --git a/unittests/Support/StreamingMemoryObject.cpp b/unittests/Support/StreamingMemoryObject.cpp new file mode 100644 index 0000000..2013649 --- /dev/null +++ b/unittests/Support/StreamingMemoryObject.cpp @@ -0,0 +1,29 @@ +//===- llvm/unittest/Support/StreamingMemoryObject.cpp - unit tests -------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/StreamingMemoryObject.h" +#include "gtest/gtest.h" +#include <string.h> + +using namespace llvm; + +namespace { +class NullDataStreamer : public DataStreamer { + size_t GetBytes(unsigned char *buf, size_t len) override { + memset(buf, 0, len); + return len; + } +}; +} + +TEST(StreamingMemoryObject, Test) { + auto *DS = new NullDataStreamer(); + StreamingMemoryObject O(DS); + EXPECT_TRUE(O.isValidAddress(32 * 1024)); +} diff --git a/unittests/Support/StringPool.cpp b/unittests/Support/StringPool.cpp index 7b7805f..ac39fec 100644 --- a/unittests/Support/StringPool.cpp +++ b/unittests/Support/StringPool.cpp @@ -1,6 +1,6 @@ -//===- llvm/unittest/Support/ThreadLocalTest.cpp - Therad Local tests ---===// +//===- llvm/unittest/Support/StringPoiil.cpp - StringPool tests -----------===// // -// The LLVM Compiler Infrastructure +// The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. diff --git a/unittests/Support/ThreadLocalTest.cpp b/unittests/Support/ThreadLocalTest.cpp index ea751be..e71c7db 100644 --- a/unittests/Support/ThreadLocalTest.cpp +++ b/unittests/Support/ThreadLocalTest.cpp @@ -1,6 +1,6 @@ -//===- llvm/unittest/Support/ThreadLocalTest.cpp - Therad Local tests ---===// +//===- llvm/unittest/Support/ThreadLocalTest.cpp - ThreadLocal tests ------===// // -// The LLVM Compiler Infrastructure +// The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. @@ -9,6 +9,7 @@ #include "llvm/Support/ThreadLocal.h" #include "gtest/gtest.h" +#include <type_traits> using namespace llvm; using namespace sys; @@ -25,6 +26,10 @@ struct S { TEST_F(ThreadLocalTest, Basics) { ThreadLocal<const S> x; + static_assert( + std::is_const<std::remove_pointer<decltype(x.get())>::type>::value, + "ThreadLocal::get didn't return a pointer to const object"); + EXPECT_EQ(nullptr, x.get()); S s; @@ -33,6 +38,20 @@ TEST_F(ThreadLocalTest, Basics) { x.erase(); EXPECT_EQ(nullptr, x.get()); + + ThreadLocal<S> y; + + static_assert( + !std::is_const<std::remove_pointer<decltype(y.get())>::type>::value, + "ThreadLocal::get returned a pointer to const object"); + + EXPECT_EQ(nullptr, y.get()); + + y.set(&s); + EXPECT_EQ(&s, y.get()); + + y.erase(); + EXPECT_EQ(nullptr, y.get()); } } diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp index 39cfaf0..ff98602 100644 --- a/unittests/Support/raw_ostream_test.cpp +++ b/unittests/Support/raw_ostream_test.cpp @@ -162,6 +162,8 @@ TEST(raw_ostreamTest, FormatHex) { EXPECT_EQ("0x1", printToString(format_hex(1, 3), 3)); EXPECT_EQ("0x12", printToString(format_hex(0x12, 3), 4)); EXPECT_EQ("0x123", printToString(format_hex(0x123, 3), 5)); + EXPECT_EQ("FF", printToString(format_hex_no_prefix(0xFF, 2, true), 4)); + EXPECT_EQ("ABCD", printToString(format_hex_no_prefix(0xABCD, 2, true), 4)); EXPECT_EQ("0xffffffffffffffff", printToString(format_hex(UINT64_MAX, 18), 18)); EXPECT_EQ("0x8000000000000000", diff --git a/unittests/Transforms/CMakeLists.txt b/unittests/Transforms/CMakeLists.txt index 8ec56f1..5d3b29c 100644 --- a/unittests/Transforms/CMakeLists.txt +++ b/unittests/Transforms/CMakeLists.txt @@ -1,2 +1,2 @@ -add_subdirectory(DebugIR) +add_subdirectory(IPO) add_subdirectory(Utils) diff --git a/unittests/Transforms/DebugIR/CMakeLists.txt b/unittests/Transforms/DebugIR/CMakeLists.txt deleted file mode 100644 index 88734d2..0000000 --- a/unittests/Transforms/DebugIR/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -set(LLVM_LINK_COMPONENTS - Core - Instrumentation - Support - ) - -add_llvm_unittest(DebugIRTests - DebugIR.cpp - ) diff --git a/unittests/Transforms/DebugIR/DebugIR.cpp b/unittests/Transforms/DebugIR/DebugIR.cpp deleted file mode 100644 index 41df147..0000000 --- a/unittests/Transforms/DebugIR/DebugIR.cpp +++ /dev/null @@ -1,308 +0,0 @@ -//===- DebugIR.cpp - Unit tests for the DebugIR pass ----------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// The tests in this file verify the DebugIR pass that generates debug metadata -// for LLVM IR. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/Triple.h" -#include "../lib/Transforms/Instrumentation/DebugIR.h" -#include "llvm/Config/config.h" -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/Errc.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/Path.h" -#include "llvm/Transforms/Instrumentation.h" - -// These tests do not depend on MCJIT, but we use the TrivialModuleBuilder -// helper class to construct some trivial Modules. -#include "../unittests/ExecutionEngine/MCJIT/MCJITTestBase.h" - -#include <string> - -#include "gtest/gtest.h" - -#if defined(LLVM_ON_WIN32) -#include <direct.h> -#define getcwd_impl _getcwd -#elif defined (HAVE_GETCWD) -#include <unistd.h> -#define getcwd_impl getcwd -#endif // LLVM_ON_WIN32 - -using namespace llvm; -using namespace std; - -namespace { - -/// Insert a mock CUDescriptor with the specified producer -void insertCUDescriptor(Module *M, StringRef File, StringRef Dir, - StringRef Producer) { - DIBuilder B(*M); - B.createCompileUnit(dwarf::DW_LANG_C99, File, Dir, Producer, false, "", 0); - B.finalize(); -} - -/// Attempts to remove file at Path and returns true if it existed, or false if -/// it did not. -bool removeIfExists(StringRef Path) { - // This is an approximation, on error we don't know in general if the file - // existed or not. - std::error_code EC = sys::fs::remove(Path, false); - return EC != llvm::errc::no_such_file_or_directory; -} - -char * current_dir() { -#if defined(LLVM_ON_WIN32) || defined(HAVE_GETCWD) - // calling getcwd (or _getcwd() on windows) with a null buffer makes it - // allocate a sufficiently sized buffer to store the current working dir. - return getcwd_impl(nullptr, 0); -#else - return 0; -#endif -} - -class TestDebugIR : public ::testing::Test, public TrivialModuleBuilder { -protected: - TestDebugIR() - : TrivialModuleBuilder(sys::getProcessTriple()) - , cwd(current_dir()) {} - - ~TestDebugIR() { free(cwd); } - - /// Returns a concatenated path string consisting of Dir and Filename - string getPath(const string &Dir, const string &Filename) { - SmallVector<char, 8> Path; - sys::path::append(Path, Dir, Filename); - Path.resize(Dir.size() + Filename.size() + 2); - Path[Dir.size() + Filename.size() + 1] = '\0'; - return string(Path.data()); - } - - LLVMContext Context; - char *cwd; - std::unique_ptr<Module> M; - std::unique_ptr<DebugIR> D; -}; - -// Test empty named Module that is not supposed to be output to disk. -TEST_F(TestDebugIR, EmptyNamedModuleNoWrite) { - string Dir = "MadeUpDirectory"; - string File = "empty_module.ll"; - string Path(getPath(Dir, File)); - - M.reset(createEmptyModule(Path)); - - // constructing DebugIR with no args should not result in any file generated. - D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass())); - D->runOnModule(*M); - - // verify DebugIR did not generate a file - ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path; -} - -// Test a non-empty unnamed module that is output to an autogenerated file name. -TEST_F(TestDebugIR, NonEmptyUnnamedModuleWriteToAutogeneratedFile) { - M.reset(createEmptyModule()); - insertAddFunction(M.get()); - D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass(true, true))); - - string Path; - D->runOnModule(*M, Path); - - // verify DebugIR generated a file, and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; -} - -// Test not specifying a name in the module -- DebugIR should generate a name -// and write the file contents. -TEST_F(TestDebugIR, EmptyModuleWriteAnonymousFile) { - M.reset(createEmptyModule()); - D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass(false, false))); - - string Path; - D->runOnModule(*M, Path); - - // verify DebugIR generated a file and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; -} - -#ifdef HAVE_GETCWD // These tests require get_current_dir_name() - -// Test empty named Module that is to be output to path specified at Module -// construction. -TEST_F(TestDebugIR, EmptyNamedModuleWriteFile) { - string Filename("NamedFile1"); - string ExpectedPath(getPath(cwd, Filename)); - - M.reset(createEmptyModule(ExpectedPath)); - D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass(true, true))); - - string Path; - D->runOnModule(*M, Path); - - // verify DebugIR was able to correctly parse the file name from module ID - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR generated a file, and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; -} - -// Test an empty unnamed module generates an output file whose path is specified -// at DebugIR construction. -TEST_F(TestDebugIR, EmptyUnnamedModuleWriteNamedFile) { - string Filename("NamedFile2"); - - M.reset(createEmptyModule()); - D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass( - false, false, StringRef(cwd), StringRef(Filename)))); - string Path; - D->runOnModule(*M, Path); - - string ExpectedPath(getPath(cwd, Filename)); - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR generated a file, and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; -} - -// Test an empty named module generates an output file at the path specified -// during DebugIR construction. -TEST_F(TestDebugIR, EmptyNamedModuleWriteNamedFile) { - string Filename("NamedFile3"); - - string UnexpectedPath(getPath(cwd, "UnexpectedFilename")); - M.reset(createEmptyModule(UnexpectedPath)); - - D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass( - false, false, StringRef(cwd), StringRef(Filename)))); - string Path; - D->runOnModule(*M, Path); - - string ExpectedPath(getPath(cwd, Filename)); - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR generated a file, and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; - - // verify DebugIR did not generate a file at the path specified at Module - // construction. - ASSERT_FALSE(removeIfExists(UnexpectedPath)) << "Unexpected file " << Path; -} - -// Test a non-empty named module that is not supposed to be output to disk -TEST_F(TestDebugIR, NonEmptyNamedModuleNoWrite) { - string Filename("NamedFile4"); - string ExpectedPath(getPath(cwd, Filename)); - - M.reset(createEmptyModule(ExpectedPath)); - insertAddFunction(M.get()); - - D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass())); - - string Path; - D->runOnModule(*M, Path); - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR did not generate a file - ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path; -} - -// Test a non-empty named module that is output to disk. -TEST_F(TestDebugIR, NonEmptyNamedModuleWriteFile) { - string Filename("NamedFile5"); - string ExpectedPath(getPath(cwd, Filename)); - - M.reset(createEmptyModule(ExpectedPath)); - insertAddFunction(M.get()); - - D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass(true, true))); - - string Path; - D->runOnModule(*M, Path); - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR generated a file, and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; -} - -// Test a non-empty unnamed module is output to a path specified at DebugIR -// construction. -TEST_F(TestDebugIR, NonEmptyUnnamedModuleWriteToNamedFile) { - string Filename("NamedFile6"); - - M.reset(createEmptyModule()); - insertAddFunction(M.get()); - - D.reset(static_cast<DebugIR *>( - llvm::createDebugIRPass(true, true, cwd, Filename))); - string Path; - D->runOnModule(*M, Path); - - string ExpectedPath(getPath(cwd, Filename)); - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR generated a file, and clean it up - ASSERT_TRUE(removeIfExists(Path)) << "Missing expected file at " << Path; -} - -// Test that information inside existing debug metadata is retained -TEST_F(TestDebugIR, ExistingMetadataRetained) { - string Filename("NamedFile7"); - string ExpectedPath(getPath(cwd, Filename)); - - M.reset(createEmptyModule(ExpectedPath)); - insertAddFunction(M.get()); - - StringRef Producer("TestProducer"); - insertCUDescriptor(M.get(), Filename, cwd, Producer); - - DebugInfoFinder Finder; - Finder.processModule(*M); - ASSERT_EQ((unsigned)1, Finder.compile_unit_count()); - D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass())); - - string Path; - D->runOnModule(*M, Path); - ASSERT_EQ(ExpectedPath, Path); - - // verify DebugIR did not generate a file - ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path; - - DICompileUnit CU(*Finder.compile_units().begin()); - - // Verify original CU information is retained - ASSERT_EQ(Filename, CU.getFilename()); - ASSERT_EQ(cwd, CU.getDirectory()); - ASSERT_EQ(Producer, CU.getProducer()); -} - -#endif // HAVE_GETCWD - -#ifdef GTEST_HAS_DEATH_TEST - -// Test a non-empty unnamed module that is not supposed to be output to disk -// NOTE: this test is expected to die with LLVM_ERROR, and such depends on -// google test's "death test" mode. -TEST_F(TestDebugIR, NonEmptyUnnamedModuleNoWrite) { - M.reset(createEmptyModule(StringRef())); - insertAddFunction(M.get()); - D.reset(static_cast<DebugIR *>(llvm::createDebugIRPass())); - - // No name in module or on DebugIR construction ==> DebugIR should assert - EXPECT_DEATH(D->runOnModule(*M), - "DebugIR unable to determine file name in input."); -} - -#endif // GTEST_HAS_DEATH_TEST -} diff --git a/unittests/Transforms/IPO/CMakeLists.txt b/unittests/Transforms/IPO/CMakeLists.txt new file mode 100644 index 0000000..58b71b2 --- /dev/null +++ b/unittests/Transforms/IPO/CMakeLists.txt @@ -0,0 +1,9 @@ +set(LLVM_LINK_COMPONENTS + Core + Support + IPO + ) + +add_llvm_unittest(IPOTests + LowerBitSets.cpp + ) diff --git a/unittests/Transforms/IPO/LowerBitSets.cpp b/unittests/Transforms/IPO/LowerBitSets.cpp new file mode 100644 index 0000000..26a4252 --- /dev/null +++ b/unittests/Transforms/IPO/LowerBitSets.cpp @@ -0,0 +1,95 @@ +//===- LowerBitSets.cpp - Unit tests for bitset lowering ------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/IPO/LowerBitSets.h" +#include "gtest/gtest.h" + +using namespace llvm; + +TEST(LowerBitSets, BitSetBuilder) { + struct { + std::vector<uint64_t> Offsets; + std::vector<uint8_t> Bits; + uint64_t ByteOffset; + uint64_t BitSize; + unsigned AlignLog2; + bool IsSingleOffset; + bool IsAllOnes; + } BSBTests[] = { + {{}, {0}, 0, 1, 0, false, false}, + {{0}, {1}, 0, 1, 0, true, true}, + {{4}, {1}, 4, 1, 0, true, true}, + {{37}, {1}, 37, 1, 0, true, true}, + {{0, 1}, {3}, 0, 2, 0, false, true}, + {{0, 4}, {3}, 0, 2, 2, false, true}, + {{0, uint64_t(1) << 33}, {3}, 0, 2, 33, false, true}, + {{3, 7}, {3}, 3, 2, 2, false, true}, + {{0, 1, 7}, {131}, 0, 8, 0, false, false}, + {{0, 2, 14}, {131}, 0, 8, 1, false, false}, + {{0, 1, 8}, {3, 1}, 0, 9, 0, false, false}, + {{0, 2, 16}, {3, 1}, 0, 9, 1, false, false}, + {{0, 1, 2, 3, 4, 5, 6, 7}, {255}, 0, 8, 0, false, true}, + {{0, 1, 2, 3, 4, 5, 6, 7, 8}, {255, 1}, 0, 9, 0, false, true}, + }; + + for (auto &&T : BSBTests) { + BitSetBuilder BSB; + for (auto Offset : T.Offsets) + BSB.addOffset(Offset); + + BitSetInfo BSI = BSB.build(); + + EXPECT_EQ(T.Bits, BSI.Bits); + EXPECT_EQ(T.ByteOffset, BSI.ByteOffset); + EXPECT_EQ(T.BitSize, BSI.BitSize); + EXPECT_EQ(T.AlignLog2, BSI.AlignLog2); + EXPECT_EQ(T.IsSingleOffset, BSI.isSingleOffset()); + EXPECT_EQ(T.IsAllOnes, BSI.isAllOnes()); + + for (auto Offset : T.Offsets) + EXPECT_TRUE(BSI.containsGlobalOffset(Offset)); + + auto I = T.Offsets.begin(); + for (uint64_t NonOffset = 0; NonOffset != 256; ++NonOffset) { + if (I != T.Offsets.end() && *I == NonOffset) { + ++I; + continue; + } + + EXPECT_FALSE(BSI.containsGlobalOffset(NonOffset)); + } + } +} + +TEST(LowerBitSets, GlobalLayoutBuilder) { + struct { + uint64_t NumObjects; + std::vector<std::set<uint64_t>> Fragments; + std::vector<uint64_t> WantLayout; + } GLBTests[] = { + {0, {}, {}}, + {4, {{0, 1}, {2, 3}}, {0, 1, 2, 3}}, + {3, {{0, 1}, {1, 2}}, {0, 1, 2}}, + {4, {{0, 1}, {1, 2}, {2, 3}}, {0, 1, 2, 3}}, + {4, {{0, 1}, {2, 3}, {1, 2}}, {0, 1, 2, 3}}, + {6, {{2, 5}, {0, 1, 2, 3, 4, 5}}, {0, 1, 2, 5, 3, 4}}, + }; + + for (auto &&T : GLBTests) { + GlobalLayoutBuilder GLB(T.NumObjects); + for (auto &&F : T.Fragments) + GLB.addFragment(F); + + std::vector<uint64_t> ComputedLayout; + for (auto &&F : GLB.Fragments) + ComputedLayout.insert(ComputedLayout.end(), F.begin(), F.end()); + + EXPECT_EQ(T.WantLayout, ComputedLayout); + } +} diff --git a/unittests/Transforms/DebugIR/Makefile b/unittests/Transforms/IPO/Makefile index 9ace8c3..f807879 100644 --- a/unittests/Transforms/DebugIR/Makefile +++ b/unittests/Transforms/IPO/Makefile @@ -1,4 +1,4 @@ -##===- unittests/Transforms/Utils/Makefile -----------------*- Makefile -*-===## +##===- unittests/Transforms/IPO/Makefile -------------------*- Makefile -*-===## # # The LLVM Compiler Infrastructure # @@ -8,8 +8,8 @@ ##===----------------------------------------------------------------------===## LEVEL = ../../.. -TESTNAME = DebugIR -LINK_COMPONENTS := Instrumentation +TESTNAME = IPO +LINK_COMPONENTS := IPO include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Transforms/Makefile b/unittests/Transforms/Makefile index d5cca39..3a2cdfc 100644 --- a/unittests/Transforms/Makefile +++ b/unittests/Transforms/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. -PARALLEL_DIRS = DebugIR Utils +PARALLEL_DIRS = IPO Utils include $(LEVEL)/Makefile.common diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index c779979..1d22d5b 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -13,16 +13,15 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Constant.h" -#include "llvm/IR/DebugInfo.h" #include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Module.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "gtest/gtest.h" using namespace llvm; |