diff options
Diffstat (limited to 'unittests')
86 files changed, 2086 insertions, 2444 deletions
diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index 8f298cd..c7ec16b 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -474,6 +474,40 @@ TEST(APFloatTest, FMA) {      f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);      EXPECT_EQ(12.0f, f1.convertToFloat());    } + +  { +    APFloat M1(APFloat::x87DoubleExtended, 1.0); +    APFloat M2(APFloat::x87DoubleExtended, 1.0); +    APFloat A(APFloat::x87DoubleExtended, 3.0); + +    bool losesInfo = false; +    M1.fusedMultiplyAdd(M1, A, APFloat::rmNearestTiesToEven); +    M1.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &losesInfo); +    EXPECT_FALSE(losesInfo); +    EXPECT_EQ(4.0f, M1.convertToFloat()); +  } +} + +TEST(APFloatTest, MinNum) { +  APFloat f1(1.0); +  APFloat f2(2.0); +  APFloat nan = APFloat::getNaN(APFloat::IEEEdouble); + +  EXPECT_EQ(1.0, minnum(f1, f2).convertToDouble()); +  EXPECT_EQ(1.0, minnum(f2, f1).convertToDouble()); +  EXPECT_EQ(1.0, minnum(f1, nan).convertToDouble()); +  EXPECT_EQ(1.0, minnum(nan, f1).convertToDouble()); +} + +TEST(APFloatTest, MaxNum) { +  APFloat f1(1.0); +  APFloat f2(2.0); +  APFloat nan = APFloat::getNaN(APFloat::IEEEdouble); + +  EXPECT_EQ(2.0, maxnum(f1, f2).convertToDouble()); +  EXPECT_EQ(2.0, maxnum(f2, f1).convertToDouble()); +  EXPECT_EQ(1.0, maxnum(f1, nan).convertToDouble()); +  EXPECT_EQ(1.0, minnum(nan, f1).convertToDouble());  }  TEST(APFloatTest, Denormal) { @@ -1342,6 +1376,17 @@ TEST(APFloatTest, getZero) {    }  } +TEST(APFloatTest, copySign) { +  EXPECT_TRUE(APFloat(-42.0).bitwiseIsEqual( +      APFloat::copySign(APFloat(42.0), APFloat(-1.0)))); +  EXPECT_TRUE(APFloat(42.0).bitwiseIsEqual( +      APFloat::copySign(APFloat(-42.0), APFloat(1.0)))); +  EXPECT_TRUE(APFloat(-42.0).bitwiseIsEqual( +      APFloat::copySign(APFloat(-42.0), APFloat(-1.0)))); +  EXPECT_TRUE(APFloat(42.0).bitwiseIsEqual( +      APFloat::copySign(APFloat(42.0), APFloat(1.0)))); +} +  TEST(APFloatTest, convert) {    bool losesInfo;    APFloat test(APFloat::IEEEdouble, "1.0"); @@ -2671,4 +2716,123 @@ TEST(APFloatTest, divide) {    }  } +TEST(APFloatTest, operatorOverloads) { +  // This is mostly testing that these operator overloads compile. +  APFloat One = APFloat(APFloat::IEEEsingle, "0x1p+0"); +  APFloat Two = APFloat(APFloat::IEEEsingle, "0x2p+0"); +  EXPECT_TRUE(Two.bitwiseIsEqual(One + One)); +  EXPECT_TRUE(One.bitwiseIsEqual(Two - One)); +  EXPECT_TRUE(Two.bitwiseIsEqual(One * Two)); +  EXPECT_TRUE(One.bitwiseIsEqual(Two / Two)); +} + +TEST(APFloatTest, abs) { +  APFloat PInf = APFloat::getInf(APFloat::IEEEsingle, false); +  APFloat MInf = APFloat::getInf(APFloat::IEEEsingle, true); +  APFloat PZero = APFloat::getZero(APFloat::IEEEsingle, false); +  APFloat MZero = APFloat::getZero(APFloat::IEEEsingle, true); +  APFloat PQNaN = APFloat::getNaN(APFloat::IEEEsingle, false); +  APFloat MQNaN = APFloat::getNaN(APFloat::IEEEsingle, true); +  APFloat PSNaN = APFloat::getSNaN(APFloat::IEEEsingle, false); +  APFloat MSNaN = APFloat::getSNaN(APFloat::IEEEsingle, true); +  APFloat PNormalValue = APFloat(APFloat::IEEEsingle, "0x1p+0"); +  APFloat MNormalValue = APFloat(APFloat::IEEEsingle, "-0x1p+0"); +  APFloat PLargestValue = APFloat::getLargest(APFloat::IEEEsingle, false); +  APFloat MLargestValue = APFloat::getLargest(APFloat::IEEEsingle, true); +  APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle, false); +  APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle, true); +  APFloat PSmallestNormalized = +    APFloat::getSmallestNormalized(APFloat::IEEEsingle, false); +  APFloat MSmallestNormalized = +    APFloat::getSmallestNormalized(APFloat::IEEEsingle, true); + +  EXPECT_TRUE(PInf.bitwiseIsEqual(abs(PInf))); +  EXPECT_TRUE(PInf.bitwiseIsEqual(abs(MInf))); +  EXPECT_TRUE(PZero.bitwiseIsEqual(abs(PZero))); +  EXPECT_TRUE(PZero.bitwiseIsEqual(abs(MZero))); +  EXPECT_TRUE(PQNaN.bitwiseIsEqual(abs(PQNaN))); +  EXPECT_TRUE(PQNaN.bitwiseIsEqual(abs(MQNaN))); +  EXPECT_TRUE(PSNaN.bitwiseIsEqual(abs(PSNaN))); +  EXPECT_TRUE(PSNaN.bitwiseIsEqual(abs(MSNaN))); +  EXPECT_TRUE(PNormalValue.bitwiseIsEqual(abs(PNormalValue))); +  EXPECT_TRUE(PNormalValue.bitwiseIsEqual(abs(MNormalValue))); +  EXPECT_TRUE(PLargestValue.bitwiseIsEqual(abs(PLargestValue))); +  EXPECT_TRUE(PLargestValue.bitwiseIsEqual(abs(MLargestValue))); +  EXPECT_TRUE(PSmallestValue.bitwiseIsEqual(abs(PSmallestValue))); +  EXPECT_TRUE(PSmallestValue.bitwiseIsEqual(abs(MSmallestValue))); +  EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(PSmallestNormalized))); +  EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(MSmallestNormalized))); +} + +TEST(APFloatTest, ilogb) { +  EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle, "0x1p+0"))); +  EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle, "-0x1p+0"))); +  EXPECT_EQ(42, ilogb(APFloat(APFloat::IEEEsingle, "0x1p+42"))); +  EXPECT_EQ(-42, ilogb(APFloat(APFloat::IEEEsingle, "0x1p-42"))); + +  EXPECT_EQ(APFloat::IEK_Inf, +            ilogb(APFloat::getInf(APFloat::IEEEsingle, false))); +  EXPECT_EQ(APFloat::IEK_Inf, +            ilogb(APFloat::getInf(APFloat::IEEEsingle, true))); +  EXPECT_EQ(APFloat::IEK_Zero, +            ilogb(APFloat::getZero(APFloat::IEEEsingle, false))); +  EXPECT_EQ(APFloat::IEK_Zero, +            ilogb(APFloat::getZero(APFloat::IEEEsingle, true))); +  EXPECT_EQ(APFloat::IEK_NaN, +            ilogb(APFloat::getNaN(APFloat::IEEEsingle, false))); +  EXPECT_EQ(APFloat::IEK_NaN, +            ilogb(APFloat::getSNaN(APFloat::IEEEsingle, false))); + +  EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle, false))); +  EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle, true))); +  EXPECT_EQ(-126, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, false))); +  EXPECT_EQ(-126, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, true))); +  EXPECT_EQ(-126, +            ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle, false))); +  EXPECT_EQ(-126, +            ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle, true))); +} + +TEST(APFloatTest, scalbn) { +  EXPECT_TRUE( +      APFloat(APFloat::IEEEsingle, "0x1p+0") +          .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 0))); +  EXPECT_TRUE( +      APFloat(APFloat::IEEEsingle, "0x1p+42") +          .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 42))); +  EXPECT_TRUE( +      APFloat(APFloat::IEEEsingle, "0x1p-42") +          .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), -42))); + +  APFloat PInf = APFloat::getInf(APFloat::IEEEsingle, false); +  APFloat MInf = APFloat::getInf(APFloat::IEEEsingle, true); +  APFloat PZero = APFloat::getZero(APFloat::IEEEsingle, false); +  APFloat MZero = APFloat::getZero(APFloat::IEEEsingle, true); +  APFloat QPNaN = APFloat::getNaN(APFloat::IEEEsingle, false); +  APFloat QMNaN = APFloat::getNaN(APFloat::IEEEsingle, true); +  APFloat SNaN = APFloat::getSNaN(APFloat::IEEEsingle, false); + +  EXPECT_TRUE(PInf.bitwiseIsEqual(scalbn(PInf, 0))); +  EXPECT_TRUE(MInf.bitwiseIsEqual(scalbn(MInf, 0))); +  EXPECT_TRUE(PZero.bitwiseIsEqual(scalbn(PZero, 0))); +  EXPECT_TRUE(MZero.bitwiseIsEqual(scalbn(MZero, 0))); +  EXPECT_TRUE(QPNaN.bitwiseIsEqual(scalbn(QPNaN, 0))); +  EXPECT_TRUE(QMNaN.bitwiseIsEqual(scalbn(QMNaN, 0))); +  EXPECT_TRUE(SNaN.bitwiseIsEqual(scalbn(SNaN, 0))); + +  EXPECT_TRUE( +      PInf.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 128))); +  EXPECT_TRUE(MInf.bitwiseIsEqual( +      scalbn(APFloat(APFloat::IEEEsingle, "-0x1p+0"), 128))); +  EXPECT_TRUE( +      PInf.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+127"), 1))); +  EXPECT_TRUE(PZero.bitwiseIsEqual( +      scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), -127))); +  EXPECT_TRUE(MZero.bitwiseIsEqual( +      scalbn(APFloat(APFloat::IEEEsingle, "-0x1p+0"), -127))); +  EXPECT_TRUE(PZero.bitwiseIsEqual( +      scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -1))); +  EXPECT_TRUE(PZero.bitwiseIsEqual( +      scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -1))); +}  } diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 19c47ab..8198c71 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -614,7 +614,7 @@ TEST(APIntTest, arrayAccess) {      0x7E7FFA5EADD8846ULL,      0x305F341CA00B613DULL    }; -  APInt A2(integerPartWidth*4, ArrayRef<integerPart>(E2, 4)); +  APInt A2(integerPartWidth*4, E2);    for (unsigned i = 0; i < 4; ++i) {      for (unsigned j = 0; j < integerPartWidth; ++j) {        EXPECT_EQ(bool(E2[i] & (1ULL << j)), @@ -653,17 +653,17 @@ TEST(APIntTest, nearestLogBase2) {    // Test round up.    integerPart I4[4] = {0x0, 0xF, 0x18, 0x0}; -  APInt A4(integerPartWidth*4, ArrayRef<integerPart>(I4, 4)); +  APInt A4(integerPartWidth*4, I4);    EXPECT_EQ(A4.nearestLogBase2(), A4.ceilLogBase2());    // Test round down.    integerPart I5[4] = {0x0, 0xF, 0x10, 0x0}; -  APInt A5(integerPartWidth*4, ArrayRef<integerPart>(I5, 4)); +  APInt A5(integerPartWidth*4, I5);    EXPECT_EQ(A5.nearestLogBase2(), A5.logBase2());    // Test ties round up.    uint64_t I6[4] = {0x0, 0x0, 0x0, 0x18}; -  APInt A6(integerPartWidth*4, ArrayRef<integerPart>(I6, 4)); +  APInt A6(integerPartWidth*4, I6);    EXPECT_EQ(A6.nearestLogBase2(), A6.ceilLogBase2());    // Test BitWidth == 1 special cases. @@ -678,4 +678,21 @@ TEST(APIntTest, nearestLogBase2) {    EXPECT_EQ(A9.nearestLogBase2(), UINT32_MAX);  } +TEST(APIntTest, SelfMoveAssignment) { +  APInt X(32, 0xdeadbeef); +  X = std::move(X); +  EXPECT_EQ(32u, X.getBitWidth()); +  EXPECT_EQ(0xdeadbeefULL, X.getLimitedValue()); + +  uint64_t Bits[] = {0xdeadbeefdeadbeefULL, 0xdeadbeefdeadbeefULL}; +  APInt Y(128, Bits); +  Y = std::move(Y); +  EXPECT_EQ(128u, Y.getBitWidth()); +  EXPECT_EQ(~0ULL, Y.getLimitedValue()); +  const uint64_t *Raw = Y.getRawData(); +  EXPECT_EQ(2u, Y.getNumWords()); +  EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[0]); +  EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[1]); +} +  } diff --git a/unittests/ADT/ArrayRefTest.cpp b/unittests/ADT/ArrayRefTest.cpp index 293afc6..f9c98a5 100644 --- a/unittests/ADT/ArrayRefTest.cpp +++ b/unittests/ADT/ArrayRefTest.cpp @@ -13,6 +13,23 @@  #include "gtest/gtest.h"  using namespace llvm; +// Check that the ArrayRef-of-pointer converting constructor only allows adding +// cv qualifiers (not removing them, or otherwise changing the type) +static_assert( +    std::is_convertible<ArrayRef<int *>, ArrayRef<const int *>>::value, +    "Adding const"); +static_assert( +    std::is_convertible<ArrayRef<int *>, ArrayRef<volatile int *>>::value, +    "Adding volatile"); +static_assert(!std::is_convertible<ArrayRef<int *>, ArrayRef<float *>>::value, +              "Changing pointer of one type to a pointer of another"); +static_assert( +    !std::is_convertible<ArrayRef<const int *>, ArrayRef<int *>>::value, +    "Removing const"); +static_assert( +    !std::is_convertible<ArrayRef<volatile int *>, ArrayRef<int *>>::value, +    "Removing volatile"); +  namespace llvm {  TEST(ArrayRefTest, AllocatorCopy) { @@ -36,5 +53,41 @@ TEST(ArrayRefTest, DropBack) {    EXPECT_TRUE(AR1.drop_back().equals(AR2));  } +TEST(ArrayRefTest, Equals) { +  static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8}; +  ArrayRef<int> AR1(A1); +  EXPECT_TRUE(AR1.equals(1, 2, 3, 4, 5, 6, 7, 8)); +  EXPECT_FALSE(AR1.equals(8, 1, 2, 4, 5, 6, 6, 7)); +  EXPECT_FALSE(AR1.equals(2, 4, 5, 6, 6, 7, 8, 1)); +  EXPECT_FALSE(AR1.equals(0, 1, 2, 4, 5, 6, 6, 7)); +  EXPECT_FALSE(AR1.equals(1, 2, 42, 4, 5, 6, 7, 8)); +  EXPECT_FALSE(AR1.equals(42, 2, 3, 4, 5, 6, 7, 8)); +  EXPECT_FALSE(AR1.equals(1, 2, 3, 4, 5, 6, 7, 42)); +  EXPECT_FALSE(AR1.equals(1, 2, 3, 4, 5, 6, 7)); +  EXPECT_FALSE(AR1.equals(1, 2, 3, 4, 5, 6, 7, 8, 9)); + +  ArrayRef<int> AR1a = AR1.drop_back(); +  EXPECT_TRUE(AR1a.equals(1, 2, 3, 4, 5, 6, 7)); +  EXPECT_FALSE(AR1a.equals(1, 2, 3, 4, 5, 6, 7, 8)); + +  ArrayRef<int> AR1b = AR1a.slice(2, 4); +  EXPECT_TRUE(AR1b.equals(3, 4, 5, 6)); +  EXPECT_FALSE(AR1b.equals(2, 3, 4, 5, 6)); +  EXPECT_FALSE(AR1b.equals(3, 4, 5, 6, 7)); +} + +TEST(ArrayRefTest, EmptyEquals) { +  EXPECT_TRUE(ArrayRef<unsigned>() == ArrayRef<unsigned>()); +} + +TEST(ArrayRefTest, ConstConvert) { +  int buf[4]; +  for (int i = 0; i < 4; ++i) +    buf[i] = i; + +  static int *A[] = {&buf[0], &buf[1], &buf[2], &buf[3]}; +  ArrayRef<const int *> a((ArrayRef<int *>(A))); +  a = ArrayRef<int *>(A); +}  } // end anonymous namespace diff --git a/unittests/ADT/CMakeLists.txt b/unittests/ADT/CMakeLists.txt index 0f214f3..d899852 100644 --- a/unittests/ADT/CMakeLists.txt +++ b/unittests/ADT/CMakeLists.txt @@ -13,6 +13,7 @@ set(ADTSources    DenseMapTest.cpp    DenseSetTest.cpp    FoldingSet.cpp +  FunctionRefTest.cpp    HashingTest.cpp    ilistTest.cpp    ImmutableMapTest.cpp @@ -26,6 +27,7 @@ set(ADTSources    PackedVectorTest.cpp    PointerIntPairTest.cpp    PointerUnionTest.cpp +  PostOrderIteratorTest.cpp    SCCIteratorTest.cpp    SmallPtrSetTest.cpp    SmallStringTest.cpp diff --git a/unittests/ADT/DenseMapTest.cpp b/unittests/ADT/DenseMapTest.cpp index 75a910a..f497983 100644 --- a/unittests/ADT/DenseMapTest.cpp +++ b/unittests/ADT/DenseMapTest.cpp @@ -244,6 +244,11 @@ TYPED_TEST(DenseMapTest, AssignmentTest) {    EXPECT_EQ(1u, copyMap.size());    EXPECT_EQ(this->getValue(), copyMap[this->getKey()]); + +  // test self-assignment. +  copyMap = copyMap; +  EXPECT_EQ(1u, copyMap.size()); +  EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);  }  // Test swap method diff --git a/unittests/ADT/DenseSetTest.cpp b/unittests/ADT/DenseSetTest.cpp index 154c589..5952353 100644 --- a/unittests/ADT/DenseSetTest.cpp +++ b/unittests/ADT/DenseSetTest.cpp @@ -27,4 +27,42 @@ TEST_F(DenseSetTest, DoubleEntrySetTest) {    EXPECT_EQ(0u, set.count(2));  } +struct TestDenseSetInfo { +  static inline unsigned getEmptyKey() { return ~0; } +  static inline unsigned getTombstoneKey() { return ~0U - 1; } +  static unsigned getHashValue(const unsigned& Val) { return Val * 37U; } +  static unsigned getHashValue(const char* Val) { +    return (unsigned)(Val[0] - 'a') * 37U; +  } +  static bool isEqual(const unsigned& LHS, const unsigned& RHS) { +    return LHS == RHS; +  } +  static bool isEqual(const char* LHS, const unsigned& RHS) { +    return (unsigned)(LHS[0] - 'a') == RHS; +  } +}; + +TEST(DenseSetCustomTest, FindAsTest) { +  DenseSet<unsigned, TestDenseSetInfo> set; +  set.insert(0); +  set.insert(1); +  set.insert(2); + +  // Size tests +  EXPECT_EQ(3u, set.size()); + +  // Normal lookup tests +  EXPECT_EQ(1u, set.count(1)); +  EXPECT_EQ(0u, *set.find(0)); +  EXPECT_EQ(1u, *set.find(1)); +  EXPECT_EQ(2u, *set.find(2)); +  EXPECT_TRUE(set.find(3) == set.end()); + +  // find_as() tests +  EXPECT_EQ(0u, *set.find_as("a")); +  EXPECT_EQ(1u, *set.find_as("b")); +  EXPECT_EQ(2u, *set.find_as("c")); +  EXPECT_TRUE(set.find_as("d") == set.end()); +} +  } diff --git a/unittests/ADT/FunctionRefTest.cpp b/unittests/ADT/FunctionRefTest.cpp new file mode 100644 index 0000000..075d9a0 --- /dev/null +++ b/unittests/ADT/FunctionRefTest.cpp @@ -0,0 +1,28 @@ +//===- llvm/unittest/ADT/MakeUniqueTest.cpp - make_unique 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/ADT/STLExtras.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +// Ensure that copies of a function_ref copy the underlying state rather than +// causing one function_ref to chain to the next. +TEST(FunctionRefTest, Copy) { +  auto A = [] { return 1; }; +  auto B = [] { return 2; }; +  function_ref<int()> X = A; +  function_ref<int()> Y = X; +  X = B; +  EXPECT_EQ(1, Y()); +} + +} diff --git a/unittests/ADT/MapVectorTest.cpp b/unittests/ADT/MapVectorTest.cpp index 11178bc..8919799 100644 --- a/unittests/ADT/MapVectorTest.cpp +++ b/unittests/ADT/MapVectorTest.cpp @@ -9,6 +9,7 @@  #include "gtest/gtest.h"  #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/iterator_range.h"  #include <utility>  using namespace llvm; @@ -53,3 +54,71 @@ TEST(MapVectorTest, insert_pop) {    EXPECT_EQ(MV[1], 2);    EXPECT_EQ(MV[4], 7);  } + +TEST(MapVectorTest, erase) { +  MapVector<int, int> 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(MapVectorTest, remove_if) { +  MapVector<int, int> 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(MapVectorTest, iteration_test) { +  MapVector<int, int> 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 2da408c..cadadce 100644 --- a/unittests/ADT/OptionalTest.cpp +++ b/unittests/ADT/OptionalTest.cpp @@ -169,6 +169,52 @@ TEST_F(OptionalTest, NullCopyConstructionTest) {    EXPECT_EQ(0u, NonDefaultConstructible::Destructions);  } +TEST_F(OptionalTest, GetValueOr) { +  Optional<int> A; +  EXPECT_EQ(42, A.getValueOr(42)); + +  A = 5; +  EXPECT_EQ(5, A.getValueOr(42)); +} + +struct MultiArgConstructor { +  int x, y; +  MultiArgConstructor(int x, int y) : x(x), y(y) {} +  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; + +  static unsigned Destructions; +  ~MultiArgConstructor() { +    ++Destructions; +  } +  static void ResetCounts() { +    Destructions = 0; +  } +}; +unsigned MultiArgConstructor::Destructions = 0; + +TEST_F(OptionalTest, Emplace) { +  MultiArgConstructor::ResetCounts(); +  Optional<MultiArgConstructor> A; +   +  A.emplace(1, 2); +  EXPECT_TRUE(A.hasValue()); +  EXPECT_EQ(1, A->x); +  EXPECT_EQ(2, A->y); +  EXPECT_EQ(0u, MultiArgConstructor::Destructions); + +  A.emplace(5, false); +  EXPECT_TRUE(A.hasValue()); +  EXPECT_EQ(5, A->x); +  EXPECT_EQ(-5, A->y); +  EXPECT_EQ(1u, MultiArgConstructor::Destructions); +} +  struct MoveOnly {    static unsigned MoveConstructions;    static unsigned Destructions; @@ -278,5 +324,58 @@ TEST_F(OptionalTest, MoveOnlyAssigningAssignment) {    EXPECT_EQ(1u, MoveOnly::Destructions);  } +struct Immovable { +  static unsigned Constructions; +  static unsigned Destructions; +  int val; +  explicit Immovable(int val) : val(val) { +    ++Constructions; +  } +  ~Immovable() { +    ++Destructions; +  } +  static void ResetCounts() { +    Constructions = 0; +    Destructions = 0; +  } +private: +  // This should disable all move/copy operations. +  Immovable(Immovable&& other) LLVM_DELETED_FUNCTION; +}; + +unsigned Immovable::Constructions = 0; +unsigned Immovable::Destructions = 0; + +TEST_F(OptionalTest, ImmovableEmplace) { +  Optional<Immovable> A; +  Immovable::ResetCounts(); +  A.emplace(4); +  EXPECT_TRUE((bool)A); +  EXPECT_EQ(4, A->val); +  EXPECT_EQ(1u, Immovable::Constructions); +  EXPECT_EQ(0u, Immovable::Destructions); +} + +#if LLVM_HAS_RVALUE_REFERENCE_THIS + +TEST_F(OptionalTest, MoveGetValueOr) { +  Optional<MoveOnly> A; + +  MoveOnly::ResetCounts(); +  EXPECT_EQ(42, std::move(A).getValueOr(MoveOnly(42)).val); +  EXPECT_EQ(1u, MoveOnly::MoveConstructions); +  EXPECT_EQ(0u, MoveOnly::MoveAssignments); +  EXPECT_EQ(2u, MoveOnly::Destructions); + +  A = MoveOnly(5); +  MoveOnly::ResetCounts(); +  EXPECT_EQ(5, std::move(A).getValueOr(MoveOnly(42)).val); +  EXPECT_EQ(1u, MoveOnly::MoveConstructions); +  EXPECT_EQ(0u, MoveOnly::MoveAssignments); +  EXPECT_EQ(2u, MoveOnly::Destructions); +} + +#endif // LLVM_HAS_RVALUE_REFERENCE_THIS +  } // end anonymous namespace diff --git a/unittests/ADT/PostOrderIteratorTest.cpp b/unittests/ADT/PostOrderIteratorTest.cpp new file mode 100644 index 0000000..1da1078 --- /dev/null +++ b/unittests/ADT/PostOrderIteratorTest.cpp @@ -0,0 +1,37 @@ +//===- PostOrderIteratorTest.cpp - PostOrderIterator unit tests -----------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "gtest/gtest.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CFG.h" +using namespace llvm; + +namespace { + +// Whether we're able to compile +TEST(PostOrderIteratorTest, Compiles) { +  typedef SmallPtrSet<void *, 4> ExtSetTy; + +  // Tests that template specializations are kept up to date +  void *Null = nullptr; +  po_iterator_storage<std::set<void *>, false> PIS; +  PIS.insertEdge(Null, Null); +  ExtSetTy Ext; +  po_iterator_storage<ExtSetTy, true> PISExt(Ext); +  PIS.insertEdge(Null, Null); + +  // Test above, but going through po_iterator (which inherits from template +  // base) +  BasicBlock *NullBB = nullptr; +  auto PI = po_end(NullBB); +  PI.insertEdge(NullBB, NullBB); +  auto PIExt = po_ext_end(NullBB, Ext); +  PIExt.insertEdge(NullBB, NullBB); +} +} diff --git a/unittests/ADT/StringMapTest.cpp b/unittests/ADT/StringMapTest.cpp index 028375d..33d668f 100644 --- a/unittests/ADT/StringMapTest.cpp +++ b/unittests/ADT/StringMapTest.cpp @@ -250,15 +250,21 @@ struct StringMapTestStruct {  TEST_F(StringMapTest, NonDefaultConstructable) {    StringMap<StringMapTestStruct> t; -  t.GetOrCreateValue("Test", StringMapTestStruct(123)); +  t.insert(std::make_pair("Test", StringMapTestStruct(123)));    StringMap<StringMapTestStruct>::iterator iter = t.find("Test");    ASSERT_NE(iter, t.end());    ASSERT_EQ(iter->second.i, 123);  } +struct Immovable { +  Immovable() {} +  Immovable(Immovable&&) LLVM_DELETED_FUNCTION; // will disable the other special members +}; +  struct MoveOnly {    int i;    MoveOnly(int i) : i(i) {} +  MoveOnly(const Immovable&) : i(0) {}    MoveOnly(MoveOnly &&RHS) : i(RHS.i) {}    MoveOnly &operator=(MoveOnly &&RHS) {      i = RHS.i; @@ -270,17 +276,23 @@ private:    MoveOnly &operator=(const MoveOnly &) LLVM_DELETED_FUNCTION;  }; -TEST_F(StringMapTest, MoveOnlyKey) { +TEST_F(StringMapTest, MoveOnly) {    StringMap<MoveOnly> t; -  t.GetOrCreateValue("Test", MoveOnly(42)); +  t.insert(std::make_pair("Test", MoveOnly(42)));    StringRef Key = "Test";    StringMapEntry<MoveOnly>::Create(Key, MoveOnly(42))        ->Destroy();  } +TEST_F(StringMapTest, CtorArg) { +  StringRef Key = "Test"; +  StringMapEntry<MoveOnly>::Create(Key, Immovable()) +      ->Destroy(); +} +  TEST_F(StringMapTest, MoveConstruct) {    StringMap<int> A; -  A.GetOrCreateValue("x", 42); +  A["x"] = 42;    StringMap<int> B = std::move(A);    ASSERT_EQ(A.size(), 0u);    ASSERT_EQ(B.size(), 1u); @@ -325,7 +337,7 @@ struct Countable {  TEST_F(StringMapTest, MoveDtor) {    int InstanceCount = 0;    StringMap<Countable> A; -  A.GetOrCreateValue("x", Countable(42, InstanceCount)); +  A.insert(std::make_pair("x", Countable(42, InstanceCount)));    ASSERT_EQ(InstanceCount, 1);    auto I = A.find("x");    ASSERT_NE(I, A.end()); diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index 2e9d585..cacbde6 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -129,6 +129,36 @@ TEST(TripleTest, ParsedIDs) {    EXPECT_EQ(Triple::UnknownOS, T.getOS());    EXPECT_EQ(Triple::EABI, T.getEnvironment()); +  T = Triple("amdil-unknown-unknown"); +  EXPECT_EQ(Triple::amdil, T.getArch()); +  EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); +  EXPECT_EQ(Triple::UnknownOS, T.getOS()); + +  T = Triple("amdil64-unknown-unknown"); +  EXPECT_EQ(Triple::amdil64, T.getArch()); +  EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); +  EXPECT_EQ(Triple::UnknownOS, T.getOS()); + +  T = Triple("hsail-unknown-unknown"); +  EXPECT_EQ(Triple::hsail, T.getArch()); +  EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); +  EXPECT_EQ(Triple::UnknownOS, T.getOS()); + +  T = Triple("hsail64-unknown-unknown"); +  EXPECT_EQ(Triple::hsail64, T.getArch()); +  EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); +  EXPECT_EQ(Triple::UnknownOS, T.getOS()); + +  T = Triple("spir-unknown-unknown"); +  EXPECT_EQ(Triple::spir, T.getArch()); +  EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); +  EXPECT_EQ(Triple::UnknownOS, T.getOS()); + +  T = Triple("spir64-unknown-unknown"); +  EXPECT_EQ(Triple::spir64, T.getArch()); +  EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); +  EXPECT_EQ(Triple::UnknownOS, T.getOS()); +    T = Triple("huh");    EXPECT_EQ(Triple::UnknownArch, T.getArch());  } @@ -190,7 +220,7 @@ TEST(TripleTest, Normalization) {           ++Vendor) {        C[1] = Triple::getVendorTypeName(Triple::VendorType(Vendor));        for (int OS = 1+Triple::UnknownOS; OS <= Triple::Minix; ++OS) { -        if (OS == Triple::Cygwin || OS == Triple::MinGW32 || OS == Triple::Win32) +        if (OS == Triple::Win32)            continue;          C[2] = Triple::getOSTypeName(Triple::OSType(OS)); @@ -341,6 +371,36 @@ TEST(TripleTest, BitWidthPredicates) {    EXPECT_FALSE(T.isArch16Bit());    EXPECT_FALSE(T.isArch32Bit());    EXPECT_TRUE(T.isArch64Bit()); + +  T.setArch(Triple::amdil); +  EXPECT_FALSE(T.isArch16Bit()); +  EXPECT_TRUE(T.isArch32Bit()); +  EXPECT_FALSE(T.isArch64Bit()); + +  T.setArch(Triple::amdil64); +  EXPECT_FALSE(T.isArch16Bit()); +  EXPECT_FALSE(T.isArch32Bit()); +  EXPECT_TRUE(T.isArch64Bit()); + +  T.setArch(Triple::hsail); +  EXPECT_FALSE(T.isArch16Bit()); +  EXPECT_TRUE(T.isArch32Bit()); +  EXPECT_FALSE(T.isArch64Bit()); + +  T.setArch(Triple::hsail64); +  EXPECT_FALSE(T.isArch16Bit()); +  EXPECT_FALSE(T.isArch32Bit()); +  EXPECT_TRUE(T.isArch64Bit()); + +  T.setArch(Triple::spir); +  EXPECT_FALSE(T.isArch16Bit()); +  EXPECT_TRUE(T.isArch32Bit()); +  EXPECT_FALSE(T.isArch64Bit()); + +  T.setArch(Triple::spir64); +  EXPECT_FALSE(T.isArch16Bit()); +  EXPECT_FALSE(T.isArch32Bit()); +  EXPECT_TRUE(T.isArch64Bit());  }  TEST(TripleTest, BitWidthArchVariants) { @@ -399,6 +459,30 @@ TEST(TripleTest, BitWidthArchVariants) {    T.setArch(Triple::x86_64);    EXPECT_EQ(Triple::x86, T.get32BitArchVariant().getArch());    EXPECT_EQ(Triple::x86_64, T.get64BitArchVariant().getArch()); + +  T.setArch(Triple::amdil); +  EXPECT_EQ(Triple::amdil, T.get32BitArchVariant().getArch()); +  EXPECT_EQ(Triple::amdil64, T.get64BitArchVariant().getArch()); + +  T.setArch(Triple::amdil64); +  EXPECT_EQ(Triple::amdil, T.get32BitArchVariant().getArch()); +  EXPECT_EQ(Triple::amdil64, T.get64BitArchVariant().getArch()); + +  T.setArch(Triple::hsail); +  EXPECT_EQ(Triple::hsail, T.get32BitArchVariant().getArch()); +  EXPECT_EQ(Triple::hsail64, T.get64BitArchVariant().getArch()); + +  T.setArch(Triple::hsail64); +  EXPECT_EQ(Triple::hsail, T.get32BitArchVariant().getArch()); +  EXPECT_EQ(Triple::hsail64, T.get64BitArchVariant().getArch()); + +  T.setArch(Triple::spir); +  EXPECT_EQ(Triple::spir, T.get32BitArchVariant().getArch()); +  EXPECT_EQ(Triple::spir64, T.get64BitArchVariant().getArch()); + +  T.setArch(Triple::spir64); +  EXPECT_EQ(Triple::spir, T.get32BitArchVariant().getArch()); +  EXPECT_EQ(Triple::spir64, T.get64BitArchVariant().getArch());  }  TEST(TripleTest, getOSVersion) { @@ -564,4 +648,20 @@ TEST(TripleTest, NormalizeWindows) {    EXPECT_EQ("i686-pc-windows-elf", Triple::normalize("i686-pc-windows-elf-elf"));  } + +TEST(TripleTest, getARMCPUForArch) { +  { +    llvm::Triple Triple("armv6-unknown-freebsd"); +    EXPECT_STREQ("arm1176jzf-s", Triple.getARMCPUForArch()); +  } +  { +    llvm::Triple Triple("armv7s-apple-ios7"); +    EXPECT_STREQ("swift", Triple.getARMCPUForArch()); +  } +  { +    llvm::Triple Triple("armv7-apple-ios7"); +    EXPECT_STREQ("cortex-a8", Triple.getARMCPUForArch()); +    EXPECT_STREQ("swift", Triple.getARMCPUForArch("armv7s")); +  } +}  } diff --git a/unittests/Analysis/CFGTest.cpp b/unittests/Analysis/CFGTest.cpp index ac5e710..dba9d49 100644 --- a/unittests/Analysis/CFGTest.cpp +++ b/unittests/Analysis/CFGTest.cpp @@ -30,20 +30,16 @@ namespace {  class IsPotentiallyReachableTest : public testing::Test {  protected:    void ParseAssembly(const char *Assembly) { -    M.reset(new Module("Module", getGlobalContext())); -      SMDiagnostic Error; -    bool Parsed = ParseAssemblyString(Assembly, M.get(), -                                      Error, M->getContext()) == M.get(); +    M = parseAssemblyString(Assembly, Error, getGlobalContext());      std::string errMsg;      raw_string_ostream os(errMsg);      Error.print("", os); -    if (!Parsed) { -      // A failure here means that the test itself is buggy. +    // A failure here means that the test itself is buggy. +    if (!M)        report_fatal_error(os.str().c_str()); -    }      Function *F = M->getFunction("test");      if (F == nullptr) diff --git a/unittests/Analysis/CMakeLists.txt b/unittests/Analysis/CMakeLists.txt index 8454860..baf0c28 100644 --- a/unittests/Analysis/CMakeLists.txt +++ b/unittests/Analysis/CMakeLists.txt @@ -1,4 +1,5 @@  set(LLVM_LINK_COMPONENTS +  IPA    Analysis    AsmParser    Core @@ -6,6 +7,7 @@ set(LLVM_LINK_COMPONENTS    )  add_llvm_unittest(AnalysisTests +  CallGraphTest.cpp    CFGTest.cpp    LazyCallGraphTest.cpp    ScalarEvolutionTest.cpp diff --git a/unittests/Analysis/CallGraphTest.cpp b/unittests/Analysis/CallGraphTest.cpp new file mode 100644 index 0000000..777907a --- /dev/null +++ b/unittests/Analysis/CallGraphTest.cpp @@ -0,0 +1,59 @@ +//=======- CallGraphTest.cpp - Unit tests for the CG analysis -------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/CallGraph.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +template <typename Ty> void canSpecializeGraphTraitsIterators(Ty *G) { +  typedef typename GraphTraits<Ty *>::NodeType NodeTy; + +  auto I = GraphTraits<Ty *>::nodes_begin(G); +  auto E = GraphTraits<Ty *>::nodes_end(G); +  auto X = ++I; + +  // Should be able to iterate over all nodes of the graph. +  static_assert(std::is_same<decltype(*I), NodeTy &>::value, +                "Node type does not match"); +  static_assert(std::is_same<decltype(*X), NodeTy &>::value, +                "Node type does not match"); +  static_assert(std::is_same<decltype(*E), NodeTy &>::value, +                "Node type does not match"); + +  NodeTy *N = GraphTraits<Ty *>::getEntryNode(G); + +  auto S = GraphTraits<NodeTy *>::child_begin(N); +  auto F = GraphTraits<NodeTy *>::child_end(N); + +  // Should be able to iterate over immediate successors of a node. +  static_assert(std::is_same<decltype(*S), NodeTy *>::value, +                "Node type does not match"); +  static_assert(std::is_same<decltype(*F), NodeTy *>::value, +                "Node type does not match"); +} + +TEST(CallGraphTest, GraphTraitsSpecialization) { +  Module M("", getGlobalContext()); +  CallGraph CG(M); + +  canSpecializeGraphTraitsIterators(&CG); +} + +TEST(CallGraphTest, GraphTraitsConstSpecialization) { +  Module M("", getGlobalContext()); +  CallGraph CG(M); + +  canSpecializeGraphTraitsIterators(const_cast<const CallGraph *>(&CG)); +} +} diff --git a/unittests/Analysis/LazyCallGraphTest.cpp b/unittests/Analysis/LazyCallGraphTest.cpp index d7c7045..6caccb8 100644 --- a/unittests/Analysis/LazyCallGraphTest.cpp +++ b/unittests/Analysis/LazyCallGraphTest.cpp @@ -22,38 +22,38 @@ using namespace llvm;  namespace {  std::unique_ptr<Module> parseAssembly(const char *Assembly) { -  auto M = make_unique<Module>("Module", getGlobalContext()); -    SMDiagnostic Error; -  bool Parsed = -      ParseAssemblyString(Assembly, M.get(), Error, M->getContext()) == M.get(); +  std::unique_ptr<Module> M = +      parseAssemblyString(Assembly, Error, getGlobalContext());    std::string ErrMsg;    raw_string_ostream OS(ErrMsg);    Error.print("", OS);    // A failure here means that the test itself is buggy. -  if (!Parsed) +  if (!M)      report_fatal_error(OS.str().c_str());    return M;  } -// IR forming a call graph with a diamond of triangle-shaped SCCs: -// -//         d1 -//        /  \ -//       d3--d2 -//      /     \ -//     b1     c1 -//   /  \    /  \ -//  b3--b2  c3--c2 -//       \  / -//        a1 -//       /  \ -//      a3--a2 -// -// All call edges go up between SCCs, and clockwise around the SCC. +/* +   IR forming a call graph with a diamond of triangle-shaped SCCs: + +           d1 +          /  \ +         d3--d2 +        /     \ +       b1     c1 +     /  \    /  \ +    b3--b2  c3--c2 +         \  / +          a1 +         /  \ +        a3--a2 + +   All call edges go up between SCCs, and clockwise around the SCC. + */  static const char DiamondOfTriangles[] =       "define void @a1() {\n"       "entry:\n" diff --git a/unittests/Analysis/Makefile b/unittests/Analysis/Makefile index 527f452..52296e7 100644 --- a/unittests/Analysis/Makefile +++ b/unittests/Analysis/Makefile @@ -9,7 +9,7 @@  LEVEL = ../..  TESTNAME = Analysis -LINK_COMPONENTS := analysis asmparser +LINK_COMPONENTS := ipa analysis asmparser  include $(LEVEL)/Makefile.config  include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Analysis/MixedTBAATest.cpp b/unittests/Analysis/MixedTBAATest.cpp index 142e047..d7935e3 100644 --- a/unittests/Analysis/MixedTBAATest.cpp +++ b/unittests/Analysis/MixedTBAATest.cpp @@ -65,7 +65,7 @@ TEST_F(MixedTBAATest, MixedTBAA) {    // Run the TBAA eval pass on a mixture of path-aware and non-path-aware TBAA.    // The order of the metadata (path-aware vs non-path-aware) is important,    // because the AA eval pass only runs one test per store-pair. -  const char* args[] = { "MixedTBAATest", "-evaluate-tbaa" }; +  const char* args[] = { "MixedTBAATest", "-evaluate-aa-metadata" };    cl::ParseCommandLineOptions(sizeof(args) / sizeof(const char*), args);    PM.add(createTypeBasedAliasAnalysisPass());    PM.add(createAAEvalPass()); diff --git a/unittests/Bitcode/BitReaderTest.cpp b/unittests/Bitcode/BitReaderTest.cpp index b6a3e9a..6eb40d6 100644 --- a/unittests/Bitcode/BitReaderTest.cpp +++ b/unittests/Bitcode/BitReaderTest.cpp @@ -10,58 +10,158 @@  #include "llvm/ADT/SmallString.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"  #include "llvm/IR/Module.h"  #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" +#include "llvm/Support/Debug.h"  #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h"  #include "gtest/gtest.h" -namespace llvm { -namespace { - -static Module *makeLLVMModule() { -  Module* Mod = new Module("test-mem", getGlobalContext()); +using namespace llvm; -  FunctionType* FuncTy = -    FunctionType::get(Type::getVoidTy(Mod->getContext()), false); -  Function* Func = Function::Create(FuncTy,GlobalValue::ExternalLinkage, -                                    "func", Mod); +namespace { -  BasicBlock* Entry = BasicBlock::Create(Mod->getContext(), "entry", Func); -  new UnreachableInst(Mod->getContext(), Entry); +std::unique_ptr<Module> parseAssembly(const char *Assembly) { +  SMDiagnostic Error; +  std::unique_ptr<Module> M = +      parseAssemblyString(Assembly, Error, getGlobalContext()); -  BasicBlock* BB = BasicBlock::Create(Mod->getContext(), "bb", Func); -  new UnreachableInst(Mod->getContext(), BB); +  std::string ErrMsg; +  raw_string_ostream OS(ErrMsg); +  Error.print("", OS); -  PointerType* Int8Ptr = Type::getInt8PtrTy(Mod->getContext()); -  new GlobalVariable(*Mod, Int8Ptr, /*isConstant=*/true, -                     GlobalValue::ExternalLinkage, -                     BlockAddress::get(BB), "table"); +  // A failure here means that the test itself is buggy. +  if (!M) +    report_fatal_error(OS.str().c_str()); -  return Mod; +  return M;  } -static void writeModuleToBuffer(SmallVectorImpl<char> &Buffer) { -  std::unique_ptr<Module> Mod(makeLLVMModule()); +static void writeModuleToBuffer(std::unique_ptr<Module> Mod, +                                SmallVectorImpl<char> &Buffer) {    raw_svector_ostream OS(Buffer);    WriteBitcodeToFile(Mod.get(), OS);  } +static std::unique_ptr<Module> getLazyModuleFromAssembly(LLVMContext &Context, +                                                         SmallString<1024> &Mem, +                                                         const char *Assembly) { +  writeModuleToBuffer(parseAssembly(Assembly), Mem); +  std::unique_ptr<MemoryBuffer> Buffer = +      MemoryBuffer::getMemBuffer(Mem.str(), "test", false); +  ErrorOr<Module *> ModuleOrErr = +      getLazyBitcodeModule(std::move(Buffer), Context); +  return std::unique_ptr<Module>(ModuleOrErr.get()); +} + +TEST(BitReaderTest, DematerializeFunctionPreservesLinkageType) { +  SmallString<1024> Mem; + +  LLVMContext Context; +  std::unique_ptr<Module> M = getLazyModuleFromAssembly( +      Context, Mem, "define internal i32 @func() {\n" +                      "ret i32 0\n" +                    "}\n"); + +  EXPECT_FALSE(verifyModule(*M, &dbgs())); + +  M->getFunction("func")->materialize(); +  EXPECT_FALSE(M->getFunction("func")->empty()); +  EXPECT_TRUE(M->getFunction("func")->getLinkage() == +              GlobalValue::InternalLinkage); + +  // Check that the linkage type is preserved after dematerialization. +  M->getFunction("func")->Dematerialize(); +  EXPECT_TRUE(M->getFunction("func")->empty()); +  EXPECT_TRUE(M->getFunction("func")->getLinkage() == +              GlobalValue::InternalLinkage); +  EXPECT_FALSE(verifyModule(*M, &dbgs())); +} +  TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677    SmallString<1024> Mem; -  writeModuleToBuffer(Mem); -  MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(Mem.str(), "test", false); -  ErrorOr<Module *> ModuleOrErr = -      getLazyBitcodeModule(Buffer, getGlobalContext()); -  std::unique_ptr<Module> m(ModuleOrErr.get()); -  PassManager passes; -  passes.add(createVerifierPass()); -  passes.add(createDebugInfoVerifierPass()); -  passes.run(*m); + +  LLVMContext Context; +  std::unique_ptr<Module> M = getLazyModuleFromAssembly( +      Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n" +                    "define void @func() {\n" +                    "  unreachable\n" +                    "bb:\n" +                    "  unreachable\n" +                    "}\n"); +  EXPECT_FALSE(verifyModule(*M, &dbgs())); + +  // Try (and fail) to dematerialize @func. +  M->getFunction("func")->Dematerialize(); +  EXPECT_FALSE(M->getFunction("func")->empty());  } +TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) { +  SmallString<1024> Mem; + +  LLVMContext Context; +  std::unique_ptr<Module> M = getLazyModuleFromAssembly( +      Context, Mem, "define i8* @before() {\n" +                    "  ret i8* blockaddress(@func, %bb)\n" +                    "}\n" +                    "define void @other() {\n" +                    "  unreachable\n" +                    "}\n" +                    "define void @func() {\n" +                    "  unreachable\n" +                    "bb:\n" +                    "  unreachable\n" +                    "}\n"); +  EXPECT_TRUE(M->getFunction("before")->empty()); +  EXPECT_TRUE(M->getFunction("func")->empty()); +  EXPECT_FALSE(verifyModule(*M, &dbgs())); + +  // Materialize @before, pulling in @func. +  EXPECT_FALSE(M->getFunction("before")->materialize()); +  EXPECT_FALSE(M->getFunction("func")->empty()); +  EXPECT_TRUE(M->getFunction("other")->empty()); +  EXPECT_FALSE(verifyModule(*M, &dbgs())); + +  // Try (and fail) to dematerialize @func. +  M->getFunction("func")->Dematerialize(); +  EXPECT_FALSE(M->getFunction("func")->empty()); +  EXPECT_FALSE(verifyModule(*M, &dbgs()));  } + +TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) { +  SmallString<1024> Mem; + +  LLVMContext Context; +  std::unique_ptr<Module> M = getLazyModuleFromAssembly( +      Context, Mem, "define void @func() {\n" +                    "  unreachable\n" +                    "bb:\n" +                    "  unreachable\n" +                    "}\n" +                    "define void @other() {\n" +                    "  unreachable\n" +                    "}\n" +                    "define i8* @after() {\n" +                    "  ret i8* blockaddress(@func, %bb)\n" +                    "}\n"); +  EXPECT_TRUE(M->getFunction("after")->empty()); +  EXPECT_TRUE(M->getFunction("func")->empty()); +  EXPECT_FALSE(verifyModule(*M, &dbgs())); + +  // Materialize @after, pulling in @func. +  EXPECT_FALSE(M->getFunction("after")->materialize()); +  EXPECT_FALSE(M->getFunction("func")->empty()); +  EXPECT_TRUE(M->getFunction("other")->empty()); +  EXPECT_FALSE(verifyModule(*M, &dbgs())); + +  // Try (and fail) to dematerialize @func. +  M->getFunction("func")->Dematerialize(); +  EXPECT_FALSE(M->getFunction("func")->empty()); +  EXPECT_FALSE(verifyModule(*M, &dbgs()));  } + +} // end namespace diff --git a/unittests/Bitcode/BitstreamReaderTest.cpp b/unittests/Bitcode/BitstreamReaderTest.cpp new file mode 100644 index 0000000..b11d7fd --- /dev/null +++ b/unittests/Bitcode/BitstreamReaderTest.cpp @@ -0,0 +1,56 @@ +//===- BitstreamReaderTest.cpp - Tests for BitstreamReader ----------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/BitstreamReader.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(BitstreamReaderTest, AtEndOfStream) { +  uint8_t Bytes[4] = { +    0x00, 0x01, 0x02, 0x03 +  }; +  BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); +  BitstreamCursor Cursor(Reader); + +  EXPECT_FALSE(Cursor.AtEndOfStream()); +  (void)Cursor.Read(8); +  EXPECT_FALSE(Cursor.AtEndOfStream()); +  (void)Cursor.Read(24); +  EXPECT_TRUE(Cursor.AtEndOfStream()); + +  Cursor.JumpToBit(0); +  EXPECT_FALSE(Cursor.AtEndOfStream()); + +  Cursor.JumpToBit(32); +  EXPECT_TRUE(Cursor.AtEndOfStream()); +} + +TEST(BitstreamReaderTest, AtEndOfStreamJump) { +  uint8_t Bytes[4] = { +    0x00, 0x01, 0x02, 0x03 +  }; +  BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); +  BitstreamCursor Cursor(Reader); + +  Cursor.JumpToBit(32); +  EXPECT_TRUE(Cursor.AtEndOfStream()); +} + +TEST(BitstreamReaderTest, AtEndOfStreamEmpty) { +  uint8_t Dummy = 0xFF; +  BitstreamReader Reader(&Dummy, &Dummy); +  BitstreamCursor Cursor(Reader); + +  EXPECT_TRUE(Cursor.AtEndOfStream()); +} + +} // end anonymous namespace diff --git a/unittests/Bitcode/CMakeLists.txt b/unittests/Bitcode/CMakeLists.txt index 743ab18..09cbcdc 100644 --- a/unittests/Bitcode/CMakeLists.txt +++ b/unittests/Bitcode/CMakeLists.txt @@ -1,4 +1,5 @@  set(LLVM_LINK_COMPONENTS +  AsmParser    BitReader    BitWriter    Core @@ -7,4 +8,5 @@ set(LLVM_LINK_COMPONENTS  add_llvm_unittest(BitcodeTests    BitReaderTest.cpp +  BitstreamReaderTest.cpp    ) diff --git a/unittests/Bitcode/Makefile b/unittests/Bitcode/Makefile index fcec879..33b09b9 100644 --- a/unittests/Bitcode/Makefile +++ b/unittests/Bitcode/Makefile @@ -9,7 +9,7 @@  LEVEL = ../..  TESTNAME = Bitcode -LINK_COMPONENTS := bitreader bitwriter +LINK_COMPONENTS := AsmParser BitReader BitWriter Core Support  include $(LEVEL)/Makefile.config  include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/ExecutionEngine/CMakeLists.txt b/unittests/ExecutionEngine/CMakeLists.txt index 489eaaf..783c9b5 100644 --- a/unittests/ExecutionEngine/CMakeLists.txt +++ b/unittests/ExecutionEngine/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS    Core    ExecutionEngine    Interpreter +  MC    Support    ) @@ -9,10 +10,9 @@ add_llvm_unittest(ExecutionEngineTests    ExecutionEngineTest.cpp    ) -# Include JIT/MCJIT tests only if native arch is a built JIT target. +# 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)  if (NOT build_idx LESS 0 AND NOT jit_idx LESS 0) -  add_subdirectory(JIT)    add_subdirectory(MCJIT)  endif() diff --git a/unittests/ExecutionEngine/ExecutionEngineTest.cpp b/unittests/ExecutionEngine/ExecutionEngineTest.cpp index f23745c..19917a4 100644 --- a/unittests/ExecutionEngine/ExecutionEngineTest.cpp +++ b/unittests/ExecutionEngine/ExecutionEngineTest.cpp @@ -8,10 +8,13 @@  //===----------------------------------------------------------------------===//  #include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"  #include "llvm/IR/DerivedTypes.h"  #include "llvm/IR/GlobalVariable.h"  #include "llvm/IR/LLVMContext.h"  #include "llvm/IR/Module.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/ManagedStatic.h"  #include "gtest/gtest.h"  using namespace llvm; @@ -19,10 +22,14 @@ using namespace llvm;  namespace {  class ExecutionEngineTest : public testing::Test { +private: +  llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. +  protected: -  ExecutionEngineTest() -    : M(new Module("<main>", getGlobalContext())), Error(""), -      Engine(EngineBuilder(M).setErrorStr(&Error).create()) { +  ExecutionEngineTest() { +    auto Owner = make_unique<Module>("<main>", getGlobalContext()); +    M = Owner.get(); +    Engine.reset(EngineBuilder(std::move(Owner)).setErrorStr(&Error).create());    }    virtual void SetUp() { @@ -35,9 +42,9 @@ protected:                                GlobalValue::ExternalLinkage, nullptr, Name);    } -  Module *const M;    std::string Error; -  const std::unique_ptr<ExecutionEngine> Engine; +  Module *M;  // Owned by ExecutionEngine. +  std::unique_ptr<ExecutionEngine> Engine;  };  TEST_F(ExecutionEngineTest, ForwardGlobalMapping) { @@ -127,4 +134,35 @@ TEST_F(ExecutionEngineTest, DestructionRemovesGlobalMapping) {    EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));  } +TEST_F(ExecutionEngineTest, LookupWithMangledName) { +  int x; +  llvm::sys::DynamicLibrary::AddSymbol("x", &x); + +  // Demonstrate that getSymbolAddress accepts mangled names and always strips +  // the leading underscore. +  EXPECT_EQ(reinterpret_cast<uint64_t>(&x), +            RTDyldMemoryManager::getSymbolAddressInProcess("_x")); +} + +TEST_F(ExecutionEngineTest, LookupWithMangledAndDemangledSymbol) { +  int x; +  int _x; +  llvm::sys::DynamicLibrary::AddSymbol("x", &x); +  llvm::sys::DynamicLibrary::AddSymbol("_x", &_x); + +  // Lookup the demangled name first, even if there's a demangled symbol that +  // matches the input already. +  EXPECT_EQ(reinterpret_cast<uint64_t>(&x), +            RTDyldMemoryManager::getSymbolAddressInProcess("_x")); +} + +TEST_F(ExecutionEngineTest, LookupwithDemangledName) { +  int _x; +  llvm::sys::DynamicLibrary::AddSymbol("_x", &_x); + +  // But do fallback to looking up a demangled name if there's no ambiguity +  EXPECT_EQ(reinterpret_cast<uint64_t>(&_x), +            RTDyldMemoryManager::getSymbolAddressInProcess("_x")); +} +  } diff --git a/unittests/ExecutionEngine/JIT/CMakeLists.txt b/unittests/ExecutionEngine/JIT/CMakeLists.txt deleted file mode 100644 index 72c1df7..0000000 --- a/unittests/ExecutionEngine/JIT/CMakeLists.txt +++ /dev/null @@ -1,64 +0,0 @@ -set(LLVM_LINK_COMPONENTS -  AsmParser -  BitReader -  BitWriter -  Core -  ExecutionEngine -  JIT -  Support -  nativecodegen -  ) - -# HACK: Declare a couple of source files as optionally compiled to satisfy the -# missing-file-checker in LLVM's weird CMake build. -set(LLVM_OPTIONAL_SOURCES -  IntelJITEventListenerTest.cpp -  OProfileJITEventListenerTest.cpp -  ) - -if( LLVM_USE_INTEL_JITEVENTS ) -  set(ProfileTestSources -    IntelJITEventListenerTest.cpp -    ) -  set(LLVM_LINK_COMPONENTS -    ${LLVM_LINK_COMPONENTS} -    DebugInfo -    IntelJITEvents -    Object -    )  -endif( LLVM_USE_INTEL_JITEVENTS ) - -if( LLVM_USE_OPROFILE ) -  set(ProfileTestSources -    ${ProfileTestSources} -    OProfileJITEventListenerTest.cpp -    ) -  set(LLVM_LINK_COMPONENTS -    ${LLVM_LINK_COMPONENTS} -    OProfileJIT -    ) -endif( LLVM_USE_OPROFILE ) - -set(JITTestsSources -  JITEventListenerTest.cpp -  JITMemoryManagerTest.cpp -  JITTest.cpp -  MultiJITTest.cpp -  ${ProfileTestSources} -  ) - -if(MSVC) -  list(APPEND JITTestsSources JITTests.def) -endif() - -# The JIT tests need to dlopen things. -set(LLVM_NO_DEAD_STRIP 1) - -add_llvm_unittest(JITTests -  ${JITTestsSources} -  ) - -if(MINGW OR CYGWIN) -  set_property(TARGET JITTests PROPERTY LINK_FLAGS -Wl,--export-all-symbols) -endif() -set_target_properties(JITTests PROPERTIES ENABLE_EXPORTS 1) diff --git a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp deleted file mode 100644 index db90887..0000000 --- a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp +++ /dev/null @@ -1,113 +0,0 @@ -//===- JITEventListenerTest.cpp - Tests for Intel JITEventListener --------===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "JITEventListenerTestCommon.h" - -using namespace llvm; - -// Because we want to keep the implementation details of the Intel API used to -// communicate with Amplifier out of the public header files, the header below -// is included from the source tree instead. -#include "../../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h" - -#include <map> -#include <list> - -namespace { - -// map of function ("method") IDs to source locations -NativeCodeMap ReportedDebugFuncs; - -} // namespace - -/// Mock implementaion of Intel JIT API jitprofiling library -namespace test_jitprofiling { - -int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) { -  switch (EventType) { -    case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: { -      EXPECT_TRUE(0 != EventSpecificData); -      iJIT_Method_Load* msg = static_cast<iJIT_Method_Load*>(EventSpecificData); - -      ReportedDebugFuncs[msg->method_id]; - -      for(unsigned int i = 0; i < msg->line_number_size; ++i) { -        EXPECT_TRUE(0 != msg->line_number_table); -        std::pair<std::string, unsigned int> loc( -          std::string(msg->source_file_name), -          msg->line_number_table[i].LineNumber); -        ReportedDebugFuncs[msg->method_id].push_back(loc); -      } -    } -    break; -    case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: { -      EXPECT_TRUE(0 != EventSpecificData); -      unsigned int UnloadId -        = *reinterpret_cast<unsigned int*>(EventSpecificData); -      EXPECT_TRUE(1 == ReportedDebugFuncs.erase(UnloadId)); -    } -    default: -      break; -  } -  return 0; -} - -iJIT_IsProfilingActiveFlags IsProfilingActive(void) { -  // for testing, pretend we have an Intel Parallel Amplifier XE 2011 -  // instance attached -  return iJIT_SAMPLING_ON; -} - -unsigned int GetNewMethodID(void) { -  static unsigned int id = 0; -  return ++id; -} - -} //namespace test_jitprofiling - -class IntelJITEventListenerTest -  : public JITEventListenerTestBase<IntelJITEventsWrapper> { -public: -  IntelJITEventListenerTest() -  : JITEventListenerTestBase<IntelJITEventsWrapper>( -      new IntelJITEventsWrapper(test_jitprofiling::NotifyEvent, 0, -        test_jitprofiling::IsProfilingActive, 0, 0, -        test_jitprofiling::GetNewMethodID)) -  { -    EXPECT_TRUE(0 != MockWrapper); - -    Listener.reset(JITEventListener::createIntelJITEventListener( -      MockWrapper.release())); -    EXPECT_TRUE(0 != Listener); -    EE->RegisterJITEventListener(Listener.get()); -  } -}; - -TEST_F(IntelJITEventListenerTest, NoDebugInfo) { -  TestNoDebugInfo(ReportedDebugFuncs); -} - -TEST_F(IntelJITEventListenerTest, SingleLine) { -  TestSingleLine(ReportedDebugFuncs); -} - -TEST_F(IntelJITEventListenerTest, MultipleLines) { -  TestMultipleLines(ReportedDebugFuncs); -} - -// This testcase is disabled because the Intel JIT API does not support a single -// JITted function with source lines associated with multiple files -/* -TEST_F(IntelJITEventListenerTest, MultipleFiles) { -  TestMultipleFiles(ReportedDebugFuncs); -} -*/ - -testing::Environment* const jit_env = -  testing::AddGlobalTestEnvironment(new JITEnvironment); diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp deleted file mode 100644 index 175b9fb..0000000 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp +++ /dev/null @@ -1,237 +0,0 @@ -//===- JITEventListenerTest.cpp - Unit tests for JITEventListeners --------===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/CodeGen/MachineCodeInfo.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/TypeBuilder.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" -#include <vector> - -using namespace llvm; - -namespace { - -struct FunctionEmittedEvent { -  // Indices are local to the RecordingJITEventListener, since the -  // JITEventListener interface makes no guarantees about the order of -  // calls between Listeners. -  unsigned Index; -  const Function *F; -  void *Code; -  size_t Size; -  JITEvent_EmittedFunctionDetails Details; -}; -struct FunctionFreedEvent { -  unsigned Index; -  void *Code; -}; - -struct RecordingJITEventListener : public JITEventListener { -  std::vector<FunctionEmittedEvent> EmittedEvents; -  std::vector<FunctionFreedEvent> FreedEvents; - -  unsigned NextIndex; - -  RecordingJITEventListener() : NextIndex(0) {} - -  virtual void NotifyFunctionEmitted(const Function &F, -                                     void *Code, size_t Size, -                                     const EmittedFunctionDetails &Details) { -    FunctionEmittedEvent Event = {NextIndex++, &F, Code, Size, Details}; -    EmittedEvents.push_back(Event); -  } - -  virtual void NotifyFreeingMachineCode(void *OldPtr) { -    FunctionFreedEvent Event = {NextIndex++, OldPtr}; -    FreedEvents.push_back(Event); -  } -}; - -class JITEventListenerTest : public testing::Test { - protected: -  JITEventListenerTest() -      : M(new Module("module", getGlobalContext())), -        EE(EngineBuilder(M) -           .setEngineKind(EngineKind::JIT) -           .create()) { -  } - -  Module *M; -  const std::unique_ptr<ExecutionEngine> EE; -}; - -// Tests on SystemZ disabled as we're running the old JIT -#if !defined(__s390__) && !defined(__aarch64__) -Function *buildFunction(Module *M) { -  Function *Result = Function::Create( -      TypeBuilder<int32_t(int32_t), false>::get(getGlobalContext()), -      GlobalValue::ExternalLinkage, "id", M); -  Value *Arg = Result->arg_begin(); -  BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result); -  ReturnInst::Create(M->getContext(), Arg, BB); -  return Result; -} - -// Tests that a single JITEventListener follows JIT events accurately. -TEST_F(JITEventListenerTest, Simple) { -  RecordingJITEventListener Listener; -  EE->RegisterJITEventListener(&Listener); -  Function *F1 = buildFunction(M); -  Function *F2 = buildFunction(M); - -  void *F1_addr = EE->getPointerToFunction(F1); -  void *F2_addr = EE->getPointerToFunction(F2); -  EE->getPointerToFunction(F1);  // Should do nothing. -  EE->freeMachineCodeForFunction(F1); -  EE->freeMachineCodeForFunction(F2); - -  ASSERT_EQ(2U, Listener.EmittedEvents.size()); -  ASSERT_EQ(2U, Listener.FreedEvents.size()); - -  EXPECT_EQ(0U, Listener.EmittedEvents[0].Index); -  EXPECT_EQ(F1, Listener.EmittedEvents[0].F); -  EXPECT_EQ(F1_addr, Listener.EmittedEvents[0].Code); -  EXPECT_LT(0U, Listener.EmittedEvents[0].Size) -      << "We don't know how big the function will be, but it had better" -      << " contain some bytes."; - -  EXPECT_EQ(1U, Listener.EmittedEvents[1].Index); -  EXPECT_EQ(F2, Listener.EmittedEvents[1].F); -  EXPECT_EQ(F2_addr, Listener.EmittedEvents[1].Code); -  EXPECT_LT(0U, Listener.EmittedEvents[1].Size) -      << "We don't know how big the function will be, but it had better" -      << " contain some bytes."; - -  EXPECT_EQ(2U, Listener.FreedEvents[0].Index); -  EXPECT_EQ(F1_addr, Listener.FreedEvents[0].Code); - -  EXPECT_EQ(3U, Listener.FreedEvents[1].Index); -  EXPECT_EQ(F2_addr, Listener.FreedEvents[1].Code); - -  F1->eraseFromParent(); -  F2->eraseFromParent(); -} - -// Tests that a single JITEventListener follows JIT events accurately. -TEST_F(JITEventListenerTest, MultipleListenersDontInterfere) { -  RecordingJITEventListener Listener1; -  RecordingJITEventListener Listener2; -  RecordingJITEventListener Listener3; -  Function *F1 = buildFunction(M); -  Function *F2 = buildFunction(M); - -  EE->RegisterJITEventListener(&Listener1); -  EE->RegisterJITEventListener(&Listener2); -  void *F1_addr = EE->getPointerToFunction(F1); -  EE->RegisterJITEventListener(&Listener3); -  EE->UnregisterJITEventListener(&Listener1); -  void *F2_addr = EE->getPointerToFunction(F2); -  EE->UnregisterJITEventListener(&Listener2); -  EE->UnregisterJITEventListener(&Listener3); -  EE->freeMachineCodeForFunction(F1); -  EE->RegisterJITEventListener(&Listener2); -  EE->RegisterJITEventListener(&Listener3); -  EE->RegisterJITEventListener(&Listener1); -  EE->freeMachineCodeForFunction(F2); -  EE->UnregisterJITEventListener(&Listener1); -  EE->UnregisterJITEventListener(&Listener2); -  EE->UnregisterJITEventListener(&Listener3); - -  // Listener 1. -  ASSERT_EQ(1U, Listener1.EmittedEvents.size()); -  ASSERT_EQ(1U, Listener1.FreedEvents.size()); - -  EXPECT_EQ(0U, Listener1.EmittedEvents[0].Index); -  EXPECT_EQ(F1, Listener1.EmittedEvents[0].F); -  EXPECT_EQ(F1_addr, Listener1.EmittedEvents[0].Code); -  EXPECT_LT(0U, Listener1.EmittedEvents[0].Size) -      << "We don't know how big the function will be, but it had better" -      << " contain some bytes."; - -  EXPECT_EQ(1U, Listener1.FreedEvents[0].Index); -  EXPECT_EQ(F2_addr, Listener1.FreedEvents[0].Code); - -  // Listener 2. -  ASSERT_EQ(2U, Listener2.EmittedEvents.size()); -  ASSERT_EQ(1U, Listener2.FreedEvents.size()); - -  EXPECT_EQ(0U, Listener2.EmittedEvents[0].Index); -  EXPECT_EQ(F1, Listener2.EmittedEvents[0].F); -  EXPECT_EQ(F1_addr, Listener2.EmittedEvents[0].Code); -  EXPECT_LT(0U, Listener2.EmittedEvents[0].Size) -      << "We don't know how big the function will be, but it had better" -      << " contain some bytes."; - -  EXPECT_EQ(1U, Listener2.EmittedEvents[1].Index); -  EXPECT_EQ(F2, Listener2.EmittedEvents[1].F); -  EXPECT_EQ(F2_addr, Listener2.EmittedEvents[1].Code); -  EXPECT_LT(0U, Listener2.EmittedEvents[1].Size) -      << "We don't know how big the function will be, but it had better" -      << " contain some bytes."; - -  EXPECT_EQ(2U, Listener2.FreedEvents[0].Index); -  EXPECT_EQ(F2_addr, Listener2.FreedEvents[0].Code); - -  // Listener 3. -  ASSERT_EQ(1U, Listener3.EmittedEvents.size()); -  ASSERT_EQ(1U, Listener3.FreedEvents.size()); - -  EXPECT_EQ(0U, Listener3.EmittedEvents[0].Index); -  EXPECT_EQ(F2, Listener3.EmittedEvents[0].F); -  EXPECT_EQ(F2_addr, Listener3.EmittedEvents[0].Code); -  EXPECT_LT(0U, Listener3.EmittedEvents[0].Size) -      << "We don't know how big the function will be, but it had better" -      << " contain some bytes."; - -  EXPECT_EQ(1U, Listener3.FreedEvents[0].Index); -  EXPECT_EQ(F2_addr, Listener3.FreedEvents[0].Code); - -  F1->eraseFromParent(); -  F2->eraseFromParent(); -} - -TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) { -  RecordingJITEventListener Listener; -  MachineCodeInfo MCI; -  Function *F = buildFunction(M); - -  EE->RegisterJITEventListener(&Listener); -  EE->runJITOnFunction(F, &MCI); -  void *F_addr = EE->getPointerToFunction(F); -  EE->freeMachineCodeForFunction(F); - -  ASSERT_EQ(1U, Listener.EmittedEvents.size()); -  ASSERT_EQ(1U, Listener.FreedEvents.size()); - -  EXPECT_EQ(0U, Listener.EmittedEvents[0].Index); -  EXPECT_EQ(F, Listener.EmittedEvents[0].F); -  EXPECT_EQ(F_addr, Listener.EmittedEvents[0].Code); -  EXPECT_EQ(MCI.address(), Listener.EmittedEvents[0].Code); -  EXPECT_EQ(MCI.size(), Listener.EmittedEvents[0].Size); - -  EXPECT_EQ(1U, Listener.FreedEvents[0].Index); -  EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code); -} -#endif - -class JITEnvironment : public testing::Environment { -  virtual void SetUp() { -    // Required to create a JIT. -    InitializeNativeTarget(); -  } -}; -testing::Environment* const jit_env = -  testing::AddGlobalTestEnvironment(new JITEnvironment); - -}  // anonymous namespace diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h b/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h deleted file mode 100644 index 61220f5..0000000 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h +++ /dev/null @@ -1,207 +0,0 @@ -//===- JITEventListenerTestCommon.h - Helper for JITEventListener tests ------------===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===-------------------------------------------------------------------------------===// - -#ifndef JIT_EVENT_LISTENER_TEST_COMMON_H -#define JIT_EVENT_LISTENER_TEST_COMMON_H - -#include "llvm/CodeGen/MachineCodeInfo.h" -#include "llvm/Config/config.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/TypeBuilder.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" -#include <string> -#include <utility> -#include <vector> - -typedef std::vector<std::pair<std::string, unsigned int> > SourceLocations; -typedef std::map<uint64_t, SourceLocations> NativeCodeMap; - -class JITEnvironment : public testing::Environment { -  virtual void SetUp() { -    // Required to create a JIT. -    llvm::InitializeNativeTarget(); -  } -}; - -inline unsigned int getLine() { -  return 12; -} - -inline unsigned int getCol() { -  return 0; -} - -inline const char* getFilename() { -  return "mock_source_file.cpp"; -} - -// Test fixture shared by tests for listener implementations -template<typename WrapperT> -class JITEventListenerTestBase : public testing::Test { -protected: -  std::unique_ptr<WrapperT> MockWrapper; -  std::unique_ptr<llvm::JITEventListener> Listener; - -public: -  llvm::Module* M; -  llvm::MDNode* Scope; -  llvm::ExecutionEngine* EE; -  llvm::DIBuilder* DebugBuilder; -  llvm::IRBuilder<> Builder; - -  JITEventListenerTestBase(WrapperT* w) -  : MockWrapper(w) -  , M(new llvm::Module("module", llvm::getGlobalContext())) -  , EE(llvm::EngineBuilder(M) -    .setEngineKind(llvm::EngineKind::JIT) -    .setOptLevel(llvm::CodeGenOpt::None) -    .create()) -  , DebugBuilder(new llvm::DIBuilder(*M)) -  , Builder(llvm::getGlobalContext()) -  { -    DebugBuilder->createCompileUnit(llvm::dwarf::DW_LANG_C_plus_plus, -                                    "JIT", -                                    "JIT", -                                    "JIT", -                                    true, -                                    "", -                                    1); - -    Scope = DebugBuilder->createFile(getFilename(), "."); -  } - -  llvm::Function *buildFunction(const SourceLocations& DebugLocations) { -    using namespace llvm; - -    LLVMContext& GlobalContext = getGlobalContext(); - -    SourceLocations::const_iterator CurrentDebugLocation -      = DebugLocations.begin(); - -    if (CurrentDebugLocation != DebugLocations.end()) { -      DebugLoc DebugLocation = DebugLoc::get(getLine(), getCol(), -          DebugBuilder->createFile(CurrentDebugLocation->first, ".")); -      Builder.SetCurrentDebugLocation(DebugLocation); -      CurrentDebugLocation++; -    } - -    Function *Result = Function::Create( -        TypeBuilder<int32_t(int32_t), false>::get(GlobalContext), -        GlobalValue::ExternalLinkage, "id", M); -    Value *Arg = Result->arg_begin(); -    BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result); -    Builder.SetInsertPoint(BB); -    Value* one = ConstantInt::get(GlobalContext, APInt(32, 1)); -    for(; CurrentDebugLocation != DebugLocations.end(); -        ++CurrentDebugLocation) { -      Arg = Builder.CreateMul(Arg, Builder.CreateAdd(Arg, one)); -      Builder.SetCurrentDebugLocation( -        DebugLoc::get(CurrentDebugLocation->second, 0, -                      DebugBuilder->createFile(CurrentDebugLocation->first, "."))); -    } -    Builder.CreateRet(Arg); -    return Result; -  } - -  void TestNoDebugInfo(NativeCodeMap& ReportedDebugFuncs) { -    SourceLocations DebugLocations; -    llvm::Function* f = buildFunction(DebugLocations); -    EXPECT_TRUE(0 != f); - -    //Cause JITting and callbacks to our listener -    EXPECT_TRUE(0 != EE->getPointerToFunction(f)); -    EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - -    EE->freeMachineCodeForFunction(f); -    EXPECT_TRUE(ReportedDebugFuncs.size() == 0); -  } - -  void TestSingleLine(NativeCodeMap& ReportedDebugFuncs) { -    SourceLocations DebugLocations; -    DebugLocations.push_back(std::make_pair(std::string(getFilename()), -                                            getLine())); -    llvm::Function* f = buildFunction(DebugLocations); -    EXPECT_TRUE(0 != f); - -    EXPECT_TRUE(0 != EE->getPointerToFunction(f)); -    EXPECT_TRUE(1 == ReportedDebugFuncs.size()); -    EXPECT_STREQ(ReportedDebugFuncs.begin()->second.begin()->first.c_str(), -                 getFilename()); -    EXPECT_EQ(ReportedDebugFuncs.begin()->second.begin()->second, getLine()); - -    EE->freeMachineCodeForFunction(f); -    EXPECT_TRUE(ReportedDebugFuncs.size() == 0); -  } - -  void TestMultipleLines(NativeCodeMap& ReportedDebugFuncs) { -    using namespace std; - -    SourceLocations DebugLocations; -    unsigned int c = 5; -    for(unsigned int i = 0; i < c; ++i) { -      DebugLocations.push_back(make_pair(string(getFilename()), getLine() + i)); -    } - -    llvm::Function* f = buildFunction(DebugLocations); -    EXPECT_TRUE(0 != f); - -    EXPECT_TRUE(0 != EE->getPointerToFunction(f)); -    EXPECT_TRUE(1 == ReportedDebugFuncs.size()); -    SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second; -    EXPECT_EQ(c, FunctionInfo.size()); - -    int VerifyCount = 0; -    for(SourceLocations::iterator i = FunctionInfo.begin(); -        i != FunctionInfo.end(); -        ++i) { -      EXPECT_STREQ(i->first.c_str(), getFilename()); -      EXPECT_EQ(i->second, getLine() + VerifyCount); -      VerifyCount++; -    } - -    EE->freeMachineCodeForFunction(f); -    EXPECT_TRUE(ReportedDebugFuncs.size() == 0); -  } - -  void TestMultipleFiles(NativeCodeMap& ReportedDebugFuncs) { - -    std::string secondFilename("another_file.cpp"); - -    SourceLocations DebugLocations; -    DebugLocations.push_back(std::make_pair(std::string(getFilename()), -                                            getLine())); -    DebugLocations.push_back(std::make_pair(secondFilename, getLine())); -    llvm::Function* f = buildFunction(DebugLocations); -    EXPECT_TRUE(0 != f); - -    EXPECT_TRUE(0 != EE->getPointerToFunction(f)); -    EXPECT_TRUE(1 == ReportedDebugFuncs.size()); -    SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second; -    EXPECT_TRUE(2 == FunctionInfo.size()); - -    EXPECT_STREQ(FunctionInfo.at(0).first.c_str(), getFilename()); -    EXPECT_STREQ(FunctionInfo.at(1).first.c_str(), secondFilename.c_str()); - -    EXPECT_EQ(FunctionInfo.at(0).second, getLine()); -    EXPECT_EQ(FunctionInfo.at(1).second, getLine()); - -    EE->freeMachineCodeForFunction(f); -    EXPECT_TRUE(ReportedDebugFuncs.size() == 0); -  } -}; - -#endif //JIT_EVENT_LISTENER_TEST_COMMON_H diff --git a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp deleted file mode 100644 index 296838d..0000000 --- a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp +++ /dev/null @@ -1,302 +0,0 @@ -//===- JITMemoryManagerTest.cpp - Unit tests for the JIT memory manager ---===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/LLVMContext.h" -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -Function *makeFakeFunction() { -  std::vector<Type*> params; -  FunctionType *FTy = -      FunctionType::get(Type::getVoidTy(getGlobalContext()), params, false); -  return Function::Create(FTy, GlobalValue::ExternalLinkage); -} - -// Allocate three simple functions that fit in the initial slab.  This exercises -// the code in the case that we don't have to allocate more memory to store the -// function bodies. -TEST(JITMemoryManagerTest, NoAllocations) { -  std::unique_ptr<JITMemoryManager> MemMgr( -      JITMemoryManager::CreateDefaultMemManager()); -  uintptr_t size; -  std::string Error; - -  // Allocate the functions. -  std::unique_ptr<Function> F1(makeFakeFunction()); -  size = 1024; -  uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size); -  memset(FunctionBody1, 0xFF, 1024); -  MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + 1024); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - -  std::unique_ptr<Function> F2(makeFakeFunction()); -  size = 1024; -  uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size); -  memset(FunctionBody2, 0xFF, 1024); -  MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + 1024); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - -  std::unique_ptr<Function> F3(makeFakeFunction()); -  size = 1024; -  uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); -  memset(FunctionBody3, 0xFF, 1024); -  MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + 1024); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - -  // Deallocate them out of order, in case that matters. -  MemMgr->deallocateFunctionBody(FunctionBody2); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -  MemMgr->deallocateFunctionBody(FunctionBody1); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -  MemMgr->deallocateFunctionBody(FunctionBody3); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -} - -// Make three large functions that take up most of the space in the slab.  Then -// try allocating three smaller functions that don't require additional slabs. -TEST(JITMemoryManagerTest, TestCodeAllocation) { -  std::unique_ptr<JITMemoryManager> MemMgr( -      JITMemoryManager::CreateDefaultMemManager()); -  uintptr_t size; -  std::string Error; - -  // Big functions are a little less than the largest block size. -  const uintptr_t smallFuncSize = 1024; -  const uintptr_t bigFuncSize = (MemMgr->GetDefaultCodeSlabSize() - -                                 smallFuncSize * 2); - -  // Allocate big functions -  std::unique_ptr<Function> F1(makeFakeFunction()); -  size = bigFuncSize; -  uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size); -  ASSERT_LE(bigFuncSize, size); -  memset(FunctionBody1, 0xFF, bigFuncSize); -  MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + bigFuncSize); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - -  std::unique_ptr<Function> F2(makeFakeFunction()); -  size = bigFuncSize; -  uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size); -  ASSERT_LE(bigFuncSize, size); -  memset(FunctionBody2, 0xFF, bigFuncSize); -  MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + bigFuncSize); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - -  std::unique_ptr<Function> F3(makeFakeFunction()); -  size = bigFuncSize; -  uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); -  ASSERT_LE(bigFuncSize, size); -  memset(FunctionBody3, 0xFF, bigFuncSize); -  MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + bigFuncSize); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - -  // Check that each large function took it's own slab. -  EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); - -  // Allocate small functions -  std::unique_ptr<Function> F4(makeFakeFunction()); -  size = smallFuncSize; -  uint8_t *FunctionBody4 = MemMgr->startFunctionBody(F4.get(), size); -  ASSERT_LE(smallFuncSize, size); -  memset(FunctionBody4, 0xFF, smallFuncSize); -  MemMgr->endFunctionBody(F4.get(), FunctionBody4, -                          FunctionBody4 + smallFuncSize); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - -  std::unique_ptr<Function> F5(makeFakeFunction()); -  size = smallFuncSize; -  uint8_t *FunctionBody5 = MemMgr->startFunctionBody(F5.get(), size); -  ASSERT_LE(smallFuncSize, size); -  memset(FunctionBody5, 0xFF, smallFuncSize); -  MemMgr->endFunctionBody(F5.get(), FunctionBody5, -                          FunctionBody5 + smallFuncSize); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - -  std::unique_ptr<Function> F6(makeFakeFunction()); -  size = smallFuncSize; -  uint8_t *FunctionBody6 = MemMgr->startFunctionBody(F6.get(), size); -  ASSERT_LE(smallFuncSize, size); -  memset(FunctionBody6, 0xFF, smallFuncSize); -  MemMgr->endFunctionBody(F6.get(), FunctionBody6, -                          FunctionBody6 + smallFuncSize); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - -  // Check that the small functions didn't allocate any new slabs. -  EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); - -  // Deallocate them out of order, in case that matters. -  MemMgr->deallocateFunctionBody(FunctionBody2); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -  MemMgr->deallocateFunctionBody(FunctionBody1); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -  MemMgr->deallocateFunctionBody(FunctionBody4); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -  MemMgr->deallocateFunctionBody(FunctionBody3); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -  MemMgr->deallocateFunctionBody(FunctionBody5); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -  MemMgr->deallocateFunctionBody(FunctionBody6); -  EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -} - -// Allocate five global ints of varying widths and alignment, and check their -// alignment and overlap. -TEST(JITMemoryManagerTest, TestSmallGlobalInts) { -  std::unique_ptr<JITMemoryManager> MemMgr( -      JITMemoryManager::CreateDefaultMemManager()); -  uint8_t  *a = (uint8_t *)MemMgr->allocateGlobal(8,  0); -  uint16_t *b = (uint16_t*)MemMgr->allocateGlobal(16, 2); -  uint32_t *c = (uint32_t*)MemMgr->allocateGlobal(32, 4); -  uint64_t *d = (uint64_t*)MemMgr->allocateGlobal(64, 8); - -  // Check the alignment. -  EXPECT_EQ(0U, ((uintptr_t)b) & 0x1); -  EXPECT_EQ(0U, ((uintptr_t)c) & 0x3); -  EXPECT_EQ(0U, ((uintptr_t)d) & 0x7); - -  // Initialize them each one at a time and make sure they don't overlap. -  *a = 0xff; -  *b = 0U; -  *c = 0U; -  *d = 0U; -  EXPECT_EQ(0xffU, *a); -  EXPECT_EQ(0U, *b); -  EXPECT_EQ(0U, *c); -  EXPECT_EQ(0U, *d); -  *a = 0U; -  *b = 0xffffU; -  EXPECT_EQ(0U, *a); -  EXPECT_EQ(0xffffU, *b); -  EXPECT_EQ(0U, *c); -  EXPECT_EQ(0U, *d); -  *b = 0U; -  *c = 0xffffffffU; -  EXPECT_EQ(0U, *a); -  EXPECT_EQ(0U, *b); -  EXPECT_EQ(0xffffffffU, *c); -  EXPECT_EQ(0U, *d); -  *c = 0U; -  *d = 0xffffffffffffffffULL; -  EXPECT_EQ(0U, *a); -  EXPECT_EQ(0U, *b); -  EXPECT_EQ(0U, *c); -  EXPECT_EQ(0xffffffffffffffffULL, *d); - -  // Make sure we didn't allocate any extra slabs for this tiny amount of data. -  EXPECT_EQ(1U, MemMgr->GetNumDataSlabs()); -} - -// Allocate a small global, a big global, and a third global, and make sure we -// only use two slabs for that. -TEST(JITMemoryManagerTest, TestLargeGlobalArray) { -  std::unique_ptr<JITMemoryManager> MemMgr( -      JITMemoryManager::CreateDefaultMemManager()); -  size_t Size = 4 * MemMgr->GetDefaultDataSlabSize(); -  uint64_t *a = (uint64_t*)MemMgr->allocateGlobal(64, 8); -  uint8_t *g = MemMgr->allocateGlobal(Size, 8); -  uint64_t *b = (uint64_t*)MemMgr->allocateGlobal(64, 8); - -  // Check the alignment. -  EXPECT_EQ(0U, ((uintptr_t)a) & 0x7); -  EXPECT_EQ(0U, ((uintptr_t)g) & 0x7); -  EXPECT_EQ(0U, ((uintptr_t)b) & 0x7); - -  // Initialize them to make sure we don't segfault and make sure they don't -  // overlap. -  memset(a, 0x1, 8); -  memset(g, 0x2, Size); -  memset(b, 0x3, 8); -  EXPECT_EQ(0x0101010101010101ULL, *a); -  // Just check the edges. -  EXPECT_EQ(0x02U, g[0]); -  EXPECT_EQ(0x02U, g[Size - 1]); -  EXPECT_EQ(0x0303030303030303ULL, *b); - -  // Check the number of slabs. -  EXPECT_EQ(2U, MemMgr->GetNumDataSlabs()); -} - -// Allocate lots of medium globals so that we can test moving the bump allocator -// to a new slab. -TEST(JITMemoryManagerTest, TestManyGlobals) { -  std::unique_ptr<JITMemoryManager> MemMgr( -      JITMemoryManager::CreateDefaultMemManager()); -  size_t SlabSize = MemMgr->GetDefaultDataSlabSize(); -  size_t Size = 128; -  int Iters = (SlabSize / Size) + 1; - -  // We should start with no slabs. -  EXPECT_EQ(0U, MemMgr->GetNumDataSlabs()); - -  // After allocating a bunch of globals, we should have two. -  for (int I = 0; I < Iters; ++I) -    MemMgr->allocateGlobal(Size, 8); -  EXPECT_EQ(2U, MemMgr->GetNumDataSlabs()); - -  // And after much more, we should have three. -  for (int I = 0; I < Iters; ++I) -    MemMgr->allocateGlobal(Size, 8); -  EXPECT_EQ(3U, MemMgr->GetNumDataSlabs()); -} - -// Allocate lots of function stubs so that we can test moving the stub bump -// allocator to a new slab. -TEST(JITMemoryManagerTest, TestManyStubs) { -  std::unique_ptr<JITMemoryManager> MemMgr( -      JITMemoryManager::CreateDefaultMemManager()); -  size_t SlabSize = MemMgr->GetDefaultStubSlabSize(); -  size_t Size = 128; -  int Iters = (SlabSize / Size) + 1; - -  // We should start with no slabs. -  EXPECT_EQ(0U, MemMgr->GetNumDataSlabs()); - -  // After allocating a bunch of stubs, we should have two. -  for (int I = 0; I < Iters; ++I) -    MemMgr->allocateStub(nullptr, Size, 8); -  EXPECT_EQ(2U, MemMgr->GetNumStubSlabs()); - -  // And after much more, we should have three. -  for (int I = 0; I < Iters; ++I) -    MemMgr->allocateStub(nullptr, Size, 8); -  EXPECT_EQ(3U, MemMgr->GetNumStubSlabs()); -} - -// Check section allocation and alignment -TEST(JITMemoryManagerTest, AllocateSection) { -  std::unique_ptr<JITMemoryManager> MemMgr( -      JITMemoryManager::CreateDefaultMemManager()); -  uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1, StringRef()); -  uint8_t *data1 = MemMgr->allocateDataSection(256, 16, 2, StringRef(), true); -  uint8_t *code2 = MemMgr->allocateCodeSection(257, 32, 3, StringRef()); -  uint8_t *data2 = MemMgr->allocateDataSection(256, 64, 4, StringRef(), false); -  uint8_t *code3 = MemMgr->allocateCodeSection(258, 64, 5, StringRef()); - -  EXPECT_NE((uint8_t*)nullptr, code1); -  EXPECT_NE((uint8_t*)nullptr, code2); -  EXPECT_NE((uint8_t*)nullptr, data1); -  EXPECT_NE((uint8_t*)nullptr, data2); - -  // Check alignment -  EXPECT_EQ((uint64_t)code1 & 0xf, 0u); -  EXPECT_EQ((uint64_t)code2 & 0x1f, 0u); -  EXPECT_EQ((uint64_t)code3 & 0x3f, 0u); -  EXPECT_EQ((uint64_t)data1 & 0xf, 0u); -  EXPECT_EQ((uint64_t)data2 & 0x3f, 0u); -} - -} diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp deleted file mode 100644 index 817d207..0000000 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ /dev/null @@ -1,728 +0,0 @@ -//===- JITTest.cpp - Unit tests for the JIT -------------------------------===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/AsmParser/Parser.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/TypeBuilder.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" -#include <vector> - -using namespace llvm; - -// This variable is intentionally defined differently in the statically-compiled -// program from the IR input to the JIT to assert that the JIT doesn't use its -// definition.  Note that this variable must be defined even on platforms where -// JIT tests are disabled as it is referenced from the .def file. -extern "C" int32_t JITTest_AvailableExternallyGlobal; -int32_t JITTest_AvailableExternallyGlobal LLVM_ATTRIBUTE_USED = 42; - -// This function is intentionally defined differently in the statically-compiled -// program from the IR input to the JIT to assert that the JIT doesn't use its -// definition.  Note that this function must be defined even on platforms where -// JIT tests are disabled as it is referenced from the .def file. -extern "C" int32_t JITTest_AvailableExternallyFunction() LLVM_ATTRIBUTE_USED; -extern "C" int32_t JITTest_AvailableExternallyFunction() { -  return 42; -} - -namespace { - -// Tests on ARM, PowerPC and SystemZ disabled as we're running the old jit -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \ -                      && !defined(__aarch64__) - -Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) { -  std::vector<Type*> params; -  FunctionType *FTy = FunctionType::get(G->getType()->getElementType(), -                                              params, false); -  Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M); -  BasicBlock *Entry = BasicBlock::Create(M->getContext(), "entry", F); -  IRBuilder<> builder(Entry); -  Value *Load = builder.CreateLoad(G); -  Type *GTy = G->getType()->getElementType(); -  Value *Add = builder.CreateAdd(Load, ConstantInt::get(GTy, 1LL)); -  builder.CreateStore(Add, G); -  builder.CreateRet(Add); -  return F; -} - -std::string DumpFunction(const Function *F) { -  std::string Result; -  raw_string_ostream(Result) << "" << *F; -  return Result; -} - -class RecordingJITMemoryManager : public JITMemoryManager { -  const std::unique_ptr<JITMemoryManager> Base; - -public: -  RecordingJITMemoryManager() -    : Base(JITMemoryManager::CreateDefaultMemManager()) { -    stubsAllocated = 0; -  } -  virtual void *getPointerToNamedFunction(const std::string &Name, -                                          bool AbortOnFailure = true) { -    return Base->getPointerToNamedFunction(Name, AbortOnFailure); -  } - -  virtual void setMemoryWritable() { Base->setMemoryWritable(); } -  virtual void setMemoryExecutable() { Base->setMemoryExecutable(); } -  virtual void setPoisonMemory(bool poison) { Base->setPoisonMemory(poison); } -  virtual void AllocateGOT() { Base->AllocateGOT(); } -  virtual uint8_t *getGOTBase() const { return Base->getGOTBase(); } -  struct StartFunctionBodyCall { -    StartFunctionBodyCall(uint8_t *Result, const Function *F, -                          uintptr_t ActualSize, uintptr_t ActualSizeResult) -      : Result(Result), F(F), F_dump(DumpFunction(F)), -        ActualSize(ActualSize), ActualSizeResult(ActualSizeResult) {} -    uint8_t *Result; -    const Function *F; -    std::string F_dump; -    uintptr_t ActualSize; -    uintptr_t ActualSizeResult; -  }; -  std::vector<StartFunctionBodyCall> startFunctionBodyCalls; -  virtual uint8_t *startFunctionBody(const Function *F, -                                     uintptr_t &ActualSize) { -    uintptr_t InitialActualSize = ActualSize; -    uint8_t *Result = Base->startFunctionBody(F, ActualSize); -    startFunctionBodyCalls.push_back( -      StartFunctionBodyCall(Result, F, InitialActualSize, ActualSize)); -    return Result; -  } -  int stubsAllocated; -  uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize, -                        unsigned Alignment) override { -    stubsAllocated++; -    return Base->allocateStub(F, StubSize, Alignment); -  } -  struct EndFunctionBodyCall { -    EndFunctionBodyCall(const Function *F, uint8_t *FunctionStart, -                        uint8_t *FunctionEnd) -      : F(F), F_dump(DumpFunction(F)), -        FunctionStart(FunctionStart), FunctionEnd(FunctionEnd) {} -    const Function *F; -    std::string F_dump; -    uint8_t *FunctionStart; -    uint8_t *FunctionEnd; -  }; -  std::vector<EndFunctionBodyCall> endFunctionBodyCalls; -  virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, -                               uint8_t *FunctionEnd) { -    endFunctionBodyCalls.push_back( -      EndFunctionBodyCall(F, FunctionStart, FunctionEnd)); -    Base->endFunctionBody(F, FunctionStart, FunctionEnd); -  } -  virtual uint8_t *allocateDataSection( -    uintptr_t Size, unsigned Alignment, unsigned SectionID, -    StringRef SectionName, bool IsReadOnly) { -    return Base->allocateDataSection( -      Size, Alignment, SectionID, SectionName, IsReadOnly); -  } -  virtual uint8_t *allocateCodeSection( -    uintptr_t Size, unsigned Alignment, unsigned SectionID, -    StringRef SectionName) { -    return Base->allocateCodeSection( -      Size, Alignment, SectionID, SectionName); -  } -  virtual bool finalizeMemory(std::string *ErrMsg) { return false; } -  virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { -    return Base->allocateSpace(Size, Alignment); -  } -  virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { -    return Base->allocateGlobal(Size, Alignment); -  } -  struct DeallocateFunctionBodyCall { -    DeallocateFunctionBodyCall(const void *Body) : Body(Body) {} -    const void *Body; -  }; -  std::vector<DeallocateFunctionBodyCall> deallocateFunctionBodyCalls; -  virtual void deallocateFunctionBody(void *Body) { -    deallocateFunctionBodyCalls.push_back(DeallocateFunctionBodyCall(Body)); -    Base->deallocateFunctionBody(Body); -  } -}; - -bool LoadAssemblyInto(Module *M, const char *assembly) { -  SMDiagnostic Error; -  bool success = -    nullptr != ParseAssemblyString(assembly, M, Error, M->getContext()); -  std::string errMsg; -  raw_string_ostream os(errMsg); -  Error.print("", os); -  EXPECT_TRUE(success) << os.str(); -  return success; -} - -class JITTest : public testing::Test { - protected: -  virtual RecordingJITMemoryManager *createMemoryManager() { -    return new RecordingJITMemoryManager; -  } - -  virtual void SetUp() { -    M = new Module("<main>", Context); -    RJMM = createMemoryManager(); -    RJMM->setPoisonMemory(true); -    std::string Error; -    TargetOptions Options; -    TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT) -                 .setJITMemoryManager(RJMM) -                 .setErrorStr(&Error) -                 .setTargetOptions(Options).create()); -    ASSERT_TRUE(TheJIT.get() != nullptr) << Error; -  } - -  void LoadAssembly(const char *assembly) { -    LoadAssemblyInto(M, assembly); -  } - -  LLVMContext Context; -  Module *M;  // Owned by ExecutionEngine. -  RecordingJITMemoryManager *RJMM; -  std::unique_ptr<ExecutionEngine> TheJIT; -}; - -// Regression test for a bug.  The JIT used to allocate globals inside the same -// memory block used for the function, and when the function code was freed, -// the global was left in the same place.  This test allocates a function -// that uses and global, deallocates it, and then makes sure that the global -// stays alive after that. -TEST(JIT, GlobalInFunction) { -  LLVMContext context; -  Module *M = new Module("<main>", context); - -  JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager(); -  // Tell the memory manager to poison freed memory so that accessing freed -  // memory is more easily tested. -  MemMgr->setPoisonMemory(true); -  std::string Error; -  std::unique_ptr<ExecutionEngine> JIT(EngineBuilder(M) -                                           .setEngineKind(EngineKind::JIT) -                                           .setErrorStr(&Error) -                                           .setJITMemoryManager(MemMgr) -                                           // The next line enables the fix: -                                           .setAllocateGVsWithCode(false) -                                           .create()); -  ASSERT_EQ(Error, ""); - -  // Create a global variable. -  Type *GTy = Type::getInt32Ty(context); -  GlobalVariable *G = new GlobalVariable( -      *M, -      GTy, -      false,  // Not constant. -      GlobalValue::InternalLinkage, -      Constant::getNullValue(GTy), -      "myglobal"); - -  // Make a function that points to a global. -  Function *F1 = makeReturnGlobal("F1", G, M); - -  // Get the pointer to the native code to force it to JIT the function and -  // allocate space for the global. -  void (*F1Ptr)() = -      reinterpret_cast<void(*)()>((intptr_t)JIT->getPointerToFunction(F1)); - -  // Since F1 was codegen'd, a pointer to G should be available. -  int32_t *GPtr = (int32_t*)JIT->getPointerToGlobalIfAvailable(G); -  ASSERT_NE((int32_t*)nullptr, GPtr); -  EXPECT_EQ(0, *GPtr); - -  // F1() should increment G. -  F1Ptr(); -  EXPECT_EQ(1, *GPtr); - -  // Make a second function identical to the first, referring to the same -  // global. -  Function *F2 = makeReturnGlobal("F2", G, M); -  void (*F2Ptr)() = -      reinterpret_cast<void(*)()>((intptr_t)JIT->getPointerToFunction(F2)); - -  // F2() should increment G. -  F2Ptr(); -  EXPECT_EQ(2, *GPtr); - -  // Deallocate F1. -  JIT->freeMachineCodeForFunction(F1); - -  // F2() should *still* increment G. -  F2Ptr(); -  EXPECT_EQ(3, *GPtr); -} - -int PlusOne(int arg) { -  return arg + 1; -} - -TEST_F(JITTest, FarCallToKnownFunction) { -  // x86-64 can only make direct calls to functions within 32 bits of -  // the current PC.  To call anything farther away, we have to load -  // the address into a register and call through the register.  The -  // current JIT does this by allocating a stub for any far call. -  // There was a bug in which the JIT tried to emit a direct call when -  // the target was already in the JIT's global mappings and lazy -  // compilation was disabled. - -  Function *KnownFunction = Function::Create( -      TypeBuilder<int(int), false>::get(Context), -      GlobalValue::ExternalLinkage, "known", M); -  TheJIT->addGlobalMapping(KnownFunction, (void*)(intptr_t)PlusOne); - -  // int test() { return known(7); } -  Function *TestFunction = Function::Create( -      TypeBuilder<int(), false>::get(Context), -      GlobalValue::ExternalLinkage, "test", M); -  BasicBlock *Entry = BasicBlock::Create(Context, "entry", TestFunction); -  IRBuilder<> Builder(Entry); -  Value *result = Builder.CreateCall( -      KnownFunction, -      ConstantInt::get(TypeBuilder<int, false>::get(Context), 7)); -  Builder.CreateRet(result); - -  TheJIT->DisableLazyCompilation(true); -  int (*TestFunctionPtr)() = reinterpret_cast<int(*)()>( -      (intptr_t)TheJIT->getPointerToFunction(TestFunction)); -  // This used to crash in trying to call PlusOne(). -  EXPECT_EQ(8, TestFunctionPtr()); -} - -// Test a function C which calls A and B which call each other. -TEST_F(JITTest, NonLazyCompilationStillNeedsStubs) { -  TheJIT->DisableLazyCompilation(true); - -  FunctionType *Func1Ty = -      cast<FunctionType>(TypeBuilder<void(void), false>::get(Context)); -  std::vector<Type*> arg_types; -  arg_types.push_back(Type::getInt1Ty(Context)); -  FunctionType *FuncTy = FunctionType::get( -      Type::getVoidTy(Context), arg_types, false); -  Function *Func1 = Function::Create(Func1Ty, Function::ExternalLinkage, -                                     "func1", M); -  Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage, -                                     "func2", M); -  Function *Func3 = Function::Create(FuncTy, Function::InternalLinkage, -                                     "func3", M); -  BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1); -  BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2); -  BasicBlock *True2 = BasicBlock::Create(Context, "cond_true", Func2); -  BasicBlock *False2 = BasicBlock::Create(Context, "cond_false", Func2); -  BasicBlock *Block3 = BasicBlock::Create(Context, "block3", Func3); -  BasicBlock *True3 = BasicBlock::Create(Context, "cond_true", Func3); -  BasicBlock *False3 = BasicBlock::Create(Context, "cond_false", Func3); - -  // Make Func1 call Func2(0) and Func3(0). -  IRBuilder<> Builder(Block1); -  Builder.CreateCall(Func2, ConstantInt::getTrue(Context)); -  Builder.CreateCall(Func3, ConstantInt::getTrue(Context)); -  Builder.CreateRetVoid(); - -  // void Func2(bool b) { if (b) { Func3(false); return; } return; } -  Builder.SetInsertPoint(Block2); -  Builder.CreateCondBr(Func2->arg_begin(), True2, False2); -  Builder.SetInsertPoint(True2); -  Builder.CreateCall(Func3, ConstantInt::getFalse(Context)); -  Builder.CreateRetVoid(); -  Builder.SetInsertPoint(False2); -  Builder.CreateRetVoid(); - -  // void Func3(bool b) { if (b) { Func2(false); return; } return; } -  Builder.SetInsertPoint(Block3); -  Builder.CreateCondBr(Func3->arg_begin(), True3, False3); -  Builder.SetInsertPoint(True3); -  Builder.CreateCall(Func2, ConstantInt::getFalse(Context)); -  Builder.CreateRetVoid(); -  Builder.SetInsertPoint(False3); -  Builder.CreateRetVoid(); - -  // Compile the function to native code -  void (*F1Ptr)() = -     reinterpret_cast<void(*)()>((intptr_t)TheJIT->getPointerToFunction(Func1)); - -  F1Ptr(); -} - -// Regression test for PR5162.  This used to trigger an AssertingVH inside the -// JIT's Function to stub mapping. -TEST_F(JITTest, NonLazyLeaksNoStubs) { -  TheJIT->DisableLazyCompilation(true); - -  // Create two functions with a single basic block each. -  FunctionType *FuncTy = -      cast<FunctionType>(TypeBuilder<int(), false>::get(Context)); -  Function *Func1 = Function::Create(FuncTy, Function::ExternalLinkage, -                                     "func1", M); -  Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage, -                                     "func2", M); -  BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1); -  BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2); - -  // The first function calls the second and returns the result -  IRBuilder<> Builder(Block1); -  Value *Result = Builder.CreateCall(Func2); -  Builder.CreateRet(Result); - -  // The second function just returns a constant -  Builder.SetInsertPoint(Block2); -  Builder.CreateRet(ConstantInt::get(TypeBuilder<int, false>::get(Context),42)); - -  // Compile the function to native code -  (void)TheJIT->getPointerToFunction(Func1); - -  // Free the JIT state for the functions -  TheJIT->freeMachineCodeForFunction(Func1); -  TheJIT->freeMachineCodeForFunction(Func2); - -  // Delete the first function (and show that is has no users) -  EXPECT_EQ(Func1->getNumUses(), 0u); -  Func1->eraseFromParent(); - -  // Delete the second function (and show that it has no users - it had one, -  // func1 but that's gone now) -  EXPECT_EQ(Func2->getNumUses(), 0u); -  Func2->eraseFromParent(); -} - -TEST_F(JITTest, ModuleDeletion) { -  TheJIT->DisableLazyCompilation(false); -  LoadAssembly("define void @main() { " -               "  call i32 @computeVal() " -               "  ret void " -               "} " -               " " -               "define internal i32 @computeVal()  { " -               "  ret i32 0 " -               "} "); -  Function *func = M->getFunction("main"); -  TheJIT->getPointerToFunction(func); -  TheJIT->removeModule(M); -  delete M; - -  SmallPtrSet<const void*, 2> FunctionsDeallocated; -  for (unsigned i = 0, e = RJMM->deallocateFunctionBodyCalls.size(); -       i != e; ++i) { -    FunctionsDeallocated.insert(RJMM->deallocateFunctionBodyCalls[i].Body); -  } -  for (unsigned i = 0, e = RJMM->startFunctionBodyCalls.size(); i != e; ++i) { -    EXPECT_TRUE(FunctionsDeallocated.count( -                  RJMM->startFunctionBodyCalls[i].Result)) -      << "Function leaked: \n" << RJMM->startFunctionBodyCalls[i].F_dump; -  } -  EXPECT_EQ(RJMM->startFunctionBodyCalls.size(), -            RJMM->deallocateFunctionBodyCalls.size()); -} - -// ARM, MIPS and PPC still emit stubs for calls since the target may be -// too far away to call directly.  This #if can probably be removed when -// http://llvm.org/PR5201 is fixed. -#if !defined(__arm__) && !defined(__mips__) && \ -    !defined(__powerpc__) && !defined(__ppc__) && !defined(__aarch64__) -typedef int (*FooPtr) (); - -TEST_F(JITTest, NoStubs) { -  LoadAssembly("define void @bar() {" -	       "entry: " -	       "ret void" -	       "}" -	       " " -	       "define i32 @foo() {" -	       "entry:" -	       "call void @bar()" -	       "ret i32 undef" -	       "}" -	       " " -	       "define i32 @main() {" -	       "entry:" -	       "%0 = call i32 @foo()" -	       "call void @bar()" -	       "ret i32 undef" -	       "}"); -  Function *foo = M->getFunction("foo"); -  uintptr_t tmp = (uintptr_t)(TheJIT->getPointerToFunction(foo)); -  FooPtr ptr = (FooPtr)(tmp); - -  (ptr)(); - -  // We should now allocate no more stubs, we have the code to foo -  // and the existing stub for bar. -  int stubsBefore = RJMM->stubsAllocated; -  Function *func = M->getFunction("main"); -  TheJIT->getPointerToFunction(func); - -  Function *bar = M->getFunction("bar"); -  TheJIT->getPointerToFunction(bar); - -  ASSERT_EQ(stubsBefore, RJMM->stubsAllocated); -} -#endif  // !ARM && !PPC - -TEST_F(JITTest, FunctionPointersOutliveTheirCreator) { -  TheJIT->DisableLazyCompilation(true); -  LoadAssembly("define i8()* @get_foo_addr() { " -               "  ret i8()* @foo " -               "} " -               " " -               "define i8 @foo() { " -               "  ret i8 42 " -               "} "); -  Function *F_get_foo_addr = M->getFunction("get_foo_addr"); - -  typedef char(*fooT)(); -  fooT (*get_foo_addr)() = reinterpret_cast<fooT(*)()>( -      (intptr_t)TheJIT->getPointerToFunction(F_get_foo_addr)); -  fooT foo_addr = get_foo_addr(); - -  // Now free get_foo_addr.  This should not free the machine code for foo or -  // any call stub returned as foo's canonical address. -  TheJIT->freeMachineCodeForFunction(F_get_foo_addr); - -  // Check by calling the reported address of foo. -  EXPECT_EQ(42, foo_addr()); - -  // The reported address should also be the same as the result of a subsequent -  // getPointerToFunction(foo). -#if 0 -  // Fails until PR5126 is fixed: -  Function *F_foo = M->getFunction("foo"); -  fooT foo = reinterpret_cast<fooT>( -      (intptr_t)TheJIT->getPointerToFunction(F_foo)); -  EXPECT_EQ((intptr_t)foo, (intptr_t)foo_addr); -#endif -} - -// ARM does not have an implementation of replaceMachineCodeForFunction(), -// so recompileAndRelinkFunction doesn't work. -#if !defined(__arm__) && !defined(__aarch64__) -TEST_F(JITTest, FunctionIsRecompiledAndRelinked) { -  Function *F = Function::Create(TypeBuilder<int(void), false>::get(Context), -                                 GlobalValue::ExternalLinkage, "test", M); -  BasicBlock *Entry = BasicBlock::Create(Context, "entry", F); -  IRBuilder<> Builder(Entry); -  Value *Val = ConstantInt::get(TypeBuilder<int, false>::get(Context), 1); -  Builder.CreateRet(Val); - -  TheJIT->DisableLazyCompilation(true); -  // Compile the function once, and make sure it works. -  int (*OrigFPtr)() = reinterpret_cast<int(*)()>( -    (intptr_t)TheJIT->recompileAndRelinkFunction(F)); -  EXPECT_EQ(1, OrigFPtr()); - -  // Now change the function to return a different value. -  Entry->eraseFromParent(); -  BasicBlock *NewEntry = BasicBlock::Create(Context, "new_entry", F); -  Builder.SetInsertPoint(NewEntry); -  Val = ConstantInt::get(TypeBuilder<int, false>::get(Context), 2); -  Builder.CreateRet(Val); -  // Recompile it, which should produce a new function pointer _and_ update the -  // old one. -  int (*NewFPtr)() = reinterpret_cast<int(*)()>( -    (intptr_t)TheJIT->recompileAndRelinkFunction(F)); - -  EXPECT_EQ(2, NewFPtr()) -    << "The new pointer should call the new version of the function"; -  EXPECT_EQ(2, OrigFPtr()) -    << "The old pointer's target should now jump to the new version"; -} -#endif  // !defined(__arm__) - -TEST_F(JITTest, AvailableExternallyGlobalIsntEmitted) { -  TheJIT->DisableLazyCompilation(true); -  LoadAssembly("@JITTest_AvailableExternallyGlobal = " -               "  available_externally global i32 7 " -               " " -               "define i32 @loader() { " -               "  %result = load i32* @JITTest_AvailableExternallyGlobal " -               "  ret i32 %result " -               "} "); -  Function *loaderIR = M->getFunction("loader"); - -  int32_t (*loader)() = reinterpret_cast<int32_t(*)()>( -    (intptr_t)TheJIT->getPointerToFunction(loaderIR)); -  EXPECT_EQ(42, loader()) << "func should return 42 from the external global," -                          << " not 7 from the IR version."; -} - -TEST_F(JITTest, AvailableExternallyFunctionIsntCompiled) { -  TheJIT->DisableLazyCompilation(true); -  LoadAssembly("define available_externally i32 " -               "    @JITTest_AvailableExternallyFunction() { " -               "  ret i32 7 " -               "} " -               " " -               "define i32 @func() { " -               "  %result = tail call i32 " -               "    @JITTest_AvailableExternallyFunction() " -               "  ret i32 %result " -               "} "); -  Function *funcIR = M->getFunction("func"); - -  int32_t (*func)() = reinterpret_cast<int32_t(*)()>( -    (intptr_t)TheJIT->getPointerToFunction(funcIR)); -  EXPECT_EQ(42, func()) << "func should return 42 from the static version," -                        << " not 7 from the IR version."; -} - -TEST_F(JITTest, EscapedLazyStubStillCallable) { -  TheJIT->DisableLazyCompilation(false); -  LoadAssembly("define internal i32 @stubbed() { " -               "  ret i32 42 " -               "} " -               " " -               "define i32()* @get_stub() { " -               "  ret i32()* @stubbed " -               "} "); -  typedef int32_t(*StubTy)(); - -  // Call get_stub() to get the address of @stubbed without actually JITting it. -  Function *get_stubIR = M->getFunction("get_stub"); -  StubTy (*get_stub)() = reinterpret_cast<StubTy(*)()>( -    (intptr_t)TheJIT->getPointerToFunction(get_stubIR)); -  StubTy stubbed = get_stub(); -  // Now get_stubIR is the only reference to stubbed's stub. -  get_stubIR->eraseFromParent(); -  // Now there are no references inside the JIT, but we've got a pointer outside -  // it.  The stub should be callable and return the right value. -  EXPECT_EQ(42, stubbed()); -} - -// Converts the LLVM assembly to bitcode and returns it in a std::string.  An -// empty string indicates an error. -std::string AssembleToBitcode(LLVMContext &Context, const char *Assembly) { -  Module TempModule("TempModule", Context); -  if (!LoadAssemblyInto(&TempModule, Assembly)) { -    return ""; -  } - -  std::string Result; -  raw_string_ostream OS(Result); -  WriteBitcodeToFile(&TempModule, OS); -  OS.flush(); -  return Result; -} - -// Returns a newly-created ExecutionEngine that reads the bitcode in 'Bitcode' -// lazily.  The associated Module (owned by the ExecutionEngine) is returned in -// M.  Both will be NULL on an error.  Bitcode must live at least as long as the -// ExecutionEngine. -ExecutionEngine *getJITFromBitcode( -  LLVMContext &Context, const std::string &Bitcode, Module *&M) { -  // c_str() is null-terminated like MemoryBuffer::getMemBuffer requires. -  MemoryBuffer *BitcodeBuffer = -    MemoryBuffer::getMemBuffer(Bitcode, "Bitcode for test"); -  ErrorOr<Module*> ModuleOrErr = getLazyBitcodeModule(BitcodeBuffer, Context); -  if (std::error_code EC = ModuleOrErr.getError()) { -    ADD_FAILURE() << EC.message(); -    delete BitcodeBuffer; -    return nullptr; -  } -  M = ModuleOrErr.get(); -  std::string errMsg; -  ExecutionEngine *TheJIT = EngineBuilder(M) -    .setEngineKind(EngineKind::JIT) -    .setErrorStr(&errMsg) -    .create(); -  if (TheJIT == nullptr) { -    ADD_FAILURE() << errMsg; -    delete M; -    M = nullptr; -    return nullptr; -  } -  return TheJIT; -} - -TEST(LazyLoadedJITTest, MaterializableAvailableExternallyFunctionIsntCompiled) { -  LLVMContext Context; -  const std::string Bitcode = -    AssembleToBitcode(Context, -                      "define available_externally i32 " -                      "    @JITTest_AvailableExternallyFunction() { " -                      "  ret i32 7 " -                      "} " -                      " " -                      "define i32 @func() { " -                      "  %result = tail call i32 " -                      "    @JITTest_AvailableExternallyFunction() " -                      "  ret i32 %result " -                      "} "); -  ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; -  Module *M; -  std::unique_ptr<ExecutionEngine> TheJIT( -      getJITFromBitcode(Context, Bitcode, M)); -  ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; -  TheJIT->DisableLazyCompilation(true); - -  Function *funcIR = M->getFunction("func"); -  Function *availableFunctionIR = -    M->getFunction("JITTest_AvailableExternallyFunction"); - -  // Double-check that the available_externally function is still unmaterialized -  // when getPointerToFunction needs to find out if it's available_externally. -  EXPECT_TRUE(availableFunctionIR->isMaterializable()); - -  int32_t (*func)() = reinterpret_cast<int32_t(*)()>( -    (intptr_t)TheJIT->getPointerToFunction(funcIR)); -  EXPECT_EQ(42, func()) << "func should return 42 from the static version," -                        << " not 7 from the IR version."; -} - -TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) { -  LLVMContext Context; -  const std::string Bitcode = -    AssembleToBitcode(Context, -                      "define i32 @recur1(i32 %a) { " -                      "  %zero = icmp eq i32 %a, 0 " -                      "  br i1 %zero, label %done, label %notdone " -                      "done: " -                      "  ret i32 3 " -                      "notdone: " -                      "  %am1 = sub i32 %a, 1 " -                      "  %result = call i32 @recur2(i32 %am1) " -                      "  ret i32 %result " -                      "} " -                      " " -                      "define i32 @recur2(i32 %b) { " -                      "  %result = call i32 @recur1(i32 %b) " -                      "  ret i32 %result " -                      "} "); -  ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; -  Module *M; -  std::unique_ptr<ExecutionEngine> TheJIT( -      getJITFromBitcode(Context, Bitcode, M)); -  ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; -  TheJIT->DisableLazyCompilation(true); - -  Function *recur1IR = M->getFunction("recur1"); -  Function *recur2IR = M->getFunction("recur2"); -  EXPECT_TRUE(recur1IR->isMaterializable()); -  EXPECT_TRUE(recur2IR->isMaterializable()); - -  int32_t (*recur1)(int32_t) = reinterpret_cast<int32_t(*)(int32_t)>( -    (intptr_t)TheJIT->getPointerToFunction(recur1IR)); -  EXPECT_EQ(3, recur1(4)); -} -#endif // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) - -} diff --git a/unittests/ExecutionEngine/JIT/JITTests.def b/unittests/ExecutionEngine/JIT/JITTests.def deleted file mode 100644 index 17c91e8..0000000 --- a/unittests/ExecutionEngine/JIT/JITTests.def +++ /dev/null @@ -1,4 +0,0 @@ -EXPORTS -getPointerToNamedFunction -JITTest_AvailableExternallyFunction -JITTest_AvailableExternallyGlobal diff --git a/unittests/ExecutionEngine/JIT/Makefile b/unittests/ExecutionEngine/JIT/Makefile deleted file mode 100644 index d86c03b..0000000 --- a/unittests/ExecutionEngine/JIT/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -##===- unittests/ExecutionEngine/JIT/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 = JIT -LINK_COMPONENTS := asmparser bitreader bitwriter jit native - -# The JIT tests need to dlopen things. -NO_DEAD_STRIP := 1 - -include $(LEVEL)/Makefile.config - -SOURCES := JITEventListenerTest.cpp JITMemoryManagerTest.cpp JITTest.cpp MultiJITTest.cpp - - -ifeq ($(USE_INTEL_JITEVENTS), 1) -  # Build the Intel JIT Events interface tests -  SOURCES += IntelJITEventListenerTest.cpp - -  # Add the Intel JIT Events include directory -  CPPFLAGS += -I$(INTEL_JITEVENTS_INCDIR) - -  # Link against the LLVM Intel JIT Evens interface library -  LINK_COMPONENTS += debuginfo inteljitevents object -endif - -ifeq ($(USE_OPROFILE), 1) -  # Build the OProfile JIT interface tests -  SOURCES += OProfileJITEventListenerTest.cpp - -  # Link against the LLVM oprofile interface library -  LINK_COMPONENTS += oprofilejit -endif - -EXPORTED_SYMBOL_FILE = $(PROJ_OBJ_DIR)/JITTests.exports - -include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest - -# Permit these tests to use the JIT's symbolic lookup. -LD.Flags += $(RDYNAMIC) - -# Symbol exports are necessary (at least for now) when building with LTO. -$(LLVMUnitTestExe): $(NativeExportsFile) -$(PROJ_OBJ_DIR)/JITTests.exports: $(PROJ_SRC_DIR)/JITTests.def $(PROJ_OBJ_DIR)/.dir -	tail -n +2 $< > $@ - diff --git a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp b/unittests/ExecutionEngine/JIT/MultiJITTest.cpp deleted file mode 100644 index f530e0d..0000000 --- a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp +++ /dev/null @@ -1,190 +0,0 @@ -//===- MultiJITTest.cpp - Unit tests for instantiating multiple JITs ------===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/AsmParser/Parser.h" -#include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/SourceMgr.h" -#include "gtest/gtest.h" -#include <vector> - -using namespace llvm; - -namespace { - -// ARM, PowerPC and SystemZ tests disabled pending fix for PR10783. -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \ -                      && !defined(__aarch64__) - -bool LoadAssemblyInto(Module *M, const char *assembly) { -  SMDiagnostic Error; -  bool success = -    nullptr != ParseAssemblyString(assembly, M, Error, M->getContext()); -  std::string errMsg; -  raw_string_ostream os(errMsg); -  Error.print("", os); -  EXPECT_TRUE(success) << os.str(); -  return success; -} - -void createModule1(LLVMContext &Context1, Module *&M1, Function *&FooF1) { -  M1 = new Module("test1", Context1); -  LoadAssemblyInto(M1, -                   "define i32 @add1(i32 %ArgX1) { " -                   "entry: " -                   "  %addresult = add i32 1, %ArgX1 " -                   "  ret i32 %addresult " -                   "} " -                   " " -                   "define i32 @foo1() { " -                   "entry: " -                   "  %add1 = call i32 @add1(i32 10) " -                   "  ret i32 %add1 " -                   "} "); -  FooF1 = M1->getFunction("foo1"); -} - -void createModule2(LLVMContext &Context2, Module *&M2, Function *&FooF2) { -  M2 = new Module("test2", Context2); -  LoadAssemblyInto(M2, -                   "define i32 @add2(i32 %ArgX2) { " -                   "entry: " -                   "  %addresult = add i32 2, %ArgX2 " -                   "  ret i32 %addresult " -                   "} " -                   " " -                   "define i32 @foo2() { " -                   "entry: " -                   "  %add2 = call i32 @add2(i32 10) " -                   "  ret i32 %add2 " -                   "} "); -  FooF2 = M2->getFunction("foo2"); -} - -TEST(MultiJitTest, EagerMode) { -  LLVMContext Context1; -  Module *M1 = nullptr; -  Function *FooF1 = nullptr; -  createModule1(Context1, M1, FooF1); - -  LLVMContext Context2; -  Module *M2 = nullptr; -  Function *FooF2 = nullptr; -  createModule2(Context2, M2, FooF2); - -  // Now we create the JIT in eager mode -  std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create()); -  EE1->DisableLazyCompilation(true); -  std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create()); -  EE2->DisableLazyCompilation(true); - -  // Call the `foo' function with no arguments: -  std::vector<GenericValue> noargs; -  GenericValue gv1 = EE1->runFunction(FooF1, noargs); -  GenericValue gv2 = EE2->runFunction(FooF2, noargs); - -  // Import result of execution: -  EXPECT_EQ(gv1.IntVal, 11); -  EXPECT_EQ(gv2.IntVal, 12); - -  EE1->freeMachineCodeForFunction(FooF1); -  EE2->freeMachineCodeForFunction(FooF2); -} - -TEST(MultiJitTest, LazyMode) { -  LLVMContext Context1; -  Module *M1 = nullptr; -  Function *FooF1 = nullptr; -  createModule1(Context1, M1, FooF1); - -  LLVMContext Context2; -  Module *M2 = nullptr; -  Function *FooF2 = nullptr; -  createModule2(Context2, M2, FooF2); - -  // Now we create the JIT in lazy mode -  std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create()); -  EE1->DisableLazyCompilation(false); -  std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create()); -  EE2->DisableLazyCompilation(false); - -  // Call the `foo' function with no arguments: -  std::vector<GenericValue> noargs; -  GenericValue gv1 = EE1->runFunction(FooF1, noargs); -  GenericValue gv2 = EE2->runFunction(FooF2, noargs); - -  // Import result of execution: -  EXPECT_EQ(gv1.IntVal, 11); -  EXPECT_EQ(gv2.IntVal, 12); - -  EE1->freeMachineCodeForFunction(FooF1); -  EE2->freeMachineCodeForFunction(FooF2); -} - -extern "C" { -  extern void *getPointerToNamedFunction(const char *Name); -} - -TEST(MultiJitTest, JitPool) { -  LLVMContext Context1; -  Module *M1 = nullptr; -  Function *FooF1 = nullptr; -  createModule1(Context1, M1, FooF1); - -  LLVMContext Context2; -  Module *M2 = nullptr; -  Function *FooF2 = nullptr; -  createModule2(Context2, M2, FooF2); - -  // Now we create two JITs -  std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create()); -  std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create()); - -  Function *F1 = EE1->FindFunctionNamed("foo1"); -  void *foo1 = EE1->getPointerToFunction(F1); - -  Function *F2 = EE2->FindFunctionNamed("foo2"); -  void *foo2 = EE2->getPointerToFunction(F2); - -  // Function in M1 -  EXPECT_EQ(getPointerToNamedFunction("foo1"), foo1); - -  // Function in M2 -  EXPECT_EQ(getPointerToNamedFunction("foo2"), foo2); - -  // Symbol search -  intptr_t -    sa = (intptr_t)getPointerToNamedFunction("getPointerToNamedFunction"); -  EXPECT_TRUE(sa != 0); -  intptr_t fa = (intptr_t)&getPointerToNamedFunction; -  EXPECT_TRUE(fa != 0); -#ifdef __i386__ -  // getPointerToNamedFunction might be indirect jump on Win32 --enable-shared. -  // FF 25 <disp32>: jmp *(pointer to IAT) -  if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) { -    fa = *(intptr_t *)(fa + 2); // Address to IAT -    EXPECT_TRUE(fa != 0); -    fa = *(intptr_t *)fa;       // Bound value of IAT -  } -#elif defined(__x86_64__) -  // getPointerToNamedFunction might be indirect jump -  // on Win32 x64 --enable-shared. -  // FF 25 <pcrel32>: jmp *(RIP + pointer to IAT) -  if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) { -    fa += *(int32_t *)(fa + 2) + 6;     // Address to IAT(RIP) -    fa = *(intptr_t *)fa;               // Bound value of IAT -  } -#endif -  EXPECT_TRUE(sa == fa); -} -#endif  // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) - -}  // anonymous namespace diff --git a/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp deleted file mode 100644 index 7057fca..0000000 --- a/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp +++ /dev/null @@ -1,165 +0,0 @@ -//===- OProfileJITEventListenerTest.cpp - Unit tests for OProfileJITEventsListener --------===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--------------------------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/OProfileWrapper.h" -#include "JITEventListenerTestCommon.h" -#include "llvm/ExecutionEngine/JITEventListener.h" -#include <list> -#include <map> - -using namespace llvm; - -namespace { - -struct OprofileNativeFunction { -  const char* Name; -  uint64_t Addr; -  const void* CodePtr; -  unsigned int CodeSize; - -  OprofileNativeFunction(const char* name, -                         uint64_t addr, -                         const void* code, -                         unsigned int size) -  : Name(name) -  , Addr(addr) -  , CodePtr(code) -  , CodeSize(size) { -  } -}; - -typedef std::list<OprofileNativeFunction> NativeFunctionList; -typedef std::list<debug_line_info> NativeDebugList; -NativeFunctionList NativeFunctions; - -NativeCodeMap ReportedDebugFuncs; - -} // namespace - -/// Mock implementaion of opagent library -namespace test_opagent { - -op_agent_t globalAgent = reinterpret_cast<op_agent_t>(42); - -op_agent_t open_agent() -{ -  // return non-null op_agent_t -  return globalAgent; -} - -int close_agent(op_agent_t agent) -{ -  EXPECT_EQ(globalAgent, agent); -  return 0; -} - -int write_native_code(op_agent_t agent, -                      const char* name, -                      uint64_t addr, -                      void const* code, -                      unsigned int size) -{ -  EXPECT_EQ(globalAgent, agent); -  OprofileNativeFunction func(name, addr, code, size); -  NativeFunctions.push_back(func); - -  // Verify no other registration has take place for the same address -  EXPECT_TRUE(ReportedDebugFuncs.find(addr) == ReportedDebugFuncs.end()); - -  ReportedDebugFuncs[addr]; -  return 0; -} - -int write_debug_line_info(op_agent_t agent, -                          void const* code, -                          size_t num_entries, -                          struct debug_line_info const* info) -{ -  EXPECT_EQ(globalAgent, agent); - -  //verify code has been loaded first -  uint64_t addr = reinterpret_cast<uint64_t>(code); -  NativeCodeMap::iterator i = ReportedDebugFuncs.find(addr); -  EXPECT_TRUE(i != ReportedDebugFuncs.end()); - -  NativeDebugList NativeInfo(info, info + num_entries); - -  SourceLocations locs; -  for(NativeDebugList::iterator i = NativeInfo.begin(); -      i != NativeInfo.end(); -      ++i) { -    locs.push_back(std::make_pair(std::string(i->filename), i->lineno)); -  } -  ReportedDebugFuncs[addr] = locs; - -  return 0; -} - -int unload_native_code(op_agent_t agent, uint64_t addr) { -  EXPECT_EQ(globalAgent, agent); - -  //verify that something for the given JIT addr has been loaded first -  NativeCodeMap::iterator i = ReportedDebugFuncs.find(addr); -  EXPECT_TRUE(i != ReportedDebugFuncs.end()); -  ReportedDebugFuncs.erase(i); -  return 0; -} - -int version() { -  return 1; -} - -bool is_oprofile_running() { -  return true; -} - -} //namespace test_opagent - -class OProfileJITEventListenerTest -: public JITEventListenerTestBase<OProfileWrapper> -{ -public: -  OProfileJITEventListenerTest() -  : JITEventListenerTestBase<OProfileWrapper>( -    new OProfileWrapper(test_opagent::open_agent, -      test_opagent::close_agent, -      test_opagent::write_native_code, -      test_opagent::write_debug_line_info, -      test_opagent::unload_native_code, -      test_opagent::version, -      test_opagent::version, -      test_opagent::is_oprofile_running)) -  { -    EXPECT_TRUE(0 != MockWrapper); - -    Listener.reset(JITEventListener::createOProfileJITEventListener( -      MockWrapper.get())); -    EXPECT_TRUE(0 != Listener); -    EE->RegisterJITEventListener(Listener.get()); -  } -}; - -TEST_F(OProfileJITEventListenerTest, NoDebugInfo) { -  TestNoDebugInfo(ReportedDebugFuncs); -} - -TEST_F(OProfileJITEventListenerTest, SingleLine) { -  TestSingleLine(ReportedDebugFuncs); -} - -TEST_F(OProfileJITEventListenerTest, MultipleLines) { -  TestMultipleLines(ReportedDebugFuncs); -} - -TEST_F(OProfileJITEventListenerTest, MultipleFiles) { -  TestMultipleFiles(ReportedDebugFuncs); -} - -testing::Environment* const jit_env = -  testing::AddGlobalTestEnvironment(new JITEnvironment); diff --git a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt index afa3f2a..b10cbb4 100644 --- a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt @@ -3,7 +3,7 @@ set(LLVM_LINK_COMPONENTS    Core    ExecutionEngine    IPO -  JIT +  MC    MCJIT    ScalarOpts    Support diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp index d03de89..c80b88b 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -139,8 +139,6 @@ protected:      // The operating systems below are known to be sufficiently incompatible      // that they will fail the MCJIT C API tests. -    UnsupportedOSs.push_back(Triple::Cygwin); -      UnsupportedEnvironments.push_back(Triple::Cygnus);    } diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp index 98587f7..0582c92 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp @@ -8,7 +8,6 @@  //===----------------------------------------------------------------------===//  #include "llvm/ExecutionEngine/SectionMemoryManager.h" -#include "llvm/ExecutionEngine/JIT.h"  #include "gtest/gtest.h"  using namespace llvm; diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp index c5ca36e..b0d1bb3 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp @@ -94,8 +94,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_case) {    Function *FA, *FB;    createTwoModuleCase(A, FA, B, FB); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B));    uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());    checkAdd(ptr); @@ -114,8 +114,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) {    Function *FA, *FB;    createTwoModuleCase(A, FA, B, FB); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B));    uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());    TheJIT->finalizeObject(); @@ -135,8 +135,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) {    Function *FA, *FB;    createTwoModuleExternCase(A, FA, B, FB); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B));    uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());    TheJIT->finalizeObject(); @@ -156,8 +156,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_extern_case) {    Function *FA, *FB;    createTwoModuleExternCase(A, FA, B, FB); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B));    uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());    checkAdd(ptr); @@ -177,8 +177,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) {    createTwoModuleExternCase(A, FA1, B, FB);    FA2 = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(A.get(), FA1); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B));    uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());    TheJIT->finalizeObject(); @@ -213,8 +213,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) {    FB = startFunction<int32_t(void)>(B.get(), "FB");    endFunctionWithRet(FB, Builder.CreateLoad(GVB)); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B));    uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str());    TheJIT->finalizeObject(); @@ -241,9 +241,9 @@ TEST_F(MCJITMultipleModuleTest, three_module_case) {    Function *FA, *FB, *FC;    createThreeModuleCase(A, FA, B, FB, C, FC); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); -  TheJIT->addModule(C.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B)); +  TheJIT->addModule(std::move(C));    uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());    checkAdd(ptr); @@ -266,9 +266,9 @@ TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) {    Function *FA, *FB, *FC;    createThreeModuleCase(A, FA, B, FB, C, FC); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); -  TheJIT->addModule(C.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B)); +  TheJIT->addModule(std::move(C));    uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());    checkAdd(ptr); @@ -291,9 +291,9 @@ TEST_F(MCJITMultipleModuleTest, three_module_chain_case) {    Function *FA, *FB, *FC;    createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); -  TheJIT->addModule(C.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B)); +  TheJIT->addModule(std::move(C));    uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());    checkAdd(ptr); @@ -316,9 +316,9 @@ TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) {    Function *FA, *FB, *FC;    createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); -  TheJIT->addModule(C.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B)); +  TheJIT->addModule(std::move(C));    uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());    checkAdd(ptr); @@ -341,8 +341,8 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) {    Function *FA, *FB1, *FB2;    createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B));    uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());    checkAccumulate(ptr); @@ -362,8 +362,8 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) {    Function *FA, *FB1, *FB2;    createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B));    uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());    checkAccumulate(ptr); @@ -383,8 +383,8 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) {    Function *FA, *FB1, *FB2;    createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); -  createJIT(A.release()); -  TheJIT->addModule(B.release()); +  createJIT(std::move(A)); +  TheJIT->addModule(std::move(B));    uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());    checkAccumulate(ptr); diff --git a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp index fbbab42..2736383 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp @@ -11,7 +11,6 @@  #include "llvm/ADT/SmallVector.h"  #include "llvm/ADT/StringMap.h"  #include "llvm/ADT/StringSet.h" -#include "llvm/ExecutionEngine/JIT.h"  #include "llvm/ExecutionEngine/MCJIT.h"  #include "llvm/ExecutionEngine/ObjectCache.h"  #include "llvm/ExecutionEngine/SectionMemoryManager.h" @@ -25,17 +24,7 @@ class TestObjectCache : public ObjectCache {  public:    TestObjectCache() : DuplicateInserted(false) { } -  virtual ~TestObjectCache() { -    // Free any buffers we've allocated. -    SmallVectorImpl<MemoryBuffer *>::iterator it, end; -    end = AllocatedBuffers.end(); -    for (it = AllocatedBuffers.begin(); it != end; ++it) { -      delete *it; -    } -    AllocatedBuffers.clear(); -  } - -  virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) { +  void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override {      // If we've seen this module before, note that.      const std::string ModuleID = M->getModuleIdentifier();      if (ObjMap.find(ModuleID) != ObjMap.end()) @@ -44,7 +33,7 @@ public:      ObjMap[ModuleID] = copyBuffer(Obj);    } -  virtual MemoryBuffer* getObject(const Module* M) { +  virtual std::unique_ptr<MemoryBuffer> getObject(const Module* M) override {      const MemoryBuffer* BufferFound = getObjectInternal(M);      ModulesLookedUp.insert(M->getModuleIdentifier());      if (!BufferFound) @@ -72,16 +61,18 @@ public:    }  private: -  MemoryBuffer *copyBuffer(const MemoryBuffer *Buf) { +  MemoryBuffer *copyBuffer(MemoryBufferRef Buf) {      // Create a local copy of the buffer. -    MemoryBuffer *NewBuffer = MemoryBuffer::getMemBufferCopy(Buf->getBuffer()); -    AllocatedBuffers.push_back(NewBuffer); -    return NewBuffer; +    std::unique_ptr<MemoryBuffer> NewBuffer = +        MemoryBuffer::getMemBufferCopy(Buf.getBuffer()); +    MemoryBuffer *Ret = NewBuffer.get(); +    AllocatedBuffers.push_back(std::move(NewBuffer)); +    return Ret;    }    StringMap<const MemoryBuffer *> ObjMap;    StringSet<>                     ModulesLookedUp; -  SmallVector<MemoryBuffer *, 2>  AllocatedBuffers; +  SmallVector<std::unique_ptr<MemoryBuffer>, 2> AllocatedBuffers;    bool                            DuplicateInserted;  }; @@ -121,7 +112,7 @@ protected:  TEST_F(MCJITObjectCacheTest, SetNullObjectCache) {    SKIP_UNSUPPORTED_PLATFORM; -  createJIT(M.release()); +  createJIT(std::move(M));    TheJIT->setObjectCache(nullptr); @@ -137,7 +128,7 @@ TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) {    // Save a copy of the module pointer before handing it off to MCJIT.    const Module * SavedModulePointer = M.get(); -  createJIT(M.release()); +  createJIT(std::move(M));    TheJIT->setObjectCache(Cache.get()); @@ -164,7 +155,7 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) {    std::unique_ptr<TestObjectCache> Cache(new TestObjectCache);    // Compile this module with an MCJIT engine -  createJIT(M.release()); +  createJIT(std::move(M));    TheJIT->setObjectCache(Cache.get());    TheJIT->finalizeObject(); @@ -181,7 +172,7 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) {    const Module * SecondModulePointer = M.get();    // Create a new MCJIT instance to load this module then execute it. -  createJIT(M.release()); +  createJIT(std::move(M));    TheJIT->setObjectCache(Cache.get());    compileAndRun(); @@ -198,7 +189,7 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) {    std::unique_ptr<TestObjectCache> Cache(new TestObjectCache);    // Compile this module with an MCJIT engine -  createJIT(M.release()); +  createJIT(std::move(M));    TheJIT->setObjectCache(Cache.get());    TheJIT->finalizeObject(); @@ -216,7 +207,7 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) {    const Module * SecondModulePointer = M.get();    // Create a new MCJIT instance to load this module then execute it. -  createJIT(M.release()); +  createJIT(std::move(M));    TheJIT->setObjectCache(Cache.get());    // Verify that our object cache does not contain the module yet. diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp index c37c1d1..64d8c2f 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp @@ -49,7 +49,7 @@ TEST_F(MCJITTest, global_variable) {    int initialValue = 5;    GlobalValue *Global = insertGlobalInt32(M.get(), "test_global", initialValue); -  createJIT(M.release()); +  createJIT(std::move(M));    void *globalPtr =  TheJIT->getPointerToGlobal(Global);    EXPECT_TRUE(nullptr != globalPtr)      << "Unable to get pointer to global value from JIT"; @@ -62,7 +62,7 @@ TEST_F(MCJITTest, add_function) {    SKIP_UNSUPPORTED_PLATFORM;    Function *F = insertAddFunction(M.get()); -  createJIT(M.release()); +  createJIT(std::move(M));    uint64_t addPtr = TheJIT->getFunctionAddress(F->getName().str());    EXPECT_TRUE(0 != addPtr)      << "Unable to get pointer to function from JIT"; @@ -83,7 +83,7 @@ TEST_F(MCJITTest, run_main) {    int rc = 6;    Function *Main = insertMainFunction(M.get(), 6); -  createJIT(M.release()); +  createJIT(std::move(M));    uint64_t ptr = TheJIT->getFunctionAddress(Main->getName().str());    EXPECT_TRUE(0 != ptr)      << "Unable to get pointer to main() from JIT"; @@ -104,7 +104,7 @@ TEST_F(MCJITTest, return_global) {    Value *ReadGlobal = Builder.CreateLoad(GV);    endFunctionWithRet(ReturnGlobal, ReadGlobal); -  createJIT(M.release()); +  createJIT(std::move(M));    uint64_t rgvPtr = TheJIT->getFunctionAddress(ReturnGlobal->getName().str());    EXPECT_TRUE(0 != rgvPtr); @@ -175,7 +175,7 @@ TEST_F(MCJITTest, multiple_functions) {      Inner = Outer;    } -  createJIT(M.release()); +  createJIT(std::move(M));    uint64_t ptr = TheJIT->getFunctionAddress(Outer->getName().str());    EXPECT_TRUE(0 != ptr)      << "Unable to get pointer to outer function from JIT"; @@ -187,4 +187,16 @@ TEST_F(MCJITTest, multiple_functions) {  #endif /*!defined(__arm__)*/ +TEST_F(MCJITTest, multiple_decl_lookups) { +  SKIP_UNSUPPORTED_PLATFORM; + +  Function *Foo = insertExternalReferenceToFunction<void(void)>(M.get(), "_exit"); +  createJIT(std::move(M)); +  void *A = TheJIT->getPointerToFunction(Foo); +  void *B = TheJIT->getPointerToFunction(Foo); + +  EXPECT_TRUE(A != 0) << "Failed lookup - test not correctly configured."; +  EXPECT_EQ(A, B) << "Repeat calls to getPointerToFunction fail."; +} +  } diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h index a48c071..7d704de 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h @@ -12,8 +12,8 @@  //  //===----------------------------------------------------------------------===// -#ifndef MCJIT_TEST_API_COMMON_H -#define MCJIT_TEST_API_COMMON_H +#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTAPICOMMON_H +#define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTAPICOMMON_H  #include "llvm/ADT/SmallVector.h"  #include "llvm/ADT/Triple.h" @@ -93,5 +93,5 @@ protected:  } // namespace llvm -#endif // MCJIT_TEST_API_COMMON_H +#endif diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h index 25de312..eea88bb 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h @@ -14,8 +14,8 @@  //===----------------------------------------------------------------------===// -#ifndef MCJIT_TEST_BASE_H -#define MCJIT_TEST_BASE_H +#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H +#define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H  #include "MCJITTestAPICommon.h"  #include "llvm/Config/config.h" @@ -107,6 +107,15 @@ protected:      return Result;    } +  // Inserts a declaration to a function defined elsewhere +  template <typename FuncType> +  Function *insertExternalReferenceToFunction(Module *M, StringRef Name) { +    Function *Result = Function::Create( +                         TypeBuilder<FuncType, false>::get(Context), +                         GlobalValue::ExternalLinkage, Name, M); +    return Result; +  } +    // Inserts an declaration to a function defined elsewhere    Function *insertExternalReferenceToFunction(Module *M, StringRef Name,                                                FunctionType *FuncTy) { @@ -302,26 +311,23 @@ protected:      // The operating systems below are known to be incompatible with MCJIT as      // they are copied from the test/ExecutionEngine/MCJIT/lit.local.cfg and      // should be kept in sync. -    UnsupportedOSs.push_back(Triple::Cygwin);      UnsupportedOSs.push_back(Triple::Darwin);      UnsupportedEnvironments.push_back(Triple::Cygnus);    } -  void createJIT(Module *M) { +  void createJIT(std::unique_ptr<Module> M) {      // Due to the EngineBuilder constructor, it is required to have a Module      // in order to construct an ExecutionEngine (i.e. MCJIT)      assert(M != 0 && "a non-null Module must be provided to create MCJIT"); -    EngineBuilder EB(M); +    EngineBuilder EB(std::move(M));      std::string Error;      TheJIT.reset(EB.setEngineKind(EngineKind::JIT) -                 .setUseMCJIT(true) /* can this be folded into the EngineKind enum? */                   .setMCJITMemoryManager(MM)                   .setErrorStr(&Error)                   .setOptLevel(CodeGenOpt::None) -                 .setAllocateGVsWithCode(false) /*does this do anything?*/                   .setCodeModel(CodeModel::JITDefault)                   .setRelocationModel(Reloc::Default)                   .setMArch(MArch) @@ -345,4 +351,4 @@ protected:  } // namespace llvm -#endif // MCJIT_TEST_H +#endif diff --git a/unittests/ExecutionEngine/MCJIT/Makefile b/unittests/ExecutionEngine/MCJIT/Makefile index c4dd740..2822b20 100644 --- a/unittests/ExecutionEngine/MCJIT/Makefile +++ b/unittests/ExecutionEngine/MCJIT/Makefile @@ -9,7 +9,7 @@  LEVEL = ../../..  TESTNAME = MCJIT -LINK_COMPONENTS := core ipo jit mcjit native support +LINK_COMPONENTS := core ipo mcjit native support  include $(LEVEL)/Makefile.config  include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/ExecutionEngine/Makefile b/unittests/ExecutionEngine/Makefile index 38e667f..8ecb883 100644 --- a/unittests/ExecutionEngine/Makefile +++ b/unittests/ExecutionEngine/Makefile @@ -14,7 +14,7 @@ LINK_COMPONENTS :=interpreter  include $(LEVEL)/Makefile.config  ifeq ($(TARGET_HAS_JIT),1) -  PARALLEL_DIRS = JIT MCJIT +  PARALLEL_DIRS = MCJIT  endif  include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index b439d59..a046209 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -10,6 +10,7 @@ set(IRSources    AttributesTest.cpp    ConstantRangeTest.cpp    ConstantsTest.cpp +  DebugInfoTest.cpp    DominatorTreeTest.cpp    IRBuilderTest.cpp    InstructionsTest.cpp @@ -21,6 +22,7 @@ set(IRSources    PatternMatch.cpp    TypeBuilderTest.cpp    TypesTest.cpp +  UseTest.cpp    UserTest.cpp    ValueHandleTest.cpp    ValueMapTest.cpp diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index 0cd8549..5414b25 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -274,5 +274,78 @@ TEST(ConstantsTest, ReplaceWithConstantTest) {  #undef CHECK +TEST(ConstantsTest, ConstantArrayReplaceWithConstant) { +  LLVMContext Context; +  std::unique_ptr<Module> M(new Module("MyModule", Context)); + +  Type *IntTy = Type::getInt8Ty(Context); +  ArrayType *ArrayTy = ArrayType::get(IntTy, 2); +  Constant *A01Vals[2] = {ConstantInt::get(IntTy, 0), +                          ConstantInt::get(IntTy, 1)}; +  Constant *A01 = ConstantArray::get(ArrayTy, A01Vals); + +  Constant *Global = new GlobalVariable(*M, IntTy, false, +                                        GlobalValue::ExternalLinkage, nullptr); +  Constant *GlobalInt = ConstantExpr::getPtrToInt(Global, IntTy); +  Constant *A0GVals[2] = {ConstantInt::get(IntTy, 0), GlobalInt}; +  Constant *A0G = ConstantArray::get(ArrayTy, A0GVals); +  ASSERT_NE(A01, A0G); + +  GlobalVariable *RefArray = +      new GlobalVariable(*M, ArrayTy, false, GlobalValue::ExternalLinkage, A0G); +  ASSERT_EQ(A0G, RefArray->getInitializer()); + +  GlobalInt->replaceAllUsesWith(ConstantInt::get(IntTy, 1)); +  ASSERT_EQ(A01, RefArray->getInitializer()); +} + +TEST(ConstantsTest, ConstantExprReplaceWithConstant) { +  LLVMContext Context; +  std::unique_ptr<Module> M(new Module("MyModule", Context)); + +  Type *IntTy = Type::getInt8Ty(Context); +  Constant *G1 = new GlobalVariable(*M, IntTy, false, +                                    GlobalValue::ExternalLinkage, nullptr); +  Constant *G2 = new GlobalVariable(*M, IntTy, false, +                                    GlobalValue::ExternalLinkage, nullptr); +  ASSERT_NE(G1, G2); + +  Constant *Int1 = ConstantExpr::getPtrToInt(G1, IntTy); +  Constant *Int2 = ConstantExpr::getPtrToInt(G2, IntTy); +  ASSERT_NE(Int1, Int2); + +  GlobalVariable *Ref = +      new GlobalVariable(*M, IntTy, false, GlobalValue::ExternalLinkage, Int1); +  ASSERT_EQ(Int1, Ref->getInitializer()); + +  G1->replaceAllUsesWith(G2); +  ASSERT_EQ(Int2, Ref->getInitializer()); +} + +TEST(ConstantsTest, GEPReplaceWithConstant) { +  LLVMContext Context; +  std::unique_ptr<Module> M(new Module("MyModule", Context)); + +  Type *IntTy = Type::getInt32Ty(Context); +  Type *PtrTy = PointerType::get(IntTy, 0); +  auto *C1 = ConstantInt::get(IntTy, 1); +  auto *Placeholder = new GlobalVariable( +      *M, IntTy, false, GlobalValue::ExternalWeakLinkage, nullptr); +  auto *GEP = ConstantExpr::getGetElementPtr(Placeholder, C1); +  ASSERT_EQ(GEP->getOperand(0), Placeholder); + +  auto *Ref = +      new GlobalVariable(*M, PtrTy, false, GlobalValue::ExternalLinkage, GEP); +  ASSERT_EQ(GEP, Ref->getInitializer()); + +  auto *Global = new GlobalVariable(*M, PtrTy, false, +                                    GlobalValue::ExternalLinkage, nullptr); +  auto *Alias = GlobalAlias::create(IntTy, 0, GlobalValue::ExternalLinkage, +                                    "alias", Global, M.get()); +  Placeholder->replaceAllUsesWith(Alias); +  ASSERT_EQ(GEP, Ref->getInitializer()); +  ASSERT_EQ(GEP->getOperand(0), Alias); +} +  }  // end anonymous namespace  }  // end namespace llvm diff --git a/unittests/IR/DebugInfoTest.cpp b/unittests/IR/DebugInfoTest.cpp new file mode 100644 index 0000000..1fa851e --- /dev/null +++ b/unittests/IR/DebugInfoTest.cpp @@ -0,0 +1,68 @@ +//===- llvm/unittest/IR/DebugInfo.cpp - DebugInfo tests -------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/DebugInfo.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace llvm { + +static void PrintTo(const StringRef &S, ::std::ostream *os) { +  *os << "(" << (const void *)S.data() << "," << S.size() << ") = '"; +  for (auto C : S) +    if (C) +      *os << C; +    else +      *os << "\\00"; +  *os << "'"; +} +static void PrintTo(const DIHeaderFieldIterator &I, ::std::ostream *os) { +  PrintTo(I.getCurrent(), os); +  *os << " in "; +  PrintTo(I.getHeader(), os); +} + +} // end namespace llvm + +namespace { + +#define MAKE_FIELD_ITERATOR(S)                                                 \ +  DIHeaderFieldIterator(StringRef(S, sizeof(S) - 1)) +TEST(DebugInfoTest, DIHeaderFieldIterator) { +  ASSERT_EQ(DIHeaderFieldIterator(), DIHeaderFieldIterator()); + +  ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("")); +  ASSERT_EQ(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("")); +  ASSERT_EQ("", *DIHeaderFieldIterator("")); + +  ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("stuff")); +  ASSERT_EQ(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("stuff")); +  ASSERT_EQ("stuff", *DIHeaderFieldIterator("stuff")); + +  ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("st\0uff")); +  ASSERT_NE(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("st\0uff")); +  ASSERT_EQ(DIHeaderFieldIterator(), ++++MAKE_FIELD_ITERATOR("st\0uff")); +  ASSERT_EQ("st", *MAKE_FIELD_ITERATOR("st\0uff")); +  ASSERT_EQ("uff", *++MAKE_FIELD_ITERATOR("st\0uff")); + +  ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("stuff\0")); +  ASSERT_NE(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("stuff\0")); +  ASSERT_EQ(DIHeaderFieldIterator(), ++++MAKE_FIELD_ITERATOR("stuff\0")); +  ASSERT_EQ("stuff", *MAKE_FIELD_ITERATOR("stuff\0")); +  ASSERT_EQ("", *++MAKE_FIELD_ITERATOR("stuff\0")); + +  ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("\0stuff")); +  ASSERT_NE(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("\0stuff")); +  ASSERT_EQ(DIHeaderFieldIterator(), ++++MAKE_FIELD_ITERATOR("\0stuff")); +  ASSERT_EQ("", *MAKE_FIELD_ITERATOR("\0stuff")); +  ASSERT_EQ("stuff", *++MAKE_FIELD_ITERATOR("\0stuff")); +} + +} // end namespace diff --git a/unittests/IR/DominatorTreeTest.cpp b/unittests/IR/DominatorTreeTest.cpp index ab43d1c..6c43d6f 100644 --- a/unittests/IR/DominatorTreeTest.cpp +++ b/unittests/IR/DominatorTreeTest.cpp @@ -186,8 +186,7 @@ namespace llvm {      };      char DPass::ID = 0; - -    Module* makeLLVMModule(DPass *P) { +    std::unique_ptr<Module> makeLLVMModule(DPass *P) {        const char *ModuleStrig =          "declare i32 @g()\n" \          "define void @f(i32 %x) {\n" \ @@ -213,12 +212,12 @@ namespace llvm {          "}\n";        LLVMContext &C = getGlobalContext();        SMDiagnostic Err; -      return ParseAssemblyString(ModuleStrig, nullptr, Err, C); +      return parseAssemblyString(ModuleStrig, Err, C);      }      TEST(DominatorTree, Unreachable) {        DPass *P = new DPass(); -      std::unique_ptr<Module> M(makeLLVMModule(P)); +      std::unique_ptr<Module> M = makeLLVMModule(P);        PassManager Passes;        Passes.add(P);        Passes.run(*M); diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp index 2108575..df5c840 100644 --- a/unittests/IR/IRBuilderTest.cpp +++ b/unittests/IR/IRBuilderTest.cpp @@ -189,12 +189,16 @@ TEST_F(IRBuilderTest, FastMathFlags) {    Builder.clearFastMathFlags(); +  // To test a copy, make sure that a '0' and a '1' change state.     F = Builder.CreateFDiv(F, F);    ASSERT_TRUE(isa<Instruction>(F));    FDiv = cast<Instruction>(F);    EXPECT_FALSE(FDiv->getFastMathFlags().any()); +  FDiv->setHasAllowReciprocal(true); +  FAdd->setHasAllowReciprocal(false);    FDiv->copyFastMathFlags(FAdd);    EXPECT_TRUE(FDiv->hasNoNaNs()); +  EXPECT_FALSE(FDiv->hasAllowReciprocal());  } diff --git a/unittests/IR/LegacyPassManagerTest.cpp b/unittests/IR/LegacyPassManagerTest.cpp index 9c2a835..4efc2f5 100644 --- a/unittests/IR/LegacyPassManagerTest.cpp +++ b/unittests/IR/LegacyPassManagerTest.cpp @@ -54,11 +54,11 @@ namespace llvm {        static char run;        static char ID;        ModuleNDNM() : ModulePass(ID) { } -      virtual bool runOnModule(Module &M) { +      bool runOnModule(Module &M) override {          run++;          return false;        } -      virtual void getAnalysisUsage(AnalysisUsage &AU) const { +      void getAnalysisUsage(AnalysisUsage &AU) const override {          AU.setPreservesAll();        }      }; @@ -70,7 +70,7 @@ namespace llvm {        static char run;        static char ID;        ModuleNDM() : ModulePass(ID) {} -      virtual bool runOnModule(Module &M) { +      bool runOnModule(Module &M) override {          run++;          return true;        } @@ -83,7 +83,7 @@ namespace llvm {        static char run;        static char ID;        ModuleNDM2() : ModulePass(ID) {} -      virtual bool runOnModule(Module &M) { +      bool runOnModule(Module &M) override {          run++;          return true;        } @@ -98,12 +98,12 @@ namespace llvm {        ModuleDNM() : ModulePass(ID) {          initializeModuleNDMPass(*PassRegistry::getPassRegistry());        } -      virtual bool runOnModule(Module &M) { +      bool runOnModule(Module &M) override {          EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>());          run++;          return false;        } -      virtual void getAnalysisUsage(AnalysisUsage &AU) const { +      void getAnalysisUsage(AnalysisUsage &AU) const override {          AU.addRequired<ModuleNDM>();          AU.setPreservesAll();        } @@ -139,7 +139,7 @@ namespace llvm {          runc = 0;        } -      virtual void releaseMemory() { +      void releaseMemory() override {          EXPECT_GT(runc, 0);          EXPECT_GT(allocated, 0);          allocated--; @@ -157,12 +157,12 @@ namespace llvm {        using llvm::Pass::doInitialization;        using llvm::Pass::doFinalization;  #endif -      virtual bool doInitialization(T &t) { +      bool doInitialization(T &t) override {          EXPECT_FALSE(PassTestBase<P>::initialized);          PassTestBase<P>::initialized = true;          return false;        } -      virtual bool doFinalization(T &t) { +      bool doFinalization(T &t) override {          EXPECT_FALSE(PassTestBase<P>::finalized);          PassTestBase<P>::finalized = true;          EXPECT_EQ(0, PassTestBase<P>::allocated); @@ -175,7 +175,7 @@ namespace llvm {        CGPass() {          initializeCGPassPass(*PassRegistry::getPassRegistry());        } -      virtual bool runOnSCC(CallGraphSCC &SCMM) { +      bool runOnSCC(CallGraphSCC &SCMM) override {          EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>());          run();          return false; @@ -184,7 +184,7 @@ namespace llvm {      struct FPass : public PassTest<Module, FunctionPass> {      public: -      virtual bool runOnFunction(Function &F) { +      bool runOnFunction(Function &F) override {          // FIXME: PR4112          // EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());          run(); @@ -209,17 +209,17 @@ namespace llvm {        }        using llvm::Pass::doInitialization;        using llvm::Pass::doFinalization; -      virtual bool doInitialization(Loop* L, LPPassManager &LPM) { +      bool doInitialization(Loop* L, LPPassManager &LPM) override {          initialized = true;          initcount++;          return false;        } -      virtual bool runOnLoop(Loop *L, LPPassManager &LPM) { +      bool runOnLoop(Loop *L, LPPassManager &LPM) override {          EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>());          run();          return false;        } -      virtual bool doFinalization() { +      bool doFinalization() override {          fincount++;          finalized = true;          return false; @@ -242,25 +242,25 @@ namespace llvm {          inited = 0;          fin = 0;        } -      virtual bool doInitialization(Module &M) { +      bool doInitialization(Module &M) override {          EXPECT_FALSE(initialized);          initialized = true;          return false;        } -      virtual bool doInitialization(Function &F) { +      bool doInitialization(Function &F) override {          inited++;          return false;        } -      virtual bool runOnBasicBlock(BasicBlock &BB) { +      bool runOnBasicBlock(BasicBlock &BB) override {          EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>());          run();          return false;        } -      virtual bool doFinalization(Function &F) { +      bool doFinalization(Function &F) override {          fin++;          return false;        } -      virtual bool doFinalization(Module &M) { +      bool doFinalization(Module &M) override {          EXPECT_FALSE(finalized);          finalized = true;          EXPECT_EQ(0, allocated); @@ -276,7 +276,7 @@ namespace llvm {        OnTheFlyTest() : ModulePass(ID) {          initializeFPassPass(*PassRegistry::getPassRegistry());        } -      virtual bool runOnModule(Module &M) { +      bool runOnModule(Module &M) override {          EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>());          for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) {            Function &F = *I; @@ -287,7 +287,7 @@ namespace llvm {          }          return false;        } -      virtual void getAnalysisUsage(AnalysisUsage &AU) const { +      void getAnalysisUsage(AnalysisUsage &AU) const override {          AU.addRequired<FPass>();        }      }; @@ -303,7 +303,7 @@ namespace llvm {        mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;        PassManager Passes; -      Passes.add(new DataLayoutPass(&M)); +      Passes.add(new DataLayoutPass());        Passes.add(mNDM2);        Passes.add(mNDM);        Passes.add(mNDNM); @@ -327,7 +327,7 @@ namespace llvm {        mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;        PassManager Passes; -      Passes.add(new DataLayoutPass(&M)); +      Passes.add(new DataLayoutPass());        Passes.add(mNDM);        Passes.add(mNDNM);        Passes.add(mNDM2);// invalidates mNDM needed by mDNM @@ -349,7 +349,7 @@ namespace llvm {        std::unique_ptr<Module> M(makeLLVMModule());        T *P = new T();        PassManager Passes; -      Passes.add(new DataLayoutPass(M.get())); +      Passes.add(new DataLayoutPass());        Passes.add(P);        Passes.run(*M);        T::finishedOK(run); @@ -360,7 +360,7 @@ namespace llvm {        Module *M = makeLLVMModule();        T *P = new T();        PassManager Passes; -      Passes.add(new DataLayoutPass(M)); +      Passes.add(new DataLayoutPass());        Passes.add(P);        Passes.run(*M);        T::finishedOK(run, N); @@ -398,7 +398,7 @@ namespace llvm {          SCOPED_TRACE("Running OnTheFlyTest");          struct OnTheFlyTest *O = new OnTheFlyTest();          PassManager Passes; -        Passes.add(new DataLayoutPass(M)); +        Passes.add(new DataLayoutPass());          Passes.add(O);          Passes.run(*M); diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp index 25037a7..d493156 100644 --- a/unittests/IR/PassManagerTest.cpp +++ b/unittests/IR/PassManagerTest.cpp @@ -168,7 +168,7 @@ struct TestInvalidationFunctionPass {  Module *parseIR(const char *IR) {    LLVMContext &C = getGlobalContext();    SMDiagnostic Err; -  return ParseAssemblyString(IR, nullptr, Err, C); +  return parseAssemblyString(IR, Err, C).release();  }  class PassManagerTest : public ::testing::Test { diff --git a/unittests/IR/UseTest.cpp b/unittests/IR/UseTest.cpp new file mode 100644 index 0000000..3f33ca6 --- /dev/null +++ b/unittests/IR/UseTest.cpp @@ -0,0 +1,112 @@ +//===- llvm/unittest/IR/UseTest.cpp - Use 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/AsmParser/Parser.h" +#include "llvm/IR/Function.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" + +using namespace llvm; + +namespace { + +TEST(UseTest, sort) { +  LLVMContext C; + +  const char *ModuleString = "define void @f(i32 %x) {\n" +                             "entry:\n" +                             "  %v0 = add i32 %x, 0\n" +                             "  %v2 = add i32 %x, 2\n" +                             "  %v5 = add i32 %x, 5\n" +                             "  %v1 = add i32 %x, 1\n" +                             "  %v3 = add i32 %x, 3\n" +                             "  %v7 = add i32 %x, 7\n" +                             "  %v6 = add i32 %x, 6\n" +                             "  %v4 = add i32 %x, 4\n" +                             "  ret void\n" +                             "}\n"; +  SMDiagnostic Err; +  char vnbuf[8]; +  std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C); +  Function *F = M->getFunction("f"); +  ASSERT_TRUE(F); +  ASSERT_TRUE(F->arg_begin() != F->arg_end()); +  Argument &X = *F->arg_begin(); +  ASSERT_EQ("x", X.getName()); + +  X.sortUseList([](const Use &L, const Use &R) { +    return L.getUser()->getName() < R.getUser()->getName(); +  }); +  unsigned I = 0; +  for (User *U : X.users()) { +    snprintf(vnbuf, sizeof(vnbuf), "v%u", I++); +    EXPECT_EQ(vnbuf, U->getName()); +  } +  ASSERT_EQ(8u, I); + +  X.sortUseList([](const Use &L, const Use &R) { +    return L.getUser()->getName() > R.getUser()->getName(); +  }); +  I = 0; +  for (User *U : X.users()) { +    snprintf(vnbuf, sizeof(vnbuf), "v%u", (7 - I++)); +    EXPECT_EQ(vnbuf, U->getName()); +  } +  ASSERT_EQ(8u, I); +} + +TEST(UseTest, reverse) { +  LLVMContext C; + +  const char *ModuleString = "define void @f(i32 %x) {\n" +                             "entry:\n" +                             "  %v0 = add i32 %x, 0\n" +                             "  %v2 = add i32 %x, 2\n" +                             "  %v5 = add i32 %x, 5\n" +                             "  %v1 = add i32 %x, 1\n" +                             "  %v3 = add i32 %x, 3\n" +                             "  %v7 = add i32 %x, 7\n" +                             "  %v6 = add i32 %x, 6\n" +                             "  %v4 = add i32 %x, 4\n" +                             "  ret void\n" +                             "}\n"; +  SMDiagnostic Err; +  char vnbuf[8]; +  std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C); +  Function *F = M->getFunction("f"); +  ASSERT_TRUE(F); +  ASSERT_TRUE(F->arg_begin() != F->arg_end()); +  Argument &X = *F->arg_begin(); +  ASSERT_EQ("x", X.getName()); + +  X.sortUseList([](const Use &L, const Use &R) { +    return L.getUser()->getName() < R.getUser()->getName(); +  }); +  unsigned I = 0; +  for (User *U : X.users()) { +    snprintf(vnbuf, sizeof(vnbuf), "v%u", I++); +    EXPECT_EQ(vnbuf, U->getName()); +  } +  ASSERT_EQ(8u, I); + +  X.reverseUseList(); +  I = 0; +  for (User *U : X.users()) { +    snprintf(vnbuf, sizeof(vnbuf), "v%u", (7 - I++)); +    EXPECT_EQ(vnbuf, U->getName()); +  } +  ASSERT_EQ(8u, I); +} + +} // end anonymous namespace diff --git a/unittests/IR/UserTest.cpp b/unittests/IR/UserTest.cpp index eb07e82..5572424 100644 --- a/unittests/IR/UserTest.cpp +++ b/unittests/IR/UserTest.cpp @@ -65,7 +65,7 @@ TEST(UserTest, ValueOpIteration) {                               "  ret void\n"                               "}\n";    SMDiagnostic Err; -  Module *M = ParseAssemblyString(ModuleString, nullptr, Err, C); +  std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);    Function *F = M->getFunction("f");    BasicBlock &ExitBB = F->back(); diff --git a/unittests/IR/ValueMapTest.cpp b/unittests/IR/ValueMapTest.cpp index 0b7198f..a6bad71 100644 --- a/unittests/IR/ValueMapTest.cpp +++ b/unittests/IR/ValueMapTest.cpp @@ -186,11 +186,11 @@ struct LockMutex : ValueMapConfig<KeyT, MutexT> {    };    static void onRAUW(const ExtraData &Data, KeyT Old, KeyT New) {      *Data.CalledRAUW = true; -    EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked."; +    EXPECT_FALSE(Data.M->try_lock()) << "Mutex should already be locked.";    }    static void onDelete(const ExtraData &Data, KeyT Old) {      *Data.CalledDeleted = true; -    EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked."; +    EXPECT_FALSE(Data.M->try_lock()) << "Mutex should already be locked.";    }    static MutexT *getMutex(const ExtraData &Data) { return Data.M; }  }; diff --git a/unittests/IR/ValueTest.cpp b/unittests/IR/ValueTest.cpp index 61e44a9..4dd0c2c 100644 --- a/unittests/IR/ValueTest.cpp +++ b/unittests/IR/ValueTest.cpp @@ -34,7 +34,7 @@ TEST(ValueTest, UsedInBasicBlock) {                               "  ret void\n"                               "}\n";    SMDiagnostic Err; -  Module *M = ParseAssemblyString(ModuleString, nullptr, Err, C); +  std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);    Function *F = M->getFunction("f"); @@ -60,6 +60,10 @@ TEST(GlobalTest, CreateAddressSpace) {                           GlobalVariable::NotThreadLocal,                           1); +  EXPECT_TRUE(Value::MaximumAlignment == 536870912U); +  Dummy0->setAlignment(536870912U); +  EXPECT_EQ(Dummy0->getAlignment(), 536870912U); +    // Make sure the address space isn't dropped when returning this.    Constant *Dummy1 = M->getOrInsertGlobal("dummy", Int32Ty);    EXPECT_EQ(Dummy0, Dummy1); @@ -83,4 +87,23 @@ TEST(GlobalTest, CreateAddressSpace) {    EXPECT_EQ(1u, DummyCast1->getType()->getPointerAddressSpace());    EXPECT_NE(DummyCast0, DummyCast1) << *DummyCast1;  } + +#ifdef GTEST_HAS_DEATH_TEST +#ifndef NDEBUG +TEST(GlobalTest, AlignDeath) { +  LLVMContext &Ctx = getGlobalContext(); +  std::unique_ptr<Module> M(new Module("TestModule", Ctx)); +  Type *Int32Ty = Type::getInt32Ty(Ctx); +  GlobalVariable *Var = +      new GlobalVariable(*M, Int32Ty, true, GlobalValue::ExternalLinkage, +                         Constant::getAllOnesValue(Int32Ty), "var", nullptr, +                         GlobalVariable::NotThreadLocal, 1); + +  EXPECT_DEATH(Var->setAlignment(536870913U), "Alignment is not a power of 2"); +  EXPECT_DEATH(Var->setAlignment(1073741824U), +               "Alignment is greater than MaximumAlignment"); +} +#endif +#endif +  } // end anonymous namespace diff --git a/unittests/LineEditor/CMakeLists.txt b/unittests/LineEditor/CMakeLists.txt index c6823d8..70d7497 100644 --- a/unittests/LineEditor/CMakeLists.txt +++ b/unittests/LineEditor/CMakeLists.txt @@ -1,5 +1,6 @@  set(LLVM_LINK_COMPONENTS    LineEditor +  Support    )  add_llvm_unittest(LineEditorTests diff --git a/unittests/Linker/CMakeLists.txt b/unittests/Linker/CMakeLists.txt index c3dccb6..05f45c0 100644 --- a/unittests/Linker/CMakeLists.txt +++ b/unittests/Linker/CMakeLists.txt @@ -1,4 +1,5 @@  set(LLVM_LINK_COMPONENTS +  AsmParser    core    linker    ) diff --git a/unittests/Linker/LinkModulesTest.cpp b/unittests/Linker/LinkModulesTest.cpp index 4ccced1..b15d180 100644 --- a/unittests/Linker/LinkModulesTest.cpp +++ b/unittests/Linker/LinkModulesTest.cpp @@ -7,12 +7,14 @@  //  //===----------------------------------------------------------------------===// +#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/Support/SourceMgr.h"  #include "gtest/gtest.h"  using namespace llvm; @@ -88,7 +90,7 @@ TEST_F(LinkModuleTest, BlockAddress) {    Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx)));    Module *LinkedModule = new Module("MyModuleLinked", Ctx); -  Linker::LinkModules(LinkedModule, M.get(), Linker::PreserveSource, nullptr); +  Linker::LinkModules(LinkedModule, M.get());    // Delete the original module.    M.reset(); @@ -122,12 +124,13 @@ TEST_F(LinkModuleTest, BlockAddress) {    delete LinkedModule;  } -TEST_F(LinkModuleTest, EmptyModule) { +static Module *getInternal(LLVMContext &Ctx) {    Module *InternalM = new Module("InternalModule", Ctx);    FunctionType *FTy = FunctionType::get(        Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/); -  F = Function::Create(FTy, Function::InternalLinkage, "bar", InternalM); +  Function *F = +      Function::Create(FTy, Function::InternalLinkage, "bar", InternalM);    F->setCallingConv(CallingConv::C);    BasicBlock *BB = BasicBlock::Create(Ctx, "", F); @@ -141,16 +144,37 @@ TEST_F(LinkModuleTest, EmptyModule) {                           GlobalValue::InternalLinkage, nullptr, "g");    GV->setInitializer(ConstantStruct::get(STy, F)); +  return InternalM; +} + +TEST_F(LinkModuleTest, EmptyModule) { +  std::unique_ptr<Module> InternalM(getInternal(Ctx)); +  std::unique_ptr<Module> EmptyM(new Module("EmptyModule1", Ctx)); +  Linker::LinkModules(EmptyM.get(), InternalM.get()); +} + +TEST_F(LinkModuleTest, EmptyModule2) { +  std::unique_ptr<Module> InternalM(getInternal(Ctx)); +  std::unique_ptr<Module> EmptyM(new Module("EmptyModule1", Ctx)); +  Linker::LinkModules(InternalM.get(), EmptyM.get()); +} + +TEST_F(LinkModuleTest, TypeMerge) { +  LLVMContext C; +  SMDiagnostic Err; + +  const char *M1Str = "%t = type {i32}\n" +                      "@t1 = weak global %t zeroinitializer\n"; +  std::unique_ptr<Module> M1 = parseAssemblyString(M1Str, Err, C); -  Module *EmptyM = new Module("EmptyModule1", Ctx); -  Linker::LinkModules(EmptyM, InternalM, Linker::PreserveSource, nullptr); +  const char *M2Str = "%t = type {i32}\n" +                      "@t2 = weak global %t zeroinitializer\n"; +  std::unique_ptr<Module> M2 = parseAssemblyString(M2Str, Err, C); -  delete EmptyM; -  EmptyM = new Module("EmptyModule2", Ctx); -  Linker::LinkModules(InternalM, EmptyM, Linker::PreserveSource, nullptr); +  Linker::LinkModules(M1.get(), M2.get(), [](const llvm::DiagnosticInfo &){}); -  delete EmptyM; -  delete InternalM; +  EXPECT_EQ(M1->getNamedGlobal("t1")->getType(), +            M1->getNamedGlobal("t2")->getType());  }  } // end anonymous namespace diff --git a/unittests/Linker/Makefile b/unittests/Linker/Makefile index c6058c4..ddbce07 100644 --- a/unittests/Linker/Makefile +++ b/unittests/Linker/Makefile @@ -9,7 +9,7 @@  LEVEL = ../..  TESTNAME = Linker -LINK_COMPONENTS := core linker +LINK_COMPONENTS := core linker asmparser  include $(LEVEL)/Makefile.config  include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/MC/CMakeLists.txt b/unittests/MC/CMakeLists.txt index e2beab2..c82bcde 100644 --- a/unittests/MC/CMakeLists.txt +++ b/unittests/MC/CMakeLists.txt @@ -1,9 +1,18 @@  set(LLVM_LINK_COMPONENTS -  MCAnalysis +  ${LLVM_TARGETS_TO_BUILD} +  MC +  MCDisassembler +  Support    )  add_llvm_unittest(MCTests -  MCAtomTest.cpp +  Disassembler.cpp    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/Disassembler.cpp b/unittests/MC/Disassembler.cpp new file mode 100644 index 0000000..dd0f1ef --- /dev/null +++ b/unittests/MC/Disassembler.cpp @@ -0,0 +1,64 @@ +//===- llvm/unittest/Object/Disassembler.cpp ------------------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/Disassembler.h" +#include "llvm/Support/TargetSelect.h" +#include "gtest/gtest.h" + +using namespace llvm; + +static const char *symbolLookupCallback(void *DisInfo, uint64_t ReferenceValue, +                                        uint64_t *ReferenceType, +                                        uint64_t ReferencePC, +                                        const char **ReferenceName) { +  *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; +  return nullptr; +} + +TEST(Disassembler, Test1) { +  llvm::InitializeAllTargetInfos(); +  llvm::InitializeAllTargetMCs(); +  llvm::InitializeAllDisassemblers(); + +  uint8_t Bytes[] = {0x90, 0x90, 0xeb, 0xfd}; +  uint8_t *BytesP = Bytes; +  const char OutStringSize = 100; +  char OutString[OutStringSize]; +  LLVMDisasmContextRef DCR = LLVMCreateDisasm("x86_64-pc-linux", nullptr, 0, +                                              nullptr, symbolLookupCallback); +  if (!DCR) +    return; + +  size_t InstSize; +  unsigned NumBytes = sizeof(Bytes); +  unsigned PC = 0; + +  InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString, +                                   OutStringSize); +  EXPECT_EQ(InstSize, 1U); +  EXPECT_EQ(StringRef(OutString), "\tnop"); +  PC += InstSize; +  BytesP += InstSize; +  NumBytes -= InstSize; + +  InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString, +                                   OutStringSize); +  EXPECT_EQ(InstSize, 1U); +  EXPECT_EQ(StringRef(OutString), "\tnop"); +  PC += InstSize; +  BytesP += InstSize; +  NumBytes -= InstSize; + +  InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString, +                                   OutStringSize); +  EXPECT_EQ(InstSize, 2U); +  EXPECT_EQ(StringRef(OutString), "\tjmp\t0x1"); + +  LLVMDisasmDispose(DCR); +} diff --git a/unittests/MC/Hexagon/CMakeLists.txt b/unittests/MC/Hexagon/CMakeLists.txt new file mode 100644 index 0000000..6d4ee93 --- /dev/null +++ b/unittests/MC/Hexagon/CMakeLists.txt @@ -0,0 +1,14 @@ +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 new file mode 100644 index 0000000..958a21f --- /dev/null +++ b/unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp @@ -0,0 +1,53 @@ +#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/MCAtomTest.cpp b/unittests/MC/MCAtomTest.cpp deleted file mode 100644 index 16228b5..0000000 --- a/unittests/MC/MCAtomTest.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//===- llvm/unittest/MC/MCAtomTest.cpp - Instructions 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/MC/MCAnalysis/MCAtom.h" -#include "llvm/MC/MCAnalysis/MCModule.h" -#include "gtest/gtest.h" - -namespace llvm { -namespace { - -TEST(MCAtomTest, MCDataSize) { -  MCModule M; -  MCDataAtom *Atom = M.createDataAtom(0, 0); -  EXPECT_EQ(uint64_t(0), Atom->getEndAddr()); -  Atom->addData(0); -  EXPECT_EQ(uint64_t(0), Atom->getEndAddr()); -  Atom->addData(1); -  EXPECT_EQ(uint64_t(1), Atom->getEndAddr()); -  Atom->addData(2); -  EXPECT_EQ(uint64_t(2), Atom->getEndAddr()); -  EXPECT_EQ(size_t(3), Atom->getData().size()); -} - -}  // end anonymous namespace -}  // end namespace llvm diff --git a/unittests/MC/Makefile b/unittests/MC/Makefile index 07a608e..3f8d1ef 100644 --- a/unittests/MC/Makefile +++ b/unittests/MC/Makefile @@ -9,7 +9,7 @@  LEVEL = ../..  TESTNAME = MC -LINK_COMPONENTS := MCAnalysis +LINK_COMPONENTS := all-targets MCDisassembler Object  include $(LEVEL)/Makefile.config  include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/MC/StringTableBuilderTest.cpp b/unittests/MC/StringTableBuilderTest.cpp index d30dc62..6b5185c 100644 --- a/unittests/MC/StringTableBuilderTest.cpp +++ b/unittests/MC/StringTableBuilderTest.cpp @@ -9,20 +9,21 @@  #include "llvm/MC/StringTableBuilder.h"  #include "gtest/gtest.h" +#include "llvm/Support/Endian.h"  #include <string>  using namespace llvm;  namespace { -TEST(StringTableBuilderTest, Basic) { +TEST(StringTableBuilderTest, BasicELF) {    StringTableBuilder B;    B.add("foo");    B.add("bar");    B.add("foobar"); -  B.finalize(); +  B.finalize(StringTableBuilder::ELF);    std::string Expected;    Expected += '\x00'; @@ -37,4 +38,34 @@ TEST(StringTableBuilderTest, Basic) {    EXPECT_EQ(8U, B.getOffset("foo"));  } +TEST(StringTableBuilderTest, BasicWinCOFF) { +  StringTableBuilder B; + +  // Strings must be 9 chars or longer to go in the table. +  B.add("hippopotamus"); +  B.add("pygmy hippopotamus"); +  B.add("river horse"); + +  B.finalize(StringTableBuilder::WinCOFF); + +  // size_field + "pygmy hippopotamus\0" + "river horse\0" +  uint32_t ExpectedSize = 4 + 19 + 12; +  EXPECT_EQ(ExpectedSize, B.data().size()); + +  std::string Expected; + +  ExpectedSize = +      support::endian::byte_swap<uint32_t, support::little>(ExpectedSize); +  Expected.append((const char*)&ExpectedSize, 4); +  Expected += "pygmy hippopotamus"; +  Expected += '\x00'; +  Expected += "river horse"; +  Expected += '\x00'; + +  EXPECT_EQ(Expected, B.data()); +  EXPECT_EQ(4U, B.getOffset("pygmy hippopotamus")); +  EXPECT_EQ(10U, B.getOffset("hippopotamus")); +  EXPECT_EQ(23U, B.getOffset("river horse")); +} +  } diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp index 0fc84c7..7f15776 100644 --- a/unittests/Support/AllocatorTest.cpp +++ b/unittests/Support/AllocatorTest.cpp @@ -17,9 +17,9 @@ namespace {  TEST(AllocatorTest, Basics) {    BumpPtrAllocator Alloc; -  int *a = (int*)Alloc.Allocate(sizeof(int), 0); -  int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 0); -  int *c = (int*)Alloc.Allocate(sizeof(int), 0); +  int *a = (int*)Alloc.Allocate(sizeof(int), 1); +  int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 1); +  int *c = (int*)Alloc.Allocate(sizeof(int), 1);    *a = 1;    b[0] = 2;    b[9] = 2; @@ -49,11 +49,11 @@ TEST(AllocatorTest, Basics) {  // Allocate enough bytes to create three slabs.  TEST(AllocatorTest, ThreeSlabs) {    BumpPtrAllocator Alloc; -  Alloc.Allocate(3000, 0); +  Alloc.Allocate(3000, 1);    EXPECT_EQ(1U, Alloc.GetNumSlabs()); -  Alloc.Allocate(3000, 0); +  Alloc.Allocate(3000, 1);    EXPECT_EQ(2U, Alloc.GetNumSlabs()); -  Alloc.Allocate(3000, 0); +  Alloc.Allocate(3000, 1);    EXPECT_EQ(3U, Alloc.GetNumSlabs());  } @@ -61,15 +61,15 @@ TEST(AllocatorTest, ThreeSlabs) {  // again.  TEST(AllocatorTest, TestReset) {    BumpPtrAllocator Alloc; -  Alloc.Allocate(3000, 0); +  Alloc.Allocate(3000, 1);    EXPECT_EQ(1U, Alloc.GetNumSlabs()); -  Alloc.Allocate(3000, 0); +  Alloc.Allocate(3000, 1);    EXPECT_EQ(2U, Alloc.GetNumSlabs());    Alloc.Reset();    EXPECT_EQ(1U, Alloc.GetNumSlabs()); -  Alloc.Allocate(3000, 0); +  Alloc.Allocate(3000, 1);    EXPECT_EQ(1U, Alloc.GetNumSlabs()); -  Alloc.Allocate(3000, 0); +  Alloc.Allocate(3000, 1);    EXPECT_EQ(2U, Alloc.GetNumSlabs());  } @@ -99,11 +99,11 @@ TEST(AllocatorTest, TestOverflow) {    BumpPtrAllocator Alloc;    // Fill the slab right up until the end pointer. -  Alloc.Allocate(4096, 0); +  Alloc.Allocate(4096, 1);    EXPECT_EQ(1U, Alloc.GetNumSlabs());    // If we don't allocate a new slab, then we will have overflowed. -  Alloc.Allocate(1, 0); +  Alloc.Allocate(1, 1);    EXPECT_EQ(2U, Alloc.GetNumSlabs());  } @@ -111,7 +111,20 @@ TEST(AllocatorTest, TestOverflow) {  TEST(AllocatorTest, TestSmallSlabSize) {    BumpPtrAllocator Alloc; -  Alloc.Allocate(8000, 0); +  Alloc.Allocate(8000, 1); +  EXPECT_EQ(1U, Alloc.GetNumSlabs()); +} + +// Test requesting alignment that goes past the end of the current slab. +TEST(AllocatorTest, TestAlignmentPastSlab) { +  BumpPtrAllocator Alloc; +  Alloc.Allocate(4095, 1); + +  // Aligning the current slab pointer is likely to move it past the end of the +  // slab, which would confuse any unsigned comparisons with the difference of +  // the the end pointer and the aligned pointer. +  Alloc.Allocate(1024, 8192); +    EXPECT_EQ(2U, Alloc.GetNumSlabs());  } @@ -130,7 +143,7 @@ public:      void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*));      // Find the slab start. -    void *Slab = alignPtr((char *)MemBase + sizeof(void *), Alignment); +    void *Slab = (void *)alignAddr((char*)MemBase + sizeof(void *), Alignment);      // Hold a pointer to the base so we can free the whole malloced block.      ((void**)Slab)[-1] = MemBase; @@ -155,7 +168,7 @@ TEST(AllocatorTest, TestBigAlignment) {    BumpPtrAllocatorImpl<MockSlabAllocator> Alloc;    // First allocate a tiny bit to ensure we have to re-align things. -  (void)Alloc.Allocate(1, 0); +  (void)Alloc.Allocate(1, 1);    // Now the big chunk with a big alignment.    (void)Alloc.Allocate(3000, 2048); diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 97c5c43..7abdd8a 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -42,3 +42,8 @@ add_llvm_unittest(SupportTests    formatted_raw_ostream_test.cpp    raw_ostream_test.cpp    ) + +# ManagedStatic.cpp uses <pthread>. +if(LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD) +  target_link_libraries(SupportTests pthread) +endif() diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index b2d71ab..ac8d3d8 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -153,14 +153,14 @@ class StrDupSaver : public cl::StringSaver {  };  typedef void ParserFunction(StringRef Source, llvm::cl::StringSaver &Saver, -                            SmallVectorImpl<const char *> &NewArgv); - +                            SmallVectorImpl<const char *> &NewArgv, +                            bool MarkEOLs);  void testCommandLineTokenizer(ParserFunction *parse, const char *Input,                                const char *const Output[], size_t OutputSize) {    SmallVector<const char *, 0> Actual;    StrDupSaver Saver; -  parse(Input, Saver, Actual); +  parse(Input, Saver, Actual, /*MarkEOLs=*/false);    EXPECT_EQ(OutputSize, Actual.size());    for (unsigned I = 0, E = Actual.size(); I != E; ++I) {      if (I < OutputSize) @@ -212,4 +212,23 @@ TEST(CommandLineTest, AliasesWithArguments) {    }  } +void testAliasRequired(int argc, const char *const *argv) { +  StackOption<std::string> Option("option", cl::Required); +  cl::alias Alias("o", llvm::cl::aliasopt(Option)); + +  cl::ParseCommandLineOptions(argc, argv); +  EXPECT_EQ("x", Option); +  EXPECT_EQ(1, Option.getNumOccurrences()); + +  Alias.removeArgument(); +} + +TEST(CommandLineTest, AliasRequired) { +  const char *opts1[] = { "-tool", "-option=x" }; +  const char *opts2[] = { "-tool", "-o", "x" }; +  testAliasRequired(array_lengthof(opts1), opts1); +  testAliasRequired(array_lengthof(opts2), opts2); +} + +  }  // anonymous namespace diff --git a/unittests/Support/ConvertUTFTest.cpp b/unittests/Support/ConvertUTFTest.cpp index 16c9beb..510b1da 100644 --- a/unittests/Support/ConvertUTFTest.cpp +++ b/unittests/Support/ConvertUTFTest.cpp @@ -39,30 +39,30 @@ TEST(ConvertUTFTest, ConvertUTF16BigEndianToUTF8String) {  TEST(ConvertUTFTest, OddLengthInput) {    std::string Result; -  bool Success = convertUTF16ToUTF8String(ArrayRef<char>("xxxxx", 5), Result); +  bool Success = convertUTF16ToUTF8String(makeArrayRef("xxxxx", 5), Result);    EXPECT_FALSE(Success);  }  TEST(ConvertUTFTest, Empty) {    std::string Result; -  bool Success = convertUTF16ToUTF8String(ArrayRef<char>(), Result); +  bool Success = convertUTF16ToUTF8String(None, Result);    EXPECT_TRUE(Success);    EXPECT_TRUE(Result.empty());  }  TEST(ConvertUTFTest, HasUTF16BOM) { -  bool HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xff\xfe", 2)); +  bool HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xff\xfe", 2));    EXPECT_TRUE(HasBOM); -  HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe\xff", 2)); +  HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff", 2));    EXPECT_TRUE(HasBOM); -  HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe\xff ", 3)); +  HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff ", 3));    EXPECT_TRUE(HasBOM); // Don't care about odd lengths. -  HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe\xff\x00asdf", 6)); +  HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff\x00asdf", 6));    EXPECT_TRUE(HasBOM); -  HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>()); +  HasBOM = hasUTF16ByteOrderMark(None);    EXPECT_FALSE(HasBOM); -  HasBOM = hasUTF16ByteOrderMark(ArrayRef<char>("\xfe", 1)); +  HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe", 1));    EXPECT_FALSE(HasBOM);  } diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp index d76e7d6..82bbe09 100644 --- a/unittests/Support/ErrorOrTest.cpp +++ b/unittests/Support/ErrorOrTest.cpp @@ -60,5 +60,36 @@ TEST(ErrorOr, Covariant) {    ErrorOr<std::unique_ptr<B> > b1(ErrorOr<std::unique_ptr<D> >(nullptr));    b1 = ErrorOr<std::unique_ptr<D> >(nullptr); + +  ErrorOr<std::unique_ptr<int>> b2(ErrorOr<int *>(nullptr)); +  ErrorOr<int *> b3(nullptr); +  ErrorOr<std::unique_ptr<int>> b4(b3);  } + +// ErrorOr<int*> x(nullptr); +// ErrorOr<std::unique_ptr<int>> y = x; // invalid conversion +static_assert( +    !std::is_convertible<const ErrorOr<int *> &, +                         ErrorOr<std::unique_ptr<int>>>::value, +    "do not invoke explicit ctors in implicit conversion from lvalue"); + +// ErrorOr<std::unique_ptr<int>> y = ErrorOr<int*>(nullptr); // invalid +//                                                           // conversion +static_assert( +    !std::is_convertible<ErrorOr<int *> &&, +                         ErrorOr<std::unique_ptr<int>>>::value, +    "do not invoke explicit ctors in implicit conversion from rvalue"); + +// ErrorOr<int*> x(nullptr); +// ErrorOr<std::unique_ptr<int>> y; +// y = x; // invalid conversion +static_assert(!std::is_assignable<ErrorOr<std::unique_ptr<int>>, +                                  const ErrorOr<int *> &>::value, +              "do not invoke explicit ctors in assignment"); + +// ErrorOr<std::unique_ptr<int>> x; +// x = ErrorOr<int*>(nullptr); // invalid conversion +static_assert(!std::is_assignable<ErrorOr<std::unique_ptr<int>>, +                                  ErrorOr<int *> &&>::value, +              "do not invoke explicit ctors in assignment");  } // end anon namespace diff --git a/unittests/Support/FileOutputBufferTest.cpp b/unittests/Support/FileOutputBufferTest.cpp index b086f1e..911d516 100644 --- a/unittests/Support/FileOutputBufferTest.cpp +++ b/unittests/Support/FileOutputBufferTest.cpp @@ -7,6 +7,7 @@  //  //===----------------------------------------------------------------------===// +#include "llvm/Support/Errc.h"  #include "llvm/Support/FileOutputBuffer.h"  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/FileSystem.h" @@ -65,9 +66,8 @@ TEST(FileOutputBuffer, Test) {      // Do *not* commit buffer.    }    // Verify file does not exist (because buffer not committed). -  bool Exists = false; -  ASSERT_NO_ERROR(fs::exists(Twine(File2), Exists)); -  EXPECT_FALSE(Exists); +  ASSERT_EQ(fs::access(Twine(File2), fs::AccessMode::Exist), +            errc::no_such_file_or_directory);    ASSERT_NO_ERROR(fs::remove(File2.str()));    // TEST 3: Verify sizing down case. diff --git a/unittests/Support/LEB128Test.cpp b/unittests/Support/LEB128Test.cpp index b1ca13e..76b63e5 100644 --- a/unittests/Support/LEB128Test.cpp +++ b/unittests/Support/LEB128Test.cpp @@ -106,6 +106,7 @@ TEST(LEB128Test, DecodeULEB128) {    EXPECT_DECODE_ULEB128_EQ(0xffu, "\xff\x01");    EXPECT_DECODE_ULEB128_EQ(0x100u, "\x80\x02");    EXPECT_DECODE_ULEB128_EQ(0x101u, "\x81\x02"); +  EXPECT_DECODE_ULEB128_EQ(4294975616ULL, "\x80\xc1\x80\x80\x10");    // Decode ULEB128 with extra padding bytes    EXPECT_DECODE_ULEB128_EQ(0u, "\x80\x00"); @@ -118,6 +119,42 @@ TEST(LEB128Test, DecodeULEB128) {  #undef EXPECT_DECODE_ULEB128_EQ  } +TEST(LEB128Test, DecodeSLEB128) { +#define EXPECT_DECODE_SLEB128_EQ(EXPECTED, VALUE) \ +  do { \ +    unsigned ActualSize = 0; \ +    int64_t Actual = decodeSLEB128(reinterpret_cast<const uint8_t *>(VALUE), \ +                                    &ActualSize); \ +    EXPECT_EQ(sizeof(VALUE) - 1, ActualSize); \ +    EXPECT_EQ(EXPECTED, Actual); \ +  } while (0) + +  // Decode SLEB128 +  EXPECT_DECODE_SLEB128_EQ(0L, "\x00"); +  EXPECT_DECODE_SLEB128_EQ(1L, "\x01"); +  EXPECT_DECODE_SLEB128_EQ(63L, "\x3f"); +  EXPECT_DECODE_SLEB128_EQ(-64L, "\x40"); +  EXPECT_DECODE_SLEB128_EQ(-63L, "\x41"); +  EXPECT_DECODE_SLEB128_EQ(-1L, "\x7f"); +  EXPECT_DECODE_SLEB128_EQ(128L, "\x80\x01"); +  EXPECT_DECODE_SLEB128_EQ(129L, "\x81\x01"); +  EXPECT_DECODE_SLEB128_EQ(-129L, "\xff\x7e"); +  EXPECT_DECODE_SLEB128_EQ(-128L, "\x80\x7f"); +  EXPECT_DECODE_SLEB128_EQ(-127L, "\x81\x7f"); +  EXPECT_DECODE_SLEB128_EQ(64L, "\xc0\x00"); +  EXPECT_DECODE_SLEB128_EQ(-12345L, "\xc7\x9f\x7f"); + +  // Decode unnormalized SLEB128 with extra padding bytes. +  EXPECT_DECODE_SLEB128_EQ(0L, "\x80\x00"); +  EXPECT_DECODE_SLEB128_EQ(0L, "\x80\x80\x00"); +  EXPECT_DECODE_SLEB128_EQ(0x7fL, "\xff\x00"); +  EXPECT_DECODE_SLEB128_EQ(0x7fL, "\xff\x80\x00"); +  EXPECT_DECODE_SLEB128_EQ(0x80L, "\x80\x81\x00"); +  EXPECT_DECODE_SLEB128_EQ(0x80L, "\x80\x81\x80\x00"); + +#undef EXPECT_DECODE_SLEB128_EQ +} +  TEST(LEB128Test, SLEB128Size) {    // Positive Value Testing Plan:    // (1) 128 ^ n - 1 ........ need (n+1) bytes diff --git a/unittests/Support/LineIteratorTest.cpp b/unittests/Support/LineIteratorTest.cpp index 18f3fa9..67f9d97 100644 --- a/unittests/Support/LineIteratorTest.cpp +++ b/unittests/Support/LineIteratorTest.cpp @@ -17,9 +17,9 @@ using namespace llvm::sys;  namespace {  TEST(LineIteratorTest, Basic) { -  std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer("line 1\n" -                                                                  "line 2\n" -                                                                  "line 3")); +  std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer("line 1\n" +                                                                    "line 2\n" +                                                                    "line 3");    line_iterator I = line_iterator(*Buffer), E; @@ -40,15 +40,17 @@ TEST(LineIteratorTest, Basic) {    EXPECT_EQ(E, I);  } -TEST(LineIteratorTest, CommentSkipping) { +TEST(LineIteratorTest, CommentAndBlankSkipping) {    std::unique_ptr<MemoryBuffer> Buffer(        MemoryBuffer::getMemBuffer("line 1\n"                                   "line 2\n"                                   "# Comment 1\n" -                                 "line 4\n" +                                 "\n" +                                 "line 5\n" +                                 "\n"                                   "# Comment 2")); -  line_iterator I = line_iterator(*Buffer, '#'), E; +  line_iterator I = line_iterator(*Buffer, true, '#'), E;    EXPECT_FALSE(I.is_at_eof());    EXPECT_NE(E, I); @@ -59,20 +61,57 @@ TEST(LineIteratorTest, CommentSkipping) {    EXPECT_EQ("line 2", *I);    EXPECT_EQ(2, I.line_number());    ++I; -  EXPECT_EQ("line 4", *I); -  EXPECT_EQ(4, I.line_number()); +  EXPECT_EQ("line 5", *I); +  EXPECT_EQ(5, I.line_number()); +  ++I; + +  EXPECT_TRUE(I.is_at_eof()); +  EXPECT_EQ(E, I); +} + +TEST(LineIteratorTest, CommentSkippingKeepBlanks) { +  std::unique_ptr<MemoryBuffer> Buffer( +      MemoryBuffer::getMemBuffer("line 1\n" +                                 "line 2\n" +                                 "# Comment 1\n" +                                 "# Comment 2\n" +                                 "\n" +                                 "line 6\n" +                                 "\n" +                                 "# Comment 3")); + +  line_iterator I = line_iterator(*Buffer, false, '#'), E; + +  EXPECT_FALSE(I.is_at_eof()); +  EXPECT_NE(E, I); + +  EXPECT_EQ("line 1", *I); +  EXPECT_EQ(1, I.line_number()); +  ++I; +  EXPECT_EQ("line 2", *I); +  EXPECT_EQ(2, I.line_number()); +  ++I; +  EXPECT_EQ("", *I); +  EXPECT_EQ(5, I.line_number()); +  ++I; +  EXPECT_EQ("line 6", *I); +  EXPECT_EQ(6, I.line_number()); +  ++I; +  EXPECT_EQ("", *I); +  EXPECT_EQ(7, I.line_number());    ++I;    EXPECT_TRUE(I.is_at_eof());    EXPECT_EQ(E, I);  } +  TEST(LineIteratorTest, BlankSkipping) { -  std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer("\n\n\n" -                                                                  "line 1\n" -                                                                  "\n\n\n" -                                                                  "line 2\n" -                                                                  "\n\n\n")); +  std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer("\n\n\n" +                                                                    "line 1\n" +                                                                    "\n\n\n" +                                                                    "line 2\n" +                                                                    "\n\n\n");    line_iterator I = line_iterator(*Buffer), E; @@ -90,26 +129,65 @@ TEST(LineIteratorTest, BlankSkipping) {    EXPECT_EQ(E, I);  } +TEST(LineIteratorTest, BlankKeeping) { +  std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer("\n\n" +                                                                    "line 3\n" +                                                                    "\n" +                                                                    "line 5\n" +                                                                    "\n\n"); +  line_iterator I = line_iterator(*Buffer, false), E; + +  EXPECT_FALSE(I.is_at_eof()); +  EXPECT_NE(E, I); + +  EXPECT_EQ("", *I); +  EXPECT_EQ(1, I.line_number()); +  ++I; +  EXPECT_EQ("", *I); +  EXPECT_EQ(2, I.line_number()); +  ++I; +  EXPECT_EQ("line 3", *I); +  EXPECT_EQ(3, I.line_number()); +  ++I; +  EXPECT_EQ("", *I); +  EXPECT_EQ(4, I.line_number()); +  ++I; +  EXPECT_EQ("line 5", *I); +  EXPECT_EQ(5, I.line_number()); +  ++I; +  EXPECT_EQ("", *I); +  EXPECT_EQ(6, I.line_number()); +  ++I; +  EXPECT_EQ("", *I); +  EXPECT_EQ(7, I.line_number()); +  ++I; + +  EXPECT_TRUE(I.is_at_eof()); +  EXPECT_EQ(E, I); +} +  TEST(LineIteratorTest, EmptyBuffers) { -  std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer("")); +  std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer("");    EXPECT_TRUE(line_iterator(*Buffer).is_at_eof());    EXPECT_EQ(line_iterator(), line_iterator(*Buffer)); +  EXPECT_TRUE(line_iterator(*Buffer, false).is_at_eof()); +  EXPECT_EQ(line_iterator(), line_iterator(*Buffer, false)); -  Buffer.reset(MemoryBuffer::getMemBuffer("\n\n\n")); +  Buffer = MemoryBuffer::getMemBuffer("\n\n\n");    EXPECT_TRUE(line_iterator(*Buffer).is_at_eof());    EXPECT_EQ(line_iterator(), line_iterator(*Buffer)); -  Buffer.reset(MemoryBuffer::getMemBuffer("# foo\n" -                                          "\n" -                                          "# bar")); -  EXPECT_TRUE(line_iterator(*Buffer, '#').is_at_eof()); -  EXPECT_EQ(line_iterator(), line_iterator(*Buffer, '#')); - -  Buffer.reset(MemoryBuffer::getMemBuffer("\n" -                                          "# baz\n" -                                          "\n")); -  EXPECT_TRUE(line_iterator(*Buffer, '#').is_at_eof()); -  EXPECT_EQ(line_iterator(), line_iterator(*Buffer, '#')); +  Buffer = MemoryBuffer::getMemBuffer("# foo\n" +                                      "\n" +                                      "# bar"); +  EXPECT_TRUE(line_iterator(*Buffer, true, '#').is_at_eof()); +  EXPECT_EQ(line_iterator(), line_iterator(*Buffer, true, '#')); + +  Buffer = MemoryBuffer::getMemBuffer("\n" +                                      "# baz\n" +                                      "\n"); +  EXPECT_TRUE(line_iterator(*Buffer, true, '#').is_at_eof()); +  EXPECT_EQ(line_iterator(), line_iterator(*Buffer, true, '#'));  }  } // anonymous namespace diff --git a/unittests/Support/LockFileManagerTest.cpp b/unittests/Support/LockFileManagerTest.cpp index 885b7d6..efe3c30 100644 --- a/unittests/Support/LockFileManagerTest.cpp +++ b/unittests/Support/LockFileManagerTest.cpp @@ -95,7 +95,7 @@ TEST(LockFileManagerTest, RelativePath) {    char PathBuf[1024];    const char *OrigPath = getcwd(PathBuf, 1024); -  chdir(TmpDir.c_str()); +  ASSERT_FALSE(chdir(TmpDir.c_str()));    sys::fs::create_directory("inner");    SmallString<64> LockedFile("inner"); @@ -118,7 +118,7 @@ TEST(LockFileManagerTest, RelativePath) {    EC = sys::fs::remove("inner");    ASSERT_FALSE(EC); -  chdir(OrigPath); +  ASSERT_FALSE(chdir(OrigPath));    EC = sys::fs::remove(StringRef(TmpDir));    ASSERT_FALSE(EC); diff --git a/unittests/Support/MD5Test.cpp b/unittests/Support/MD5Test.cpp index 7c1331b..c4fa5cd 100644 --- a/unittests/Support/MD5Test.cpp +++ b/unittests/Support/MD5Test.cpp @@ -41,19 +41,19 @@ void TestMD5Sum(StringRef Input, StringRef Final) {  }  TEST(MD5Test, MD5) { -  TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"", (size_t) 0), +  TestMD5Sum(makeArrayRef((const uint8_t *)"", (size_t) 0),               "d41d8cd98f00b204e9800998ecf8427e"); -  TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"a", (size_t) 1), +  TestMD5Sum(makeArrayRef((const uint8_t *)"a", (size_t) 1),               "0cc175b9c0f1b6a831c399e269772661"); -  TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"abcdefghijklmnopqrstuvwxyz", -                               (size_t) 26), +  TestMD5Sum(makeArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz", +                          (size_t) 26),               "c3fcd3d76192e4007dfb496cca67e13b"); -  TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"\0", (size_t) 1), +  TestMD5Sum(makeArrayRef((const uint8_t *)"\0", (size_t) 1),               "93b885adfe0da089cdf634904fd59f71"); -  TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"a\0", (size_t) 2), +  TestMD5Sum(makeArrayRef((const uint8_t *)"a\0", (size_t) 2),               "4144e195f46de78a3623da7364d04f11"); -  TestMD5Sum(ArrayRef<uint8_t>((const uint8_t *)"abcdefghijklmnopqrstuvwxyz\0", -                               (size_t) 27), +  TestMD5Sum(makeArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz\0", +                          (size_t) 27),               "81948d1f1554f58cd1a56ebb01f808cb");    TestMD5Sum("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b");  } diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp index 93bf301..1cdd6ad 100644 --- a/unittests/Support/MemoryBufferTest.cpp +++ b/unittests/Support/MemoryBufferTest.cpp @@ -169,4 +169,54 @@ TEST_F(MemoryBufferTest, getOpenFileReopened) {    testGetOpenFileSlice(true);  } + +TEST_F(MemoryBufferTest, slice) { +  // Create a file that is six pages long with different data on each page. +  int FD; +  SmallString<64> TestPath; +  sys::fs::createTemporaryFile("MemoryBufferTest_Slice", "temp", FD, TestPath); +  raw_fd_ostream OF(FD, true, /*unbuffered=*/true); +  for (unsigned i = 0; i < 0x2000 / 8; ++i) { +    OF << "12345678"; +  } +  for (unsigned i = 0; i < 0x2000 / 8; ++i) { +    OF << "abcdefgh"; +  } +  for (unsigned i = 0; i < 0x2000 / 8; ++i) { +    OF << "ABCDEFGH"; +  } +  OF.close(); + +  // Try offset of one page. +  ErrorOr<OwningBuffer> MB = MemoryBuffer::getFileSlice(TestPath.str(), +                                                        0x4000, 0x1000); +  std::error_code EC = MB.getError(); +  ASSERT_FALSE(EC); +  EXPECT_EQ(0x4000UL, MB.get()->getBufferSize()); +  +  StringRef BufData = MB.get()->getBuffer(); +  EXPECT_TRUE(BufData.substr(0x0000,8).equals("12345678")); +  EXPECT_TRUE(BufData.substr(0x0FF8,8).equals("12345678")); +  EXPECT_TRUE(BufData.substr(0x1000,8).equals("abcdefgh")); +  EXPECT_TRUE(BufData.substr(0x2FF8,8).equals("abcdefgh")); +  EXPECT_TRUE(BufData.substr(0x3000,8).equals("ABCDEFGH")); +  EXPECT_TRUE(BufData.substr(0x3FF8,8).equals("ABCDEFGH")); +    +  // Try non-page aligned. +  ErrorOr<OwningBuffer> MB2 = MemoryBuffer::getFileSlice(TestPath.str(), +                                                         0x3000, 0x0800); +  EC = MB2.getError(); +  ASSERT_FALSE(EC); +  EXPECT_EQ(0x3000UL, MB2.get()->getBufferSize()); +   +  StringRef BufData2 = MB2.get()->getBuffer(); +  EXPECT_TRUE(BufData2.substr(0x0000,8).equals("12345678")); +  EXPECT_TRUE(BufData2.substr(0x17F8,8).equals("12345678")); +  EXPECT_TRUE(BufData2.substr(0x1800,8).equals("abcdefgh")); +  EXPECT_TRUE(BufData2.substr(0x2FF8,8).equals("abcdefgh")); +  +} + + +  } diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index cf2e1ee..502cda2 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -16,6 +16,7 @@  #include "gtest/gtest.h"  #ifdef LLVM_ON_WIN32 +#include <Windows.h>  #include <winerror.h>  #endif @@ -91,6 +92,7 @@ TEST(Support, Path) {    paths.push_back("c:\\foo/");    paths.push_back("c:/foo\\bar"); +  SmallVector<StringRef, 5> ComponentStack;    for (SmallVector<StringRef, 40>::const_iterator i = paths.begin(),                                                    e = paths.end();                                                    i != e; @@ -100,18 +102,17 @@ TEST(Support, Path) {                                     ci != ce;                                     ++ci) {        ASSERT_FALSE(ci->empty()); +      ComponentStack.push_back(*ci);      } -#if 0 // Valgrind is whining about this. -    outs() << "    Reverse Iteration: [";      for (sys::path::reverse_iterator ci = sys::path::rbegin(*i),                                       ce = sys::path::rend(*i);                                       ci != ce;                                       ++ci) { -      outs() << *ci << ','; +      ASSERT_TRUE(*ci == ComponentStack.back()); +      ComponentStack.pop_back();      } -    outs() << "]\n"; -#endif +    ASSERT_TRUE(ComponentStack.empty());      path::has_root_path(*i);      path::root_path(*i); @@ -141,7 +142,7 @@ TEST(Support, Path) {      StringRef filename(temp_store.begin(), temp_store.size()), stem, ext;      stem = path::stem(filename);      ext  = path::extension(filename); -    EXPECT_EQ(*(--sys::path::end(filename)), (stem + ext).str()); +    EXPECT_EQ(*sys::path::rbegin(filename), (stem + ext).str());      path::native(*i, temp_store);    } @@ -227,7 +228,7 @@ TEST(Support, AbsolutePathIteratorEnd) {  #endif    for (StringRef Path : Paths) { -    StringRef LastComponent = *--path::end(Path); +    StringRef LastComponent = *path::rbegin(Path);      EXPECT_EQ(".", LastComponent);    } @@ -239,7 +240,7 @@ TEST(Support, AbsolutePathIteratorEnd) {  #endif    for (StringRef Path : RootPaths) { -    StringRef LastComponent = *--path::end(Path); +    StringRef LastComponent = *path::rbegin(Path);      EXPECT_EQ(1u, LastComponent.size());      EXPECT_TRUE(path::is_separator(LastComponent[0]));    } @@ -261,7 +262,7 @@ TEST(Support, HomeDirectory) {  class FileSystemTest : public testing::Test {  protected:    /// Unique temporary directory in which all created filesystem entities must -  /// be placed. It is recursively removed at the end of each test. +  /// be placed. It is removed at the end of each test (must be empty).    SmallString<128> TestDirectory;    virtual void SetUp() { @@ -334,9 +335,7 @@ TEST_F(FileSystemTest, TempFiles) {        fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath));    // Make sure it exists. -  bool TempFileExists; -  ASSERT_NO_ERROR(sys::fs::exists(Twine(TempPath), TempFileExists)); -  EXPECT_TRUE(TempFileExists); +  ASSERT_TRUE(sys::fs::exists(Twine(TempPath)));    // Create another temp tile.    int FD2; @@ -363,8 +362,8 @@ TEST_F(FileSystemTest, TempFiles) {    EXPECT_EQ(B.type(), fs::file_type::file_not_found);    // Make sure Temp2 doesn't exist. -  ASSERT_NO_ERROR(fs::exists(Twine(TempPath2), TempFileExists)); -  EXPECT_FALSE(TempFileExists); +  ASSERT_EQ(fs::access(Twine(TempPath2), sys::fs::AccessMode::Exist), +            errc::no_such_file_or_directory);    SmallString<64> TempPath3;    ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "", TempPath3)); @@ -387,8 +386,8 @@ TEST_F(FileSystemTest, TempFiles) {    ASSERT_NO_ERROR(fs::remove(Twine(TempPath2)));    // Make sure Temp1 doesn't exist. -  ASSERT_NO_ERROR(fs::exists(Twine(TempPath), TempFileExists)); -  EXPECT_FALSE(TempFileExists); +  ASSERT_EQ(fs::access(Twine(TempPath), sys::fs::AccessMode::Exist), +            errc::no_such_file_or_directory);  #ifdef LLVM_ON_WIN32    // Path name > 260 chars should get an error. @@ -398,8 +397,16 @@ TEST_F(FileSystemTest, TempFiles) {      "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4"      "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2"      "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; -  EXPECT_EQ(fs::createUniqueFile(Twine(Path270), FileDescriptor, TempPath), -            errc::no_such_file_or_directory); +  EXPECT_EQ(fs::createUniqueFile(Path270, FileDescriptor, TempPath), +            errc::invalid_argument); +  // Relative path < 247 chars, no problem. +  const char *Path216 = +    "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6" +    "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" +    "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" +    "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; +  ASSERT_NO_ERROR(fs::createTemporaryFile(Path216, "", TempPath)); +  ASSERT_NO_ERROR(fs::remove(Twine(TempPath)));  #endif  } @@ -409,6 +416,54 @@ TEST_F(FileSystemTest, CreateDir) {    ASSERT_EQ(fs::create_directory(Twine(TestDirectory) + "foo", false),              errc::file_exists);    ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "foo")); + +#ifdef LLVM_ON_WIN32 +  // Prove that create_directories() can handle a pathname > 248 characters, +  // which is the documented limit for CreateDirectory(). +  // (248 is MAX_PATH subtracting room for an 8.3 filename.) +  // Generate a directory path guaranteed to fall into that range. +  size_t TmpLen = TestDirectory.size(); +  const char *OneDir = "\\123456789"; +  size_t OneDirLen = strlen(OneDir); +  ASSERT_LT(OneDirLen, 12U); +  size_t NLevels = ((248 - TmpLen) / OneDirLen) + 1; +  SmallString<260> LongDir(TestDirectory); +  for (size_t I = 0; I < NLevels; ++I) +    LongDir.append(OneDir); +  ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir))); +  ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir))); +  ASSERT_EQ(fs::create_directories(Twine(LongDir), false), +            errc::file_exists); +  // Tidy up, "recursively" removing the directories. +  StringRef ThisDir(LongDir); +  for (size_t J = 0; J < NLevels; ++J) { +    ASSERT_NO_ERROR(fs::remove(ThisDir)); +    ThisDir = path::parent_path(ThisDir); +  } + +  // Similarly for a relative pathname.  Need to set the current directory to +  // TestDirectory so that the one we create ends up in the right place. +  char PreviousDir[260]; +  size_t PreviousDirLen = ::GetCurrentDirectoryA(260, PreviousDir); +  ASSERT_GT(PreviousDirLen, 0U); +  ASSERT_LT(PreviousDirLen, 260U); +  ASSERT_NE(::SetCurrentDirectoryA(TestDirectory.c_str()), 0); +  LongDir.clear(); +  // Generate a relative directory name with absolute length > 248. +  size_t LongDirLen = 249 - TestDirectory.size(); +  LongDir.assign(LongDirLen, 'a'); +  ASSERT_NO_ERROR(fs::create_directory(Twine(LongDir))); +  // While we're here, prove that .. and . handling works in these long paths. +  const char *DotDotDirs = "\\..\\.\\b"; +  LongDir.append(DotDotDirs); +  ASSERT_NO_ERROR(fs::create_directory("b")); +  ASSERT_EQ(fs::create_directory(Twine(LongDir), false), errc::file_exists); +  // And clean up. +  ASSERT_NO_ERROR(fs::remove("b")); +  ASSERT_NO_ERROR(fs::remove( +    Twine(LongDir.substr(0, LongDir.size() - strlen(DotDotDirs))))); +  ASSERT_NE(::SetCurrentDirectoryA(PreviousDir), 0); +#endif  }  TEST_F(FileSystemTest, DirectoryIteration) { @@ -485,6 +540,8 @@ TEST_F(FileSystemTest, DirectoryIteration) {  const char archive[] = "!<arch>\x0A";  const char bitcode[] = "\xde\xc0\x17\x0b";  const char coff_object[] = "\x00\x00......"; +const char coff_bigobj[] = "\x00\x00\xff\xff\x00\x02......" +    "\xc7\xa1\xba\xd1\xee\xba\xa9\x4b\xaf\x20\xfa\xf6\x6a\xa4\xdc\xb8";  const char coff_import_library[] = "\x00\x00\xff\xff....";  const char elf_relocatable[] = { 0x7f, 'E', 'L', 'F', 1, 2, 1, 0, 0,                                   0,    0,   0,   0,   0, 0, 0, 0, 1 }; @@ -501,6 +558,8 @@ 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 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";  TEST_F(FileSystemTest, Magic) {    struct type { @@ -514,6 +573,7 @@ TEST_F(FileSystemTest, Magic) {      DEFINE(archive),      DEFINE(bitcode),      DEFINE(coff_object), +    { "coff_bigobj", coff_bigobj, sizeof(coff_bigobj), fs::file_magic::coff_object },      DEFINE(coff_import_library),      DEFINE(elf_relocatable),      DEFINE(macho_universal_binary), @@ -525,6 +585,7 @@ TEST_F(FileSystemTest, Magic) {      DEFINE(macho_dynamically_linked_shared_lib),      DEFINE(macho_dynamic_linker),      DEFINE(macho_bundle), +    DEFINE(macho_dynamically_linked_shared_lib_stub),      DEFINE(macho_dsym_companion),      DEFINE(windows_resource)  #undef DEFINE @@ -535,8 +596,8 @@ TEST_F(FileSystemTest, Magic) {                                                                       ++i) {      SmallString<128> file_pathname(TestDirectory);      path::append(file_pathname, i->filename); -    std::string ErrMsg; -    raw_fd_ostream file(file_pathname.c_str(), ErrMsg, sys::fs::F_None); +    std::error_code EC; +    raw_fd_ostream file(file_pathname, EC, sys::fs::F_None);      ASSERT_FALSE(file.has_error());      StringRef magic(i->magic_str, i->magic_str_len);      file << magic; @@ -549,27 +610,27 @@ TEST_F(FileSystemTest, Magic) {  #ifdef LLVM_ON_WIN32  TEST_F(FileSystemTest, CarriageReturn) {    SmallString<128> FilePathname(TestDirectory); -  std::string ErrMsg; +  std::error_code EC;    path::append(FilePathname, "test");    { -    raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_Text); -    EXPECT_EQ(ErrMsg, ""); +    raw_fd_ostream File(FilePathname, EC, sys::fs::F_Text); +    ASSERT_NO_ERROR(EC);      File << '\n';    }    { -    auto Buf = MemoryBuffer::getFile(FilePathname.c_str()); +    auto Buf = MemoryBuffer::getFile(FilePathname.str());      EXPECT_TRUE((bool)Buf);      EXPECT_EQ(Buf.get()->getBuffer(), "\r\n");    }    { -    raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_None); -    EXPECT_EQ(ErrMsg, ""); +    raw_fd_ostream File(FilePathname, EC, sys::fs::F_None); +    ASSERT_NO_ERROR(EC);      File << '\n';    }    { -    auto Buf = MemoryBuffer::getFile(FilePathname.c_str()); +    auto Buf = MemoryBuffer::getFile(FilePathname.str());      EXPECT_TRUE((bool)Buf);      EXPECT_EQ(Buf.get()->getBuffer(), "\n");    } @@ -640,22 +701,22 @@ TEST(Support, NormalizePath) {    SmallString<64> Path5("\\a");    SmallString<64> Path6("a\\"); -  ASSERT_NO_ERROR(fs::normalize_separators(Path1)); +  path::native(Path1);    EXPECT_PATH_IS(Path1, "a", "a"); -  ASSERT_NO_ERROR(fs::normalize_separators(Path2)); -  EXPECT_PATH_IS(Path2, "a/b", "a/b"); +  path::native(Path2); +  EXPECT_PATH_IS(Path2, "a\\b", "a/b"); -  ASSERT_NO_ERROR(fs::normalize_separators(Path3)); +  path::native(Path3);    EXPECT_PATH_IS(Path3, "a\\b", "a/b"); -  ASSERT_NO_ERROR(fs::normalize_separators(Path4)); +  path::native(Path4);    EXPECT_PATH_IS(Path4, "a\\\\b", "a\\\\b"); -  ASSERT_NO_ERROR(fs::normalize_separators(Path5)); +  path::native(Path5);    EXPECT_PATH_IS(Path5, "\\a", "/a"); -  ASSERT_NO_ERROR(fs::normalize_separators(Path6)); +  path::native(Path6);    EXPECT_PATH_IS(Path6, "a\\", "a/");  #undef EXPECT_PATH_IS diff --git a/unittests/Support/ProcessTest.cpp b/unittests/Support/ProcessTest.cpp index f406072..3045c30 100644 --- a/unittests/Support/ProcessTest.cpp +++ b/unittests/Support/ProcessTest.cpp @@ -31,12 +31,12 @@ TEST(ProcessTest, SelfProcess) {    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()); +  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) { diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp index 4e7316f..c0e6e80 100644 --- a/unittests/Support/ProgramTest.cpp +++ b/unittests/Support/ProgramTest.cpp @@ -34,6 +34,16 @@ void sleep_for(unsigned int seconds) {  #error sleep_for is not implemented on your platform.  #endif +#define ASSERT_NO_ERROR(x)                                                     \ +  if (std::error_code ASSERT_NO_ERROR_ec = x) {                                \ +    SmallString<128> MessageStorage;                                           \ +    raw_svector_ostream Message(MessageStorage);                               \ +    Message << #x ": did not return errc::success.\n"                          \ +            << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n"          \ +            << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n";      \ +    GTEST_FATAL_FAILURE_(MessageStorage.c_str());                              \ +  } else {                                                                     \ +  }  // From TestMain.cpp.  extern const char *TestMainArgv0; @@ -220,4 +230,44 @@ TEST(ProgramTest, TestExecuteNegative) {  } +#ifdef LLVM_ON_WIN32 +const char utf16le_text[] = +    "\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61\x00"; +const char utf16be_text[] = +    "\x00\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61"; +#endif +const char utf8_text[] = "\x6c\x69\x6e\x67\xc3\xbc\x69\xc3\xa7\x61"; + +TEST(ProgramTest, TestWriteWithSystemEncoding) { +  SmallString<128> TestDirectory; +  ASSERT_NO_ERROR(fs::createUniqueDirectory("program-test", TestDirectory)); +  errs() << "Test Directory: " << TestDirectory << '\n'; +  errs().flush(); +  SmallString<128> file_pathname(TestDirectory); +  path::append(file_pathname, "international-file.txt"); +  // Only on Windows we should encode in UTF16. For other systems, use UTF8 +  ASSERT_NO_ERROR(sys::writeFileWithEncoding(file_pathname.c_str(), utf8_text, +                                             sys::WEM_UTF16)); +  int fd = 0; +  ASSERT_NO_ERROR(fs::openFileForRead(file_pathname.c_str(), fd)); +#if defined(LLVM_ON_WIN32) +  char buf[18]; +  ASSERT_EQ(::read(fd, buf, 18), 18); +  if (strncmp(buf, "\xfe\xff", 2) == 0) { // UTF16-BE +    ASSERT_EQ(strncmp(&buf[2], utf16be_text, 16), 0); +  } else if (strncmp(buf, "\xff\xfe", 2) == 0) { // UTF16-LE +    ASSERT_EQ(strncmp(&buf[2], utf16le_text, 16), 0); +  } else { +    FAIL() << "Invalid BOM in UTF-16 file"; +  } +#else +  char buf[10]; +  ASSERT_EQ(::read(fd, buf, 10), 10); +  ASSERT_EQ(strncmp(buf, utf8_text, 10), 0); +#endif +  ::close(fd); +  ASSERT_NO_ERROR(fs::remove(file_pathname.str())); +  ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); +} +  } // end anonymous namespace diff --git a/unittests/Support/SourceMgrTest.cpp b/unittests/Support/SourceMgrTest.cpp index 2b69fe9..79c2d72 100644 --- a/unittests/Support/SourceMgrTest.cpp +++ b/unittests/Support/SourceMgrTest.cpp @@ -23,8 +23,9 @@ public:    std::string Output;    void setMainBuffer(StringRef Text, StringRef BufferName) { -    MemoryBuffer *MainBuffer = MemoryBuffer::getMemBuffer(Text, BufferName); -    MainBufferID = SM.AddNewSourceBuffer(MainBuffer, llvm::SMLoc()); +    std::unique_ptr<MemoryBuffer> MainBuffer = +        MemoryBuffer::getMemBuffer(Text, BufferName); +    MainBufferID = SM.AddNewSourceBuffer(std::move(MainBuffer), llvm::SMLoc());    }    SMLoc getLoc(unsigned Offset) { diff --git a/unittests/Support/SpecialCaseListTest.cpp b/unittests/Support/SpecialCaseListTest.cpp index bb9c351..740dbfe 100644 --- a/unittests/Support/SpecialCaseListTest.cpp +++ b/unittests/Support/SpecialCaseListTest.cpp @@ -17,14 +17,15 @@ namespace {  class SpecialCaseListTest : public ::testing::Test {  protected: -  SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) { -    std::unique_ptr<MemoryBuffer> MB(MemoryBuffer::getMemBuffer(List)); +  std::unique_ptr<SpecialCaseList> makeSpecialCaseList(StringRef List, +                                                       std::string &Error) { +    std::unique_ptr<MemoryBuffer> MB = MemoryBuffer::getMemBuffer(List);      return SpecialCaseList::create(MB.get(), Error);    } -  SpecialCaseList *makeSpecialCaseList(StringRef List) { +  std::unique_ptr<SpecialCaseList> makeSpecialCaseList(StringRef List) {      std::string Error; -    SpecialCaseList *SCL = makeSpecialCaseList(List, Error); +    auto SCL = makeSpecialCaseList(List, Error);      assert(SCL);      assert(Error == "");      return SCL; @@ -32,13 +33,13 @@ protected:  };  TEST_F(SpecialCaseListTest, Basic) { -  std::unique_ptr<SpecialCaseList> SCL( +  std::unique_ptr<SpecialCaseList> SCL =        makeSpecialCaseList("# This is a comment.\n"                            "\n"                            "src:hello\n"                            "src:bye\n"                            "src:hi=category\n" -                          "src:z*=category\n")); +                          "src:z*=category\n");    EXPECT_TRUE(SCL->inSection("src", "hello"));    EXPECT_TRUE(SCL->inSection("src", "bye"));    EXPECT_TRUE(SCL->inSection("src", "hi", "category")); @@ -48,39 +49,21 @@ TEST_F(SpecialCaseListTest, Basic) {    EXPECT_FALSE(SCL->inSection("src", "hello", "category"));  } -TEST_F(SpecialCaseListTest, GlobalInitCompat) { -  std::unique_ptr<SpecialCaseList> SCL( -      makeSpecialCaseList("global:foo=init\n")); +TEST_F(SpecialCaseListTest, GlobalInit) { +  std::unique_ptr<SpecialCaseList> SCL = +      makeSpecialCaseList("global:foo=init\n");    EXPECT_FALSE(SCL->inSection("global", "foo"));    EXPECT_FALSE(SCL->inSection("global", "bar"));    EXPECT_TRUE(SCL->inSection("global", "foo", "init"));    EXPECT_FALSE(SCL->inSection("global", "bar", "init")); -  SCL.reset(makeSpecialCaseList("global-init:foo\n")); -  EXPECT_FALSE(SCL->inSection("global", "foo")); -  EXPECT_FALSE(SCL->inSection("global", "bar")); -  EXPECT_TRUE(SCL->inSection("global", "foo", "init")); -  EXPECT_FALSE(SCL->inSection("global", "bar", "init")); - -  SCL.reset(makeSpecialCaseList("type:t2=init\n")); +  SCL = makeSpecialCaseList("type:t2=init\n");    EXPECT_FALSE(SCL->inSection("type", "t1"));    EXPECT_FALSE(SCL->inSection("type", "t2"));    EXPECT_FALSE(SCL->inSection("type", "t1", "init"));    EXPECT_TRUE(SCL->inSection("type", "t2", "init")); -  SCL.reset(makeSpecialCaseList("global-init-type:t2\n")); -  EXPECT_FALSE(SCL->inSection("type", "t1")); -  EXPECT_FALSE(SCL->inSection("type", "t2")); -  EXPECT_FALSE(SCL->inSection("type", "t1", "init")); -  EXPECT_TRUE(SCL->inSection("type", "t2", "init")); - -  SCL.reset(makeSpecialCaseList("src:hello=init\n")); -  EXPECT_FALSE(SCL->inSection("src", "hello")); -  EXPECT_FALSE(SCL->inSection("src", "bye")); -  EXPECT_TRUE(SCL->inSection("src", "hello", "init")); -  EXPECT_FALSE(SCL->inSection("src", "bye", "init")); - -  SCL.reset(makeSpecialCaseList("global-init-src:hello\n")); +  SCL = makeSpecialCaseList("src:hello=init\n");    EXPECT_FALSE(SCL->inSection("src", "hello"));    EXPECT_FALSE(SCL->inSection("src", "bye"));    EXPECT_TRUE(SCL->inSection("src", "hello", "init")); @@ -88,14 +71,14 @@ TEST_F(SpecialCaseListTest, GlobalInitCompat) {  }  TEST_F(SpecialCaseListTest, Substring) { -  std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("src:hello\n" -                                                           "fun:foo\n" -                                                           "global:bar\n")); +  std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:hello\n" +                                                             "fun:foo\n" +                                                             "global:bar\n");    EXPECT_FALSE(SCL->inSection("src", "othello"));    EXPECT_FALSE(SCL->inSection("fun", "tomfoolery"));    EXPECT_FALSE(SCL->inSection("global", "bartender")); -  SCL.reset(makeSpecialCaseList("fun:*foo*\n")); +  SCL = makeSpecialCaseList("fun:*foo*\n");    EXPECT_TRUE(SCL->inSection("fun", "tomfoolery"));    EXPECT_TRUE(SCL->inSection("fun", "foobar"));  } @@ -117,7 +100,7 @@ TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) {  }  TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { -  std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("")); +  std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("");    EXPECT_FALSE(SCL->inSection("foo", "bar"));  } diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 8aed980..074e27f 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -84,6 +84,13 @@ TEST(YAMLIO, TestMapRead) {    }  } +TEST(YAMLIO, TestMalformedMapRead) { +  FooBar doc; +  Input yin("{foo: 3; bar: 5}", nullptr, suppressErrorMessages); +  yin >> doc; +  EXPECT_TRUE(!!yin.error()); +} +  //  // Test the reading of a yaml sequence of mappings  // diff --git a/unittests/Support/YAMLParserTest.cpp b/unittests/Support/YAMLParserTest.cpp index e983935..823a0d6 100644 --- a/unittests/Support/YAMLParserTest.cpp +++ b/unittests/Support/YAMLParserTest.cpp @@ -18,7 +18,7 @@  namespace llvm {  static void SuppressDiagnosticsOutput(const SMDiagnostic &, void *) { -  // Prevent SourceMgr from writing errors to stderr  +  // Prevent SourceMgr from writing errors to stderr    // to reduce noise in unit test runs.  } @@ -210,8 +210,9 @@ TEST(YAMLParser, DiagnosticFilenameFromBufferID) {    // When we construct a YAML stream over a named buffer,    // we get its ID as filename in diagnostics. -  MemoryBuffer* Buffer = MemoryBuffer::getMemBuffer("[]", "buffername.yaml"); -  yaml::Stream Stream(Buffer, SM); +  std::unique_ptr<MemoryBuffer> Buffer = +      MemoryBuffer::getMemBuffer("[]", "buffername.yaml"); +  yaml::Stream Stream(Buffer->getMemBufferRef(), SM);    Stream.printError(Stream.begin()->getRoot(), "Hello, World!");    EXPECT_EQ("buffername.yaml", GeneratedDiag.getFilename());  } diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp index 44d27d0..39cfaf0 100644 --- a/unittests/Support/raw_ostream_test.cpp +++ b/unittests/Support/raw_ostream_test.cpp @@ -143,4 +143,41 @@ TEST(raw_ostreamTest, WriteEscaped) {    EXPECT_EQ("\\001\\010\\200", Str);  } +TEST(raw_ostreamTest, Justify) {   +  EXPECT_EQ("xyz   ", printToString(left_justify("xyz", 6), 6)); +  EXPECT_EQ("abc",    printToString(left_justify("abc", 3), 3)); +  EXPECT_EQ("big",    printToString(left_justify("big", 1), 3)); +  EXPECT_EQ("   xyz", printToString(right_justify("xyz", 6), 6)); +  EXPECT_EQ("abc",    printToString(right_justify("abc", 3), 3)); +  EXPECT_EQ("big",    printToString(right_justify("big", 1), 3)); +} + +TEST(raw_ostreamTest, FormatHex) {   +  EXPECT_EQ("0x1234",     printToString(format_hex(0x1234, 6), 6)); +  EXPECT_EQ("0x001234",   printToString(format_hex(0x1234, 8), 8)); +  EXPECT_EQ("0x00001234", printToString(format_hex(0x1234, 10), 10)); +  EXPECT_EQ("0x1234",     printToString(format_hex(0x1234, 4), 6)); +  EXPECT_EQ("0xff",       printToString(format_hex(255, 4), 4)); +  EXPECT_EQ("0xFF",       printToString(format_hex(255, 4, true), 4)); +  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("0xffffffffffffffff",      +                          printToString(format_hex(UINT64_MAX, 18), 18)); +  EXPECT_EQ("0x8000000000000000",      +                          printToString(format_hex((INT64_MIN), 18), 18)); +} + +TEST(raw_ostreamTest, FormatDecimal) {   +  EXPECT_EQ("   0",        printToString(format_decimal(0, 4), 4)); +  EXPECT_EQ("  -1",        printToString(format_decimal(-1, 4), 4)); +  EXPECT_EQ("    -1",      printToString(format_decimal(-1, 6), 6)); +  EXPECT_EQ("1234567890",  printToString(format_decimal(1234567890, 10), 10)); +  EXPECT_EQ("  9223372036854775807",  +                          printToString(format_decimal(INT64_MAX, 21), 21)); +  EXPECT_EQ(" -9223372036854775808",  +                          printToString(format_decimal(INT64_MIN, 21), 21)); +} + +  } diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index b3a1f5b..c779979 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -232,7 +232,7 @@ protected:      // Function DI      DIFile File = DBuilder.createFile("filename.c", "/file/dir/"); -    DIArray ParamTypes = DBuilder.getOrCreateArray(ArrayRef<Value*>()); +    DITypeArray ParamTypes = DBuilder.getOrCreateTypeArray(None);      DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes);      DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99,          "filename.c", "/file/dir", "CloneFunc", false, "", 0); @@ -255,10 +255,11 @@ protected:      // Create a local variable around the alloca      DIType IntType = DBuilder.createBasicType("int", 32, 0,          dwarf::DW_ATE_signed); +    DIExpression E = DBuilder.createExpression();      DIVariable Variable = DBuilder.createLocalVariable(        dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true); -    DBuilder.insertDeclare(Alloca, Variable, Store); -    DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, Terminator); +    DBuilder.insertDeclare(Alloca, Variable, E, Store); +    DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, Terminator);      // Finalize the debug info      DBuilder.finalize();  | 
