diff options
author | Stephen Hines <srhines@google.com> | 2014-04-23 16:57:46 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-04-24 15:53:16 -0700 |
commit | 36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch) | |
tree | e6cfb69fbbd937f450eeb83bfb83b9da3b01275a /unittests | |
parent | 69a8640022b04415ae9fac62f8ab090601d8f889 (diff) | |
download | external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2 |
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'unittests')
97 files changed, 3842 insertions, 943 deletions
diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 3c0dfe1..19c47ab 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -597,4 +597,85 @@ TEST(APIntTest, tcDecrement) { EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0); } } + +TEST(APIntTest, arrayAccess) { + // Single word check. + uint64_t E1 = 0x2CA7F46BF6569915ULL; + APInt A1(64, E1); + for (unsigned i = 0, e = 64; i < e; ++i) { + EXPECT_EQ(bool(E1 & (1ULL << i)), + A1[i]); + } + + // Multiword check. + integerPart E2[4] = { + 0xEB6EB136591CBA21ULL, + 0x7B9358BD6A33F10AULL, + 0x7E7FFA5EADD8846ULL, + 0x305F341CA00B613DULL + }; + APInt A2(integerPartWidth*4, ArrayRef<integerPart>(E2, 4)); + for (unsigned i = 0; i < 4; ++i) { + for (unsigned j = 0; j < integerPartWidth; ++j) { + EXPECT_EQ(bool(E2[i] & (1ULL << j)), + A2[i*integerPartWidth + j]); + } + } +} + +TEST(APIntTest, LargeAPIntConstruction) { + // Check that we can properly construct very large APInt. It is very + // unlikely that people will ever do this, but it is a legal input, + // so we should not crash on it. + APInt A9(UINT32_MAX, 0); + EXPECT_FALSE(A9.getBoolValue()); +} + +TEST(APIntTest, nearestLogBase2) { + // Single word check. + + // Test round up. + uint64_t I1 = 0x1800001; + APInt A1(64, I1); + EXPECT_EQ(A1.nearestLogBase2(), A1.ceilLogBase2()); + + // Test round down. + uint64_t I2 = 0x1000011; + APInt A2(64, I2); + EXPECT_EQ(A2.nearestLogBase2(), A2.logBase2()); + + // Test ties round up. + uint64_t I3 = 0x1800000; + APInt A3(64, I3); + EXPECT_EQ(A3.nearestLogBase2(), A3.ceilLogBase2()); + + // Multiple word check. + + // Test round up. + integerPart I4[4] = {0x0, 0xF, 0x18, 0x0}; + APInt A4(integerPartWidth*4, ArrayRef<integerPart>(I4, 4)); + EXPECT_EQ(A4.nearestLogBase2(), A4.ceilLogBase2()); + + // Test round down. + integerPart I5[4] = {0x0, 0xF, 0x10, 0x0}; + APInt A5(integerPartWidth*4, ArrayRef<integerPart>(I5, 4)); + 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)); + EXPECT_EQ(A6.nearestLogBase2(), A6.ceilLogBase2()); + + // Test BitWidth == 1 special cases. + APInt A7(1, 1); + EXPECT_EQ(A7.nearestLogBase2(), 0ULL); + APInt A8(1, 0); + EXPECT_EQ(A8.nearestLogBase2(), UINT32_MAX); + + // Test the zero case when we have a bit width large enough such + // that the bit width is larger than UINT32_MAX-1. + APInt A9(UINT32_MAX, 0); + EXPECT_EQ(A9.nearestLogBase2(), UINT32_MAX); +} + } diff --git a/unittests/ADT/APSIntTest.cpp b/unittests/ADT/APSIntTest.cpp new file mode 100644 index 0000000..eef9c8a --- /dev/null +++ b/unittests/ADT/APSIntTest.cpp @@ -0,0 +1,44 @@ +//===- llvm/unittest/ADT/APSIntTest.cpp - APSInt 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/APSInt.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(APSIntTest, MoveTest) { + APSInt A(32, true); + EXPECT_TRUE(A.isUnsigned()); + + APSInt B(128, false); + A = B; + EXPECT_FALSE(A.isUnsigned()); + + APSInt C(B); + EXPECT_FALSE(C.isUnsigned()); + + APInt Wide(256, 0); + const uint64_t *Bits = Wide.getRawData(); + APSInt D(std::move(Wide)); + EXPECT_TRUE(D.isUnsigned()); + EXPECT_EQ(Bits, D.getRawData()); // Verify that "Wide" was really moved. + + A = APSInt(64, true); + EXPECT_TRUE(A.isUnsigned()); + + Wide = APInt(128, 1); + Bits = Wide.getRawData(); + A = std::move(Wide); + EXPECT_TRUE(A.isUnsigned()); + EXPECT_EQ(Bits, A.getRawData()); // Verify that "Wide" was really moved. +} + +} diff --git a/unittests/ADT/ArrayRefTest.cpp b/unittests/ADT/ArrayRefTest.cpp new file mode 100644 index 0000000..7133ca7 --- /dev/null +++ b/unittests/ADT/ArrayRefTest.cpp @@ -0,0 +1,33 @@ +//===- llvm/unittest/ADT/ArrayRefTest.cpp - ArrayRef 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/ArrayRef.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/raw_ostream.h" +#include "gtest/gtest.h" +using namespace llvm; + +namespace llvm { + +TEST(ArrayRefTest, AllocatorCopy) { + BumpPtrAllocator Alloc; + static const uint16_t Words1[] = { 1, 4, 200, 37 }; + ArrayRef<uint16_t> Array1 = makeArrayRef(Words1, 4); + static const uint16_t Words2[] = { 11, 4003, 67, 64000, 13 }; + ArrayRef<uint16_t> Array2 = makeArrayRef(Words2, 5); + ArrayRef<uint16_t> Array1c = Array1.copy(Alloc); + ArrayRef<uint16_t> Array2c = Array2.copy(Alloc);; + EXPECT_TRUE(Array1.equals(Array1c)); + EXPECT_NE(Array1.data(), Array1c.data()); + EXPECT_TRUE(Array2.equals(Array2c)); + EXPECT_NE(Array2.data(), Array2c.data()); +} + + +} // end anonymous namespace diff --git a/unittests/ADT/BitVectorTest.cpp b/unittests/ADT/BitVectorTest.cpp index d7cde89..3deaff0 100644 --- a/unittests/ADT/BitVectorTest.cpp +++ b/unittests/ADT/BitVectorTest.cpp @@ -356,6 +356,12 @@ TYPED_TEST(BitVectorTest, RangeOps) { EXPECT_TRUE( E.test(1)); EXPECT_TRUE( E.test(32)); EXPECT_FALSE(E.test(33)); + + TypeParam BufferOverrun; + unsigned size = sizeof(unsigned long) * 8; + BufferOverrun.resize(size); + BufferOverrun.reset(0, size); + BufferOverrun.set(0, size); } TYPED_TEST(BitVectorTest, CompoundTestReset) { diff --git a/unittests/ADT/CMakeLists.txt b/unittests/ADT/CMakeLists.txt index 8ad303a..5119723 100644 --- a/unittests/ADT/CMakeLists.txt +++ b/unittests/ADT/CMakeLists.txt @@ -5,6 +5,8 @@ set(LLVM_LINK_COMPONENTS set(ADTSources APFloatTest.cpp APIntTest.cpp + APSIntTest.cpp + ArrayRefTest.cpp BitVectorTest.cpp DAGDeltaAlgorithmTest.cpp DeltaAlgorithmTest.cpp @@ -18,9 +20,12 @@ set(ADTSources IntEqClassesTest.cpp IntervalMapTest.cpp IntrusiveRefCntPtrTest.cpp + MakeUniqueTest.cpp MapVectorTest.cpp OptionalTest.cpp + OwningPtrTest.cpp PackedVectorTest.cpp + PointerIntPairTest.cpp PointerUnionTest.cpp SCCIteratorTest.cpp SmallPtrSetTest.cpp @@ -35,18 +40,8 @@ set(ADTSources TripleTest.cpp TwineTest.cpp VariadicFunctionTest.cpp - polymorphic_ptr_test.cpp ) -# They cannot be compiled on MSVC9 due to its bug. -if(MSVC AND MSVC_VERSION LESS 1600) - set(LLVM_OPTIONAL_SOURCES - DenseMapTest.cpp - SmallVectorTest.cpp - ) - list(REMOVE_ITEM ADTSources ${LLVM_OPTIONAL_SOURCES}) -endif() - add_llvm_unittest(ADTTests ${ADTSources} ) diff --git a/unittests/ADT/DenseMapTest.cpp b/unittests/ADT/DenseMapTest.cpp index 15eb698..dd49071 100644 --- a/unittests/ADT/DenseMapTest.cpp +++ b/unittests/ADT/DenseMapTest.cpp @@ -119,7 +119,7 @@ TYPED_TEST(DenseMapTest, EmptyIntMapTest) { // Lookup tests EXPECT_FALSE(this->Map.count(this->getKey())); EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.end()); -#ifndef _MSC_VER +#if !defined(_MSC_VER) || defined(__clang__) EXPECT_EQ(typename TypeParam::mapped_type(), this->Map.lookup(this->getKey())); #else @@ -209,6 +209,34 @@ TYPED_TEST(DenseMapTest, CopyConstructorTest) { EXPECT_EQ(this->getValue(), copyMap[this->getKey()]); } +// Test copy constructor method where SmallDenseMap isn't small. +TYPED_TEST(DenseMapTest, CopyConstructorNotSmallTest) { + for (int Key = 0; Key < 5; ++Key) + this->Map[this->getKey(Key)] = this->getValue(Key); + TypeParam copyMap(this->Map); + + EXPECT_EQ(5u, copyMap.size()); + for (int Key = 0; Key < 5; ++Key) + EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]); +} + +// Test copying from a default-constructed map. +TYPED_TEST(DenseMapTest, CopyConstructorFromDefaultTest) { + TypeParam copyMap(this->Map); + + EXPECT_TRUE(copyMap.empty()); +} + +// Test copying from an empty map where SmallDenseMap isn't small. +TYPED_TEST(DenseMapTest, CopyConstructorFromEmptyTest) { + for (int Key = 0; Key < 5; ++Key) + this->Map[this->getKey(Key)] = this->getValue(Key); + this->Map.clear(); + TypeParam copyMap(this->Map); + + EXPECT_TRUE(copyMap.empty()); +} + // Test assignment operator method TYPED_TEST(DenseMapTest, AssignmentTest) { this->Map[this->getKey()] = this->getValue(); diff --git a/unittests/ADT/HashingTest.cpp b/unittests/ADT/HashingTest.cpp index 1b3d061..60917ae 100644 --- a/unittests/ADT/HashingTest.cpp +++ b/unittests/ADT/HashingTest.cpp @@ -41,7 +41,7 @@ struct NonPOD { namespace hashing { namespace detail { -template <> struct is_hashable_data<LargeTestInteger> : true_type {}; +template <> struct is_hashable_data<LargeTestInteger> : std::true_type {}; } // namespace detail } // namespace hashing diff --git a/unittests/ADT/MakeUniqueTest.cpp b/unittests/ADT/MakeUniqueTest.cpp new file mode 100644 index 0000000..3b4938a --- /dev/null +++ b/unittests/ADT/MakeUniqueTest.cpp @@ -0,0 +1,76 @@ +//===- 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" +#include <tuple> +using namespace llvm; + +namespace { + +TEST(MakeUniqueTest, SingleObject) { + auto p0 = make_unique<int>(); + EXPECT_TRUE((bool)p0); + EXPECT_EQ(0, *p0); + + auto p1 = make_unique<int>(5); + EXPECT_TRUE((bool)p1); + EXPECT_EQ(5, *p1); + + auto p2 = make_unique<std::tuple<int, int>>(0, 1); + EXPECT_TRUE((bool)p2); + EXPECT_EQ(std::make_tuple(0, 1), *p2); + + auto p3 = make_unique<std::tuple<int, int, int>>(0, 1, 2); + EXPECT_TRUE((bool)p3); + EXPECT_EQ(std::make_tuple(0, 1, 2), *p3); + + auto p4 = make_unique<std::tuple<int, int, int, int>>(0, 1, 2, 3); + EXPECT_TRUE((bool)p4); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3), *p4); + + auto p5 = make_unique<std::tuple<int, int, int, int, int>>(0, 1, 2, 3, 4); + EXPECT_TRUE((bool)p5); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4), *p5); + + auto p6 = + make_unique<std::tuple<int, int, int, int, int, int>>(0, 1, 2, 3, 4, 5); + EXPECT_TRUE((bool)p6); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5), *p6); + + auto p7 = make_unique<std::tuple<int, int, int, int, int, int, int>>( + 0, 1, 2, 3, 4, 5, 6); + EXPECT_TRUE((bool)p7); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6), *p7); + + auto p8 = make_unique<std::tuple<int, int, int, int, int, int, int, int>>( + 0, 1, 2, 3, 4, 5, 6, 7); + EXPECT_TRUE((bool)p8); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7), *p8); + + auto p9 = + make_unique<std::tuple<int, int, int, int, int, int, int, int, int>>( + 0, 1, 2, 3, 4, 5, 6, 7, 8); + EXPECT_TRUE((bool)p9); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7, 8), *p9); + + auto p10 = + make_unique<std::tuple<int, int, int, int, int, int, int, int, int, int>>( + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + EXPECT_TRUE((bool)p10); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), *p10); +} + +TEST(MakeUniqueTest, Array) { + auto p1 = make_unique<int[]>(2); + EXPECT_TRUE((bool)p1); + EXPECT_EQ(0, p1[0]); + EXPECT_EQ(0, p1[1]); +} +} diff --git a/unittests/ADT/OptionalTest.cpp b/unittests/ADT/OptionalTest.cpp index 21e3847..2da408c 100644 --- a/unittests/ADT/OptionalTest.cpp +++ b/unittests/ADT/OptionalTest.cpp @@ -169,7 +169,6 @@ TEST_F(OptionalTest, NullCopyConstructionTest) { EXPECT_EQ(0u, NonDefaultConstructible::Destructions); } -#if LLVM_HAS_RVALUE_REFERENCES struct MoveOnly { static unsigned MoveConstructions; static unsigned Destructions; @@ -278,7 +277,6 @@ TEST_F(OptionalTest, MoveOnlyAssigningAssignment) { EXPECT_EQ(1u, MoveOnly::MoveAssignments); EXPECT_EQ(1u, MoveOnly::Destructions); } -#endif } // end anonymous namespace diff --git a/unittests/ADT/OwningPtrTest.cpp b/unittests/ADT/OwningPtrTest.cpp new file mode 100644 index 0000000..aee955b --- /dev/null +++ b/unittests/ADT/OwningPtrTest.cpp @@ -0,0 +1,273 @@ +//===- llvm/unittest/ADT/OwningPtrTest.cpp - OwningPtr 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/OwningPtr.h" +#include "gtest/gtest.h" +using namespace llvm; + +namespace { + +struct TrackDestructor { + static unsigned Destructions; + int val; + explicit TrackDestructor(int val) : val(val) {} + ~TrackDestructor() { ++Destructions; } + static void ResetCounts() { Destructions = 0; } + +private: + TrackDestructor(const TrackDestructor &other) LLVM_DELETED_FUNCTION; + TrackDestructor & + operator=(const TrackDestructor &other) LLVM_DELETED_FUNCTION; + TrackDestructor(TrackDestructor &&other) LLVM_DELETED_FUNCTION; + TrackDestructor &operator=(TrackDestructor &&other) LLVM_DELETED_FUNCTION; +}; + +unsigned TrackDestructor::Destructions = 0; + +// Test fixture +class OwningPtrTest : public testing::Test {}; + +TEST_F(OwningPtrTest, DefaultConstruction) { + TrackDestructor::ResetCounts(); + { + OwningPtr<TrackDestructor> O; + EXPECT_FALSE(O); + EXPECT_TRUE(!O); + EXPECT_FALSE(O.get()); + EXPECT_FALSE(O.isValid()); + } + EXPECT_EQ(0u, TrackDestructor::Destructions); +} + +TEST_F(OwningPtrTest, PtrConstruction) { + TrackDestructor::ResetCounts(); + { + OwningPtr<TrackDestructor> O(new TrackDestructor(3)); + EXPECT_TRUE((bool)O); + EXPECT_FALSE(!O); + EXPECT_TRUE(O.get()); + EXPECT_TRUE(O.isValid()); + EXPECT_EQ(3, (*O).val); + EXPECT_EQ(3, O->val); + EXPECT_EQ(0u, TrackDestructor::Destructions); + } + EXPECT_EQ(1u, TrackDestructor::Destructions); +} + +TEST_F(OwningPtrTest, Reset) { + TrackDestructor::ResetCounts(); + OwningPtr<TrackDestructor> O(new TrackDestructor(3)); + EXPECT_EQ(0u, TrackDestructor::Destructions); + O.reset(); + EXPECT_FALSE((bool)O); + EXPECT_TRUE(!O); + EXPECT_FALSE(O.get()); + EXPECT_FALSE(O.isValid()); + EXPECT_EQ(1u, TrackDestructor::Destructions); +} + +TEST_F(OwningPtrTest, Take) { + TrackDestructor::ResetCounts(); + TrackDestructor *T = 0; + { + OwningPtr<TrackDestructor> O(new TrackDestructor(3)); + T = O.take(); + EXPECT_FALSE((bool)O); + EXPECT_TRUE(!O); + EXPECT_FALSE(O.get()); + EXPECT_FALSE(O.isValid()); + EXPECT_TRUE(T); + EXPECT_EQ(3, T->val); + EXPECT_EQ(0u, TrackDestructor::Destructions); + } + delete T; + EXPECT_EQ(1u, TrackDestructor::Destructions); +} + +TEST_F(OwningPtrTest, Release) { + TrackDestructor::ResetCounts(); + TrackDestructor *T = 0; + { + OwningPtr<TrackDestructor> O(new TrackDestructor(3)); + T = O.release(); + EXPECT_FALSE((bool)O); + EXPECT_TRUE(!O); + EXPECT_FALSE(O.get()); + EXPECT_FALSE(O.isValid()); + EXPECT_TRUE(T); + EXPECT_EQ(3, T->val); + EXPECT_EQ(0u, TrackDestructor::Destructions); + } + delete T; + EXPECT_EQ(1u, TrackDestructor::Destructions); +} + +TEST_F(OwningPtrTest, MoveConstruction) { + TrackDestructor::ResetCounts(); + { + OwningPtr<TrackDestructor> A(new TrackDestructor(3)); + OwningPtr<TrackDestructor> B = std::move(A); + EXPECT_FALSE((bool)A); + EXPECT_TRUE(!A); + EXPECT_FALSE(A.get()); + EXPECT_FALSE(A.isValid()); + EXPECT_TRUE((bool)B); + EXPECT_FALSE(!B); + EXPECT_TRUE(B.get()); + EXPECT_TRUE(B.isValid()); + EXPECT_EQ(3, (*B).val); + EXPECT_EQ(3, B->val); + EXPECT_EQ(0u, TrackDestructor::Destructions); + } + EXPECT_EQ(1u, TrackDestructor::Destructions); +} + +TEST_F(OwningPtrTest, MoveAssignment) { + TrackDestructor::ResetCounts(); + { + OwningPtr<TrackDestructor> A(new TrackDestructor(3)); + OwningPtr<TrackDestructor> B(new TrackDestructor(4)); + B = std::move(A); + EXPECT_FALSE(A); + EXPECT_TRUE(!A); + EXPECT_FALSE(A.get()); + EXPECT_FALSE(A.isValid()); + EXPECT_TRUE((bool)B); + EXPECT_FALSE(!B); + EXPECT_TRUE(B.get()); + EXPECT_TRUE(B.isValid()); + EXPECT_EQ(3, (*B).val); + EXPECT_EQ(3, B->val); + EXPECT_EQ(1u, TrackDestructor::Destructions); + } + EXPECT_EQ(2u, TrackDestructor::Destructions); +} + +TEST_F(OwningPtrTest, Swap) { + TrackDestructor::ResetCounts(); + { + OwningPtr<TrackDestructor> A(new TrackDestructor(3)); + OwningPtr<TrackDestructor> B(new TrackDestructor(4)); + B.swap(A); + EXPECT_TRUE((bool)A); + EXPECT_FALSE(!A); + EXPECT_TRUE(A.get()); + EXPECT_TRUE(A.isValid()); + EXPECT_EQ(4, (*A).val); + EXPECT_EQ(4, A->val); + EXPECT_TRUE((bool)B); + EXPECT_FALSE(!B); + EXPECT_TRUE(B.get()); + EXPECT_TRUE(B.isValid()); + EXPECT_EQ(3, (*B).val); + EXPECT_EQ(3, B->val); + EXPECT_EQ(0u, TrackDestructor::Destructions); + } + EXPECT_EQ(2u, TrackDestructor::Destructions); + TrackDestructor::ResetCounts(); + { + OwningPtr<TrackDestructor> A(new TrackDestructor(3)); + OwningPtr<TrackDestructor> B(new TrackDestructor(4)); + swap(A, B); + EXPECT_TRUE((bool)A); + EXPECT_FALSE(!A); + EXPECT_TRUE(A.get()); + EXPECT_TRUE(A.isValid()); + EXPECT_EQ(4, (*A).val); + EXPECT_EQ(4, A->val); + EXPECT_TRUE((bool)B); + EXPECT_FALSE(!B); + EXPECT_TRUE(B.get()); + EXPECT_TRUE(B.isValid()); + EXPECT_EQ(3, (*B).val); + EXPECT_EQ(3, B->val); + EXPECT_EQ(0u, TrackDestructor::Destructions); + } + EXPECT_EQ(2u, TrackDestructor::Destructions); +} + +TEST_F(OwningPtrTest, UniqueToOwningConstruction) { + TrackDestructor::ResetCounts(); + { + std::unique_ptr<TrackDestructor> A(new TrackDestructor(3)); + OwningPtr<TrackDestructor> B = std::move(A); + EXPECT_FALSE(A); + EXPECT_TRUE(!A); + EXPECT_FALSE(A.get()); + EXPECT_TRUE((bool)B); + EXPECT_FALSE(!B); + EXPECT_TRUE(B.get()); + EXPECT_TRUE(B.isValid()); + EXPECT_EQ(3, (*B).val); + EXPECT_EQ(3, B->val); + EXPECT_EQ(0u, TrackDestructor::Destructions); + } + EXPECT_EQ(1u, TrackDestructor::Destructions); +} + +TEST_F(OwningPtrTest, UniqueToOwningAssignment) { + TrackDestructor::ResetCounts(); + { + std::unique_ptr<TrackDestructor> A(new TrackDestructor(3)); + OwningPtr<TrackDestructor> B(new TrackDestructor(4)); + B = std::move(A); + EXPECT_FALSE(A); + EXPECT_TRUE(!A); + EXPECT_FALSE(A.get()); + EXPECT_TRUE((bool)B); + EXPECT_FALSE(!B); + EXPECT_TRUE(B.get()); + EXPECT_TRUE(B.isValid()); + EXPECT_EQ(3, (*B).val); + EXPECT_EQ(3, B->val); + EXPECT_EQ(1u, TrackDestructor::Destructions); + } + EXPECT_EQ(2u, TrackDestructor::Destructions); +} + +TEST_F(OwningPtrTest, TakeUniqueConstruction) { + TrackDestructor::ResetCounts(); + { + OwningPtr<TrackDestructor> A(new TrackDestructor(3)); + std::unique_ptr<TrackDestructor> B = A.take_unique(); + EXPECT_FALSE(A); + EXPECT_TRUE(!A); + EXPECT_FALSE(A.get()); + EXPECT_FALSE(A.isValid()); + EXPECT_TRUE((bool)B); + EXPECT_FALSE(!B); + EXPECT_TRUE(B.get()); + EXPECT_EQ(3, (*B).val); + EXPECT_EQ(3, B->val); + EXPECT_EQ(0u, TrackDestructor::Destructions); + } + EXPECT_EQ(1u, TrackDestructor::Destructions); +} + +#if LLVM_HAS_RVALUE_REFERENCE_THIS +TEST_F(OwningPtrTest, OwningToUniqueConstruction) { + TrackDestructor::ResetCounts(); + { + OwningPtr<TrackDestructor> A(new TrackDestructor(3)); + std::unique_ptr<TrackDestructor> B = std::move(A); + EXPECT_FALSE(A); + EXPECT_TRUE(!A); + EXPECT_FALSE(A.get()); + EXPECT_FALSE(A.isValid()); + EXPECT_TRUE((bool)B); + EXPECT_FALSE(!B); + EXPECT_TRUE(B.get()); + EXPECT_EQ(3, (*B).val); + EXPECT_EQ(3, B->val); + EXPECT_EQ(0u, TrackDestructor::Destructions); + } + EXPECT_EQ(1u, TrackDestructor::Destructions); +} +#endif +} diff --git a/unittests/ADT/PointerIntPairTest.cpp b/unittests/ADT/PointerIntPairTest.cpp new file mode 100644 index 0000000..296d475 --- /dev/null +++ b/unittests/ADT/PointerIntPairTest.cpp @@ -0,0 +1,76 @@ +//===- llvm/unittest/ADT/PointerIntPairTest.cpp - Unit tests --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "gtest/gtest.h" +#include "llvm/ADT/PointerIntPair.h" +#include <limits> +using namespace llvm; + +namespace { + +// Test fixture +class PointerIntPairTest : public testing::Test { +}; + +TEST_F(PointerIntPairTest, GetSet) { + PointerIntPair<PointerIntPairTest *, 2> Pair(this, 1U); + EXPECT_EQ(this, Pair.getPointer()); + EXPECT_EQ(1U, Pair.getInt()); + + Pair.setInt(2); + EXPECT_EQ(this, Pair.getPointer()); + EXPECT_EQ(2U, Pair.getInt()); + + Pair.setPointer(nullptr); + EXPECT_EQ(nullptr, Pair.getPointer()); + EXPECT_EQ(2U, Pair.getInt()); + + Pair.setPointerAndInt(this, 3U); + EXPECT_EQ(this, Pair.getPointer()); + EXPECT_EQ(3U, Pair.getInt()); +} + +TEST_F(PointerIntPairTest, DefaultInitialize) { + PointerIntPair<PointerIntPairTest *, 2> Pair; + EXPECT_EQ(nullptr, Pair.getPointer()); + EXPECT_EQ(0U, Pair.getInt()); +} + +#if !(defined(_MSC_VER) && _MSC_VER==1700) +TEST_F(PointerIntPairTest, ManyUnusedBits) { + // In real code this would be a word-sized integer limited to 31 bits. + struct Fixnum31 { + uintptr_t Value; + }; + class FixnumPointerTraits { + public: + static inline void *getAsVoidPointer(Fixnum31 Num) { + return reinterpret_cast<void *>(Num.Value << NumLowBitsAvailable); + } + static inline Fixnum31 getFromVoidPointer(void *P) { + // In real code this would assert that the value is in range. + return { reinterpret_cast<uintptr_t>(P) >> NumLowBitsAvailable }; + } + enum { NumLowBitsAvailable = std::numeric_limits<uintptr_t>::digits - 31 }; + }; + + PointerIntPair<Fixnum31, 1, bool, FixnumPointerTraits> pair; + EXPECT_EQ((uintptr_t)0, pair.getPointer().Value); + EXPECT_FALSE(pair.getInt()); + + pair.setPointerAndInt({ 0x7FFFFFFF }, true ); + EXPECT_EQ((uintptr_t)0x7FFFFFFF, pair.getPointer().Value); + EXPECT_TRUE(pair.getInt()); + + EXPECT_EQ(FixnumPointerTraits::NumLowBitsAvailable - 1, + PointerLikeTypeTraits<decltype(pair)>::NumLowBitsAvailable); +} +#endif + +} // end anonymous namespace diff --git a/unittests/ADT/SmallPtrSetTest.cpp b/unittests/ADT/SmallPtrSetTest.cpp index f85d7c9..fdd1cbb 100644 --- a/unittests/ADT/SmallPtrSetTest.cpp +++ b/unittests/ADT/SmallPtrSetTest.cpp @@ -16,7 +16,30 @@ using namespace llvm; -// SmallPtrSet swapping test. +TEST(SmallPtrSetTest, Assignment) { + int buf[8]; + for (int i = 0; i < 8; ++i) + buf[i] = 0; + + SmallPtrSet<int *, 4> s1; + s1.insert(&buf[0]); + s1.insert(&buf[1]); + + SmallPtrSet<int *, 4> s2; + (s2 = s1).insert(&buf[2]); + + // Self assign as well. + (s2 = s2).insert(&buf[3]); + + s1 = s2; + EXPECT_EQ(4U, s1.size()); + for (int i = 0; i < 8; ++i) + if (i < 4) + EXPECT_TRUE(s1.count(&buf[i])); + else + EXPECT_FALSE(s1.count(&buf[i])); +} + TEST(SmallPtrSetTest, GrowthTest) { int i; int buf[8]; @@ -71,6 +94,68 @@ TEST(SmallPtrSetTest, GrowthTest) { EXPECT_EQ(1,buf[i]); } +TEST(SmallPtrSetTest, CopyAndMoveTest) { + int buf[8]; + for (int i = 0; i < 8; ++i) + buf[i] = 0; + + SmallPtrSet<int *, 4> s1; + s1.insert(&buf[0]); + s1.insert(&buf[1]); + s1.insert(&buf[2]); + s1.insert(&buf[3]); + EXPECT_EQ(4U, s1.size()); + for (int i = 0; i < 8; ++i) + if (i < 4) + EXPECT_TRUE(s1.count(&buf[i])); + else + EXPECT_FALSE(s1.count(&buf[i])); + + SmallPtrSet<int *, 4> s2(s1); + EXPECT_EQ(4U, s2.size()); + for (int i = 0; i < 8; ++i) + if (i < 4) + EXPECT_TRUE(s2.count(&buf[i])); + else + EXPECT_FALSE(s2.count(&buf[i])); + + s1 = s2; + EXPECT_EQ(4U, s1.size()); + EXPECT_EQ(4U, s2.size()); + for (int i = 0; i < 8; ++i) + if (i < 4) + EXPECT_TRUE(s1.count(&buf[i])); + else + EXPECT_FALSE(s1.count(&buf[i])); + + SmallPtrSet<int *, 4> s3(std::move(s1)); + EXPECT_EQ(4U, s3.size()); + EXPECT_TRUE(s1.empty()); + for (int i = 0; i < 8; ++i) + if (i < 4) + EXPECT_TRUE(s3.count(&buf[i])); + else + EXPECT_FALSE(s3.count(&buf[i])); + + // Move assign into the moved-from object. Also test move of a non-small + // container. + s3.insert(&buf[4]); + s3.insert(&buf[5]); + s3.insert(&buf[6]); + s3.insert(&buf[7]); + s1 = std::move(s3); + EXPECT_EQ(8U, s1.size()); + EXPECT_TRUE(s3.empty()); + for (int i = 0; i < 8; ++i) + EXPECT_TRUE(s1.count(&buf[i])); + + // Copy assign into a moved-from object. + s3 = s1; + EXPECT_EQ(8U, s3.size()); + EXPECT_EQ(8U, s1.size()); + for (int i = 0; i < 8; ++i) + EXPECT_TRUE(s3.count(&buf[i])); +} TEST(SmallPtrSetTest, SwapTest) { int buf[10]; diff --git a/unittests/ADT/StringMapTest.cpp b/unittests/ADT/StringMapTest.cpp index 5bb65cb..b6d41bc 100644 --- a/unittests/ADT/StringMapTest.cpp +++ b/unittests/ADT/StringMapTest.cpp @@ -183,23 +183,6 @@ TEST_F(StringMapTest, IterationTest) { } } -} // end anonymous namespace - -namespace llvm { - -template <> -class StringMapEntryInitializer<uint32_t> { -public: - template <typename InitTy> - static void Initialize(StringMapEntry<uint32_t> &T, InitTy InitVal) { - T.second = InitVal; - } -}; - -} // end llvm namespace - -namespace { - // Test StringMapEntry::Create() method. TEST_F(StringMapTest, StringMapEntryTest) { StringMap<uint32_t>::value_type* entry = @@ -220,4 +203,19 @@ TEST_F(StringMapTest, InsertTest) { assertSingleItemMap(); } +// Create a non-default constructable value +struct StringMapTestStruct { + StringMapTestStruct(int i) : i(i) {} + StringMapTestStruct() LLVM_DELETED_FUNCTION; + int i; +}; + +TEST_F(StringMapTest, NonDefaultConstructable) { + StringMap<StringMapTestStruct> t; + t.GetOrCreateValue("Test", StringMapTestStruct(123)); + StringMap<StringMapTestStruct>::iterator iter = t.find("Test"); + ASSERT_NE(iter, t.end()); + ASSERT_EQ(iter->second.i, 123); +} + } // end anonymous namespace diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp index 88691ae..c7fd9d0 100644 --- a/unittests/ADT/StringRefTest.cpp +++ b/unittests/ADT/StringRefTest.cpp @@ -8,9 +8,10 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" using namespace llvm; @@ -531,4 +532,18 @@ TEST(StringRefTest, joinStrings) { EXPECT_TRUE(v2_join3); } + +TEST(StringRefTest, AllocatorCopy) { + BumpPtrAllocator Alloc; + StringRef Str1 = "hello"; + StringRef Str2 = "bye"; + StringRef Str1c = Str1.copy(Alloc); + StringRef Str2c = Str2.copy(Alloc); + EXPECT_TRUE(Str1.equals(Str1c)); + EXPECT_NE(Str1.data(), Str1c.data()); + EXPECT_TRUE(Str2.equals(Str2c)); + EXPECT_NE(Str2.data(), Str2c.data()); +} + + } // end anonymous namespace diff --git a/unittests/ADT/TinyPtrVectorTest.cpp b/unittests/ADT/TinyPtrVectorTest.cpp index a4f92ff..ec868d4 100644 --- a/unittests/ADT/TinyPtrVectorTest.cpp +++ b/unittests/ADT/TinyPtrVectorTest.cpp @@ -36,7 +36,7 @@ template <typename VectorT> class TinyPtrVectorTest : public testing::Test { protected: typedef typename VectorT::value_type PtrT; - typedef typename remove_pointer<PtrT>::type ValueT; + typedef typename std::remove_pointer<PtrT>::type ValueT; VectorT V; VectorT V2; @@ -72,9 +72,9 @@ protected: EXPECT_EQ(Values.size(), V.size()); for (size_t i = 0, e = Values.size(); i != e; ++i) { EXPECT_EQ(Values[i], V[i]); - EXPECT_EQ(Values[i], *llvm::next(V.begin(), i)); + EXPECT_EQ(Values[i], *std::next(V.begin(), i)); } - EXPECT_EQ(V.end(), llvm::next(V.begin(), Values.size())); + EXPECT_EQ(V.end(), std::next(V.begin(), Values.size())); } }; @@ -157,170 +157,136 @@ TYPED_TEST(TinyPtrVectorTest, CopyAndMoveCtorTest) { this->expectValues(Copy2, this->testArray(42)); this->expectValues(this->V2, this->testArray(0)); -#if LLVM_HAS_RVALUE_REFERENCES TypeParam Move(std::move(Copy2)); this->expectValues(Move, this->testArray(42)); this->expectValues(Copy2, this->testArray(0)); -#endif } TYPED_TEST(TinyPtrVectorTest, CopyAndMoveTest) { this->V = this->V2; this->expectValues(this->V, this->testArray(0)); this->expectValues(this->V2, this->testArray(0)); -#if LLVM_HAS_RVALUE_REFERENCES this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(0)); -#endif this->setVectors(this->testArray(1), this->testArray(0)); this->V = this->V2; this->expectValues(this->V, this->testArray(0)); this->expectValues(this->V2, this->testArray(0)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(1), this->testArray(0)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(0)); -#endif this->setVectors(this->testArray(2), this->testArray(0)); this->V = this->V2; this->expectValues(this->V, this->testArray(0)); this->expectValues(this->V2, this->testArray(0)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(2), this->testArray(0)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(0)); -#endif this->setVectors(this->testArray(42), this->testArray(0)); this->V = this->V2; this->expectValues(this->V, this->testArray(0)); this->expectValues(this->V2, this->testArray(0)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(42), this->testArray(0)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(0)); -#endif this->setVectors(this->testArray(0), this->testArray(1)); this->V = this->V2; this->expectValues(this->V, this->testArray(1)); this->expectValues(this->V2, this->testArray(1)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(0), this->testArray(1)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(1)); -#endif this->setVectors(this->testArray(0), this->testArray(2)); this->V = this->V2; this->expectValues(this->V, this->testArray(2)); this->expectValues(this->V2, this->testArray(2)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(0), this->testArray(2)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(2)); -#endif this->setVectors(this->testArray(0), this->testArray(42)); this->V = this->V2; this->expectValues(this->V, this->testArray(42)); this->expectValues(this->V2, this->testArray(42)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(0), this->testArray(42)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(42)); -#endif this->setVectors(this->testArray(1), this->testArray(1)); this->V = this->V2; this->expectValues(this->V, this->testArray(1)); this->expectValues(this->V2, this->testArray(1)); -#if LLVM_HAS_RVALUE_REFERENCES this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(1)); -#endif this->setVectors(this->testArray(1), this->testArray(2)); this->V = this->V2; this->expectValues(this->V, this->testArray(2)); this->expectValues(this->V2, this->testArray(2)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(1), this->testArray(2)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(2)); -#endif this->setVectors(this->testArray(1), this->testArray(42)); this->V = this->V2; this->expectValues(this->V, this->testArray(42)); this->expectValues(this->V2, this->testArray(42)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(1), this->testArray(42)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(42)); -#endif this->setVectors(this->testArray(2), this->testArray(1)); this->V = this->V2; this->expectValues(this->V, this->testArray(1)); this->expectValues(this->V2, this->testArray(1)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(2), this->testArray(1)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(1)); -#endif this->setVectors(this->testArray(2), this->testArray(2)); this->V = this->V2; this->expectValues(this->V, this->testArray(2)); this->expectValues(this->V2, this->testArray(2)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(2), this->testArray(2)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(2)); -#endif this->setVectors(this->testArray(2), this->testArray(42)); this->V = this->V2; this->expectValues(this->V, this->testArray(42)); this->expectValues(this->V2, this->testArray(42)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(2), this->testArray(42)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(42)); -#endif this->setVectors(this->testArray(42), this->testArray(1)); this->V = this->V2; this->expectValues(this->V, this->testArray(1)); this->expectValues(this->V2, this->testArray(1)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(42), this->testArray(1)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(1)); -#endif this->setVectors(this->testArray(42), this->testArray(2)); this->V = this->V2; this->expectValues(this->V, this->testArray(2)); this->expectValues(this->V2, this->testArray(2)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(42), this->testArray(2)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(2)); -#endif this->setVectors(this->testArray(42), this->testArray(42)); this->V = this->V2; this->expectValues(this->V, this->testArray(42)); this->expectValues(this->V2, this->testArray(42)); -#if LLVM_HAS_RVALUE_REFERENCES this->setVectors(this->testArray(42), this->testArray(42)); this->V = std::move(this->V2); this->expectValues(this->V, this->testArray(42)); -#endif } TYPED_TEST(TinyPtrVectorTest, EraseTest) { @@ -334,17 +300,17 @@ TYPED_TEST(TinyPtrVectorTest, EraseTest) { this->V.erase(this->V.begin()); this->TestPtrs.erase(this->TestPtrs.begin()); this->expectValues(this->V, this->testArray(41)); - this->V.erase(llvm::next(this->V.begin(), 1)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 1)); + this->V.erase(std::next(this->V.begin(), 1)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 1)); this->expectValues(this->V, this->testArray(40)); - this->V.erase(llvm::next(this->V.begin(), 2)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 2)); + this->V.erase(std::next(this->V.begin(), 2)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 2)); this->expectValues(this->V, this->testArray(39)); - this->V.erase(llvm::next(this->V.begin(), 5)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 5)); + this->V.erase(std::next(this->V.begin(), 5)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 5)); this->expectValues(this->V, this->testArray(38)); - this->V.erase(llvm::next(this->V.begin(), 13)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 13)); + this->V.erase(std::next(this->V.begin(), 13)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 13)); this->expectValues(this->V, this->testArray(37)); typename TypeParam::iterator I = this->V.begin(); @@ -366,27 +332,27 @@ TYPED_TEST(TinyPtrVectorTest, EraseRangeTest) { this->appendValues(this->V, this->testArray(42)); this->expectValues(this->V, this->testArray(42)); - this->V.erase(this->V.begin(), llvm::next(this->V.begin(), 1)); + this->V.erase(this->V.begin(), std::next(this->V.begin(), 1)); this->TestPtrs.erase(this->TestPtrs.begin(), - llvm::next(this->TestPtrs.begin(), 1)); + std::next(this->TestPtrs.begin(), 1)); this->expectValues(this->V, this->testArray(41)); - this->V.erase(llvm::next(this->V.begin(), 1), llvm::next(this->V.begin(), 2)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 1), - llvm::next(this->TestPtrs.begin(), 2)); + this->V.erase(std::next(this->V.begin(), 1), std::next(this->V.begin(), 2)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 1), + std::next(this->TestPtrs.begin(), 2)); this->expectValues(this->V, this->testArray(40)); - this->V.erase(llvm::next(this->V.begin(), 2), llvm::next(this->V.begin(), 4)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 2), - llvm::next(this->TestPtrs.begin(), 4)); + this->V.erase(std::next(this->V.begin(), 2), std::next(this->V.begin(), 4)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 2), + std::next(this->TestPtrs.begin(), 4)); this->expectValues(this->V, this->testArray(38)); - this->V.erase(llvm::next(this->V.begin(), 5), llvm::next(this->V.begin(), 10)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 5), - llvm::next(this->TestPtrs.begin(), 10)); + this->V.erase(std::next(this->V.begin(), 5), std::next(this->V.begin(), 10)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 5), + std::next(this->TestPtrs.begin(), 10)); this->expectValues(this->V, this->testArray(33)); - this->V.erase(llvm::next(this->V.begin(), 13), llvm::next(this->V.begin(), 26)); - this->TestPtrs.erase(llvm::next(this->TestPtrs.begin(), 13), - llvm::next(this->TestPtrs.begin(), 26)); + this->V.erase(std::next(this->V.begin(), 13), std::next(this->V.begin(), 26)); + this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 13), + std::next(this->TestPtrs.begin(), 26)); this->expectValues(this->V, this->testArray(20)); - this->V.erase(llvm::next(this->V.begin(), 7), this->V.end()); + this->V.erase(std::next(this->V.begin(), 7), this->V.end()); this->expectValues(this->V, this->testArray(7)); this->V.erase(this->V.begin(), this->V.end()); this->expectValues(this->V, this->testArray(0)); @@ -403,8 +369,8 @@ TYPED_TEST(TinyPtrVectorTest, Insert) { this->V.insert(this->V.begin(), this->TestPtrs[42]); this->TestPtrs.insert(this->TestPtrs.begin(), this->TestPtrs[42]); this->expectValues(this->V, this->testArray(6)); - this->V.insert(llvm::next(this->V.begin(), 3), this->TestPtrs[43]); - this->TestPtrs.insert(llvm::next(this->TestPtrs.begin(), 3), + this->V.insert(std::next(this->V.begin(), 3), this->TestPtrs[43]); + this->TestPtrs.insert(std::next(this->TestPtrs.begin(), 3), this->TestPtrs[43]); this->expectValues(this->V, this->testArray(7)); } @@ -418,30 +384,30 @@ TYPED_TEST(TinyPtrVectorTest, InsertRange) { this->V.insert(this->V.end(), this->TestPtrs.end(), this->TestPtrs.end()); this->expectValues(this->V, this->testArray(0)); this->V.insert(this->V.end(), this->TestPtrs.begin(), - llvm::next(this->TestPtrs.begin())); + std::next(this->TestPtrs.begin())); this->expectValues(this->V, this->testArray(1)); this->V.clear(); this->V.insert(this->V.end(), this->TestPtrs.begin(), - llvm::next(this->TestPtrs.begin(), 2)); + std::next(this->TestPtrs.begin(), 2)); this->expectValues(this->V, this->testArray(2)); this->V.clear(); this->V.insert(this->V.end(), this->TestPtrs.begin(), - llvm::next(this->TestPtrs.begin(), 42)); + std::next(this->TestPtrs.begin(), 42)); this->expectValues(this->V, this->testArray(42)); this->V.clear(); this->V.insert(this->V.end(), - llvm::next(this->TestPtrs.begin(), 5), - llvm::next(this->TestPtrs.begin(), 13)); + std::next(this->TestPtrs.begin(), 5), + std::next(this->TestPtrs.begin(), 13)); this->V.insert(this->V.begin(), - llvm::next(this->TestPtrs.begin(), 0), - llvm::next(this->TestPtrs.begin(), 3)); - this->V.insert(llvm::next(this->V.begin(), 2), - llvm::next(this->TestPtrs.begin(), 2), - llvm::next(this->TestPtrs.begin(), 4)); - this->V.erase(llvm::next(this->V.begin(), 4)); - this->V.insert(llvm::next(this->V.begin(), 4), - llvm::next(this->TestPtrs.begin(), 4), - llvm::next(this->TestPtrs.begin(), 5)); + std::next(this->TestPtrs.begin(), 0), + std::next(this->TestPtrs.begin(), 3)); + this->V.insert(std::next(this->V.begin(), 2), + std::next(this->TestPtrs.begin(), 2), + std::next(this->TestPtrs.begin(), 4)); + this->V.erase(std::next(this->V.begin(), 4)); + this->V.insert(std::next(this->V.begin(), 4), + std::next(this->TestPtrs.begin(), 4), + std::next(this->TestPtrs.begin(), 5)); this->expectValues(this->V, this->testArray(13)); } diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index b402896..2e9d585 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -190,6 +190,9 @@ 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) + continue; + C[2] = Triple::getOSTypeName(Triple::OSType(OS)); std::string E = Join(C[0], C[1], C[2]); @@ -201,7 +204,7 @@ TEST(TripleTest, Normalization) { EXPECT_EQ(E, Triple::normalize(Join(C[2], C[0], C[1]))); EXPECT_EQ(E, Triple::normalize(Join(C[2], C[1], C[0]))); - for (int Env = 1+Triple::UnknownEnvironment; Env <= Triple::MachO; + for (int Env = 1 + Triple::UnknownEnvironment; Env <= Triple::Android; ++Env) { C[3] = Triple::getEnvironmentTypeName(Triple::EnvironmentType(Env)); @@ -238,7 +241,7 @@ TEST(TripleTest, Normalization) { // Various real-world funky triples. The value returned by GCC's config.sub // is given in the comment. - EXPECT_EQ("i386--mingw32", Triple::normalize("i386-mingw32")); // i386-pc-mingw32 + EXPECT_EQ("i386--windows-gnu", Triple::normalize("i386-mingw32")); // i386-pc-mingw32 EXPECT_EQ("x86_64--linux-gnu", Triple::normalize("x86_64-linux-gnu")); // x86_64-pc-linux-gnu EXPECT_EQ("i486--linux-gnu", Triple::normalize("i486-linux-gnu")); // i486-pc-linux-gnu EXPECT_EQ("i386-redhat-linux", Triple::normalize("i386-redhat-linux")); // i386-redhat-linux-gnu @@ -349,10 +352,6 @@ TEST(TripleTest, BitWidthArchVariants) { EXPECT_EQ(Triple::UnknownArch, T.get32BitArchVariant().getArch()); EXPECT_EQ(Triple::UnknownArch, T.get64BitArchVariant().getArch()); - T.setArch(Triple::arm); - EXPECT_EQ(Triple::arm, T.get32BitArchVariant().getArch()); - EXPECT_EQ(Triple::UnknownArch, T.get64BitArchVariant().getArch()); - T.setArch(Triple::mips); EXPECT_EQ(Triple::mips, T.get32BitArchVariant().getArch()); EXPECT_EQ(Triple::mips64, T.get64BitArchVariant().getArch()); @@ -417,7 +416,7 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)5, Minor); EXPECT_EQ((unsigned)0, Micro); T.getiOSVersion(Major, Minor, Micro); - EXPECT_EQ((unsigned)3, Major); + EXPECT_EQ((unsigned)5, Major); EXPECT_EQ((unsigned)0, Minor); EXPECT_EQ((unsigned)0, Micro); @@ -432,7 +431,7 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)5, Minor); EXPECT_EQ((unsigned)0, Micro); T.getiOSVersion(Major, Minor, Micro); - EXPECT_EQ((unsigned)3, Major); + EXPECT_EQ((unsigned)5, Major); EXPECT_EQ((unsigned)0, Minor); EXPECT_EQ((unsigned)0, Micro); @@ -447,7 +446,7 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)4, Minor); EXPECT_EQ((unsigned)0, Micro); T.getiOSVersion(Major, Minor, Micro); - EXPECT_EQ((unsigned)3, Major); + EXPECT_EQ((unsigned)5, Major); EXPECT_EQ((unsigned)0, Minor); EXPECT_EQ((unsigned)0, Micro); @@ -462,7 +461,7 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)7, Minor); EXPECT_EQ((unsigned)0, Micro); T.getiOSVersion(Major, Minor, Micro); - EXPECT_EQ((unsigned)3, Major); + EXPECT_EQ((unsigned)5, Major); EXPECT_EQ((unsigned)0, Minor); EXPECT_EQ((unsigned)0, Micro); @@ -477,11 +476,11 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)4, Minor); EXPECT_EQ((unsigned)0, Micro); T.getiOSVersion(Major, Minor, Micro); - EXPECT_EQ((unsigned)3, Major); + EXPECT_EQ((unsigned)5, Major); EXPECT_EQ((unsigned)0, Minor); EXPECT_EQ((unsigned)0, Micro); - T = Triple("armv7-apple-ios5.0"); + T = Triple("armv7-apple-ios7.0"); EXPECT_FALSE(T.isMacOSX()); EXPECT_TRUE(T.isiOS()); EXPECT_FALSE(T.isArch16Bit()); @@ -492,9 +491,77 @@ TEST(TripleTest, getOSVersion) { EXPECT_EQ((unsigned)4, Minor); EXPECT_EQ((unsigned)0, Micro); T.getiOSVersion(Major, Minor, Micro); - EXPECT_EQ((unsigned)5, Major); + EXPECT_EQ((unsigned)7, Major); EXPECT_EQ((unsigned)0, Minor); EXPECT_EQ((unsigned)0, Micro); } +TEST(TripleTest, FileFormat) { + EXPECT_EQ(Triple::ELF, Triple("i686-unknown-linux-gnu").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686-unknown-freebsd").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686-unknown-netbsd").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686--win32-elf").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686---elf").getObjectFormat()); + + EXPECT_EQ(Triple::MachO, Triple("i686-apple-macosx").getObjectFormat()); + EXPECT_EQ(Triple::MachO, Triple("i686-apple-ios").getObjectFormat()); + EXPECT_EQ(Triple::MachO, Triple("i686---macho").getObjectFormat()); + + EXPECT_EQ(Triple::COFF, Triple("i686--win32").getObjectFormat()); + + EXPECT_EQ(Triple::ELF, Triple("i686-pc-windows-msvc-elf").getObjectFormat()); + EXPECT_EQ(Triple::ELF, Triple("i686-pc-cygwin-elf").getObjectFormat()); + + Triple MSVCNormalized(Triple::normalize("i686-pc-windows-msvc-elf")); + EXPECT_EQ(Triple::ELF, MSVCNormalized.getObjectFormat()); + + Triple GNUWindowsNormalized(Triple::normalize("i686-pc-windows-gnu-elf")); + EXPECT_EQ(Triple::ELF, GNUWindowsNormalized.getObjectFormat()); + + Triple CygnusNormalised(Triple::normalize("i686-pc-windows-cygnus-elf")); + EXPECT_EQ(Triple::ELF, CygnusNormalised.getObjectFormat()); + + Triple CygwinNormalized(Triple::normalize("i686-pc-cygwin-elf")); + EXPECT_EQ(Triple::ELF, CygwinNormalized.getObjectFormat()); + + Triple T = Triple(""); + T.setObjectFormat(Triple::ELF); + EXPECT_EQ(Triple::ELF, T.getObjectFormat()); +} + +TEST(TripleTest, NormalizeWindows) { + EXPECT_EQ("i686-pc-windows-msvc", Triple::normalize("i686-pc-win32")); + EXPECT_EQ("i686--windows-msvc", Triple::normalize("i686-win32")); + EXPECT_EQ("i686-pc-windows-gnu", Triple::normalize("i686-pc-mingw32")); + EXPECT_EQ("i686--windows-gnu", Triple::normalize("i686-mingw32")); + EXPECT_EQ("i686-pc-windows-gnu", Triple::normalize("i686-pc-mingw32-w64")); + EXPECT_EQ("i686--windows-gnu", Triple::normalize("i686-mingw32-w64")); + EXPECT_EQ("i686-pc-windows-cygnus", Triple::normalize("i686-pc-cygwin")); + EXPECT_EQ("i686--windows-cygnus", Triple::normalize("i686-cygwin")); + + EXPECT_EQ("x86_64-pc-windows-msvc", Triple::normalize("x86_64-pc-win32")); + EXPECT_EQ("x86_64--windows-msvc", Triple::normalize("x86_64-win32")); + EXPECT_EQ("x86_64-pc-windows-gnu", Triple::normalize("x86_64-pc-mingw32")); + EXPECT_EQ("x86_64--windows-gnu", Triple::normalize("x86_64-mingw32")); + EXPECT_EQ("x86_64-pc-windows-gnu", Triple::normalize("x86_64-pc-mingw32-w64")); + EXPECT_EQ("x86_64--windows-gnu", Triple::normalize("x86_64-mingw32-w64")); + + EXPECT_EQ("i686-pc-windows-elf", Triple::normalize("i686-pc-win32-elf")); + EXPECT_EQ("i686--windows-elf", Triple::normalize("i686-win32-elf")); + EXPECT_EQ("i686-pc-windows-macho", Triple::normalize("i686-pc-win32-macho")); + EXPECT_EQ("i686--windows-macho", Triple::normalize("i686-win32-macho")); + + EXPECT_EQ("x86_64-pc-windows-elf", Triple::normalize("x86_64-pc-win32-elf")); + EXPECT_EQ("x86_64--windows-elf", Triple::normalize("x86_64-win32-elf")); + EXPECT_EQ("x86_64-pc-windows-macho", Triple::normalize("x86_64-pc-win32-macho")); + EXPECT_EQ("x86_64--windows-macho", Triple::normalize("x86_64-win32-macho")); + + EXPECT_EQ("i686-pc-windows-cygnus", + Triple::normalize("i686-pc-windows-cygnus")); + EXPECT_EQ("i686-pc-windows-gnu", Triple::normalize("i686-pc-windows-gnu")); + EXPECT_EQ("i686-pc-windows-itanium", Triple::normalize("i686-pc-windows-itanium")); + EXPECT_EQ("i686-pc-windows-msvc", Triple::normalize("i686-pc-windows-msvc")); + + EXPECT_EQ("i686-pc-windows-elf", Triple::normalize("i686-pc-windows-elf-elf")); +} } diff --git a/unittests/ADT/ilistTest.cpp b/unittests/ADT/ilistTest.cpp index 0c0cd0f..134607c 100644 --- a/unittests/ADT/ilistTest.cpp +++ b/unittests/ADT/ilistTest.cpp @@ -51,15 +51,15 @@ TEST(ilistTest, SpliceOne) { List.splice(List.begin(), List, List.begin()); EXPECT_EQ(1u, List.size()); EXPECT_EQ(1, List.front().Value); - EXPECT_TRUE(llvm::next(List.begin()) == List.end()); + EXPECT_TRUE(std::next(List.begin()) == List.end()); // Altenative noop. Move the first element behind itself. List.push_back(2); List.push_back(3); - List.splice(llvm::next(List.begin()), List, List.begin()); + List.splice(std::next(List.begin()), List, List.begin()); EXPECT_EQ(3u, List.size()); EXPECT_EQ(1, List.front().Value); - EXPECT_EQ(2, llvm::next(List.begin())->Value); + EXPECT_EQ(2, std::next(List.begin())->Value); EXPECT_EQ(3, List.back().Value); } diff --git a/unittests/ADT/polymorphic_ptr_test.cpp b/unittests/ADT/polymorphic_ptr_test.cpp deleted file mode 100644 index bd5d838..0000000 --- a/unittests/ADT/polymorphic_ptr_test.cpp +++ /dev/null @@ -1,129 +0,0 @@ -//===- llvm/unittest/ADT/polymorphic_ptr.h - polymorphic_ptr<T> 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/polymorphic_ptr.h" -#include "llvm/Support/raw_ostream.h" - -using namespace llvm; - -namespace { - -struct S { - S(int x) : x(x) {} - S *clone() { return new S(*this); } - int x; -}; - -// A function that forces the return of a copy. -template <typename T> -T dummy_copy(const T &arg) { return arg; } - -TEST(polymorphic_ptr_test, Basic) { - polymorphic_ptr<S> null; - EXPECT_FALSE((bool)null); - EXPECT_TRUE(!null); - EXPECT_EQ((S*)0, null.get()); - - S *s = new S(42); - polymorphic_ptr<S> p(s); - EXPECT_TRUE((bool)p); - EXPECT_FALSE(!p); - EXPECT_TRUE(p != null); - EXPECT_FALSE(p == null); - EXPECT_TRUE(p == s); - EXPECT_TRUE(s == p); - EXPECT_FALSE(p != s); - EXPECT_FALSE(s != p); - EXPECT_EQ(s, &*p); - EXPECT_EQ(s, p.operator->()); - EXPECT_EQ(s, p.get()); - EXPECT_EQ(42, p->x); - - EXPECT_EQ(s, p.take()); - EXPECT_FALSE((bool)p); - EXPECT_TRUE(!p); - p = s; - EXPECT_TRUE((bool)p); - EXPECT_FALSE(!p); - EXPECT_EQ(s, &*p); - EXPECT_EQ(s, p.operator->()); - EXPECT_EQ(s, p.get()); - EXPECT_EQ(42, p->x); - - polymorphic_ptr<S> p2((llvm_move(p))); -#if !LLVM_HAS_RVALUE_REFERENCES - // 'p' may not have been moved from in C++98, fake it for the test. - p2 = p.take(); -#endif - EXPECT_FALSE((bool)p); - EXPECT_TRUE(!p); - EXPECT_TRUE((bool)p2); - EXPECT_FALSE(!p2); - EXPECT_EQ(s, &*p2); - - using std::swap; - swap(p, p2); - EXPECT_TRUE((bool)p); - EXPECT_FALSE(!p); - EXPECT_EQ(s, &*p); - EXPECT_FALSE((bool)p2); - EXPECT_TRUE(!p2); - - // Force copies and that everything survives. - polymorphic_ptr<S> p3 = dummy_copy(polymorphic_ptr<S>(p)); - EXPECT_TRUE((bool)p3); - EXPECT_FALSE(!p3); - EXPECT_NE(s, &*p3); - EXPECT_EQ(42, p3->x); - - // Force copies of null without trying to dereference anything. - polymorphic_ptr<S> null_copy = dummy_copy(polymorphic_ptr<S>(null)); - EXPECT_FALSE((bool)null_copy); - EXPECT_TRUE(!null_copy); - EXPECT_EQ(null, null_copy); -} - -struct Base { - virtual ~Base() {} - virtual Base *clone() = 0; - virtual StringRef name() { return "Base"; } -}; - -struct DerivedA : Base { - virtual DerivedA *clone() { return new DerivedA(); } - virtual StringRef name() { return "DerivedA"; } -}; -struct DerivedB : Base { - virtual DerivedB *clone() { return new DerivedB(); } - virtual StringRef name() { return "DerivedB"; } -}; - -TEST(polymorphic_ptr_test, Polymorphism) { - polymorphic_ptr<Base> a(new DerivedA()); - polymorphic_ptr<Base> b(new DerivedB()); - - EXPECT_EQ("DerivedA", a->name()); - EXPECT_EQ("DerivedB", b->name()); - - polymorphic_ptr<Base> copy = dummy_copy(a); - EXPECT_NE(a, copy); - EXPECT_EQ("DerivedA", copy->name()); - - copy = dummy_copy(b); - EXPECT_NE(b, copy); - EXPECT_EQ("DerivedB", copy->name()); - - // Test creating a copy out of a temporary directly. - copy = dummy_copy<polymorphic_ptr<Base> >(new DerivedA()); - EXPECT_NE(a, copy); - EXPECT_EQ("DerivedA", copy->name()); -} - -} diff --git a/unittests/Analysis/CFGTest.cpp b/unittests/Analysis/CFGTest.cpp index e931709..8d8c560 100644 --- a/unittests/Analysis/CFGTest.cpp +++ b/unittests/Analysis/CFGTest.cpp @@ -8,18 +8,17 @@ //===----------------------------------------------------------------------===// #include "llvm/Analysis/CFG.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/LoopInfo.h" -#include "llvm/Assembly/Parser.h" -#include "llvm/IR/LLVMContext.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/InstIterator.h" -#include "llvm/Support/SourceMgr.h" #include "llvm/Pass.h" #include "llvm/PassManager.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" using namespace llvm; @@ -78,14 +77,15 @@ protected: "", &ID, 0, true, true); PassRegistry::getPassRegistry()->registerPass(*PI, false); initializeLoopInfoPass(*PassRegistry::getPassRegistry()); - initializeDominatorTreePass(*PassRegistry::getPassRegistry()); + initializeDominatorTreeWrapperPassPass( + *PassRegistry::getPassRegistry()); return 0; } void getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequired<LoopInfo>(); - AU.addRequired<DominatorTree>(); + AU.addRequired<DominatorTreeWrapperPass>(); } bool runOnFunction(Function &F) { @@ -93,7 +93,8 @@ protected: return false; LoopInfo *LI = &getAnalysis<LoopInfo>(); - DominatorTree *DT = &getAnalysis<DominatorTree>(); + DominatorTree *DT = + &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); EXPECT_EQ(isPotentiallyReachable(A, B, 0, 0), ExpectedResult); EXPECT_EQ(isPotentiallyReachable(A, B, DT, 0), ExpectedResult); EXPECT_EQ(isPotentiallyReachable(A, B, 0, LI), ExpectedResult); @@ -113,8 +114,8 @@ protected: PM.add(P); PM.run(*M); } -private: - OwningPtr<Module> M; + + std::unique_ptr<Module> M; Instruction *A, *B; }; @@ -350,27 +351,40 @@ TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOtherInsideAThirdLoop) { ExpectPath(true); } +static const char *BranchInsideLoopIR = + "declare i1 @switch()\n" + "\n" + "define void @test() {\n" + "entry:\n" + " br label %loop\n" + "loop:\n" + " %x = call i1 @switch()\n" + " br i1 %x, label %nextloopblock, label %exit\n" + "nextloopblock:\n" + " %y = call i1 @switch()\n" + " br i1 %y, label %left, label %right\n" + "left:\n" + " %A = bitcast i8 undef to i8\n" + " br label %loop\n" + "right:\n" + " %B = bitcast i8 undef to i8\n" + " br label %loop\n" + "exit:\n" + " ret void\n" + "}"; + TEST_F(IsPotentiallyReachableTest, BranchInsideLoop) { - ParseAssembly( - "declare i1 @switch()\n" - "\n" - "define void @test() {\n" - "entry:\n" - " br label %loop\n" - "loop:\n" - " %x = call i1 @switch()\n" - " br i1 %x, label %nextloopblock, label %exit\n" - "nextloopblock:\n" - " %y = call i1 @switch()\n" - " br i1 %y, label %left, label %right\n" - "left:\n" - " %A = bitcast i8 undef to i8\n" - " br label %loop\n" - "right:\n" - " %B = bitcast i8 undef to i8\n" - " br label %loop\n" - "exit:\n" - " ret void\n" - "}"); + ParseAssembly(BranchInsideLoopIR); + ExpectPath(true); +} + +TEST_F(IsPotentiallyReachableTest, ModifyTest) { + ParseAssembly(BranchInsideLoopIR); + + succ_iterator S = succ_begin(++M->getFunction("test")->begin()); + BasicBlock *OldBB = S[0]; + S[0] = S[1]; + ExpectPath(false); + S[0] = OldBB; ExpectPath(true); } diff --git a/unittests/Analysis/CMakeLists.txt b/unittests/Analysis/CMakeLists.txt index 7e5b358..d9f8c0c 100644 --- a/unittests/Analysis/CMakeLists.txt +++ b/unittests/Analysis/CMakeLists.txt @@ -1,6 +1,8 @@ set(LLVM_LINK_COMPONENTS Analysis AsmParser + Core + Support ) add_llvm_unittest(AnalysisTests diff --git a/unittests/Bitcode/BitReaderTest.cpp b/unittests/Bitcode/BitReaderTest.cpp index f33af2f..ba03023 100644 --- a/unittests/Bitcode/BitReaderTest.cpp +++ b/unittests/Bitcode/BitReaderTest.cpp @@ -8,13 +8,13 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/SmallString.h" -#include "llvm/Analysis/Verifier.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Bitcode/ReaderWriter.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/MemoryBuffer.h" #include "gtest/gtest.h" @@ -45,7 +45,7 @@ static Module *makeLLVMModule() { } static void writeModuleToBuffer(SmallVectorImpl<char> &Buffer) { - OwningPtr<Module> Mod(makeLLVMModule()); + std::unique_ptr<Module> Mod(makeLLVMModule()); raw_svector_ostream OS(Buffer); WriteBitcodeToFile(Mod.get(), OS); } @@ -54,8 +54,9 @@ TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677 SmallString<1024> Mem; writeModuleToBuffer(Mem); MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(Mem.str(), "test", false); - std::string errMsg; - OwningPtr<Module> m(getLazyBitcodeModule(Buffer, getGlobalContext(), &errMsg)); + ErrorOr<Module *> ModuleOrErr = + getLazyBitcodeModule(Buffer, getGlobalContext()); + std::unique_ptr<Module> m(ModuleOrErr.get()); PassManager passes; passes.add(createVerifierPass()); passes.run(*m); diff --git a/unittests/Bitcode/CMakeLists.txt b/unittests/Bitcode/CMakeLists.txt index d8f5fe1..743ab18 100644 --- a/unittests/Bitcode/CMakeLists.txt +++ b/unittests/Bitcode/CMakeLists.txt @@ -1,6 +1,8 @@ set(LLVM_LINK_COMPONENTS BitReader BitWriter + Core + Support ) add_llvm_unittest(BitcodeTests diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index 52702ba..9e2f60c 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -1,6 +1,12 @@ add_custom_target(UnitTests) set_target_properties(UnitTests PROPERTIES FOLDER "Tests") +if (APPLE) + set(CMAKE_INSTALL_RPATH "@executable_path/../../lib") +else(UNIX) + set(CMAKE_INSTALL_RPATH "\$ORIGIN/../../lib") +endif() + function(add_llvm_unittest test_dirname) add_unittest(UnitTests ${test_dirname} ${ARGN}) endfunction() @@ -12,6 +18,7 @@ add_subdirectory(CodeGen) add_subdirectory(DebugInfo) add_subdirectory(ExecutionEngine) add_subdirectory(IR) +add_subdirectory(LineEditor) add_subdirectory(MC) add_subdirectory(Object) add_subdirectory(Option) diff --git a/unittests/CodeGen/CMakeLists.txt b/unittests/CodeGen/CMakeLists.txt index 5973bae..65c0ac3 100644 --- a/unittests/CodeGen/CMakeLists.txt +++ b/unittests/CodeGen/CMakeLists.txt @@ -1,7 +1,6 @@ set(LLVM_LINK_COMPONENTS - asmprinter - codegen - support + AsmPrinter + Support ) set(CodeGenSources diff --git a/unittests/CodeGen/DIEHashTest.cpp b/unittests/CodeGen/DIEHashTest.cpp index 8d8fc39..c874cef 100644 --- a/unittests/CodeGen/DIEHashTest.cpp +++ b/unittests/CodeGen/DIEHashTest.cpp @@ -9,8 +9,8 @@ #include "../lib/CodeGen/AsmPrinter/DIE.h" #include "../lib/CodeGen/AsmPrinter/DIEHash.h" -#include "llvm/Support/Dwarf.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" #include "gtest/gtest.h" @@ -91,7 +91,8 @@ TEST(DIEHashTest, TypeWithMember) { DIEString MemberStr(&Four, "member"); Member->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemberStr); DIEInteger Zero(0); - Member->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); + Member->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, + &Zero); Unnamed.addChild(Member); @@ -121,14 +122,16 @@ TEST(DIEHashTest, ReusedType) { DIEString Mem1Str(&Four, "mem1"); Mem1->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem1Str); DIEInteger Zero(0); - Mem1->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); + Mem1->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, + &Zero); Unnamed.addChild(Mem1); DIE *Mem2 = new DIE(dwarf::DW_TAG_member); DIEString Mem2Str(&Four, "mem2"); Mem2->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem2Str); - Mem2->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Four); + Mem2->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, + &Four); Unnamed.addChild(Mem2); @@ -282,7 +285,8 @@ TEST(DIEHashTest, PtrToMember) { DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type); DIEEntry FooEntry(&Foo); PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry); - PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &FooEntry); + PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, + &FooEntry); DIEEntry PtrToFooMemRef(&PtrToFooMem); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef); @@ -478,7 +482,7 @@ TEST(DIEHashTest, RefUnnamedType) { ASSERT_EQ(0x954e026f01c02529ULL, MD5Res); } -// struct { struct bar { }; }; +// struct { struct foo { }; }; TEST(DIEHashTest, NestedType) { DIE Unnamed(dwarf::DW_TAG_structure_type); DIEInteger One(1); @@ -514,4 +518,135 @@ TEST(DIEHashTest, MemberFunc) { // The exact same hash GCC produces for this DIE. ASSERT_EQ(0xd36a1b6dfb604ba0ULL, MD5Res); } + +// struct A { +// static void func(); +// }; +TEST(DIEHashTest, MemberFuncFlag) { + DIE A(dwarf::DW_TAG_structure_type); + DIEInteger One(1); + DIEString AStr(&One, "A"); + A.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &AStr); + A.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); + A.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); + A.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One); + + DIE *Func = new DIE(dwarf::DW_TAG_subprogram); + DIEString FuncStr(&One, "func"); + DIEString FuncLinkage(&One, "_ZN1A4funcEv"); + DIEInteger Two(2); + Func->addValue(dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, &One); + Func->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FuncStr); + Func->addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); + Func->addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &Two); + Func->addValue(dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp, &FuncLinkage); + Func->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One); + + A.addChild(Func); + + uint64_t MD5Res = DIEHash().computeTypeSignature(A); + + // The exact same hash GCC produces for this DIE. + ASSERT_EQ(0x8f78211ddce3df10ULL, MD5Res); +} + +// Derived from: +// struct A { +// const static int PI = -3; +// }; +// A a; +TEST(DIEHashTest, MemberSdata) { + DIE A(dwarf::DW_TAG_structure_type); + DIEInteger One(1); + DIEString AStr(&One, "A"); + A.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &AStr); + A.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); + A.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); + A.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One); + + DIEInteger Four(4); + DIEInteger Five(5); + DIEString FStr(&One, "int"); + DIE *IntTyDIE = new DIE(dwarf::DW_TAG_base_type); + IntTyDIE->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four); + IntTyDIE->addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five); + IntTyDIE->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FStr); + + DIEEntry IntTy(IntTyDIE); + DIE *PITyDIE = new DIE(dwarf::DW_TAG_const_type); + PITyDIE->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntTy); + + DIEEntry PITy(PITyDIE); + DIE *PI = new DIE(dwarf::DW_TAG_member); + DIEString PIStr(&One, "PI"); + DIEInteger Two(2); + DIEInteger NegThree(-3); + PI->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &PIStr); + PI->addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); + PI->addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &Two); + PI->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PITy); + PI->addValue(dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, &One); + PI->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One); + PI->addValue(dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, &NegThree); + + A.addChild(PI); + + uint64_t MD5Res = DIEHash().computeTypeSignature(A); + ASSERT_EQ(0x9a216000dd3788a7ULL, MD5Res); +} + +// Derived from: +// struct A { +// const static float PI = 3.14; +// }; +// A a; +TEST(DIEHashTest, MemberBlock) { + DIE A(dwarf::DW_TAG_structure_type); + DIEInteger One(1); + DIEString AStr(&One, "A"); + A.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &AStr); + A.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); + A.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); + A.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One); + + DIEInteger Four(4); + DIEString FStr(&One, "float"); + DIE *FloatTyDIE = new DIE(dwarf::DW_TAG_base_type); + FloatTyDIE->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four); + FloatTyDIE->addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Four); + FloatTyDIE->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FStr); + + DIEEntry FloatTy(FloatTyDIE); + DIE *PITyDIE = new DIE(dwarf::DW_TAG_const_type); + PITyDIE->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FloatTy); + + DIEEntry PITy(PITyDIE); + DIE *PI = new DIE(dwarf::DW_TAG_member); + DIEString PIStr(&One, "PI"); + DIEInteger Two(2); + PI->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &PIStr); + PI->addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); + PI->addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &Two); + PI->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PITy); + PI->addValue(dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, &One); + PI->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One); + + DIEBlock *PIBlock = new DIEBlock(); + DIEInteger Blk1(0xc3); + DIEInteger Blk2(0xf5); + DIEInteger Blk3(0x48); + DIEInteger Blk4(0x40); + + PIBlock->addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk1); + PIBlock->addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk2); + PIBlock->addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk3); + PIBlock->addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk4); + + PI->addValue(dwarf::DW_AT_const_value, dwarf::DW_FORM_block1, PIBlock); + + A.addChild(PI); + + uint64_t MD5Res = DIEHash().computeTypeSignature(A); + ASSERT_EQ(0x493af53ad3d3f651ULL, MD5Res); +} } diff --git a/unittests/DebugInfo/CMakeLists.txt b/unittests/DebugInfo/CMakeLists.txt index ec580b7..e844e95 100644 --- a/unittests/DebugInfo/CMakeLists.txt +++ b/unittests/DebugInfo/CMakeLists.txt @@ -1,7 +1,5 @@ set(LLVM_LINK_COMPONENTS - debuginfo - object - support + DebugInfo ) set(DebugInfoSources diff --git a/unittests/ExecutionEngine/CMakeLists.txt b/unittests/ExecutionEngine/CMakeLists.txt index 4eefc1e..7ef509b 100644 --- a/unittests/ExecutionEngine/CMakeLists.txt +++ b/unittests/ExecutionEngine/CMakeLists.txt @@ -1,5 +1,8 @@ set(LLVM_LINK_COMPONENTS - interpreter + Core + ExecutionEngine + Interpreter + Support ) add_llvm_unittest(ExecutionEngineTests diff --git a/unittests/ExecutionEngine/ExecutionEngineTest.cpp b/unittests/ExecutionEngine/ExecutionEngineTest.cpp index 3e304e7..e6f07dc 100644 --- a/unittests/ExecutionEngine/ExecutionEngineTest.cpp +++ b/unittests/ExecutionEngine/ExecutionEngineTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Interpreter.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/LLVMContext.h" @@ -38,7 +37,7 @@ protected: Module *const M; std::string Error; - const OwningPtr<ExecutionEngine> Engine; + const std::unique_ptr<ExecutionEngine> Engine; }; TEST_F(ExecutionEngineTest, ForwardGlobalMapping) { diff --git a/unittests/ExecutionEngine/JIT/CMakeLists.txt b/unittests/ExecutionEngine/JIT/CMakeLists.txt index ef37026..72c1df7 100644 --- a/unittests/ExecutionEngine/JIT/CMakeLists.txt +++ b/unittests/ExecutionEngine/JIT/CMakeLists.txt @@ -1,8 +1,11 @@ set(LLVM_LINK_COMPONENTS - asmparser - bitreader - bitwriter - jit + AsmParser + BitReader + BitWriter + Core + ExecutionEngine + JIT + Support nativecodegen ) @@ -48,6 +51,9 @@ 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} ) diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp index 87f4824..175b9fb 100644 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/CodeGen/MachineCodeInfo.h" #include "llvm/ExecutionEngine/JIT.h" #include "llvm/IR/Instructions.h" @@ -21,8 +20,6 @@ using namespace llvm; -int dummy; - namespace { struct FunctionEmittedEvent { @@ -71,11 +68,11 @@ class JITEventListenerTest : public testing::Test { } Module *M; - const OwningPtr<ExecutionEngine> EE; + const std::unique_ptr<ExecutionEngine> EE; }; // Tests on SystemZ disabled as we're running the old JIT -#if !defined(__s390__) +#if !defined(__s390__) && !defined(__aarch64__) Function *buildFunction(Module *M) { Function *Result = Function::Create( TypeBuilder<int32_t(int32_t), false>::get(getGlobalContext()), diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h b/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h index d1c2124..61220f5 100644 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h +++ b/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h @@ -12,10 +12,10 @@ #include "llvm/CodeGen/MachineCodeInfo.h" #include "llvm/Config/config.h" -#include "llvm/DIBuilder.h" -#include "llvm/DebugInfo.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" @@ -53,8 +53,8 @@ inline const char* getFilename() { template<typename WrapperT> class JITEventListenerTestBase : public testing::Test { protected: - llvm::OwningPtr<WrapperT> MockWrapper; - llvm::OwningPtr<llvm::JITEventListener> Listener; + std::unique_ptr<WrapperT> MockWrapper; + std::unique_ptr<llvm::JITEventListener> Listener; public: llvm::Module* M; diff --git a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp index 731f780..ab30884 100644 --- a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp @@ -9,7 +9,6 @@ #include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalValue.h" @@ -31,27 +30,27 @@ Function *makeFakeFunction() { // the code in the case that we don't have to allocate more memory to store the // function bodies. TEST(JITMemoryManagerTest, NoAllocations) { - OwningPtr<JITMemoryManager> MemMgr( + std::unique_ptr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); uintptr_t size; std::string Error; // Allocate the functions. - OwningPtr<Function> F1(makeFakeFunction()); + 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; - OwningPtr<Function> F2(makeFakeFunction()); + 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; - OwningPtr<Function> F3(makeFakeFunction()); + std::unique_ptr<Function> F3(makeFakeFunction()); size = 1024; uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); memset(FunctionBody3, 0xFF, 1024); @@ -70,7 +69,7 @@ TEST(JITMemoryManagerTest, NoAllocations) { // 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) { - OwningPtr<JITMemoryManager> MemMgr( + std::unique_ptr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); uintptr_t size; std::string Error; @@ -81,7 +80,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { smallFuncSize * 2); // Allocate big functions - OwningPtr<Function> F1(makeFakeFunction()); + std::unique_ptr<Function> F1(makeFakeFunction()); size = bigFuncSize; uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size); ASSERT_LE(bigFuncSize, size); @@ -89,7 +88,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + bigFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - OwningPtr<Function> F2(makeFakeFunction()); + std::unique_ptr<Function> F2(makeFakeFunction()); size = bigFuncSize; uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size); ASSERT_LE(bigFuncSize, size); @@ -97,7 +96,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + bigFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - OwningPtr<Function> F3(makeFakeFunction()); + std::unique_ptr<Function> F3(makeFakeFunction()); size = bigFuncSize; uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); ASSERT_LE(bigFuncSize, size); @@ -109,7 +108,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); // Allocate small functions - OwningPtr<Function> F4(makeFakeFunction()); + std::unique_ptr<Function> F4(makeFakeFunction()); size = smallFuncSize; uint8_t *FunctionBody4 = MemMgr->startFunctionBody(F4.get(), size); ASSERT_LE(smallFuncSize, size); @@ -118,7 +117,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { FunctionBody4 + smallFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - OwningPtr<Function> F5(makeFakeFunction()); + std::unique_ptr<Function> F5(makeFakeFunction()); size = smallFuncSize; uint8_t *FunctionBody5 = MemMgr->startFunctionBody(F5.get(), size); ASSERT_LE(smallFuncSize, size); @@ -127,7 +126,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { FunctionBody5 + smallFuncSize); EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - OwningPtr<Function> F6(makeFakeFunction()); + std::unique_ptr<Function> F6(makeFakeFunction()); size = smallFuncSize; uint8_t *FunctionBody6 = MemMgr->startFunctionBody(F6.get(), size); ASSERT_LE(smallFuncSize, size); @@ -157,7 +156,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { // Allocate five global ints of varying widths and alignment, and check their // alignment and overlap. TEST(JITMemoryManagerTest, TestSmallGlobalInts) { - OwningPtr<JITMemoryManager> MemMgr( + 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); @@ -204,7 +203,7 @@ TEST(JITMemoryManagerTest, TestSmallGlobalInts) { // Allocate a small global, a big global, and a third global, and make sure we // only use two slabs for that. TEST(JITMemoryManagerTest, TestLargeGlobalArray) { - OwningPtr<JITMemoryManager> MemMgr( + std::unique_ptr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); size_t Size = 4 * MemMgr->GetDefaultDataSlabSize(); uint64_t *a = (uint64_t*)MemMgr->allocateGlobal(64, 8); @@ -234,7 +233,7 @@ TEST(JITMemoryManagerTest, TestLargeGlobalArray) { // Allocate lots of medium globals so that we can test moving the bump allocator // to a new slab. TEST(JITMemoryManagerTest, TestManyGlobals) { - OwningPtr<JITMemoryManager> MemMgr( + std::unique_ptr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); size_t SlabSize = MemMgr->GetDefaultDataSlabSize(); size_t Size = 128; @@ -257,7 +256,7 @@ TEST(JITMemoryManagerTest, TestManyGlobals) { // Allocate lots of function stubs so that we can test moving the stub bump // allocator to a new slab. TEST(JITMemoryManagerTest, TestManyStubs) { - OwningPtr<JITMemoryManager> MemMgr( + std::unique_ptr<JITMemoryManager> MemMgr( JITMemoryManager::CreateDefaultMemManager()); size_t SlabSize = MemMgr->GetDefaultStubSlabSize(); size_t Size = 128; @@ -279,7 +278,7 @@ TEST(JITMemoryManagerTest, TestManyStubs) { // Check section allocation and alignment TEST(JITMemoryManagerTest, AllocateSection) { - OwningPtr<JITMemoryManager> MemMgr( + 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); diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp index 4c7b1e2..9e65fee 100644 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITTest.cpp @@ -8,9 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Assembly/Parser.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/ExecutionEngine/JITMemoryManager.h" #include "llvm/IR/BasicBlock.h" @@ -52,7 +51,8 @@ extern "C" int32_t JITTest_AvailableExternallyFunction() { namespace { // Tests on ARM, PowerPC and SystemZ disabled as we're running the old jit -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) +#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \ + && !defined(__aarch64__) Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) { std::vector<Type*> params; @@ -76,7 +76,8 @@ std::string DumpFunction(const Function *F) { } class RecordingJITMemoryManager : public JITMemoryManager { - const OwningPtr<JITMemoryManager> Base; + const std::unique_ptr<JITMemoryManager> Base; + public: RecordingJITMemoryManager() : Base(JITMemoryManager::CreateDefaultMemManager()) { @@ -202,7 +203,7 @@ class JITTest : public testing::Test { LLVMContext Context; Module *M; // Owned by ExecutionEngine. RecordingJITMemoryManager *RJMM; - OwningPtr<ExecutionEngine> TheJIT; + std::unique_ptr<ExecutionEngine> TheJIT; }; // Regression test for a bug. The JIT used to allocate globals inside the same @@ -219,13 +220,13 @@ TEST(JIT, GlobalInFunction) { // memory is more easily tested. MemMgr->setPoisonMemory(true); std::string Error; - OwningPtr<ExecutionEngine> JIT(EngineBuilder(M) - .setEngineKind(EngineKind::JIT) - .setErrorStr(&Error) - .setJITMemoryManager(MemMgr) - // The next line enables the fix: - .setAllocateGVsWithCode(false) - .create()); + 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. @@ -438,7 +439,7 @@ TEST_F(JITTest, ModuleDeletion) { // 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(__powerpc__) && !defined(__ppc__) && !defined(__aarch64__) typedef int (*FooPtr) (); TEST_F(JITTest, NoStubs) { @@ -514,7 +515,7 @@ TEST_F(JITTest, FunctionPointersOutliveTheirCreator) { // ARM does not have an implementation of replaceMachineCodeForFunction(), // so recompileAndRelinkFunction doesn't work. -#if !defined(__arm__) +#if !defined(__arm__) && !defined(__aarch64__) TEST_F(JITTest, FunctionIsRecompiledAndRelinked) { Function *F = Function::Create(TypeBuilder<int(void), false>::get(Context), GlobalValue::ExternalLinkage, "test", M); @@ -631,13 +632,14 @@ ExecutionEngine *getJITFromBitcode( // c_str() is null-terminated like MemoryBuffer::getMemBuffer requires. MemoryBuffer *BitcodeBuffer = MemoryBuffer::getMemBuffer(Bitcode, "Bitcode for test"); - std::string errMsg; - M = getLazyBitcodeModule(BitcodeBuffer, Context, &errMsg); - if (M == NULL) { - ADD_FAILURE() << errMsg; + ErrorOr<Module*> ModuleOrErr = getLazyBitcodeModule(BitcodeBuffer, Context); + if (error_code EC = ModuleOrErr.getError()) { + ADD_FAILURE() << EC.message(); delete BitcodeBuffer; return NULL; } + M = ModuleOrErr.get(); + std::string errMsg; ExecutionEngine *TheJIT = EngineBuilder(M) .setEngineKind(EngineKind::JIT) .setErrorStr(&errMsg) @@ -667,7 +669,8 @@ TEST(LazyLoadedJITTest, MaterializableAvailableExternallyFunctionIsntCompiled) { "} "); ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; Module *M; - OwningPtr<ExecutionEngine> TheJIT(getJITFromBitcode(Context, Bitcode, M)); + std::unique_ptr<ExecutionEngine> TheJIT( + getJITFromBitcode(Context, Bitcode, M)); ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; TheJIT->DisableLazyCompilation(true); @@ -706,7 +709,8 @@ TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) { "} "); ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; Module *M; - OwningPtr<ExecutionEngine> TheJIT(getJITFromBitcode(Context, Bitcode, M)); + std::unique_ptr<ExecutionEngine> TheJIT( + getJITFromBitcode(Context, Bitcode, M)); ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; TheJIT->DisableLazyCompilation(true); diff --git a/unittests/ExecutionEngine/JIT/Makefile b/unittests/ExecutionEngine/JIT/Makefile index ef8b827..d86c03b 100644 --- a/unittests/ExecutionEngine/JIT/Makefile +++ b/unittests/ExecutionEngine/JIT/Makefile @@ -11,6 +11,9 @@ 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 diff --git a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp b/unittests/ExecutionEngine/JIT/MultiJITTest.cpp index 4018cd5..5016532 100644 --- a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp +++ b/unittests/ExecutionEngine/JIT/MultiJITTest.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/JIT.h" -#include "llvm/Assembly/Parser.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/ExecutionEngine/GenericValue.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -21,7 +21,8 @@ using namespace llvm; namespace { // ARM, PowerPC and SystemZ tests disabled pending fix for PR10783. -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) +#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \ + && !defined(__aarch64__) bool LoadAssemblyInto(Module *M, const char *assembly) { SMDiagnostic Error; @@ -80,9 +81,9 @@ TEST(MultiJitTest, EagerMode) { createModule2(Context2, M2, FooF2); // Now we create the JIT in eager mode - OwningPtr<ExecutionEngine> EE1(EngineBuilder(M1).create()); + std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create()); EE1->DisableLazyCompilation(true); - OwningPtr<ExecutionEngine> EE2(EngineBuilder(M2).create()); + std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create()); EE2->DisableLazyCompilation(true); // Call the `foo' function with no arguments: @@ -110,9 +111,9 @@ TEST(MultiJitTest, LazyMode) { createModule2(Context2, M2, FooF2); // Now we create the JIT in lazy mode - OwningPtr<ExecutionEngine> EE1(EngineBuilder(M1).create()); + std::unique_ptr<ExecutionEngine> EE1(EngineBuilder(M1).create()); EE1->DisableLazyCompilation(false); - OwningPtr<ExecutionEngine> EE2(EngineBuilder(M2).create()); + std::unique_ptr<ExecutionEngine> EE2(EngineBuilder(M2).create()); EE2->DisableLazyCompilation(false); // Call the `foo' function with no arguments: @@ -144,8 +145,8 @@ TEST(MultiJitTest, JitPool) { createModule2(Context2, M2, FooF2); // Now we create two JITs - OwningPtr<ExecutionEngine> EE1(EngineBuilder(M1).create()); - OwningPtr<ExecutionEngine> EE2(EngineBuilder(M2).create()); + 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); @@ -173,6 +174,14 @@ TEST(MultiJitTest, JitPool) { 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); } diff --git a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt index ed43099..afa3f2a 100644 --- a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt @@ -1,8 +1,13 @@ set(LLVM_LINK_COMPONENTS - asmparser - bitreader - bitwriter - mcjit + Analysis + Core + ExecutionEngine + IPO + JIT + MCJIT + ScalarOpts + Support + Target nativecodegen ) diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp index 46d6d9b..3813d59 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -13,18 +13,21 @@ //===----------------------------------------------------------------------===// #include "llvm-c/Analysis.h" +#include "MCJITTestAPICommon.h" #include "llvm-c/Core.h" #include "llvm-c/ExecutionEngine.h" #include "llvm-c/Target.h" +#include "llvm-c/Transforms/PassManagerBuilder.h" #include "llvm-c/Transforms/Scalar.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/Host.h" -#include "MCJITTestAPICommon.h" #include "gtest/gtest.h" using namespace llvm; static bool didCallAllocateCodeSection; +static bool didAllocateCompactUnwindSection; static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size, unsigned alignment, @@ -40,6 +43,8 @@ static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size, unsigned sectionID, const char *sectionName, LLVMBool isReadOnly) { + if (!strcmp(sectionName, "__compact_unwind")) + didAllocateCompactUnwindSection = true; return static_cast<SectionMemoryManager*>(object)->allocateDataSection( size, alignment, sectionID, sectionName, isReadOnly); } @@ -60,6 +65,54 @@ static void roundTripDestroy(void *object) { } namespace { + +// memory manager to test reserve allocation space callback +class TestReserveAllocationSpaceMemoryManager: public SectionMemoryManager { +public: + uintptr_t ReservedCodeSize; + uintptr_t UsedCodeSize; + uintptr_t ReservedDataSizeRO; + uintptr_t UsedDataSizeRO; + uintptr_t ReservedDataSizeRW; + uintptr_t UsedDataSizeRW; + + TestReserveAllocationSpaceMemoryManager() : + ReservedCodeSize(0), UsedCodeSize(0), ReservedDataSizeRO(0), + UsedDataSizeRO(0), ReservedDataSizeRW(0), UsedDataSizeRW(0) { + } + + virtual bool needsToReserveAllocationSpace() { + return true; + } + + virtual void reserveAllocationSpace( + uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) { + ReservedCodeSize = CodeSize; + ReservedDataSizeRO = DataSizeRO; + ReservedDataSizeRW = DataSizeRW; + } + + void useSpace(uintptr_t* UsedSize, uintptr_t Size, unsigned Alignment) { + uintptr_t AlignedSize = (Size + Alignment - 1) / Alignment * Alignment; + uintptr_t AlignedBegin = (*UsedSize + Alignment - 1) / Alignment * Alignment; + *UsedSize = AlignedBegin + AlignedSize; + } + + virtual uint8_t* allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName, bool IsReadOnly) { + useSpace(IsReadOnly ? &UsedDataSizeRO : &UsedDataSizeRW, Size, Alignment); + return SectionMemoryManager::allocateDataSection(Size, Alignment, + SectionID, SectionName, IsReadOnly); + } + + uint8_t* allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, StringRef SectionName) { + useSpace(&UsedCodeSize, Size, Alignment); + return SectionMemoryManager::allocateCodeSection(Size, Alignment, + SectionID, SectionName); + } +}; + class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon { protected: MCJITCAPITest() { @@ -82,10 +135,13 @@ 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); } virtual void SetUp() { didCallAllocateCodeSection = false; + didAllocateCompactUnwindSection = false; Module = 0; Function = 0; Engine = 0; @@ -119,6 +175,84 @@ protected: LLVMDisposeBuilder(builder); } + void buildFunctionThatUsesStackmap() { + Module = LLVMModuleCreateWithName("simple_module"); + + LLVMSetTarget(Module, HostTriple.c_str()); + + LLVMTypeRef stackmapParamTypes[] = { LLVMInt64Type(), LLVMInt32Type() }; + LLVMValueRef stackmap = LLVMAddFunction( + Module, "llvm.experimental.stackmap", + LLVMFunctionType(LLVMVoidType(), stackmapParamTypes, 2, 1)); + LLVMSetLinkage(stackmap, LLVMExternalLinkage); + + Function = LLVMAddFunction( + Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0)); + + LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry"); + LLVMBuilderRef builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(builder, entry); + LLVMValueRef stackmapArgs[] = { + LLVMConstInt(LLVMInt64Type(), 0, 0), LLVMConstInt(LLVMInt32Type(), 5, 0), + LLVMConstInt(LLVMInt32Type(), 42, 0) + }; + LLVMBuildCall(builder, stackmap, stackmapArgs, 3, ""); + LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0)); + + LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error); + LLVMDisposeMessage(Error); + + LLVMDisposeBuilder(builder); + } + + void buildModuleWithCodeAndData() { + Module = LLVMModuleCreateWithName("simple_module"); + + LLVMSetTarget(Module, HostTriple.c_str()); + + // build a global int32 variable initialized to 42. + LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "intVal"); + LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0)); + + { + Function = LLVMAddFunction( + Module, "getGlobal", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0)); + LLVMSetFunctionCallConv(Function, LLVMCCallConv); + + LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function, "entry"); + LLVMBuilderRef Builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(Builder, Entry); + + LLVMValueRef IntVal = LLVMBuildLoad(Builder, GlobalVar, "intVal"); + LLVMBuildRet(Builder, IntVal); + + LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error); + LLVMDisposeMessage(Error); + + LLVMDisposeBuilder(Builder); + } + + { + LLVMTypeRef ParamTypes[] = { LLVMInt32Type() }; + Function2 = LLVMAddFunction( + Module, "setGlobal", LLVMFunctionType(LLVMVoidType(), ParamTypes, 1, 0)); + LLVMSetFunctionCallConv(Function2, LLVMCCallConv); + + LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function2, "entry"); + LLVMBuilderRef Builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(Builder, Entry); + + LLVMValueRef Arg = LLVMGetParam(Function2, 0); + LLVMBuildStore(Builder, Arg, GlobalVar); + LLVMBuildRetVoid(Builder); + + LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error); + LLVMDisposeMessage(Error); + + LLVMDisposeBuilder(Builder); + } + } + void buildMCJITOptions() { LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options)); Options.OptLevel = 2; @@ -135,7 +269,7 @@ protected: roundTripFinalizeMemory, roundTripDestroy); } - + void buildMCJITEngine() { ASSERT_EQ( 0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options, @@ -151,8 +285,41 @@ protected: LLVMDisposePassManager(pass); } + void buildAndRunOptPasses() { + LLVMPassManagerBuilderRef passBuilder; + + passBuilder = LLVMPassManagerBuilderCreate(); + LLVMPassManagerBuilderSetOptLevel(passBuilder, 2); + LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0); + + LLVMPassManagerRef functionPasses = + LLVMCreateFunctionPassManagerForModule(Module); + LLVMPassManagerRef modulePasses = + LLVMCreatePassManager(); + + LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), modulePasses); + + LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder, + functionPasses); + LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses); + + LLVMPassManagerBuilderDispose(passBuilder); + + LLVMInitializeFunctionPassManager(functionPasses); + for (LLVMValueRef value = LLVMGetFirstFunction(Module); + value; value = LLVMGetNextFunction(value)) + LLVMRunFunctionPassManager(functionPasses, value); + LLVMFinalizeFunctionPassManager(functionPasses); + + LLVMRunPassManager(modulePasses, Module); + + LLVMDisposePassManager(functionPasses); + LLVMDisposePassManager(modulePasses); + } + LLVMModuleRef Module; LLVMValueRef Function; + LLVMValueRef Function2; LLVMMCJITCompilerOptions Options; LLVMExecutionEngineRef Engine; char *Error; @@ -194,3 +361,71 @@ TEST_F(MCJITCAPITest, custom_memory_manager) { EXPECT_EQ(42, functionPointer.usable()); EXPECT_TRUE(didCallAllocateCodeSection); } + +TEST_F(MCJITCAPITest, stackmap_creates_compact_unwind_on_darwin) { + SKIP_UNSUPPORTED_PLATFORM; + + // This test is also not supported on non-x86 platforms. + if (Triple(HostTriple).getArch() != Triple::x86_64) + return; + + buildFunctionThatUsesStackmap(); + buildMCJITOptions(); + useRoundTripSectionMemoryManager(); + buildMCJITEngine(); + buildAndRunOptPasses(); + + union { + void *raw; + int (*usable)(); + } functionPointer; + functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function); + + EXPECT_EQ(42, functionPointer.usable()); + EXPECT_TRUE(didCallAllocateCodeSection); + + // Up to this point, the test is specific only to X86-64. But this next + // expectation is only valid on Darwin because it assumes that unwind + // data is made available only through compact_unwind. It would be + // worthwhile to extend this to handle non-Darwin platforms, in which + // case you'd want to look for an eh_frame or something. + // + // FIXME: Currently, MCJIT relies on a configure-time check to determine which + // sections to emit. The JIT client should have runtime control over this. + EXPECT_TRUE( + Triple(HostTriple).getOS() != Triple::Darwin || + Triple(HostTriple).isMacOSXVersionLT(10, 7) || + didAllocateCompactUnwindSection); +} + +TEST_F(MCJITCAPITest, reserve_allocation_space) { + SKIP_UNSUPPORTED_PLATFORM; + + TestReserveAllocationSpaceMemoryManager* MM = new TestReserveAllocationSpaceMemoryManager(); + + buildModuleWithCodeAndData(); + buildMCJITOptions(); + Options.MCJMM = wrap(MM); + buildMCJITEngine(); + buildAndRunPasses(); + + union { + void *raw; + int (*usable)(); + } GetGlobalFct; + GetGlobalFct.raw = LLVMGetPointerToGlobal(Engine, Function); + + union { + void *raw; + void (*usable)(int); + } SetGlobalFct; + SetGlobalFct.raw = LLVMGetPointerToGlobal(Engine, Function2); + + SetGlobalFct.usable(789); + EXPECT_EQ(789, GetGlobalFct.usable()); + EXPECT_LE(MM->UsedCodeSize, MM->ReservedCodeSize); + EXPECT_LE(MM->UsedDataSizeRO, MM->ReservedDataSizeRO); + EXPECT_LE(MM->UsedDataSizeRW, MM->ReservedDataSizeRW); + EXPECT_TRUE(MM->UsedCodeSize > 0); + EXPECT_TRUE(MM->UsedDataSizeRW > 0); +} diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp index c24346d..f862999 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/SectionMemoryManager.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ExecutionEngine/JIT.h" #include "gtest/gtest.h" @@ -17,7 +16,7 @@ using namespace llvm; namespace { TEST(MCJITMemoryManagerTest, BasicAllocations) { - OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); + std::unique_ptr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1, ""); uint8_t *data1 = MemMgr->allocateDataSection(256, 0, 2, "", true); @@ -50,7 +49,7 @@ TEST(MCJITMemoryManagerTest, BasicAllocations) { } TEST(MCJITMemoryManagerTest, LargeAllocations) { - OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); + std::unique_ptr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); uint8_t *code1 = MemMgr->allocateCodeSection(0x100000, 0, 1, ""); uint8_t *data1 = MemMgr->allocateDataSection(0x100000, 0, 2, "", true); @@ -83,7 +82,7 @@ TEST(MCJITMemoryManagerTest, LargeAllocations) { } TEST(MCJITMemoryManagerTest, ManyAllocations) { - OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); + std::unique_ptr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); uint8_t* code[10000]; uint8_t* data[10000]; @@ -118,7 +117,7 @@ TEST(MCJITMemoryManagerTest, ManyAllocations) { } TEST(MCJITMemoryManagerTest, ManyVariedAllocations) { - OwningPtr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); + std::unique_ptr<SectionMemoryManager> MemMgr(new SectionMemoryManager()); uint8_t* code[10000]; uint8_t* data[10000]; diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp index 7c3239e..c5ca36e 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp @@ -90,12 +90,12 @@ TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) { TEST_F(MCJITMultipleModuleTest, two_module_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB; createTwoModuleCase(A, FA, B, FB); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -110,12 +110,12 @@ TEST_F(MCJITMultipleModuleTest, two_module_case) { TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB; createTwoModuleCase(A, FA, B, FB); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -131,12 +131,12 @@ TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) { TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB; createTwoModuleExternCase(A, FA, B, FB); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -152,12 +152,12 @@ TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) { TEST_F(MCJITMultipleModuleTest, two_module_extern_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB; createTwoModuleExternCase(A, FA, B, FB); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -172,13 +172,13 @@ TEST_F(MCJITMultipleModuleTest, two_module_extern_case) { TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA1, *FA2, *FB; createTwoModuleExternCase(A, FA1, B, FB); FA2 = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(A.get(), FA1); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -199,7 +199,7 @@ TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) { TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB; GlobalVariable *GVA, *GVB; A.reset(createEmptyModule("A")); @@ -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.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -237,13 +237,13 @@ TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) { TEST_F(MCJITMultipleModuleTest, three_module_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B, C; + std::unique_ptr<Module> A, B, C; Function *FA, *FB, *FC; createThreeModuleCase(A, FA, B, FB, C, FC); - createJIT(A.take()); - TheJIT->addModule(B.take()); - TheJIT->addModule(C.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); + TheJIT->addModule(C.release()); uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); checkAdd(ptr); @@ -262,13 +262,13 @@ TEST_F(MCJITMultipleModuleTest, three_module_case) { TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B, C; + std::unique_ptr<Module> A, B, C; Function *FA, *FB, *FC; createThreeModuleCase(A, FA, B, FB, C, FC); - createJIT(A.take()); - TheJIT->addModule(B.take()); - TheJIT->addModule(C.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); + TheJIT->addModule(C.release()); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -287,13 +287,13 @@ TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) { TEST_F(MCJITMultipleModuleTest, three_module_chain_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B, C; + std::unique_ptr<Module> A, B, C; Function *FA, *FB, *FC; createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); - createJIT(A.take()); - TheJIT->addModule(B.take()); - TheJIT->addModule(C.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); + TheJIT->addModule(C.release()); uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); checkAdd(ptr); @@ -312,13 +312,13 @@ TEST_F(MCJITMultipleModuleTest, three_module_chain_case) { TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B, C; + std::unique_ptr<Module> A, B, C; Function *FA, *FB, *FC; createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); - createJIT(A.take()); - TheJIT->addModule(B.take()); - TheJIT->addModule(C.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); + TheJIT->addModule(C.release()); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -337,12 +337,12 @@ TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) { TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB1, *FB2; createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAccumulate(ptr); @@ -358,12 +358,12 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) { TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB1, *FB2; createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); checkAccumulate(ptr); @@ -379,12 +379,12 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) { TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<Module> A, B; + std::unique_ptr<Module> A, B; Function *FA, *FB1, *FB2; createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); - createJIT(A.take()); - TheJIT->addModule(B.take()); + createJIT(A.release()); + TheJIT->addModule(B.release()); 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 7073a52..46847d3 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/OwningPtr.h" +#include "MCJITTestBase.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" @@ -15,7 +15,6 @@ #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" -#include "MCJITTestBase.h" #include "gtest/gtest.h" using namespace llvm; @@ -101,7 +100,7 @@ protected: void compileAndRun(int ExpectedRC = OriginalRC) { // This function shouldn't be called until after SetUp. - ASSERT_TRUE(TheJIT.isValid()); + ASSERT_TRUE(bool(TheJIT)); ASSERT_TRUE(0 != Main); // We may be using a null cache, so ensure compilation is valid. @@ -122,7 +121,7 @@ protected: TEST_F(MCJITObjectCacheTest, SetNullObjectCache) { SKIP_UNSUPPORTED_PLATFORM; - createJIT(M.take()); + createJIT(M.release()); TheJIT->setObjectCache(NULL); @@ -133,12 +132,12 @@ TEST_F(MCJITObjectCacheTest, SetNullObjectCache) { TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<TestObjectCache> Cache(new TestObjectCache); + std::unique_ptr<TestObjectCache> Cache(new TestObjectCache); // Save a copy of the module pointer before handing it off to MCJIT. const Module * SavedModulePointer = M.get(); - createJIT(M.take()); + createJIT(M.release()); TheJIT->setObjectCache(Cache.get()); @@ -162,10 +161,10 @@ TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) { TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<TestObjectCache> Cache(new TestObjectCache); + std::unique_ptr<TestObjectCache> Cache(new TestObjectCache); // Compile this module with an MCJIT engine - createJIT(M.take()); + createJIT(M.release()); TheJIT->setObjectCache(Cache.get()); TheJIT->finalizeObject(); @@ -182,7 +181,7 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { const Module * SecondModulePointer = M.get(); // Create a new MCJIT instance to load this module then execute it. - createJIT(M.take()); + createJIT(M.release()); TheJIT->setObjectCache(Cache.get()); compileAndRun(); @@ -196,10 +195,10 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { SKIP_UNSUPPORTED_PLATFORM; - OwningPtr<TestObjectCache> Cache(new TestObjectCache); + std::unique_ptr<TestObjectCache> Cache(new TestObjectCache); // Compile this module with an MCJIT engine - createJIT(M.take()); + createJIT(M.release()); TheJIT->setObjectCache(Cache.get()); TheJIT->finalizeObject(); @@ -217,7 +216,7 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { const Module * SecondModulePointer = M.get(); // Create a new MCJIT instance to load this module then execute it. - createJIT(M.take()); + createJIT(M.release()); 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 fab8155..a439508 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.take()); + createJIT(M.release()); void *globalPtr = TheJIT->getPointerToGlobal(Global); EXPECT_TRUE(0 != 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.take()); + createJIT(M.release()); 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.take()); + createJIT(M.release()); 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.take()); + createJIT(M.release()); 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.take()); + createJIT(M.release()); uint64_t ptr = TheJIT->getFunctionAddress(Outer->getName().str()); EXPECT_TRUE(0 != ptr) << "Unable to get pointer to outer function from JIT"; diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h index 7b6e39f..a48c071 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h @@ -71,10 +71,15 @@ protected: /// Returns true if the host OS is known to support MCJIT bool OSSupportsMCJIT() { Triple Host(HostTriple); + + if (std::find(UnsupportedEnvironments.begin(), UnsupportedEnvironments.end(), + Host.getEnvironment()) != UnsupportedEnvironments.end()) + return false; + if (std::find(UnsupportedOSs.begin(), UnsupportedOSs.end(), Host.getOS()) - == UnsupportedOSs.end()) { + == UnsupportedOSs.end()) return true; - } + return false; } @@ -83,6 +88,7 @@ protected: SmallVector<Triple::ArchType, 1> HasSubArchs; SmallVector<std::string, 2> SupportedSubArchs; // We need to own the memory SmallVector<Triple::OSType, 4> UnsupportedOSs; + SmallVector<Triple::EnvironmentType, 1> UnsupportedEnvironments; }; } // namespace llvm diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h index b42a9c0..25de312 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h @@ -17,6 +17,7 @@ #ifndef MCJIT_TEST_BASE_H #define MCJIT_TEST_BASE_H +#include "MCJITTestAPICommon.h" #include "llvm/Config/config.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" @@ -26,7 +27,6 @@ #include "llvm/IR/Module.h" #include "llvm/IR/TypeBuilder.h" #include "llvm/Support/CodeGen.h" -#include "MCJITTestAPICommon.h" namespace llvm { @@ -185,11 +185,9 @@ protected: // Populates Modules A and B: // Module A { Extern FB1, Function FA which calls FB1 }, // Module B { Extern FA, Function FB1, Function FB2 which calls FA }, - void createCrossModuleRecursiveCase(OwningPtr<Module> &A, - Function *&FA, - OwningPtr<Module> &B, - Function *&FB1, - Function *&FB2) { + void createCrossModuleRecursiveCase(std::unique_ptr<Module> &A, Function *&FA, + std::unique_ptr<Module> &B, + Function *&FB1, Function *&FB2) { // Define FB1 in B. B.reset(createEmptyModule("B")); FB1 = insertAccumulateFunction(B.get(), 0, "FB1"); @@ -211,12 +209,10 @@ protected: // Module A { Function FA }, // Module B { Extern FA, Function FB which calls FA }, // Module C { Extern FB, Function FC which calls FB }, - void createThreeModuleChainedCallsCase(OwningPtr<Module> &A, - Function *&FA, - OwningPtr<Module> &B, - Function *&FB, - OwningPtr<Module> &C, - Function *&FC) { + void + createThreeModuleChainedCallsCase(std::unique_ptr<Module> &A, Function *&FA, + std::unique_ptr<Module> &B, Function *&FB, + std::unique_ptr<Module> &C, Function *&FC) { A.reset(createEmptyModule("A")); FA = insertAddFunction(A.get()); @@ -233,8 +229,8 @@ protected: // Module A { Function FA }, // Populates Modules A and B: // Module B { Function FB } - void createTwoModuleCase(OwningPtr<Module> &A, Function *&FA, - OwningPtr<Module> &B, Function *&FB) { + void createTwoModuleCase(std::unique_ptr<Module> &A, Function *&FA, + std::unique_ptr<Module> &B, Function *&FB) { A.reset(createEmptyModule("A")); FA = insertAddFunction(A.get()); @@ -244,8 +240,8 @@ protected: // Module A { Function FA }, // Module B { Extern FA, Function FB which calls FA } - void createTwoModuleExternCase(OwningPtr<Module> &A, Function *&FA, - OwningPtr<Module> &B, Function *&FB) { + void createTwoModuleExternCase(std::unique_ptr<Module> &A, Function *&FA, + std::unique_ptr<Module> &B, Function *&FB) { A.reset(createEmptyModule("A")); FA = insertAddFunction(A.get()); @@ -258,12 +254,9 @@ protected: // Module A { Function FA }, // Module B { Extern FA, Function FB which calls FA }, // Module C { Extern FB, Function FC which calls FA }, - void createThreeModuleCase(OwningPtr<Module> &A, - Function *&FA, - OwningPtr<Module> &B, - Function *&FB, - OwningPtr<Module> &C, - Function *&FC) { + void createThreeModuleCase(std::unique_ptr<Module> &A, Function *&FA, + std::unique_ptr<Module> &B, Function *&FB, + std::unique_ptr<Module> &C, Function *&FC) { A.reset(createEmptyModule("A")); FA = insertAddFunction(A.get()); @@ -311,6 +304,8 @@ protected: // should be kept in sync. UnsupportedOSs.push_back(Triple::Cygwin); UnsupportedOSs.push_back(Triple::Darwin); + + UnsupportedEnvironments.push_back(Triple::Cygnus); } void createJIT(Module *M) { @@ -342,10 +337,10 @@ protected: CodeModel::Model CodeModel; StringRef MArch; SmallVector<std::string, 1> MAttrs; - OwningPtr<ExecutionEngine> TheJIT; + std::unique_ptr<ExecutionEngine> TheJIT; RTDyldMemoryManager *MM; - OwningPtr<Module> M; + std::unique_ptr<Module> M; }; } // namespace llvm diff --git a/unittests/ExecutionEngine/MCJIT/Makefile b/unittests/ExecutionEngine/MCJIT/Makefile index 33b043b..c4dd740 100644 --- a/unittests/ExecutionEngine/MCJIT/Makefile +++ b/unittests/ExecutionEngine/MCJIT/Makefile @@ -9,7 +9,7 @@ LEVEL = ../../.. TESTNAME = MCJIT -LINK_COMPONENTS := core mcjit native support +LINK_COMPONENTS := core ipo jit mcjit native support include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index fd0831f..7368a24 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -1,15 +1,19 @@ set(LLVM_LINK_COMPONENTS - asmparser - core - ipa + Analysis + AsmParser + Core + IPA + Support ) set(IRSources AttributesTest.cpp + ConstantRangeTest.cpp ConstantsTest.cpp DominatorTreeTest.cpp IRBuilderTest.cpp InstructionsTest.cpp + LeakDetectorTest.cpp LegacyPassManagerTest.cpp MDBuilderTest.cpp MetadataTest.cpp @@ -17,18 +21,13 @@ set(IRSources PatternMatch.cpp TypeBuilderTest.cpp TypesTest.cpp + ValueHandleTest.cpp ValueMapTest.cpp ValueTest.cpp VerifierTest.cpp WaymarkTest.cpp ) -# MSVC9 and 8 cannot compile ValueMapTest.cpp due to their bug. -# See issue#331418 in Visual Studio. -if(MSVC AND MSVC_VERSION LESS 1600) - list(REMOVE_ITEM IRSources ValueMapTest.cpp) -endif() - # 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 diff --git a/unittests/Support/ConstantRangeTest.cpp b/unittests/IR/ConstantRangeTest.cpp index 3e0a085..cdf7378 100644 --- a/unittests/Support/ConstantRangeTest.cpp +++ b/unittests/IR/ConstantRangeTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/Support/ConstantRangeTest.cpp - ConstantRange tests --===// +//===- ConstantRangeTest.cpp - ConstantRange tests ------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/ConstantRange.h" +#include "llvm/IR/ConstantRange.h" #include "llvm/IR/Instructions.h" #include "gtest/gtest.h" diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index fee38b8..b3aa810 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -162,7 +162,7 @@ TEST(ConstantsTest, PointerCast) { } TEST(ConstantsTest, AsInstructionsTest) { - OwningPtr<Module> M(new Module("MyModule", getGlobalContext())); + std::unique_ptr<Module> M(new Module("MyModule", getGlobalContext())); Type *Int64Ty = Type::getInt64Ty(getGlobalContext()); Type *Int32Ty = Type::getInt32Ty(getGlobalContext()); diff --git a/unittests/IR/DominatorTreeTest.cpp b/unittests/IR/DominatorTreeTest.cpp index 4e5af93..98c2317 100644 --- a/unittests/IR/DominatorTreeTest.cpp +++ b/unittests/IR/DominatorTreeTest.cpp @@ -7,8 +7,9 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/Dominators.h" -#include "llvm/Assembly/Parser.h" +#include "llvm/IR/Dominators.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -25,7 +26,9 @@ namespace llvm { struct DPass : public FunctionPass { static char ID; virtual bool runOnFunction(Function &F) { - DominatorTree *DT = &getAnalysis<DominatorTree>(); + DominatorTree *DT = + &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); + PostDominatorTree *PDT = &getAnalysis<PostDominatorTree>(); Function::iterator FI = F.begin(); BasicBlock *BB0 = FI++; @@ -148,10 +151,34 @@ namespace llvm { EXPECT_TRUE(DT->dominates(Y6, BB3)); + // Post dominance. + EXPECT_TRUE(PDT->dominates(BB0, BB0)); + EXPECT_FALSE(PDT->dominates(BB1, BB0)); + EXPECT_FALSE(PDT->dominates(BB2, BB0)); + EXPECT_FALSE(PDT->dominates(BB3, BB0)); + EXPECT_TRUE(PDT->dominates(BB4, BB1)); + + // Dominance descendants. + SmallVector<BasicBlock *, 8> DominatedBBs, PostDominatedBBs; + + DT->getDescendants(BB0, DominatedBBs); + PDT->getDescendants(BB0, PostDominatedBBs); + EXPECT_EQ(DominatedBBs.size(), 4UL); + EXPECT_EQ(PostDominatedBBs.size(), 1UL); + + // BB3 is unreachable. It should have no dominators nor postdominators. + DominatedBBs.clear(); + PostDominatedBBs.clear(); + DT->getDescendants(BB3, DominatedBBs); + DT->getDescendants(BB3, PostDominatedBBs); + EXPECT_EQ(DominatedBBs.size(), 0UL); + EXPECT_EQ(PostDominatedBBs.size(), 0UL); + return false; } virtual void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<DominatorTree>(); + AU.addRequired<DominatorTreeWrapperPass>(); + AU.addRequired<PostDominatorTree>(); } DPass() : FunctionPass(ID) { initializeDPassPass(*PassRegistry::getPassRegistry()); @@ -191,7 +218,7 @@ namespace llvm { TEST(DominatorTree, Unreachable) { DPass *P = new DPass(); - OwningPtr<Module> M(makeLLVMModule(P)); + std::unique_ptr<Module> M(makeLLVMModule(P)); PassManager Passes; Passes.add(P); Passes.run(*M); @@ -200,5 +227,6 @@ namespace llvm { } INITIALIZE_PASS_BEGIN(DPass, "dpass", "dpass", false, false) -INITIALIZE_PASS_DEPENDENCY(DominatorTree) +INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) +INITIALIZE_PASS_DEPENDENCY(PostDominatorTree) INITIALIZE_PASS_END(DPass, "dpass", "dpass", false, false) diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp index 2f390f7..9796e44 100644 --- a/unittests/IR/IRBuilderTest.cpp +++ b/unittests/IR/IRBuilderTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/IRBuilder.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" @@ -16,6 +15,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/IR/NoFolder.h" #include "gtest/gtest.h" using namespace llvm; @@ -40,7 +40,7 @@ protected: } LLVMContext Ctx; - OwningPtr<Module> M; + std::unique_ptr<Module> M; Function *F; BasicBlock *BB; GlobalVariable *GV; @@ -107,6 +107,14 @@ TEST_F(IRBuilderTest, LandingPadName) { EXPECT_EQ(LP->getName(), "LP"); } +TEST_F(IRBuilderTest, DataLayout) { + std::unique_ptr<Module> M(new Module("test", Ctx)); + M->setDataLayout("e-n32"); + EXPECT_TRUE(M->getDataLayout()->isLegalInteger(32)); + M->setDataLayout("e"); + EXPECT_FALSE(M->getDataLayout()->isLegalInteger(32)); +} + TEST_F(IRBuilderTest, GetIntTy) { IRBuilder<> Builder(BB); IntegerType *Ty1 = Builder.getInt1Ty(); @@ -147,6 +155,13 @@ TEST_F(IRBuilderTest, FastMathFlags) { FAdd = cast<Instruction>(F); EXPECT_TRUE(FAdd->hasNoNaNs()); + // Now, try it with CreateBinOp + F = Builder.CreateBinOp(Instruction::FAdd, F, F); + EXPECT_TRUE(Builder.getFastMathFlags().any()); + ASSERT_TRUE(isa<Instruction>(F)); + FAdd = cast<Instruction>(F); + EXPECT_TRUE(FAdd->hasNoNaNs()); + F = Builder.CreateFDiv(F, F); EXPECT_TRUE(Builder.getFastMathFlags().any()); EXPECT_TRUE(Builder.getFastMathFlags().UnsafeAlgebra); @@ -183,6 +198,56 @@ TEST_F(IRBuilderTest, FastMathFlags) { } +TEST_F(IRBuilderTest, WrapFlags) { + IRBuilder<true, NoFolder> Builder(BB); + + // Test instructions. + GlobalVariable *G = new GlobalVariable(*M, Builder.getInt32Ty(), true, + GlobalValue::ExternalLinkage, 0); + Value *V = Builder.CreateLoad(G); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNSWAdd(V, V))->hasNoSignedWrap()); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNSWMul(V, V))->hasNoSignedWrap()); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNSWSub(V, V))->hasNoSignedWrap()); + EXPECT_TRUE(cast<BinaryOperator>( + Builder.CreateShl(V, V, "", /* NUW */ false, /* NSW */ true)) + ->hasNoSignedWrap()); + + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNUWAdd(V, V))->hasNoUnsignedWrap()); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNUWMul(V, V))->hasNoUnsignedWrap()); + EXPECT_TRUE( + cast<BinaryOperator>(Builder.CreateNUWSub(V, V))->hasNoUnsignedWrap()); + EXPECT_TRUE(cast<BinaryOperator>( + Builder.CreateShl(V, V, "", /* NUW */ true, /* NSW */ false)) + ->hasNoUnsignedWrap()); + + // Test operators created with constants. + Constant *C = Builder.getInt32(42); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWAdd(C, C)) + ->hasNoSignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWSub(C, C)) + ->hasNoSignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWMul(C, C)) + ->hasNoSignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>( + Builder.CreateShl(C, C, "", /* NUW */ false, /* NSW */ true)) + ->hasNoSignedWrap()); + + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWAdd(C, C)) + ->hasNoUnsignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWSub(C, C)) + ->hasNoUnsignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWMul(C, C)) + ->hasNoUnsignedWrap()); + EXPECT_TRUE(cast<OverflowingBinaryOperator>( + Builder.CreateShl(C, C, "", /* NUW */ true, /* NSW */ false)) + ->hasNoUnsignedWrap()); +} + TEST_F(IRBuilderTest, RAIIHelpersTest) { IRBuilder<> Builder(BB); EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal()); diff --git a/unittests/IR/InstructionsTest.cpp b/unittests/IR/InstructionsTest.cpp index 65f85ba..e76afa8 100644 --- a/unittests/IR/InstructionsTest.cpp +++ b/unittests/IR/InstructionsTest.cpp @@ -14,11 +14,14 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "gtest/gtest.h" +#include <memory> namespace llvm { namespace { @@ -47,6 +50,58 @@ TEST(InstructionsTest, ReturnInst) { delete r1; } +// Test fixture that provides a module and a single function within it. Useful +// for tests that need to refer to the function in some way. +class ModuleWithFunctionTest : public testing::Test { +protected: + ModuleWithFunctionTest() : M(new Module("MyModule", Ctx)) { + FArgTypes.push_back(Type::getInt8Ty(Ctx)); + FArgTypes.push_back(Type::getInt32Ty(Ctx)); + FArgTypes.push_back(Type::getInt64Ty(Ctx)); + FunctionType *FTy = + FunctionType::get(Type::getVoidTy(Ctx), FArgTypes, false); + F = Function::Create(FTy, Function::ExternalLinkage, "", M.get()); + } + + LLVMContext Ctx; + std::unique_ptr<Module> M; + SmallVector<Type *, 3> FArgTypes; + Function *F; +}; + +TEST_F(ModuleWithFunctionTest, CallInst) { + Value *Args[] = {ConstantInt::get(Type::getInt8Ty(Ctx), 20), + ConstantInt::get(Type::getInt32Ty(Ctx), 9999), + ConstantInt::get(Type::getInt64Ty(Ctx), 42)}; + std::unique_ptr<CallInst> Call(CallInst::Create(F, Args)); + + // Make sure iteration over a call's arguments works as expected. + unsigned Idx = 0; + for (Value *Arg : Call->arg_operands()) { + EXPECT_EQ(FArgTypes[Idx], Arg->getType()); + EXPECT_EQ(Call->getArgOperand(Idx)->getType(), Arg->getType()); + Idx++; + } +} + +TEST_F(ModuleWithFunctionTest, InvokeInst) { + BasicBlock *BB1 = BasicBlock::Create(Ctx, "", F); + BasicBlock *BB2 = BasicBlock::Create(Ctx, "", F); + + Value *Args[] = {ConstantInt::get(Type::getInt8Ty(Ctx), 20), + ConstantInt::get(Type::getInt32Ty(Ctx), 9999), + ConstantInt::get(Type::getInt64Ty(Ctx), 42)}; + std::unique_ptr<InvokeInst> Invoke(InvokeInst::Create(F, BB1, BB2, Args)); + + // Make sure iteration over invoke's arguments works as expected. + unsigned Idx = 0; + for (Value *Arg : Invoke->arg_operands()) { + EXPECT_EQ(FArgTypes[Idx], Arg->getType()); + EXPECT_EQ(Invoke->getArgOperand(Idx)->getType(), Arg->getType()); + Idx++; + } +} + TEST(InstructionsTest, BranchInst) { LLVMContext &C(getGlobalContext()); @@ -65,9 +120,9 @@ TEST(InstructionsTest, BranchInst) { EXPECT_EQ(1U, b0->getNumOperands()); EXPECT_NE(b0->op_begin(), b0->op_end()); - EXPECT_EQ(b0->op_end(), llvm::next(b0->op_begin())); + EXPECT_EQ(b0->op_end(), std::next(b0->op_begin())); - EXPECT_EQ(b0->op_end(), llvm::next(b0->op_begin())); + EXPECT_EQ(b0->op_end(), std::next(b0->op_begin())); IntegerType* Int1 = IntegerType::get(C, 1); Constant* One = ConstantInt::get(Int1, 1, true); @@ -145,6 +200,7 @@ TEST(InstructionsTest, CastInst) { Type *V2Int64PtrTy = VectorType::get(Int64PtrTy, 2); Type *V2Int32PtrTy = VectorType::get(Int32PtrTy, 2); + Type *V4Int32PtrTy = VectorType::get(Int32PtrTy, 4); const Constant* c8 = Constant::getNullValue(V8x8Ty); const Constant* c64 = Constant::getNullValue(V8x64Ty); @@ -205,6 +261,21 @@ TEST(InstructionsTest, CastInst) { EXPECT_FALSE(CastInst::isBitCastable(V2Int64Ty, V2Int32Ty)); + EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, + Constant::getNullValue(V4Int32PtrTy), + V2Int32PtrTy)); + EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast, + Constant::getNullValue(V2Int32PtrTy), + V4Int32PtrTy)); + + EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast, + Constant::getNullValue(V4Int32PtrAS1Ty), + V2Int32PtrTy)); + EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast, + Constant::getNullValue(V2Int32PtrTy), + V4Int32PtrAS1Ty)); + + // Check that assertion is not hit when creating a cast with a vector of // pointers // First form @@ -269,7 +340,7 @@ TEST(InstructionsTest, VectorGep) { int64_t Offset; DataLayout TD("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3" - "2:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80" + "2:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-s:64:64-f80" ":128:128-n8:16:32:64-S128"); // Make sure we don't crash GetPointerBaseWithConstantOffset(Gep0, Offset, &TD); @@ -381,7 +452,7 @@ TEST(InstructionsTest, isEliminableCastPair) { // or if we don't have available pointer size information. DataLayout DL("e-p:32:32:32-p1:16:16:16-p2:64:64:64-i1:8:8-i8:8:8-i16:16:16" "-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64" - "-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"); + "-v128:128:128-a:0:64-s:64:64-f80:128:128-n8:16:32:64-S128"); Type* Int64PtrTyAS1 = Type::getInt64PtrTy(C, 1); Type* Int64PtrTyAS2 = Type::getInt64PtrTy(C, 2); diff --git a/unittests/Support/LeakDetectorTest.cpp b/unittests/IR/LeakDetectorTest.cpp index d198c7a..94eed4c 100644 --- a/unittests/Support/LeakDetectorTest.cpp +++ b/unittests/IR/LeakDetectorTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/LeakDetector/LeakDetector.cpp - LeakDetector tests ---===// +//===- LeakDetectorTest.cpp -----------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "llvm/IR/LeakDetector.h" #include "gtest/gtest.h" -#include "llvm/Support/LeakDetector.h" using namespace llvm; diff --git a/unittests/IR/LegacyPassManagerTest.cpp b/unittests/IR/LegacyPassManagerTest.cpp index 11841bd..df6f460 100644 --- a/unittests/IR/LegacyPassManagerTest.cpp +++ b/unittests/IR/LegacyPassManagerTest.cpp @@ -19,8 +19,6 @@ #include "llvm/Analysis/CallGraphSCCPass.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/LoopPass.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Assembly/PrintModulePass.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CallingConv.h" #include "llvm/IR/Constants.h" @@ -28,10 +26,12 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" #include "llvm/Pass.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -99,7 +99,7 @@ namespace llvm { initializeModuleNDMPass(*PassRegistry::getPassRegistry()); } virtual bool runOnModule(Module &M) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run++; return false; } @@ -176,7 +176,7 @@ namespace llvm { initializeCGPassPass(*PassRegistry::getPassRegistry()); } virtual bool runOnSCC(CallGraphSCC &SCMM) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run(); return false; } @@ -215,7 +215,7 @@ namespace llvm { return false; } virtual bool runOnLoop(Loop *L, LPPassManager &LPM) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run(); return false; } @@ -252,7 +252,7 @@ namespace llvm { return false; } virtual bool runOnBasicBlock(BasicBlock &BB) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run(); return false; } @@ -277,7 +277,7 @@ namespace llvm { initializeFPassPass(*PassRegistry::getPassRegistry()); } virtual bool runOnModule(Module &M) { - EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); + EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) { Function &F = *I; { @@ -303,7 +303,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; PassManager Passes; - Passes.add(new DataLayout(&M)); + Passes.add(new DataLayoutPass(&M)); 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 DataLayout(&M)); + Passes.add(new DataLayoutPass(&M)); Passes.add(mNDM); Passes.add(mNDNM); Passes.add(mNDM2);// invalidates mNDM needed by mDNM @@ -346,10 +346,10 @@ namespace llvm { template<typename T> void MemoryTestHelper(int run) { - OwningPtr<Module> M(makeLLVMModule()); + std::unique_ptr<Module> M(makeLLVMModule()); T *P = new T(); PassManager Passes; - Passes.add(new DataLayout(M.get())); + Passes.add(new DataLayoutPass(M.get())); 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 DataLayout(M)); + Passes.add(new DataLayoutPass(M)); 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 DataLayout(M)); + Passes.add(new DataLayoutPass(M)); Passes.add(O); Passes.run(*M); @@ -412,7 +412,7 @@ namespace llvm { Module* mod = new Module("test-mem", getGlobalContext()); mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-" - "a0:0:64-s0:64:64-f80:128:128"); + "a:0:64-s:64:64-f80:128:128"); mod->setTargetTriple("x86_64-unknown-linux-gnu"); // Type Definitions @@ -550,7 +550,7 @@ namespace llvm { INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false) INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false) -INITIALIZE_PASS_DEPENDENCY(CallGraph) +INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false) INITIALIZE_PASS(FPass, "fp","fp", false, false) INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false) diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index 352e83e..00a2783 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -13,7 +13,7 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" -#include "llvm/Support/ValueHandle.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" using namespace llvm; diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp index 7b60e38..310e48f 100644 --- a/unittests/IR/PassManagerTest.cpp +++ b/unittests/IR/PassManagerTest.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Assembly/Parser.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -19,21 +19,21 @@ using namespace llvm; namespace { -class TestAnalysisPass { +class TestFunctionAnalysis { public: - typedef Function IRUnitT; - struct Result { Result(int Count) : InstructionCount(Count) {} - bool invalidate(Function *) { return true; } int InstructionCount; }; /// \brief Returns an opaque, unique ID for this pass type. static void *ID() { return (void *)&PassID; } + TestFunctionAnalysis(int &Runs) : Runs(Runs) {} + /// \brief Run the analysis pass over the function and return a result. - Result run(Function *F) { + Result run(Function *F, FunctionAnalysisManager *AM) { + ++Runs; int Count = 0; for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; ++BBI) for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; @@ -45,38 +45,124 @@ public: private: /// \brief Private static data to provide unique ID. static char PassID; + + int &Runs; }; -char TestAnalysisPass::PassID; +char TestFunctionAnalysis::PassID; + +class TestModuleAnalysis { +public: + struct Result { + Result(int Count) : FunctionCount(Count) {} + int FunctionCount; + }; + + static void *ID() { return (void *)&PassID; } + + TestModuleAnalysis(int &Runs) : Runs(Runs) {} + + Result run(Module *M, ModuleAnalysisManager *AM) { + ++Runs; + int Count = 0; + for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + ++Count; + return Result(Count); + } + +private: + static char PassID; + + int &Runs; +}; + +char TestModuleAnalysis::PassID; struct TestModulePass { TestModulePass(int &RunCount) : RunCount(RunCount) {} - bool run(Module *M) { + PreservedAnalyses run(Module *M) { ++RunCount; - return true; + return PreservedAnalyses::none(); } + static StringRef name() { return "TestModulePass"; } + int &RunCount; }; -struct TestFunctionPass { - TestFunctionPass(AnalysisManager &AM, int &RunCount, int &AnalyzedInstrCount) - : AM(AM), RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount) { +struct TestPreservingModulePass { + PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); } + + static StringRef name() { return "TestPreservingModulePass"; } +}; + +struct TestMinPreservingModulePass { + PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses PA; + + // Force running an analysis. + (void)AM->getResult<TestModuleAnalysis>(M); + + PA.preserve<FunctionAnalysisManagerModuleProxy>(); + return PA; } - bool run(Function *F) { + static StringRef name() { return "TestMinPreservingModulePass"; } +}; + +struct TestFunctionPass { + TestFunctionPass(int &RunCount, int &AnalyzedInstrCount, + int &AnalyzedFunctionCount, + bool OnlyUseCachedResults = false) + : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount), + AnalyzedFunctionCount(AnalyzedFunctionCount), + OnlyUseCachedResults(OnlyUseCachedResults) {} + + PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM) { ++RunCount; - const TestAnalysisPass::Result &AR = AM.getResult<TestAnalysisPass>(F); - AnalyzedInstrCount += AR.InstructionCount; + const ModuleAnalysisManager &MAM = + AM->getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); + if (TestModuleAnalysis::Result *TMA = + MAM.getCachedResult<TestModuleAnalysis>(F->getParent())) + AnalyzedFunctionCount += TMA->FunctionCount; - return true; + if (OnlyUseCachedResults) { + // Hack to force the use of the cached interface. + if (TestFunctionAnalysis::Result *AR = + AM->getCachedResult<TestFunctionAnalysis>(F)) + AnalyzedInstrCount += AR->InstructionCount; + } else { + // Typical path just runs the analysis as needed. + TestFunctionAnalysis::Result &AR = AM->getResult<TestFunctionAnalysis>(F); + AnalyzedInstrCount += AR.InstructionCount; + } + + return PreservedAnalyses::all(); } - AnalysisManager &AM; + static StringRef name() { return "TestFunctionPass"; } + int &RunCount; int &AnalyzedInstrCount; + int &AnalyzedFunctionCount; + bool OnlyUseCachedResults; +}; + +// A test function pass that invalidates all function analyses for a function +// with a specific name. +struct TestInvalidationFunctionPass { + TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {} + + PreservedAnalyses run(Function *F) { + return F->getName() == Name ? PreservedAnalyses::none() + : PreservedAnalyses::all(); + } + + static StringRef name() { return "TestInvalidationFunctionPass"; } + + StringRef Name; }; Module *parseIR(const char *IR) { @@ -87,7 +173,7 @@ Module *parseIR(const char *IR) { class PassManagerTest : public ::testing::Test { protected: - OwningPtr<Module> M; + std::unique_ptr<Module> M; public: PassManagerTest() @@ -105,27 +191,154 @@ public: "}\n")) {} }; +TEST_F(PassManagerTest, BasicPreservedAnalyses) { + PreservedAnalyses PA1 = PreservedAnalyses(); + EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>()); + PreservedAnalyses PA2 = PreservedAnalyses::none(); + EXPECT_FALSE(PA2.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA2.preserved<TestModuleAnalysis>()); + PreservedAnalyses PA3 = PreservedAnalyses::all(); + EXPECT_TRUE(PA3.preserved<TestFunctionAnalysis>()); + EXPECT_TRUE(PA3.preserved<TestModuleAnalysis>()); + PreservedAnalyses PA4 = PA1; + EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>()); + PA4 = PA3; + EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>()); + EXPECT_TRUE(PA4.preserved<TestModuleAnalysis>()); + PA4 = std::move(PA2); + EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>()); + PA4.preserve<TestFunctionAnalysis>(); + EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>()); + PA1.preserve<TestModuleAnalysis>(); + EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>()); + EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>()); + PA1.preserve<TestFunctionAnalysis>(); + EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>()); + EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>()); + PA1.intersect(PA4); + EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>()); + EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>()); +} + TEST_F(PassManagerTest, Basic) { - AnalysisManager AM(M.get()); - AM.registerAnalysisPass(TestAnalysisPass()); + FunctionAnalysisManager FAM; + int FunctionAnalysisRuns = 0; + FAM.registerPass(TestFunctionAnalysis(FunctionAnalysisRuns)); - ModulePassManager MPM(M.get(), &AM); - FunctionPassManager FPM(&AM); + ModuleAnalysisManager MAM; + int ModuleAnalysisRuns = 0; + MAM.registerPass(TestModuleAnalysis(ModuleAnalysisRuns)); + MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM)); + FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM)); + + ModulePassManager MPM; + + // Count the runs over a Function. + int FunctionPassRunCount1 = 0; + int AnalyzedInstrCount1 = 0; + int AnalyzedFunctionCount1 = 0; + { + // Pointless scoped copy to test move assignment. + ModulePassManager NestedMPM; + FunctionPassManager FPM; + { + // Pointless scope to test move assignment. + FunctionPassManager NestedFPM; + NestedFPM.addPass(TestFunctionPass(FunctionPassRunCount1, AnalyzedInstrCount1, + AnalyzedFunctionCount1)); + FPM = std::move(NestedFPM); + } + NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + MPM = std::move(NestedMPM); + } // Count the runs over a module. int ModulePassRunCount = 0; MPM.addPass(TestModulePass(ModulePassRunCount)); - // Count the runs over a Function. - int FunctionPassRunCount = 0; - int AnalyzedInstrCount = 0; - FPM.addPass(TestFunctionPass(AM, FunctionPassRunCount, AnalyzedInstrCount)); - MPM.addPass(FPM); + // Count the runs over a Function in a separate manager. + int FunctionPassRunCount2 = 0; + int AnalyzedInstrCount2 = 0; + int AnalyzedFunctionCount2 = 0; + { + FunctionPassManager FPM; + FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2, + AnalyzedFunctionCount2)); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } + + // A third function pass manager but with only preserving intervening passes + // and with a function pass that invalidates exactly one analysis. + MPM.addPass(TestPreservingModulePass()); + int FunctionPassRunCount3 = 0; + int AnalyzedInstrCount3 = 0; + int AnalyzedFunctionCount3 = 0; + { + FunctionPassManager FPM; + FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3, + AnalyzedFunctionCount3)); + FPM.addPass(TestInvalidationFunctionPass("f")); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } + + // A fourth function pass manager but with a minimal intervening passes. + MPM.addPass(TestMinPreservingModulePass()); + int FunctionPassRunCount4 = 0; + int AnalyzedInstrCount4 = 0; + int AnalyzedFunctionCount4 = 0; + { + FunctionPassManager FPM; + FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4, + AnalyzedFunctionCount4)); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } - MPM.run(); + // A fifth function pass manager but which uses only cached results. + int FunctionPassRunCount5 = 0; + int AnalyzedInstrCount5 = 0; + int AnalyzedFunctionCount5 = 0; + { + FunctionPassManager FPM; + FPM.addPass(TestInvalidationFunctionPass("f")); + FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5, + AnalyzedFunctionCount5, + /*OnlyUseCachedResults=*/true)); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } + + MPM.run(M.get(), &MAM); + + // Validate module pass counters. EXPECT_EQ(1, ModulePassRunCount); - EXPECT_EQ(3, FunctionPassRunCount); - EXPECT_EQ(5, AnalyzedInstrCount); -} + // Validate all function pass counter sets are the same. + EXPECT_EQ(3, FunctionPassRunCount1); + EXPECT_EQ(5, AnalyzedInstrCount1); + EXPECT_EQ(0, AnalyzedFunctionCount1); + EXPECT_EQ(3, FunctionPassRunCount2); + EXPECT_EQ(5, AnalyzedInstrCount2); + EXPECT_EQ(0, AnalyzedFunctionCount2); + EXPECT_EQ(3, FunctionPassRunCount3); + EXPECT_EQ(5, AnalyzedInstrCount3); + EXPECT_EQ(0, AnalyzedFunctionCount3); + EXPECT_EQ(3, FunctionPassRunCount4); + EXPECT_EQ(5, AnalyzedInstrCount4); + EXPECT_EQ(0, AnalyzedFunctionCount4); + EXPECT_EQ(3, FunctionPassRunCount5); + EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached. + EXPECT_EQ(0, AnalyzedFunctionCount5); + + // Validate the analysis counters: + // first run over 3 functions, then module pass invalidates + // second run over 3 functions, nothing invalidates + // third run over 0 functions, but 1 function invalidated + // fourth run over 1 function + EXPECT_EQ(7, FunctionAnalysisRuns); + + EXPECT_EQ(1, ModuleAnalysisRuns); +} } diff --git a/unittests/IR/PatternMatch.cpp b/unittests/IR/PatternMatch.cpp index 7c6d8ce..bebee15 100644 --- a/unittests/IR/PatternMatch.cpp +++ b/unittests/IR/PatternMatch.cpp @@ -13,253 +13,286 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Instructions.h" +#include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/NoFolder.h" #include "llvm/IR/Operator.h" -#include "llvm/Support/NoFolder.h" -#include "llvm/Support/PatternMatch.h" +#include "llvm/IR/PatternMatch.h" +#include "llvm/IR/Type.h" #include "gtest/gtest.h" +using namespace llvm; using namespace llvm::PatternMatch; -namespace llvm { namespace { -/// Ordered floating point minimum/maximum tests. - -static void m_OrdFMin_expect_match_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); - EXPECT_EQ(L, MatchL); - EXPECT_EQ(R, MatchR); - delete Select; - delete Cmp; -} - -static void m_OrdFMin_expect_nomatch_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); - delete Select; - delete Cmp; +struct PatternMatchTest : ::testing::Test { + LLVMContext Ctx; + std::unique_ptr<Module> M; + Function *F; + BasicBlock *BB; + IRBuilder<true, NoFolder> IRB; + + PatternMatchTest() + : M(new Module("PatternMatchTestModule", Ctx)), + F(Function::Create( + FunctionType::get(Type::getVoidTy(Ctx), /* IsVarArg */ false), + Function::ExternalLinkage, "f", M.get())), + BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB) {} +}; + +TEST_F(PatternMatchTest, OneUse) { + // Build up a little tree of values: + // + // One = (1 + 2) + 42 + // Two = One + 42 + // Leaf = (Two + 8) + (Two + 13) + Value *One = IRB.CreateAdd(IRB.CreateAdd(IRB.getInt32(1), IRB.getInt32(2)), + IRB.getInt32(42)); + Value *Two = IRB.CreateAdd(One, IRB.getInt32(42)); + Value *Leaf = IRB.CreateAdd(IRB.CreateAdd(Two, IRB.getInt32(8)), + IRB.CreateAdd(Two, IRB.getInt32(13))); + Value *V; + + EXPECT_TRUE(m_OneUse(m_Value(V)).match(One)); + EXPECT_EQ(One, V); + + EXPECT_FALSE(m_OneUse(m_Value()).match(Two)); + EXPECT_FALSE(m_OneUse(m_Value()).match(Leaf)); } -static void m_OrdFMax_expect_match_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); - EXPECT_EQ(L, MatchL); - EXPECT_EQ(R, MatchR); - delete Select; - delete Cmp; -} - -static void m_OrdFMax_expect_nomatch_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); - delete Select; - delete Cmp; -} - - - -TEST(PatternMatchTest, FloatingPointOrderedMin) { - LLVMContext &C(getGlobalContext()); - IRBuilder<true, NoFolder> Builder(C); - - Type *FltTy = Builder.getFloatTy(); +TEST_F(PatternMatchTest, FloatingPointOrderedMin) { + Type *FltTy = IRB.getFloatTy(); Value *L = ConstantFP::get(FltTy, 1.0); Value *R = ConstantFP::get(FltTy, 2.0); + Value *MatchL, *MatchR; // Test OLT. - Value *Cmp = Builder.CreateFCmpOLT(L, R); - Value *Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test OLE. - Cmp = Builder.CreateFCmpOLE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test no match on OGE. - Cmp = Builder.CreateFCmpOGE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R))); // Test no match on OGT. - Cmp = Builder.CreateFCmpOGT(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R))); // Test match on OGE with inverted select. - Cmp = Builder.CreateFCmpOGE(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test match on OGT with inverted select. - Cmp = Builder.CreateFCmpOGT(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_OrdFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); } -TEST(PatternMatchTest, FloatingPointOrderedMax) { - LLVMContext &C(getGlobalContext()); - IRBuilder<true, NoFolder> Builder(C); - - Type *FltTy = Builder.getFloatTy(); +TEST_F(PatternMatchTest, FloatingPointOrderedMax) { + Type *FltTy = IRB.getFloatTy(); Value *L = ConstantFP::get(FltTy, 1.0); Value *R = ConstantFP::get(FltTy, 2.0); + Value *MatchL, *MatchR; // Test OGT. - Value *Cmp = Builder.CreateFCmpOGT(L, R); - Value *Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test OGE. - Cmp = Builder.CreateFCmpOGE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test no match on OLE. - Cmp = Builder.CreateFCmpOLE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R))); // Test no match on OLT. - Cmp = Builder.CreateFCmpOLT(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_OrdFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R))); // Test match on OLE with inverted select. - Cmp = Builder.CreateFCmpOLE(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); - - // Test match on OLT with inverted select. - Cmp = Builder.CreateFCmpOLT(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_OrdFMax_expect_match_and_delete(Cmp, Select, L, R); -} - -/// Unordered floating point minimum/maximum tests. - -static void m_UnordFMin_expect_match_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L))); EXPECT_EQ(L, MatchL); EXPECT_EQ(R, MatchR); - delete Select; - delete Cmp; -} -static void m_UnordFMin_expect_nomatch_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)).match(Select)); - delete Select; - delete Cmp; -} - -static void m_UnordFMax_expect_match_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); + // Test match on OLT with inverted select. + EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L))); EXPECT_EQ(L, MatchL); EXPECT_EQ(R, MatchR); - delete Select; - delete Cmp; -} - -static void m_UnordFMax_expect_nomatch_and_delete(Value *Cmp, Value *Select, - Value *L, Value *R) { - Value *MatchL, *MatchR; - EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)).match(Select)); - delete Select; - delete Cmp; } -TEST(PatternMatchTest, FloatingPointUnorderedMin) { - LLVMContext &C(getGlobalContext()); - IRBuilder<true, NoFolder> Builder(C); - - Type *FltTy = Builder.getFloatTy(); +TEST_F(PatternMatchTest, FloatingPointUnorderedMin) { + Type *FltTy = IRB.getFloatTy(); Value *L = ConstantFP::get(FltTy, 1.0); Value *R = ConstantFP::get(FltTy, 2.0); + Value *MatchL, *MatchR; // Test ULT. - Value *Cmp = Builder.CreateFCmpULT(L, R); - Value *Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test ULE. - Cmp = Builder.CreateFCmpULE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test no match on UGE. - Cmp = Builder.CreateFCmpUGE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R))); // Test no match on UGT. - Cmp = Builder.CreateFCmpUGT(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMin_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R))); // Test match on UGE with inverted select. - Cmp = Builder.CreateFCmpUGE(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test match on UGT with inverted select. - Cmp = Builder.CreateFCmpUGT(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_UnordFMin_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); } -TEST(PatternMatchTest, FloatingPointUnorderedMax) { - LLVMContext &C(getGlobalContext()); - IRBuilder<true, NoFolder> Builder(C); - - Type *FltTy = Builder.getFloatTy(); +TEST_F(PatternMatchTest, FloatingPointUnorderedMax) { + Type *FltTy = IRB.getFloatTy(); Value *L = ConstantFP::get(FltTy, 1.0); Value *R = ConstantFP::get(FltTy, 2.0); + Value *MatchL, *MatchR; // Test UGT. - Value *Cmp = Builder.CreateFCmpUGT(L, R); - Value *Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test UGE. - Cmp = Builder.CreateFCmpUGE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test no match on ULE. - Cmp = Builder.CreateFCmpULE(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R))); // Test no match on ULT. - Cmp = Builder.CreateFCmpULT(L, R); - Select = Builder.CreateSelect(Cmp, L, R); - m_UnordFMax_expect_nomatch_and_delete(Cmp, Select, L, R); + EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R))); // Test match on ULE with inverted select. - Cmp = Builder.CreateFCmpULE(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); // Test match on ULT with inverted select. - Cmp = Builder.CreateFCmpULT(L, R); - Select = Builder.CreateSelect(Cmp, R, L); - m_UnordFMax_expect_match_and_delete(Cmp, Select, L, R); + EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR)) + .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), R, L))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); +} + +TEST_F(PatternMatchTest, OverflowingBinOps) { + Value *L = IRB.getInt32(1); + Value *R = IRB.getInt32(2); + Value *MatchL, *MatchR; + + EXPECT_TRUE( + m_NSWAdd(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWAdd(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE( + m_NSWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWSub(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE( + m_NSWMul(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWMul(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE(m_NSWShl(m_Value(MatchL), m_Value(MatchR)).match( + IRB.CreateShl(L, R, "", /* NUW */ false, /* NSW */ true))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + + EXPECT_TRUE( + m_NUWAdd(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWAdd(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE( + m_NUWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWSub(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE( + m_NUWMul(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWMul(L, R))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + MatchL = MatchR = 0; + EXPECT_TRUE(m_NUWShl(m_Value(MatchL), m_Value(MatchR)).match( + IRB.CreateShl(L, R, "", /* NUW */ true, /* NSW */ false))); + EXPECT_EQ(L, MatchL); + EXPECT_EQ(R, MatchR); + + EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateAdd(L, R))); + EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateNSWSub(L, R))); + EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateSub(L, R))); + EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateNUWSub(L, R))); + EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateMul(L, R))); + EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateNUWMul(L, R))); + EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(IRB.CreateShl(L, R))); + EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match( + IRB.CreateShl(L, R, "", /* NUW */ true, /* NSW */ false))); + EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + + EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateAdd(L, R))); + EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R))); + EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateNUWSub(L, R))); + EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateSub(L, R))); + EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateNSWSub(L, R))); + EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateMul(L, R))); + EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateNSWMul(L, R))); + EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); + EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(IRB.CreateShl(L, R))); + EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match( + IRB.CreateShl(L, R, "", /* NUW */ false, /* NSW */ true))); + EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R))); } } // anonymous namespace. -} // llvm namespace. diff --git a/unittests/Support/ValueHandleTest.cpp b/unittests/IR/ValueHandleTest.cpp index 05aafa2..15a0c22 100644 --- a/unittests/Support/ValueHandleTest.cpp +++ b/unittests/IR/ValueHandleTest.cpp @@ -1,4 +1,4 @@ -//===- llvm/unittest/Support/ValueHandleTest.cpp - ValueHandle tests --------===// +//===- ValueHandleTest.cpp - ValueHandle tests ----------------------------===// // // The LLVM Compiler Infrastructure // @@ -7,8 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Support/ValueHandle.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" @@ -336,7 +335,7 @@ TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) { class DestroyingVH : public CallbackVH { public: - OwningPtr<WeakVH> ToClear[2]; + std::unique_ptr<WeakVH> ToClear[2]; DestroyingVH(Value *V) { ToClear[0].reset(new WeakVH(V)); setValPtr(V); diff --git a/unittests/IR/ValueMapTest.cpp b/unittests/IR/ValueMapTest.cpp index 5aaf905..6fd87b1 100644 --- a/unittests/IR/ValueMapTest.cpp +++ b/unittests/IR/ValueMapTest.cpp @@ -7,8 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/ValueMap.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/IR/ValueMap.h" #include "llvm/Config/llvm-config.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" @@ -24,8 +23,8 @@ template<typename T> class ValueMapTest : public testing::Test { protected: Constant *ConstantV; - OwningPtr<BitCastInst> BitcastV; - OwningPtr<BinaryOperator> AddV; + std::unique_ptr<BitCastInst> BitcastV; + std::unique_ptr<BinaryOperator> AddV; ValueMapTest() : ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), @@ -117,7 +116,8 @@ TYPED_TEST(ValueMapTest, OperationsWork) { template<typename ExpectedType, typename VarType> void CompileAssertHasType(VarType) { - typedef char assert[is_same<ExpectedType, VarType>::value ? 1 : -1]; + static_assert(std::is_same<ExpectedType, VarType>::value, + "Not the same type"); } TYPED_TEST(ValueMapTest, Iteration) { diff --git a/unittests/IR/ValueTest.cpp b/unittests/IR/ValueTest.cpp index ebe23e8..d92bc82 100644 --- a/unittests/IR/ValueTest.cpp +++ b/unittests/IR/ValueTest.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Assembly/Parser.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -45,7 +45,7 @@ TEST(ValueTest, UsedInBasicBlock) { TEST(GlobalTest, CreateAddressSpace) { LLVMContext &Ctx = getGlobalContext(); - OwningPtr<Module> M(new Module("TestModule", Ctx)); + std::unique_ptr<Module> M(new Module("TestModule", Ctx)); Type *Int8Ty = Type::getInt8Ty(Ctx); Type *Int32Ty = Type::getInt32Ty(Ctx); diff --git a/unittests/IR/VerifierTest.cpp b/unittests/IR/VerifierTest.cpp index 31936c3..0a660a6 100644 --- a/unittests/IR/VerifierTest.cpp +++ b/unittests/IR/VerifierTest.cpp @@ -7,8 +7,7 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/Verifier.h" -#include "llvm/ADT/OwningPtr.h" +#include "llvm/IR/Verifier.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" @@ -42,7 +41,7 @@ TEST(VerifierTest, Branch_i1) { Constant *Zero32 = ConstantInt::get(IntegerType::get(C, 32), 0); BI->setOperand(0, Zero32); - EXPECT_TRUE(verifyFunction(*F, ReturnStatusAction)); + EXPECT_TRUE(verifyFunction(*F)); } TEST(VerifierTest, AliasUnnamedAddr) { @@ -58,8 +57,10 @@ TEST(VerifierTest, AliasUnnamedAddr) { "bar", Aliasee, &M); GA->setUnnamedAddr(true); std::string Error; - EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error)); - EXPECT_TRUE(StringRef(Error).startswith("Alias cannot have unnamed_addr")); + raw_string_ostream ErrorOS(Error); + EXPECT_TRUE(verifyModule(M, &ErrorOS)); + EXPECT_TRUE( + StringRef(ErrorOS.str()).startswith("Alias cannot have unnamed_addr")); } TEST(VerifierTest, InvalidRetAttribute) { @@ -72,9 +73,10 @@ TEST(VerifierTest, InvalidRetAttribute) { Attribute::UWTable)); std::string Error; - EXPECT_TRUE(verifyModule(M, ReturnStatusAction, &Error)); - EXPECT_TRUE(StringRef(Error). - startswith("Attribute 'uwtable' only applies to functions!")); + raw_string_ostream ErrorOS(Error); + EXPECT_TRUE(verifyModule(M, &ErrorOS)); + EXPECT_TRUE(StringRef(ErrorOS.str()).startswith( + "Attribute 'uwtable' only applies to functions!")); } } diff --git a/unittests/LineEditor/CMakeLists.txt b/unittests/LineEditor/CMakeLists.txt new file mode 100644 index 0000000..c6823d8 --- /dev/null +++ b/unittests/LineEditor/CMakeLists.txt @@ -0,0 +1,7 @@ +set(LLVM_LINK_COMPONENTS + LineEditor + ) + +add_llvm_unittest(LineEditorTests + LineEditor.cpp + ) diff --git a/unittests/LineEditor/LineEditor.cpp b/unittests/LineEditor/LineEditor.cpp new file mode 100644 index 0000000..cb115bd --- /dev/null +++ b/unittests/LineEditor/LineEditor.cpp @@ -0,0 +1,82 @@ +//===-- LineEditor.cpp ----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/Path.h" +#include "gtest/gtest.h" + +using namespace llvm; + +class LineEditorTest : public testing::Test { +public: + SmallString<64> HistPath; + LineEditor *LE; + + LineEditorTest() { + init(); + } + + void init() { + sys::fs::createTemporaryFile("temp", "history", HistPath); + ASSERT_FALSE(HistPath.empty()); + LE = new LineEditor("test", HistPath); + } + + ~LineEditorTest() { + delete LE; + sys::fs::remove(HistPath.str()); + } +}; + +TEST_F(LineEditorTest, HistorySaveLoad) { + LE->saveHistory(); + LE->loadHistory(); +} + +struct TestListCompleter { + std::vector<LineEditor::Completion> Completions; + + TestListCompleter(const std::vector<LineEditor::Completion> &Completions) + : Completions(Completions) {} + + std::vector<LineEditor::Completion> operator()(StringRef Buffer, + size_t Pos) const { + EXPECT_TRUE(Buffer.empty()); + EXPECT_EQ(0u, Pos); + return Completions; + } +}; + +TEST_F(LineEditorTest, ListCompleters) { + std::vector<LineEditor::Completion> Comps; + + Comps.push_back(LineEditor::Completion("foo", "int foo()")); + LE->setListCompleter(TestListCompleter(Comps)); + LineEditor::CompletionAction CA = LE->getCompletionAction("", 0); + EXPECT_EQ(LineEditor::CompletionAction::AK_Insert, CA.Kind); + EXPECT_EQ("foo", CA.Text); + + Comps.push_back(LineEditor::Completion("bar", "int bar()")); + LE->setListCompleter(TestListCompleter(Comps)); + CA = LE->getCompletionAction("", 0); + EXPECT_EQ(LineEditor::CompletionAction::AK_ShowCompletions, CA.Kind); + ASSERT_EQ(2u, CA.Completions.size()); + ASSERT_EQ("int foo()", CA.Completions[0]); + ASSERT_EQ("int bar()", CA.Completions[1]); + + Comps.clear(); + Comps.push_back(LineEditor::Completion("fee", "int fee()")); + Comps.push_back(LineEditor::Completion("fi", "int fi()")); + Comps.push_back(LineEditor::Completion("foe", "int foe()")); + Comps.push_back(LineEditor::Completion("fum", "int fum()")); + LE->setListCompleter(TestListCompleter(Comps)); + CA = LE->getCompletionAction("", 0); + EXPECT_EQ(LineEditor::CompletionAction::AK_Insert, CA.Kind); + EXPECT_EQ("f", CA.Text); +} diff --git a/unittests/LineEditor/Makefile b/unittests/LineEditor/Makefile new file mode 100644 index 0000000..058b6e46 --- /dev/null +++ b/unittests/LineEditor/Makefile @@ -0,0 +1,15 @@ +##===- unittests/LineEditor/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 = LineEditor +LINK_COMPONENTS := lineeditor + +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Linker/CMakeLists.txt b/unittests/Linker/CMakeLists.txt new file mode 100644 index 0000000..c3dccb6 --- /dev/null +++ b/unittests/Linker/CMakeLists.txt @@ -0,0 +1,12 @@ +set(LLVM_LINK_COMPONENTS + core + linker + ) + +set(LinkerSources + LinkModulesTest.cpp + ) + +add_llvm_unittest(LinkerTests + ${LinkerSources} + ) diff --git a/unittests/Linker/LinkModulesTest.cpp b/unittests/Linker/LinkModulesTest.cpp new file mode 100644 index 0000000..7b40b9f --- /dev/null +++ b/unittests/Linker/LinkModulesTest.cpp @@ -0,0 +1,165 @@ +//===- llvm/unittest/Linker/LinkModulesTest.cpp - IRBuilder tests ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#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 "gtest/gtest.h" + +using namespace llvm; + +namespace { + +class LinkModuleTest : public testing::Test { +protected: + virtual void SetUp() { + LLVMContext &Ctx = getGlobalContext(); + M.reset(new Module("MyModule", Ctx)); + FunctionType *FTy = FunctionType::get(Type::getInt8PtrTy(Ctx), + Type::getInt32Ty(Ctx), + false /*=isVarArg*/); + F = Function::Create(FTy, Function::ExternalLinkage, "ba_func", M.get()); + F->setCallingConv(CallingConv::C); + + EntryBB = BasicBlock::Create(Ctx, "entry", F); + SwitchCase1BB = BasicBlock::Create(Ctx, "switch.case.1", F); + SwitchCase2BB = BasicBlock::Create(Ctx, "switch.case.2", F); + ExitBB = BasicBlock::Create(Ctx, "exit", F); + + ArrayType *AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3); + + GV = new GlobalVariable(*M.get(), AT, false /*=isConstant*/, + GlobalValue::InternalLinkage, + 0, "switch.bas"); + + + // Global Initializer + std::vector<Constant*> Init; + Constant *SwitchCase1BA = BlockAddress::get(SwitchCase1BB); + Init.push_back(SwitchCase1BA); + + Constant *SwitchCase2BA = BlockAddress::get(SwitchCase2BB); + Init.push_back(SwitchCase2BA); + + ConstantInt *One = ConstantInt::get(Type::getInt32Ty(Ctx), 1); + Constant *OnePtr = ConstantExpr::getCast(Instruction::IntToPtr, + One, Type::getInt8PtrTy(Ctx)); + Init.push_back(OnePtr); + + GV->setInitializer(ConstantArray::get(AT, Init)); + } + + virtual void TearDown() { + M.reset(); + } + + std::unique_ptr<Module> M; + Function *F; + GlobalVariable *GV; + BasicBlock *EntryBB; + BasicBlock *SwitchCase1BB; + BasicBlock *SwitchCase2BB; + BasicBlock *ExitBB; +}; + +TEST_F(LinkModuleTest, BlockAddress) { + LLVMContext &Ctx = getGlobalContext(); + IRBuilder<> Builder(EntryBB); + + std::vector<Value*> GEPIndices; + GEPIndices.push_back(ConstantInt::get(Type::getInt32Ty(Ctx), 0)); + GEPIndices.push_back(F->arg_begin()); + + Value *GEP = Builder.CreateGEP(GV, GEPIndices, "switch.gep"); + Value *Load = Builder.CreateLoad(GEP, "switch.load"); + + Builder.CreateRet(Load); + + Builder.SetInsertPoint(SwitchCase1BB); + Builder.CreateBr(ExitBB); + + Builder.SetInsertPoint(SwitchCase2BB); + Builder.CreateBr(ExitBB); + + Builder.SetInsertPoint(ExitBB); + Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx))); + + Module *LinkedModule = new Module("MyModuleLinked", getGlobalContext()); + Linker::LinkModules(LinkedModule, M.get(), Linker::PreserveSource, 0); + + // Delete the original module. + M.reset(); + + // Check that the global "@switch.bas" is well-formed. + const GlobalVariable *LinkedGV = LinkedModule->getNamedGlobal("switch.bas"); + const Constant *Init = LinkedGV->getInitializer(); + + // @switch.bas = internal global [3 x i8*] + // [i8* blockaddress(@ba_func, %switch.case.1), + // i8* blockaddress(@ba_func, %switch.case.2), + // i8* inttoptr (i32 1 to i8*)] + + ArrayType *AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3); + EXPECT_EQ(AT, Init->getType()); + + Value *Elem = Init->getOperand(0); + ASSERT_TRUE(isa<BlockAddress>(Elem)); + EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(), + LinkedModule->getFunction("ba_func")); + EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(), + LinkedModule->getFunction("ba_func")); + + Elem = Init->getOperand(1); + ASSERT_TRUE(isa<BlockAddress>(Elem)); + EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(), + LinkedModule->getFunction("ba_func")); + EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(), + LinkedModule->getFunction("ba_func")); + + delete LinkedModule; +} + +TEST_F(LinkModuleTest, EmptyModule) { + LLVMContext &Ctx = getGlobalContext(); + 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); + F->setCallingConv(CallingConv::C); + + BasicBlock *BB = BasicBlock::Create(Ctx, "", F); + IRBuilder<> Builder(BB); + Builder.CreateRetVoid(); + + StructType *STy = StructType::create(Ctx, PointerType::get(FTy, 0)); + + GlobalVariable *GV = + new GlobalVariable(*InternalM, STy, false /*=isConstant*/, + GlobalValue::InternalLinkage, 0, "g"); + + GV->setInitializer(ConstantStruct::get(STy, F)); + + + Module *EmptyM = new Module("EmptyModule1", Ctx); + Linker::LinkModules(EmptyM, InternalM, Linker::PreserveSource, 0); + + delete EmptyM; + EmptyM = new Module("EmptyModule2", Ctx); + Linker::LinkModules(InternalM, EmptyM, Linker::PreserveSource, 0); + + delete EmptyM; + delete InternalM; +} + +} // end anonymous namespace diff --git a/unittests/Linker/Makefile b/unittests/Linker/Makefile new file mode 100644 index 0000000..c6058c4 --- /dev/null +++ b/unittests/Linker/Makefile @@ -0,0 +1,15 @@ +##===- unittests/Linker/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 = Linker +LINK_COMPONENTS := core linker + +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Makefile b/unittests/Makefile index 06ba932..37f6540 100644 --- a/unittests/Makefile +++ b/unittests/Makefile @@ -10,9 +10,10 @@ LEVEL = .. PARALLEL_DIRS = ADT Analysis Bitcode CodeGen DebugInfo ExecutionEngine IR \ - MC Object Option Support Transforms + LineEditor Linker MC Object Option Support Transforms -include $(LEVEL)/Makefile.common +include $(LEVEL)/Makefile.config +include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest clean:: $(Verb) $(RM) -f *Tests diff --git a/unittests/Makefile.unittest b/unittests/Makefile.unittest index bd32aed..a39edc6 100644 --- a/unittests/Makefile.unittest +++ b/unittests/Makefile.unittest @@ -11,13 +11,23 @@ # ##===----------------------------------------------------------------------===## -# Set up variables for building a unit test. -ifdef TESTNAME - ifndef MAKEFILE_UNITTEST_NO_INCLUDE_COMMON include $(LEVEL)/Makefile.common endif +# Clean up out-of-tree stray unittests for Lit not to pick one up. +.PHONY: cleanup-local +cleanup-local: + -$(Verb) $(FIND) $(filter-out $(PARALLEL_DIRS), $(wildcard *)) -type f \ + -path '*/$(BuildMode)/*Tests$(EXEEXT)' \ + -exec rm -f '{}' \; + +all:: cleanup-local +clean:: cleanup-local + +# Set up variables for building a unit test. +ifdef TESTNAME + LLVMUnitTestExe = $(BuildMode)/$(TESTNAME)Tests$(EXEEXT) # Note that these flags are duplicated when building GoogleTest itself in @@ -42,9 +52,6 @@ ifeq ($(ENABLE_SHARED), 1) # we'll never install unittests. LD.Flags += $(RPATH) -Wl,$(SharedLibDir) endif - # Also set {DYLD,LD}_LIBRARY_PATH because OSX ignores the rpath most - # of the time. - Run.Shared := $(SHLIBPATH_VAR)="$(SharedLibDir)$${$(SHLIBPATH_VAR):+:}$$$(SHLIBPATH_VAR)" endif $(LLVMUnitTestExe): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) @@ -57,6 +64,6 @@ $(LLVMUnitTestExe): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) all:: $(LLVMUnitTestExe) unitcheck:: $(LLVMUnitTestExe) - $(Run.Shared) $(LLVMUnitTestExe) + $(LLVMUnitTestExe) endif diff --git a/unittests/Object/CMakeLists.txt b/unittests/Object/CMakeLists.txt index b491dd7..6dd66ce 100644 --- a/unittests/Object/CMakeLists.txt +++ b/unittests/Object/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS - object + Object + Support ) add_llvm_unittest(ObjectTests diff --git a/unittests/Object/YAMLTest.cpp b/unittests/Object/YAMLTest.cpp index 3ae92ae..1eb1113 100644 --- a/unittests/Object/YAMLTest.cpp +++ b/unittests/Object/YAMLTest.cpp @@ -34,5 +34,5 @@ TEST(ObjectYAML, BinaryRef) { llvm::raw_svector_ostream OS(Buf); yaml::Output YOut(OS); YOut << BH; - EXPECT_NE(OS.str().find("\"\""), StringRef::npos); + EXPECT_NE(OS.str().find("''"), StringRef::npos); } diff --git a/unittests/Option/CMakeLists.txt b/unittests/Option/CMakeLists.txt index 185d503..07f7b91 100644 --- a/unittests/Option/CMakeLists.txt +++ b/unittests/Option/CMakeLists.txt @@ -11,5 +11,3 @@ add_public_tablegen_target(OptsTestTableGen) add_llvm_unittest(OptionTests OptionParsingTest.cpp ) - -add_dependencies(OptionTests OptsTestTableGen) diff --git a/unittests/Option/OptionParsingTest.cpp b/unittests/Option/OptionParsingTest.cpp index 11d6d1e..6beb286 100644 --- a/unittests/Option/OptionParsingTest.cpp +++ b/unittests/Option/OptionParsingTest.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" @@ -68,7 +67,8 @@ const char *Args[] = { TEST(Option, OptionParsing) { TestOptTable T; unsigned MAI, MAC; - OwningPtr<InputArgList> AL(T.ParseArgs(Args, array_endof(Args), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(Args, array_endof(Args), MAI, MAC)); // Check they all exist. EXPECT_TRUE(AL->hasArg(OPT_A)); @@ -111,7 +111,7 @@ TEST(Option, OptionParsing) { TEST(Option, ParseWithFlagExclusions) { TestOptTable T; unsigned MAI, MAC; - OwningPtr<InputArgList> AL; + std::unique_ptr<InputArgList> AL; // Exclude flag3 to avoid parsing as OPT_SLASH_C. AL.reset(T.ParseArgs(Args, array_endof(Args), MAI, MAC, @@ -142,7 +142,8 @@ TEST(Option, ParseAliasInGroup) { unsigned MAI, MAC; const char *MyArgs[] = { "-I" }; - OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_H)); } @@ -151,7 +152,8 @@ TEST(Option, AliasArgs) { unsigned MAI, MAC; const char *MyArgs[] = { "-J", "-Joo" }; - OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_B)); EXPECT_EQ(AL->getAllArgValues(OPT_B)[0], "foo"); EXPECT_EQ(AL->getAllArgValues(OPT_B)[1], "bar"); @@ -162,7 +164,8 @@ TEST(Option, IgnoreCase) { unsigned MAI, MAC; const char *MyArgs[] = { "-a", "-joo" }; - OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_A)); EXPECT_TRUE(AL->hasArg(OPT_B)); } @@ -172,7 +175,8 @@ TEST(Option, DoNotIgnoreCase) { unsigned MAI, MAC; const char *MyArgs[] = { "-a", "-joo" }; - OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); EXPECT_FALSE(AL->hasArg(OPT_A)); EXPECT_FALSE(AL->hasArg(OPT_B)); } @@ -182,7 +186,8 @@ TEST(Option, SlurpEmpty) { unsigned MAI, MAC; const char *MyArgs[] = { "-A", "-slurp" }; - OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_A)); EXPECT_TRUE(AL->hasArg(OPT_Slurp)); EXPECT_EQ(AL->getAllArgValues(OPT_Slurp).size(), 0U); @@ -193,7 +198,8 @@ TEST(Option, Slurp) { unsigned MAI, MAC; const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" }; - OwningPtr<InputArgList> AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr<InputArgList> AL( + T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); EXPECT_EQ(AL->size(), 2U); EXPECT_TRUE(AL->hasArg(OPT_A)); EXPECT_FALSE(AL->hasArg(OPT_B)); diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp index cb9fa43..bcf6bf1 100644 --- a/unittests/Support/AllocatorTest.cpp +++ b/unittests/Support/AllocatorTest.cpp @@ -33,7 +33,7 @@ TEST(AllocatorTest, Basics) { // Allocate enough bytes to create three slabs. TEST(AllocatorTest, ThreeSlabs) { - BumpPtrAllocator Alloc(4096, 4096); + BumpPtrAllocator Alloc; Alloc.Allocate(3000, 0); EXPECT_EQ(1U, Alloc.GetNumSlabs()); Alloc.Allocate(3000, 0); @@ -45,7 +45,7 @@ TEST(AllocatorTest, ThreeSlabs) { // Allocate enough bytes to create two slabs, reset the allocator, and do it // again. TEST(AllocatorTest, TestReset) { - BumpPtrAllocator Alloc(4096, 4096); + BumpPtrAllocator Alloc; Alloc.Allocate(3000, 0); EXPECT_EQ(1U, Alloc.GetNumSlabs()); Alloc.Allocate(3000, 0); @@ -81,7 +81,7 @@ TEST(AllocatorTest, TestAlignment) { // Test allocating just over the slab size. This tests a bug where before the // allocator incorrectly calculated the buffer end pointer. TEST(AllocatorTest, TestOverflow) { - BumpPtrAllocator Alloc(4096, 4096); + BumpPtrAllocator Alloc; // Fill the slab right up until the end pointer. Alloc.Allocate(4096 - sizeof(MemSlab), 0); @@ -94,9 +94,9 @@ TEST(AllocatorTest, TestOverflow) { // Test allocating with a size larger than the initial slab size. TEST(AllocatorTest, TestSmallSlabSize) { - BumpPtrAllocator Alloc(128); + BumpPtrAllocator Alloc; - Alloc.Allocate(200, 0); + Alloc.Allocate(8000, 0); EXPECT_EQ(2U, Alloc.GetNumSlabs()); } @@ -141,7 +141,7 @@ public: // will not. TEST(AllocatorTest, TestBigAlignment) { MockSlabAllocator SlabAlloc; - BumpPtrAllocator Alloc(4096, 4096, SlabAlloc); + BumpPtrAllocator Alloc(SlabAlloc); uintptr_t Ptr = (uintptr_t)Alloc.Allocate(3000, 2048); MemSlab *Slab = SlabAlloc.GetLastSlab(); EXPECT_LE(Ptr + 3000, ((uintptr_t)Slab) + Slab->Size); diff --git a/unittests/Support/BlockFrequencyTest.cpp b/unittests/Support/BlockFrequencyTest.cpp index ffdea2c..c318451 100644 --- a/unittests/Support/BlockFrequencyTest.cpp +++ b/unittests/Support/BlockFrequencyTest.cpp @@ -237,4 +237,12 @@ TEST(BlockFrequencyTest, ProbabilityCompare) { EXPECT_FALSE(BigZero >= BigOne); } +TEST(BlockFrequencyTest, SaturatingRightShift) { + BlockFrequency Freq(0x10080ULL); + Freq >>= 2; + EXPECT_EQ(Freq.getFrequency(), 0x4020ULL); + Freq >>= 20; + EXPECT_EQ(Freq.getFrequency(), 0x1ULL); +} + } diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 0abc2ff..4afa4fd 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -1,6 +1,5 @@ set(LLVM_LINK_COMPONENTS Support - Core ) add_llvm_unittest(SupportTests @@ -11,13 +10,13 @@ add_llvm_unittest(SupportTests Casting.cpp CommandLineTest.cpp CompressionTest.cpp - ConstantRangeTest.cpp ConvertUTFTest.cpp DataExtractorTest.cpp EndianTest.cpp ErrorOrTest.cpp FileOutputBufferTest.cpp - LeakDetectorTest.cpp + LEB128Test.cpp + LineIteratorTest.cpp LockFileManagerTest.cpp ManagedStatic.cpp MathExtrasTest.cpp @@ -33,7 +32,6 @@ add_llvm_unittest(SupportTests ThreadLocalTest.cpp TimeValueTest.cpp UnicodeTest.cpp - ValueHandleTest.cpp YAMLIOTest.cpp YAMLParserTest.cpp formatted_raw_ostream_test.cpp diff --git a/unittests/Support/Casting.cpp b/unittests/Support/Casting.cpp index 362abee..228c90b 100644 --- a/unittests/Support/Casting.cpp +++ b/unittests/Support/Casting.cpp @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Casting.h" +#include "llvm/IR/User.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/IR/User.h" #include "gtest/gtest.h" #include <cstdlib> @@ -77,12 +77,16 @@ using namespace llvm; // Test the peculiar behavior of Use in simplify_type. -int Check1[is_same<simplify_type<Use>::SimpleType, Value *>::value ? 1 : -1]; -int Check2[is_same<simplify_type<Use *>::SimpleType, Value *>::value ? 1 : -1]; +static_assert(std::is_same<simplify_type<Use>::SimpleType, Value *>::value, + "Use doesn't simplify correctly!"); +static_assert(std::is_same<simplify_type<Use *>::SimpleType, Value *>::value, + "Use doesn't simplify correctly!"); // Test that a regular class behaves as expected. -int Check3[is_same<simplify_type<foo>::SimpleType, int>::value ? 1 : -1]; -int Check4[is_same<simplify_type<foo *>::SimpleType, foo *>::value ? 1 : -1]; +static_assert(std::is_same<simplify_type<foo>::SimpleType, int>::value, + "Unexpected simplify_type result!"); +static_assert(std::is_same<simplify_type<foo *>::SimpleType, foo *>::value, + "Unexpected simplify_type result!"); namespace { diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index c54e1b9..b0f1eb1 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -8,8 +8,8 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/STLExtras.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Config/config.h" +#include "llvm/Support/CommandLine.h" #include "gtest/gtest.h" #include <stdlib.h> #include <string> @@ -42,6 +42,33 @@ class TempEnvVar { const char *const name; }; +template <typename T> +class StackOption : public cl::opt<T> { + typedef cl::opt<T> Base; +public: + // One option... + template<class M0t> + explicit StackOption(const M0t &M0) : Base(M0) {} + + // Two options... + template<class M0t, class M1t> + StackOption(const M0t &M0, const M1t &M1) : Base(M0, M1) {} + + // Three options... + template<class M0t, class M1t, class M2t> + StackOption(const M0t &M0, const M1t &M1, const M2t &M2) : Base(M0, M1, M2) {} + + // Four options... + template<class M0t, class M1t, class M2t, class M3t> + StackOption(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Base(M0, M1, M2, M3) {} + + ~StackOption() { + this->removeArgument(); + } +}; + + cl::OptionCategory TestCategory("Test Options", "Description"); cl::opt<int> TestOption("test-option", cl::desc("old description")); TEST(CommandLineTest, ModifyExisitingOption) { @@ -103,7 +130,7 @@ TEST(CommandLineTest, ParseEnvironment) { // command line system will still hold a pointer to a deallocated cl::Option. TEST(CommandLineTest, ParseEnvironmentToLocalVar) { // Put cl::opt on stack to check for proper initialization of fields. - cl::opt<std::string> EnvironmentTestOptionLocal("env-test-opt-local"); + StackOption<std::string> EnvironmentTestOptionLocal("env-test-opt-local"); TempEnvVar TEV(test_env_var, "-env-test-opt-local=hello-local"); EXPECT_EQ("", EnvironmentTestOptionLocal); cl::ParseEnvironmentOptions("CommandLineTest", test_env_var); @@ -113,14 +140,14 @@ TEST(CommandLineTest, ParseEnvironmentToLocalVar) { #endif // SKIP_ENVIRONMENT_TESTS TEST(CommandLineTest, UseOptionCategory) { - cl::opt<int> TestOption2("test-option", cl::cat(TestCategory)); + StackOption<int> TestOption2("test-option", cl::cat(TestCategory)); ASSERT_EQ(&TestCategory,TestOption2.Category) << "Failed to assign Option " "Category."; } class StrDupSaver : public cl::StringSaver { - const char *SaveString(const char *Str) LLVM_OVERRIDE { + const char *SaveString(const char *Str) override { return strdup(Str); } }; @@ -161,4 +188,28 @@ TEST(CommandLineTest, TokenizeWindowsCommandLine) { array_lengthof(Output)); } +TEST(CommandLineTest, AliasesWithArguments) { + static const size_t ARGC = 3; + const char *const Inputs[][ARGC] = { + { "-tool", "-actual=x", "-extra" }, + { "-tool", "-actual", "x" }, + { "-tool", "-alias=x", "-extra" }, + { "-tool", "-alias", "x" } + }; + + for (size_t i = 0, e = array_lengthof(Inputs); i < e; ++i) { + StackOption<std::string> Actual("actual"); + StackOption<bool> Extra("extra"); + StackOption<std::string> Input(cl::Positional); + + cl::alias Alias("alias", llvm::cl::aliasopt(Actual)); + + cl::ParseCommandLineOptions(ARGC, Inputs[i]); + EXPECT_EQ("x", Actual); + EXPECT_EQ(0, Input.getNumOccurrences()); + + Alias.removeArgument(); + } +} + } // anonymous namespace diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp index c0a9ada..db6a8bb 100644 --- a/unittests/Support/CompressionTest.cpp +++ b/unittests/Support/CompressionTest.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Compression.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/Config/config.h" #include "llvm/Support/MemoryBuffer.h" @@ -25,8 +24,8 @@ namespace { #if LLVM_ENABLE_ZLIB == 1 && HAVE_LIBZ void TestZlibCompression(StringRef Input, zlib::CompressionLevel Level) { - OwningPtr<MemoryBuffer> Compressed; - OwningPtr<MemoryBuffer> Uncompressed; + std::unique_ptr<MemoryBuffer> Compressed; + std::unique_ptr<MemoryBuffer> Uncompressed; EXPECT_EQ(zlib::StatusOK, zlib::compress(Input, Compressed, Level)); // Check that uncompressed buffer is the same as original. EXPECT_EQ(zlib::StatusOK, zlib::uncompress(Compressed->getBuffer(), diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp index feb6a08..18ce507 100644 --- a/unittests/Support/ErrorOrTest.cpp +++ b/unittests/Support/ErrorOrTest.cpp @@ -8,9 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/ErrorOr.h" - #include "gtest/gtest.h" - #include <memory> using namespace llvm; @@ -22,22 +20,25 @@ ErrorOr<int> t2() { return errc::invalid_argument; } TEST(ErrorOr, SimpleValue) { ErrorOr<int> a = t1(); - EXPECT_TRUE(a); + // FIXME: This is probably a bug in gtest. EXPECT_TRUE should expand to + // include the !! to make it friendly to explicit bool operators. + EXPECT_TRUE(!!a); EXPECT_EQ(1, *a); + ErrorOr<int> b = a; + EXPECT_EQ(1, *b); + a = t2(); EXPECT_FALSE(a); - EXPECT_EQ(errc::invalid_argument, a); + EXPECT_EQ(errc::invalid_argument, a.getError()); #ifdef EXPECT_DEBUG_DEATH EXPECT_DEBUG_DEATH(*a, "Cannot get value when an error exists"); #endif } -#if LLVM_HAS_CXX11_STDLIB ErrorOr<std::unique_ptr<int> > t3() { return std::unique_ptr<int>(new int(3)); } -#endif TEST(ErrorOr, Types) { int x; @@ -45,10 +46,8 @@ TEST(ErrorOr, Types) { *a = 42; EXPECT_EQ(42, x); -#if LLVM_HAS_CXX11_STDLIB // Move only types. EXPECT_EQ(3, **t3()); -#endif } struct B {}; @@ -58,9 +57,7 @@ TEST(ErrorOr, Covariant) { ErrorOr<B*> b(ErrorOr<D*>(0)); b = ErrorOr<D*>(0); -#if LLVM_HAS_CXX11_STDLIB ErrorOr<std::unique_ptr<B> > b1(ErrorOr<std::unique_ptr<D> >(0)); b1 = ErrorOr<std::unique_ptr<D> >(0); -#endif } } // end anon namespace diff --git a/unittests/Support/FileOutputBufferTest.cpp b/unittests/Support/FileOutputBufferTest.cpp index 5e87319..6d62999 100644 --- a/unittests/Support/FileOutputBufferTest.cpp +++ b/unittests/Support/FileOutputBufferTest.cpp @@ -56,6 +56,7 @@ TEST(FileOutputBuffer, Test) { uint64_t File1Size; ASSERT_NO_ERROR(fs::file_size(Twine(File1), File1Size)); ASSERT_EQ(File1Size, 8192ULL); + ASSERT_NO_ERROR(fs::remove(File1.str())); // TEST 2: Verify abort case. SmallString<128> File2(TestDirectory); @@ -67,10 +68,11 @@ TEST(FileOutputBuffer, Test) { memcpy(Buffer2->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20); // Do *not* commit buffer. } - // Verify file does not exist (because buffer not commited). + // Verify file does not exist (because buffer not committed). bool Exists = false; ASSERT_NO_ERROR(fs::exists(Twine(File2), Exists)); EXPECT_FALSE(Exists); + ASSERT_NO_ERROR(fs::remove(File2.str())); // TEST 3: Verify sizing down case. SmallString<128> File3(TestDirectory); @@ -94,6 +96,7 @@ TEST(FileOutputBuffer, Test) { uint64_t File3Size; ASSERT_NO_ERROR(fs::file_size(Twine(File3), File3Size)); ASSERT_EQ(File3Size, 5000ULL); + ASSERT_NO_ERROR(fs::remove(File3.str())); // TEST 4: Verify file can be made executable. SmallString<128> File4(TestDirectory); @@ -112,9 +115,9 @@ TEST(FileOutputBuffer, Test) { ASSERT_NO_ERROR(fs::status(Twine(File4), Status)); bool IsExecutable = (Status.permissions() & fs::owner_exe); EXPECT_TRUE(IsExecutable); + ASSERT_NO_ERROR(fs::remove(File4.str())); // Clean up. - uint32_t RemovedCount; - ASSERT_NO_ERROR(fs::remove_all(TestDirectory.str(), RemovedCount)); + ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); } } // anonymous namespace diff --git a/unittests/Support/LEB128Test.cpp b/unittests/Support/LEB128Test.cpp new file mode 100644 index 0000000..b1ca13e --- /dev/null +++ b/unittests/Support/LEB128Test.cpp @@ -0,0 +1,311 @@ +//===- llvm/unittest/Support/LEB128Test.cpp - LEB128 function 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/Support/DataTypes.h" +#include "llvm/Support/LEB128.h" +#include "llvm/Support/raw_ostream.h" +#include <string> +using namespace llvm; + +namespace { + +TEST(LEB128Test, EncodeSLEB128) { +#define EXPECT_SLEB128_EQ(EXPECTED, VALUE) \ + do { \ + /* encodeSLEB128(uint64_t, raw_ostream &) */ \ + std::string Expected(EXPECTED, sizeof(EXPECTED) - 1); \ + std::string Actual; \ + raw_string_ostream Stream(Actual); \ + encodeSLEB128(VALUE, Stream); \ + Stream.flush(); \ + EXPECT_EQ(Expected, Actual); \ + } while (0) + + // Encode SLEB128 + EXPECT_SLEB128_EQ("\x00", 0); + EXPECT_SLEB128_EQ("\x01", 1); + EXPECT_SLEB128_EQ("\x7f", -1); + EXPECT_SLEB128_EQ("\x3f", 63); + EXPECT_SLEB128_EQ("\x41", -63); + EXPECT_SLEB128_EQ("\x40", -64); + EXPECT_SLEB128_EQ("\xbf\x7f", -65); + EXPECT_SLEB128_EQ("\xc0\x00", 64); + +#undef EXPECT_SLEB128_EQ +} + +TEST(LEB128Test, EncodeULEB128) { +#define EXPECT_ULEB128_EQ(EXPECTED, VALUE, PAD) \ + do { \ + std::string Expected(EXPECTED, sizeof(EXPECTED) - 1); \ + \ + /* encodeULEB128(uint64_t, raw_ostream &, unsigned) */ \ + std::string Actual1; \ + raw_string_ostream Stream(Actual1); \ + encodeULEB128(VALUE, Stream, PAD); \ + Stream.flush(); \ + EXPECT_EQ(Expected, Actual1); \ + \ + /* encodeULEB128(uint64_t, uint8_t *, unsigned) */ \ + uint8_t Buffer[32]; \ + unsigned Size = encodeULEB128(VALUE, Buffer, PAD); \ + std::string Actual2(reinterpret_cast<const char *>(Buffer), Size); \ + EXPECT_EQ(Expected, Actual2); \ + } while (0) + + // Encode ULEB128 + EXPECT_ULEB128_EQ("\x00", 0, 0); + EXPECT_ULEB128_EQ("\x01", 1, 0); + EXPECT_ULEB128_EQ("\x3f", 63, 0); + EXPECT_ULEB128_EQ("\x40", 64, 0); + EXPECT_ULEB128_EQ("\x7f", 0x7f, 0); + EXPECT_ULEB128_EQ("\x80\x01", 0x80, 0); + EXPECT_ULEB128_EQ("\x81\x01", 0x81, 0); + EXPECT_ULEB128_EQ("\x90\x01", 0x90, 0); + EXPECT_ULEB128_EQ("\xff\x01", 0xff, 0); + EXPECT_ULEB128_EQ("\x80\x02", 0x100, 0); + EXPECT_ULEB128_EQ("\x81\x02", 0x101, 0); + + // Encode ULEB128 with some extra padding bytes + EXPECT_ULEB128_EQ("\x80\x00", 0, 1); + EXPECT_ULEB128_EQ("\x80\x80\x00", 0, 2); + EXPECT_ULEB128_EQ("\xff\x00", 0x7f, 1); + EXPECT_ULEB128_EQ("\xff\x80\x00", 0x7f, 2); + EXPECT_ULEB128_EQ("\x80\x81\x00", 0x80, 1); + EXPECT_ULEB128_EQ("\x80\x81\x80\x00", 0x80, 2); + +#undef EXPECT_ULEB128_EQ +} + +TEST(LEB128Test, DecodeULEB128) { +#define EXPECT_DECODE_ULEB128_EQ(EXPECTED, VALUE) \ + do { \ + unsigned ActualSize = 0; \ + uint64_t Actual = decodeULEB128(reinterpret_cast<const uint8_t *>(VALUE), \ + &ActualSize); \ + EXPECT_EQ(sizeof(VALUE) - 1, ActualSize); \ + EXPECT_EQ(EXPECTED, Actual); \ + } while (0) + + // Decode ULEB128 + EXPECT_DECODE_ULEB128_EQ(0u, "\x00"); + EXPECT_DECODE_ULEB128_EQ(1u, "\x01"); + EXPECT_DECODE_ULEB128_EQ(63u, "\x3f"); + EXPECT_DECODE_ULEB128_EQ(64u, "\x40"); + EXPECT_DECODE_ULEB128_EQ(0x7fu, "\x7f"); + EXPECT_DECODE_ULEB128_EQ(0x80u, "\x80\x01"); + EXPECT_DECODE_ULEB128_EQ(0x81u, "\x81\x01"); + EXPECT_DECODE_ULEB128_EQ(0x90u, "\x90\x01"); + EXPECT_DECODE_ULEB128_EQ(0xffu, "\xff\x01"); + EXPECT_DECODE_ULEB128_EQ(0x100u, "\x80\x02"); + EXPECT_DECODE_ULEB128_EQ(0x101u, "\x81\x02"); + + // Decode ULEB128 with extra padding bytes + EXPECT_DECODE_ULEB128_EQ(0u, "\x80\x00"); + EXPECT_DECODE_ULEB128_EQ(0u, "\x80\x80\x00"); + EXPECT_DECODE_ULEB128_EQ(0x7fu, "\xff\x00"); + EXPECT_DECODE_ULEB128_EQ(0x7fu, "\xff\x80\x00"); + EXPECT_DECODE_ULEB128_EQ(0x80u, "\x80\x81\x00"); + EXPECT_DECODE_ULEB128_EQ(0x80u, "\x80\x81\x80\x00"); + +#undef EXPECT_DECODE_ULEB128_EQ +} + +TEST(LEB128Test, SLEB128Size) { + // Positive Value Testing Plan: + // (1) 128 ^ n - 1 ........ need (n+1) bytes + // (2) 128 ^ n ............ need (n+1) bytes + // (3) 128 ^ n * 63 ....... need (n+1) bytes + // (4) 128 ^ n * 64 - 1 ... need (n+1) bytes + // (5) 128 ^ n * 64 ....... need (n+2) bytes + + EXPECT_EQ(1u, getSLEB128Size(0x0LL)); + EXPECT_EQ(1u, getSLEB128Size(0x1LL)); + EXPECT_EQ(1u, getSLEB128Size(0x3fLL)); + EXPECT_EQ(1u, getSLEB128Size(0x3fLL)); + EXPECT_EQ(2u, getSLEB128Size(0x40LL)); + + EXPECT_EQ(2u, getSLEB128Size(0x7fLL)); + EXPECT_EQ(2u, getSLEB128Size(0x80LL)); + EXPECT_EQ(2u, getSLEB128Size(0x1f80LL)); + EXPECT_EQ(2u, getSLEB128Size(0x1fffLL)); + EXPECT_EQ(3u, getSLEB128Size(0x2000LL)); + + EXPECT_EQ(3u, getSLEB128Size(0x3fffLL)); + EXPECT_EQ(3u, getSLEB128Size(0x4000LL)); + EXPECT_EQ(3u, getSLEB128Size(0xfc000LL)); + EXPECT_EQ(3u, getSLEB128Size(0xfffffLL)); + EXPECT_EQ(4u, getSLEB128Size(0x100000LL)); + + EXPECT_EQ(4u, getSLEB128Size(0x1fffffLL)); + EXPECT_EQ(4u, getSLEB128Size(0x200000LL)); + EXPECT_EQ(4u, getSLEB128Size(0x7e00000LL)); + EXPECT_EQ(4u, getSLEB128Size(0x7ffffffLL)); + EXPECT_EQ(5u, getSLEB128Size(0x8000000LL)); + + EXPECT_EQ(5u, getSLEB128Size(0xfffffffLL)); + EXPECT_EQ(5u, getSLEB128Size(0x10000000LL)); + EXPECT_EQ(5u, getSLEB128Size(0x3f0000000LL)); + EXPECT_EQ(5u, getSLEB128Size(0x3ffffffffLL)); + EXPECT_EQ(6u, getSLEB128Size(0x400000000LL)); + + EXPECT_EQ(6u, getSLEB128Size(0x7ffffffffLL)); + EXPECT_EQ(6u, getSLEB128Size(0x800000000LL)); + EXPECT_EQ(6u, getSLEB128Size(0x1f800000000LL)); + EXPECT_EQ(6u, getSLEB128Size(0x1ffffffffffLL)); + EXPECT_EQ(7u, getSLEB128Size(0x20000000000LL)); + + EXPECT_EQ(7u, getSLEB128Size(0x3ffffffffffLL)); + EXPECT_EQ(7u, getSLEB128Size(0x40000000000LL)); + EXPECT_EQ(7u, getSLEB128Size(0xfc0000000000LL)); + EXPECT_EQ(7u, getSLEB128Size(0xffffffffffffLL)); + EXPECT_EQ(8u, getSLEB128Size(0x1000000000000LL)); + + EXPECT_EQ(8u, getSLEB128Size(0x1ffffffffffffLL)); + EXPECT_EQ(8u, getSLEB128Size(0x2000000000000LL)); + EXPECT_EQ(8u, getSLEB128Size(0x7e000000000000LL)); + EXPECT_EQ(8u, getSLEB128Size(0x7fffffffffffffLL)); + EXPECT_EQ(9u, getSLEB128Size(0x80000000000000LL)); + + EXPECT_EQ(9u, getSLEB128Size(0xffffffffffffffLL)); + EXPECT_EQ(9u, getSLEB128Size(0x100000000000000LL)); + EXPECT_EQ(9u, getSLEB128Size(0x3f00000000000000LL)); + EXPECT_EQ(9u, getSLEB128Size(0x3fffffffffffffffLL)); + EXPECT_EQ(10u, getSLEB128Size(0x4000000000000000LL)); + + EXPECT_EQ(10u, getSLEB128Size(0x7fffffffffffffffLL)); + EXPECT_EQ(10u, getSLEB128Size(INT64_MAX)); + + // Negative Value Testing Plan: + // (1) - 128 ^ n - 1 ........ need (n+1) bytes + // (2) - 128 ^ n ............ need (n+1) bytes + // (3) - 128 ^ n * 63 ....... need (n+1) bytes + // (4) - 128 ^ n * 64 ....... need (n+1) bytes (different from positive one) + // (5) - 128 ^ n * 65 - 1 ... need (n+2) bytes (if n > 0) + // (6) - 128 ^ n * 65 ....... need (n+2) bytes + + EXPECT_EQ(1u, getSLEB128Size(0x0LL)); + EXPECT_EQ(1u, getSLEB128Size(-0x1LL)); + EXPECT_EQ(1u, getSLEB128Size(-0x3fLL)); + EXPECT_EQ(1u, getSLEB128Size(-0x40LL)); + EXPECT_EQ(1u, getSLEB128Size(-0x40LL)); // special case + EXPECT_EQ(2u, getSLEB128Size(-0x41LL)); + + EXPECT_EQ(2u, getSLEB128Size(-0x7fLL)); + EXPECT_EQ(2u, getSLEB128Size(-0x80LL)); + EXPECT_EQ(2u, getSLEB128Size(-0x1f80LL)); + EXPECT_EQ(2u, getSLEB128Size(-0x2000LL)); + EXPECT_EQ(3u, getSLEB128Size(-0x207fLL)); + EXPECT_EQ(3u, getSLEB128Size(-0x2080LL)); + + EXPECT_EQ(3u, getSLEB128Size(-0x3fffLL)); + EXPECT_EQ(3u, getSLEB128Size(-0x4000LL)); + EXPECT_EQ(3u, getSLEB128Size(-0xfc000LL)); + EXPECT_EQ(3u, getSLEB128Size(-0x100000LL)); + EXPECT_EQ(4u, getSLEB128Size(-0x103fffLL)); + EXPECT_EQ(4u, getSLEB128Size(-0x104000LL)); + + EXPECT_EQ(4u, getSLEB128Size(-0x1fffffLL)); + EXPECT_EQ(4u, getSLEB128Size(-0x200000LL)); + EXPECT_EQ(4u, getSLEB128Size(-0x7e00000LL)); + EXPECT_EQ(4u, getSLEB128Size(-0x8000000LL)); + EXPECT_EQ(5u, getSLEB128Size(-0x81fffffLL)); + EXPECT_EQ(5u, getSLEB128Size(-0x8200000LL)); + + EXPECT_EQ(5u, getSLEB128Size(-0xfffffffLL)); + EXPECT_EQ(5u, getSLEB128Size(-0x10000000LL)); + EXPECT_EQ(5u, getSLEB128Size(-0x3f0000000LL)); + EXPECT_EQ(5u, getSLEB128Size(-0x400000000LL)); + EXPECT_EQ(6u, getSLEB128Size(-0x40fffffffLL)); + EXPECT_EQ(6u, getSLEB128Size(-0x410000000LL)); + + EXPECT_EQ(6u, getSLEB128Size(-0x7ffffffffLL)); + EXPECT_EQ(6u, getSLEB128Size(-0x800000000LL)); + EXPECT_EQ(6u, getSLEB128Size(-0x1f800000000LL)); + EXPECT_EQ(6u, getSLEB128Size(-0x20000000000LL)); + EXPECT_EQ(7u, getSLEB128Size(-0x207ffffffffLL)); + EXPECT_EQ(7u, getSLEB128Size(-0x20800000000LL)); + + EXPECT_EQ(7u, getSLEB128Size(-0x3ffffffffffLL)); + EXPECT_EQ(7u, getSLEB128Size(-0x40000000000LL)); + EXPECT_EQ(7u, getSLEB128Size(-0xfc0000000000LL)); + EXPECT_EQ(7u, getSLEB128Size(-0x1000000000000LL)); + EXPECT_EQ(8u, getSLEB128Size(-0x103ffffffffffLL)); + EXPECT_EQ(8u, getSLEB128Size(-0x1040000000000LL)); + + EXPECT_EQ(8u, getSLEB128Size(-0x1ffffffffffffLL)); + EXPECT_EQ(8u, getSLEB128Size(-0x2000000000000LL)); + EXPECT_EQ(8u, getSLEB128Size(-0x7e000000000000LL)); + EXPECT_EQ(8u, getSLEB128Size(-0x80000000000000LL)); + EXPECT_EQ(9u, getSLEB128Size(-0x81ffffffffffffLL)); + EXPECT_EQ(9u, getSLEB128Size(-0x82000000000000LL)); + + EXPECT_EQ(9u, getSLEB128Size(-0xffffffffffffffLL)); + EXPECT_EQ(9u, getSLEB128Size(-0x100000000000000LL)); + EXPECT_EQ(9u, getSLEB128Size(-0x3f00000000000000LL)); + EXPECT_EQ(9u, getSLEB128Size(-0x4000000000000000LL)); + EXPECT_EQ(10u, getSLEB128Size(-0x40ffffffffffffffLL)); + EXPECT_EQ(10u, getSLEB128Size(-0x4100000000000000LL)); + + EXPECT_EQ(10u, getSLEB128Size(-0x7fffffffffffffffLL)); + EXPECT_EQ(10u, getSLEB128Size(-0x8000000000000000LL)); + EXPECT_EQ(10u, getSLEB128Size(INT64_MIN)); +} + +TEST(LEB128Test, ULEB128Size) { + // Testing Plan: + // (1) 128 ^ n ............ need (n+1) bytes + // (2) 128 ^ n * 64 ....... need (n+1) bytes + // (3) 128 ^ (n+1) - 1 .... need (n+1) bytes + + EXPECT_EQ(1u, getULEB128Size(0)); // special case + + EXPECT_EQ(1u, getULEB128Size(0x1ULL)); + EXPECT_EQ(1u, getULEB128Size(0x40ULL)); + EXPECT_EQ(1u, getULEB128Size(0x7fULL)); + + EXPECT_EQ(2u, getULEB128Size(0x80ULL)); + EXPECT_EQ(2u, getULEB128Size(0x2000ULL)); + EXPECT_EQ(2u, getULEB128Size(0x3fffULL)); + + EXPECT_EQ(3u, getULEB128Size(0x4000ULL)); + EXPECT_EQ(3u, getULEB128Size(0x100000ULL)); + EXPECT_EQ(3u, getULEB128Size(0x1fffffULL)); + + EXPECT_EQ(4u, getULEB128Size(0x200000ULL)); + EXPECT_EQ(4u, getULEB128Size(0x8000000ULL)); + EXPECT_EQ(4u, getULEB128Size(0xfffffffULL)); + + EXPECT_EQ(5u, getULEB128Size(0x10000000ULL)); + EXPECT_EQ(5u, getULEB128Size(0x400000000ULL)); + EXPECT_EQ(5u, getULEB128Size(0x7ffffffffULL)); + + EXPECT_EQ(6u, getULEB128Size(0x800000000ULL)); + EXPECT_EQ(6u, getULEB128Size(0x20000000000ULL)); + EXPECT_EQ(6u, getULEB128Size(0x3ffffffffffULL)); + + EXPECT_EQ(7u, getULEB128Size(0x40000000000ULL)); + EXPECT_EQ(7u, getULEB128Size(0x1000000000000ULL)); + EXPECT_EQ(7u, getULEB128Size(0x1ffffffffffffULL)); + + EXPECT_EQ(8u, getULEB128Size(0x2000000000000ULL)); + EXPECT_EQ(8u, getULEB128Size(0x80000000000000ULL)); + EXPECT_EQ(8u, getULEB128Size(0xffffffffffffffULL)); + + EXPECT_EQ(9u, getULEB128Size(0x100000000000000ULL)); + EXPECT_EQ(9u, getULEB128Size(0x4000000000000000ULL)); + EXPECT_EQ(9u, getULEB128Size(0x7fffffffffffffffULL)); + + EXPECT_EQ(10u, getULEB128Size(0x8000000000000000ULL)); + + EXPECT_EQ(10u, getULEB128Size(UINT64_MAX)); +} + +} // anonymous namespace diff --git a/unittests/Support/LineIteratorTest.cpp b/unittests/Support/LineIteratorTest.cpp new file mode 100644 index 0000000..18f3fa9 --- /dev/null +++ b/unittests/Support/LineIteratorTest.cpp @@ -0,0 +1,115 @@ +//===- LineIterator.cpp - Unit tests --------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/LineIterator.h" +#include "llvm/Support/MemoryBuffer.h" +#include "gtest/gtest.h" + +using namespace llvm; +using namespace llvm::sys; + +namespace { + +TEST(LineIteratorTest, Basic) { + std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer("line 1\n" + "line 2\n" + "line 3")); + + line_iterator I = line_iterator(*Buffer), 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("line 3", *I); + EXPECT_EQ(3, I.line_number()); + ++I; + + EXPECT_TRUE(I.is_at_eof()); + EXPECT_EQ(E, I); +} + +TEST(LineIteratorTest, CommentSkipping) { + std::unique_ptr<MemoryBuffer> Buffer( + MemoryBuffer::getMemBuffer("line 1\n" + "line 2\n" + "# Comment 1\n" + "line 4\n" + "# Comment 2")); + + line_iterator I = line_iterator(*Buffer, '#'), 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("line 4", *I); + EXPECT_EQ(4, 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")); + + line_iterator I = line_iterator(*Buffer), E; + + EXPECT_FALSE(I.is_at_eof()); + EXPECT_NE(E, I); + + EXPECT_EQ("line 1", *I); + EXPECT_EQ(4, I.line_number()); + ++I; + EXPECT_EQ("line 2", *I); + EXPECT_EQ(8, I.line_number()); + ++I; + + EXPECT_TRUE(I.is_at_eof()); + EXPECT_EQ(E, I); +} + +TEST(LineIteratorTest, EmptyBuffers) { + std::unique_ptr<MemoryBuffer> Buffer(MemoryBuffer::getMemBuffer("")); + EXPECT_TRUE(line_iterator(*Buffer).is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer)); + + Buffer.reset(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, '#')); +} + +} // anonymous namespace diff --git a/unittests/Support/LockFileManagerTest.cpp b/unittests/Support/LockFileManagerTest.cpp index 5c73b9f..93fa10b 100644 --- a/unittests/Support/LockFileManagerTest.cpp +++ b/unittests/Support/LockFileManagerTest.cpp @@ -10,9 +10,7 @@ #include "llvm/Support/LockFileManager.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" - #include "gtest/gtest.h" - #include <memory> using namespace llvm; @@ -42,7 +40,88 @@ TEST(LockFileManagerTest, Basic) { // Now that the lock is out of scope, the file should be gone. EXPECT_FALSE(sys::fs::exists(StringRef(LockedFile))); - sys::fs::remove_all(StringRef(TmpDir)); + EC = sys::fs::remove(StringRef(TmpDir)); + ASSERT_FALSE(EC); +} + +TEST(LockFileManagerTest, LinkLockExists) { + SmallString<64> TmpDir; + error_code EC; + EC = sys::fs::createUniqueDirectory("LockFileManagerTestDir", TmpDir); + ASSERT_FALSE(EC); + + SmallString<64> LockedFile(TmpDir); + sys::path::append(LockedFile, "file"); + + SmallString<64> FileLocK(TmpDir); + sys::path::append(FileLocK, "file.lock"); + + SmallString<64> TmpFileLock(TmpDir); + sys::path::append(TmpFileLock, "file.lock-000"); + + int FD; + EC = sys::fs::openFileForWrite(StringRef(TmpFileLock), FD, sys::fs::F_None); + ASSERT_FALSE(EC); + + int Ret = close(FD); + ASSERT_EQ(Ret, 0); + + EC = sys::fs::create_link(TmpFileLock.str(), FileLocK.str()); + ASSERT_FALSE(EC); + + EC = sys::fs::remove(StringRef(TmpFileLock)); + ASSERT_FALSE(EC); + + { + // The lock file doesn't point to a real file, so we should successfully + // acquire it. + LockFileManager Locked(LockedFile); + EXPECT_EQ(LockFileManager::LFS_Owned, Locked.getState()); + } + + // Now that the lock is out of scope, the file should be gone. + EXPECT_FALSE(sys::fs::exists(StringRef(LockedFile))); + + EC = sys::fs::remove(StringRef(TmpDir)); + ASSERT_FALSE(EC); +} + + +TEST(LockFileManagerTest, RelativePath) { + SmallString<64> TmpDir; + error_code EC; + EC = sys::fs::createUniqueDirectory("LockFileManagerTestDir", TmpDir); + ASSERT_FALSE(EC); + + char PathBuf[1024]; + const char *OrigPath = getcwd(PathBuf, 1024); + chdir(TmpDir.c_str()); + + sys::fs::create_directory("inner"); + SmallString<64> LockedFile("inner"); + sys::path::append(LockedFile, "file"); + + SmallString<64> FileLock(LockedFile); + FileLock += ".lock"; + + { + // The lock file should not exist, so we should successfully acquire it. + LockFileManager Locked(LockedFile); + EXPECT_EQ(LockFileManager::LFS_Owned, Locked.getState()); + EXPECT_TRUE(sys::fs::exists(FileLock.str())); + } + + // Now that the lock is out of scope, the file should be gone. + EXPECT_FALSE(sys::fs::exists(LockedFile.str())); + EXPECT_FALSE(sys::fs::exists(FileLock.str())); + + EC = sys::fs::remove("inner"); + ASSERT_FALSE(EC); + + chdir(OrigPath); + + EC = sys::fs::remove(StringRef(TmpDir)); + ASSERT_FALSE(EC); } } // end anonymous namespace diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp index 2b8806c..43b7e0d 100644 --- a/unittests/Support/MemoryBufferTest.cpp +++ b/unittests/Support/MemoryBufferTest.cpp @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/FileSystem.h" +#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/OwningPtr.h" #include "gtest/gtest.h" using namespace llvm; @@ -78,7 +78,7 @@ TEST_F(MemoryBufferTest, NullTerminator4K) { } OF.close(); - OwningPtr<MemoryBuffer> MB; + OwningBuffer MB; error_code EC = MemoryBuffer::getFile(TestPath.c_str(), MB); ASSERT_FALSE(EC); diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index 0316241..b79d055 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -210,6 +210,48 @@ TEST(Support, AbsolutePathIteratorWin32) { } #endif // LLVM_ON_WIN32 +TEST(Support, AbsolutePathIteratorEnd) { + // Trailing slashes are converted to '.' unless they are part of the root path. + SmallVector<StringRef, 4> Paths; + Paths.push_back("/foo/"); + Paths.push_back("/foo//"); + Paths.push_back("//net//"); +#ifdef LLVM_ON_WIN32 + Paths.push_back("c:\\\\"); +#endif + + for (StringRef Path : Paths) { + StringRef LastComponent = *--path::end(Path); + EXPECT_EQ(".", LastComponent); + } + + SmallVector<StringRef, 3> RootPaths; + RootPaths.push_back("/"); + RootPaths.push_back("//net/"); +#ifdef LLVM_ON_WIN32 + RootPaths.push_back("c:\\"); +#endif + + for (StringRef Path : RootPaths) { + StringRef LastComponent = *--path::end(Path); + EXPECT_EQ(1u, LastComponent.size()); + EXPECT_TRUE(path::is_separator(LastComponent[0])); + } +} + +TEST(Support, HomeDirectory) { +#ifdef LLVM_ON_UNIX + // This test only makes sense on Unix if $HOME is set. + if (::getenv("HOME")) { +#endif + SmallString<128> HomeDir; + EXPECT_TRUE(path::home_directory(HomeDir)); + EXPECT_FALSE(HomeDir.empty()); +#ifdef LLVM_ON_UNIX + } +#endif +} + class FileSystemTest : public testing::Test { protected: /// Unique temporary directory in which all created filesystem entities must @@ -225,8 +267,7 @@ protected: } virtual void TearDown() { - uint32_t removed; - ASSERT_NO_ERROR(fs::remove_all(TestDirectory.str(), removed)); + ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); } }; @@ -258,7 +299,7 @@ TEST_F(FileSystemTest, Unique) { // Two paths representing the same file on disk should still provide the // same unique id. We can test this by making a hard link. - ASSERT_NO_ERROR(fs::create_hard_link(Twine(TempPath), Twine(TempPath2))); + ASSERT_NO_ERROR(fs::create_link(Twine(TempPath), Twine(TempPath2))); fs::UniqueID D2; ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath2), D2)); ASSERT_EQ(D2, F1); @@ -306,8 +347,10 @@ TEST_F(FileSystemTest, TempFiles) { ::close(FD2); // Remove Temp2. - ASSERT_NO_ERROR(fs::remove(Twine(TempPath2), TempFileExists)); - EXPECT_TRUE(TempFileExists); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); + ASSERT_EQ(fs::remove(Twine(TempPath2), false), + errc::no_such_file_or_directory); error_code EC = fs::status(TempPath2.c_str(), B); EXPECT_EQ(EC, errc::no_such_file_or_directory); @@ -322,7 +365,7 @@ TEST_F(FileSystemTest, TempFiles) { ASSERT_FALSE(TempPath3.endswith(".")); // Create a hard link to Temp1. - ASSERT_NO_ERROR(fs::create_hard_link(Twine(TempPath), Twine(TempPath2))); + ASSERT_NO_ERROR(fs::create_link(Twine(TempPath), Twine(TempPath2))); bool equal; ASSERT_NO_ERROR(fs::equivalent(Twine(TempPath), Twine(TempPath2), equal)); EXPECT_TRUE(equal); @@ -332,12 +375,10 @@ TEST_F(FileSystemTest, TempFiles) { // Remove Temp1. ::close(FileDescriptor); - ASSERT_NO_ERROR(fs::remove(Twine(TempPath), TempFileExists)); - EXPECT_TRUE(TempFileExists); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath))); // Remove the hard link. - ASSERT_NO_ERROR(fs::remove(Twine(TempPath2), TempFileExists)); - EXPECT_TRUE(TempFileExists); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); // Make sure Temp1 doesn't exist. ASSERT_NO_ERROR(fs::exists(Twine(TempPath), TempFileExists)); @@ -356,23 +397,30 @@ TEST_F(FileSystemTest, TempFiles) { #endif } +TEST_F(FileSystemTest, CreateDir) { + ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo")); + ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo")); + ASSERT_EQ(fs::create_directory(Twine(TestDirectory) + "foo", false), + errc::file_exists); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "foo")); +} + TEST_F(FileSystemTest, DirectoryIteration) { error_code ec; for (fs::directory_iterator i(".", ec), e; i != e; i.increment(ec)) ASSERT_NO_ERROR(ec); // Create a known hierarchy to recurse over. - bool existed; - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/a0/aa1", existed)); - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/a0/ab1", existed)); - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/dontlookhere/da1", existed)); - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/z0/za1", existed)); - ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) - + "/recursive/pop/p1", existed)); + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/recursive/a0/aa1")); + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/recursive/a0/ab1")); + ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) + + "/recursive/dontlookhere/da1")); + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/recursive/z0/za1")); + ASSERT_NO_ERROR( + fs::create_directories(Twine(TestDirectory) + "/recursive/pop/p1")); typedef std::vector<std::string> v_t; v_t visited; for (fs::recursive_directory_iterator i(Twine(TestDirectory) @@ -414,6 +462,18 @@ TEST_F(FileSystemTest, DirectoryIteration) { ASSERT_LT(a0, aa1); ASSERT_LT(a0, ab1); ASSERT_LT(z0, za1); + + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0/aa1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0/ab1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0")); + ASSERT_NO_ERROR( + fs::remove(Twine(TestDirectory) + "/recursive/dontlookhere/da1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/dontlookhere")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/pop/p1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/pop")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/z0/za1")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/z0")); + ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive")); } const char archive[] = "!<arch>\x0A"; @@ -470,7 +530,7 @@ TEST_F(FileSystemTest, Magic) { 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_Binary); + raw_fd_ostream file(file_pathname.c_str(), ErrMsg, sys::fs::F_None); ASSERT_FALSE(file.has_error()); StringRef magic(i->magic_str, i->magic_str_len); file << magic; @@ -479,6 +539,7 @@ TEST_F(FileSystemTest, Magic) { ASSERT_NO_ERROR(fs::has_magic(file_pathname.c_str(), magic, res)); EXPECT_TRUE(res); EXPECT_EQ(i->magic, fs::identify_magic(magic)); + ASSERT_NO_ERROR(fs::remove(Twine(file_pathname))); } } @@ -489,26 +550,27 @@ TEST_F(FileSystemTest, CarriageReturn) { path::append(FilePathname, "test"); { - raw_fd_ostream File(FilePathname.c_str(), ErrMsg); + raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_Text); EXPECT_EQ(ErrMsg, ""); File << '\n'; } { - OwningPtr<MemoryBuffer> Buf; + std::unique_ptr<MemoryBuffer> Buf; MemoryBuffer::getFile(FilePathname.c_str(), Buf); EXPECT_EQ(Buf->getBuffer(), "\r\n"); } { - raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_Binary); + raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_None); EXPECT_EQ(ErrMsg, ""); File << '\n'; } { - OwningPtr<MemoryBuffer> Buf; + std::unique_ptr<MemoryBuffer> Buf; MemoryBuffer::getFile(FilePathname.c_str(), Buf); EXPECT_EQ(Buf->getBuffer(), "\n"); } + ASSERT_NO_ERROR(fs::remove(Twine(FilePathname))); } #endif @@ -548,7 +610,6 @@ TEST_F(FileSystemTest, FileMapping) { // Unmap temp file -#if LLVM_HAS_RVALUE_REFERENCES fs::mapped_file_region m(Twine(TempPath), fs::mapped_file_region::readonly, 0, @@ -556,8 +617,44 @@ TEST_F(FileSystemTest, FileMapping) { EC); ASSERT_NO_ERROR(EC); const char *Data = m.const_data(); - fs::mapped_file_region mfrrv(llvm_move(m)); + fs::mapped_file_region mfrrv(std::move(m)); EXPECT_EQ(mfrrv.const_data(), Data); +} + +TEST(Support, NormalizePath) { +#if defined(LLVM_ON_WIN32) +#define EXPECT_PATH_IS(path__, windows__, not_windows__) \ + EXPECT_EQ(path__, windows__); +#else +#define EXPECT_PATH_IS(path__, windows__, not_windows__) \ + EXPECT_EQ(path__, not_windows__); #endif + + SmallString<64> Path1("a"); + SmallString<64> Path2("a/b"); + SmallString<64> Path3("a\\b"); + SmallString<64> Path4("a\\\\b"); + SmallString<64> Path5("\\a"); + SmallString<64> Path6("a\\"); + + ASSERT_NO_ERROR(fs::normalize_separators(Path1)); + EXPECT_PATH_IS(Path1, "a", "a"); + + ASSERT_NO_ERROR(fs::normalize_separators(Path2)); + EXPECT_PATH_IS(Path2, "a/b", "a/b"); + + ASSERT_NO_ERROR(fs::normalize_separators(Path3)); + EXPECT_PATH_IS(Path3, "a\\b", "a/b"); + + ASSERT_NO_ERROR(fs::normalize_separators(Path4)); + EXPECT_PATH_IS(Path4, "a\\\\b", "a\\\\b"); + + ASSERT_NO_ERROR(fs::normalize_separators(Path5)); + EXPECT_PATH_IS(Path5, "\\a", "/a"); + + ASSERT_NO_ERROR(fs::normalize_separators(Path6)); + EXPECT_PATH_IS(Path6, "a\\", "a/"); + +#undef EXPECT_PATH_IS } } // anonymous namespace diff --git a/unittests/Support/ProcessTest.cpp b/unittests/Support/ProcessTest.cpp index 27c2318..f406072 100644 --- a/unittests/Support/ProcessTest.cpp +++ b/unittests/Support/ProcessTest.cpp @@ -11,7 +11,7 @@ #include "gtest/gtest.h" #ifdef LLVM_ON_WIN32 -#include "windows.h" +#include <windows.h> #endif namespace { @@ -39,6 +39,13 @@ TEST(ProcessTest, SelfProcess) { EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_wall_time()); } +TEST(ProcessTest, GetRandomNumberTest) { + const unsigned r1 = Process::GetRandomNumber(); + const unsigned r2 = Process::GetRandomNumber(); + // It should be extremely unlikely that both r1 and r2 are 0. + EXPECT_NE((r1 | r2), 0u); +} + #ifdef _MSC_VER #define setenv(name, var, ignore) _putenv_s(name, var) #endif diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp index 6eb990f..800df14 100644 --- a/unittests/Support/ProgramTest.cpp +++ b/unittests/Support/ProgramTest.cpp @@ -12,7 +12,6 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" #include "gtest/gtest.h" - #include <stdlib.h> #if defined(__APPLE__) # include <crt_externs.h> diff --git a/unittests/Support/RegexTest.cpp b/unittests/Support/RegexTest.cpp index 7b977f7..c045c49 100644 --- a/unittests/Support/RegexTest.cpp +++ b/unittests/Support/RegexTest.cpp @@ -90,23 +90,23 @@ TEST_F(RegexTest, Substitution) { // Standard Escapes EXPECT_EQ("a\\ber", Regex("[0-9]+").sub("\\\\", "a1234ber", &Error)); - EXPECT_EQ(Error, ""); + EXPECT_EQ("", Error); EXPECT_EQ("a\nber", Regex("[0-9]+").sub("\\n", "a1234ber", &Error)); - EXPECT_EQ(Error, ""); + EXPECT_EQ("", Error); EXPECT_EQ("a\tber", Regex("[0-9]+").sub("\\t", "a1234ber", &Error)); - EXPECT_EQ(Error, ""); + EXPECT_EQ("", Error); EXPECT_EQ("ajber", Regex("[0-9]+").sub("\\j", "a1234ber", &Error)); - EXPECT_EQ(Error, ""); + EXPECT_EQ("", Error); EXPECT_EQ("aber", Regex("[0-9]+").sub("\\", "a1234ber", &Error)); EXPECT_EQ(Error, "replacement string contained trailing backslash"); // Backreferences EXPECT_EQ("aa1234bber", Regex("a[0-9]+b").sub("a\\0b", "a1234ber", &Error)); - EXPECT_EQ(Error, ""); + EXPECT_EQ("", Error); EXPECT_EQ("a1234ber", Regex("a([0-9]+)b").sub("a\\1b", "a1234ber", &Error)); - EXPECT_EQ(Error, ""); + EXPECT_EQ("", Error); EXPECT_EQ("aber", Regex("a[0-9]+b").sub("a\\100b", "a1234ber", &Error)); EXPECT_EQ(Error, "invalid backreference string '100'"); @@ -127,6 +127,11 @@ TEST_F(RegexTest, IsLiteralERE) { EXPECT_FALSE(Regex::isLiteralERE("abc{1,2}")); } +TEST_F(RegexTest, Escape) { + EXPECT_EQ("a\\[bc\\]", Regex::escape("a[bc]")); + EXPECT_EQ("abc\\{1\\\\,2\\}", Regex::escape("abc{1\\,2}")); +} + TEST_F(RegexTest, IsValid) { std::string Error; EXPECT_FALSE(Regex("(foo").isValid(Error)); @@ -135,4 +140,17 @@ TEST_F(RegexTest, IsValid) { EXPECT_EQ("invalid character range", Error); } +TEST_F(RegexTest, MoveConstruct) { + Regex r1("^[0-9]+$"); + Regex r2(std::move(r1)); + EXPECT_TRUE(r2.match("916")); +} + +TEST_F(RegexTest, MoveAssign) { + Regex r1("^[0-9]+$"); + Regex r2("abc"); + r2 = std::move(r1); + EXPECT_TRUE(r2.match("916")); +} + } diff --git a/unittests/Support/SwapByteOrderTest.cpp b/unittests/Support/SwapByteOrderTest.cpp index c2a0c27..85ac6f3 100644 --- a/unittests/Support/SwapByteOrderTest.cpp +++ b/unittests/Support/SwapByteOrderTest.cpp @@ -17,7 +17,7 @@ using namespace llvm; namespace { -// In these first two tests all of the origional_uintx values are truncated +// In these first two tests all of the original_uintx values are truncated // except for 64. We could avoid this, but there's really no point. TEST(SwapByteOrder, UnsignedRoundTrip) { @@ -25,21 +25,21 @@ TEST(SwapByteOrder, UnsignedRoundTrip) { // in every byte. uint64_t value = 1; for (std::size_t i = 0; i <= sizeof(value); ++i) { - uint8_t origional_uint8 = static_cast<uint8_t>(value); - EXPECT_EQ(origional_uint8, - sys::SwapByteOrder(sys::SwapByteOrder(origional_uint8))); + uint8_t original_uint8 = static_cast<uint8_t>(value); + EXPECT_EQ(original_uint8, + sys::SwapByteOrder(sys::SwapByteOrder(original_uint8))); - uint16_t origional_uint16 = static_cast<uint16_t>(value); - EXPECT_EQ(origional_uint16, - sys::SwapByteOrder(sys::SwapByteOrder(origional_uint16))); + uint16_t original_uint16 = static_cast<uint16_t>(value); + EXPECT_EQ(original_uint16, + sys::SwapByteOrder(sys::SwapByteOrder(original_uint16))); - uint32_t origional_uint32 = static_cast<uint32_t>(value); - EXPECT_EQ(origional_uint32, - sys::SwapByteOrder(sys::SwapByteOrder(origional_uint32))); + uint32_t original_uint32 = static_cast<uint32_t>(value); + EXPECT_EQ(original_uint32, + sys::SwapByteOrder(sys::SwapByteOrder(original_uint32))); - uint64_t origional_uint64 = static_cast<uint64_t>(value); - EXPECT_EQ(origional_uint64, - sys::SwapByteOrder(sys::SwapByteOrder(origional_uint64))); + uint64_t original_uint64 = static_cast<uint64_t>(value); + EXPECT_EQ(original_uint64, + sys::SwapByteOrder(sys::SwapByteOrder(original_uint64))); value = (value << 8) | 0x55; // binary 0101 0101. } @@ -50,40 +50,40 @@ TEST(SwapByteOrder, SignedRoundTrip) { // in every byte. uint64_t value = 1; for (std::size_t i = 0; i <= sizeof(value); ++i) { - int8_t origional_int8 = static_cast<int8_t>(value); - EXPECT_EQ(origional_int8, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int8))); + int8_t original_int8 = static_cast<int8_t>(value); + EXPECT_EQ(original_int8, + sys::SwapByteOrder(sys::SwapByteOrder(original_int8))); - int16_t origional_int16 = static_cast<int16_t>(value); - EXPECT_EQ(origional_int16, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int16))); + int16_t original_int16 = static_cast<int16_t>(value); + EXPECT_EQ(original_int16, + sys::SwapByteOrder(sys::SwapByteOrder(original_int16))); - int32_t origional_int32 = static_cast<int32_t>(value); - EXPECT_EQ(origional_int32, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int32))); + int32_t original_int32 = static_cast<int32_t>(value); + EXPECT_EQ(original_int32, + sys::SwapByteOrder(sys::SwapByteOrder(original_int32))); - int64_t origional_int64 = static_cast<int64_t>(value); - EXPECT_EQ(origional_int64, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int64))); + int64_t original_int64 = static_cast<int64_t>(value); + EXPECT_EQ(original_int64, + sys::SwapByteOrder(sys::SwapByteOrder(original_int64))); // Test other sign. value *= -1; - origional_int8 = static_cast<int8_t>(value); - EXPECT_EQ(origional_int8, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int8))); + original_int8 = static_cast<int8_t>(value); + EXPECT_EQ(original_int8, + sys::SwapByteOrder(sys::SwapByteOrder(original_int8))); - origional_int16 = static_cast<int16_t>(value); - EXPECT_EQ(origional_int16, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int16))); + original_int16 = static_cast<int16_t>(value); + EXPECT_EQ(original_int16, + sys::SwapByteOrder(sys::SwapByteOrder(original_int16))); - origional_int32 = static_cast<int32_t>(value); - EXPECT_EQ(origional_int32, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int32))); + original_int32 = static_cast<int32_t>(value); + EXPECT_EQ(original_int32, + sys::SwapByteOrder(sys::SwapByteOrder(original_int32))); - origional_int64 = static_cast<int64_t>(value); - EXPECT_EQ(origional_int64, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int64))); + original_int64 = static_cast<int64_t>(value); + EXPECT_EQ(original_int64, + sys::SwapByteOrder(sys::SwapByteOrder(original_int64))); // Return to normal sign and twiddle. value *= -1; diff --git a/unittests/Support/TimeValueTest.cpp b/unittests/Support/TimeValueTest.cpp index fb2abe3..8058812 100644 --- a/unittests/Support/TimeValueTest.cpp +++ b/unittests/Support/TimeValueTest.cpp @@ -17,7 +17,7 @@ namespace { TEST(TimeValue, time_t) { sys::TimeValue now = sys::TimeValue::now(); time_t now_t = time(NULL); - EXPECT_TRUE(abs(static_cast<long>(now_t - now.toEpochTime())) < 2); + EXPECT_TRUE(std::abs(static_cast<long>(now_t - now.toEpochTime())) < 2); } TEST(TimeValue, Win32FILETIME) { @@ -30,7 +30,8 @@ TEST(TimeValue, Win32FILETIME) { epoch.fromWin32Time(ft1970); // The "seconds" part in Posix time may be expected as zero. - EXPECT_EQ(ns / 100, epoch.toPosixTime()); + EXPECT_EQ(0u, epoch.toEpochTime()); + EXPECT_EQ(ns, static_cast<uint32_t>(epoch.nanoseconds())); // Confirm it reversible. EXPECT_EQ(ft1970, epoch.toWin32Time()); diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 6c0b9e6..52a8f6b 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -27,6 +27,13 @@ using llvm::yaml::Hex32; using llvm::yaml::Hex64; + + +static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) { +} + + + //===----------------------------------------------------------------------===// // Test MappingTraits //===----------------------------------------------------------------------===// @@ -140,6 +147,7 @@ TEST(YAMLIO, TestSequenceMapWriteAndRead) { struct BuiltInTypes { llvm::StringRef str; + std::string stdstr; uint64_t u64; uint32_t u32; uint16_t u16; @@ -163,6 +171,7 @@ namespace yaml { struct MappingTraits<BuiltInTypes> { static void mapping(IO &io, BuiltInTypes& bt) { io.mapRequired("str", bt.str); + io.mapRequired("stdstr", bt.stdstr); io.mapRequired("u64", bt.u64); io.mapRequired("u32", bt.u32); io.mapRequired("u16", bt.u16); @@ -191,6 +200,7 @@ TEST(YAMLIO, TestReadBuiltInTypes) { BuiltInTypes map; Input yin("---\n" "str: hello there\n" + "stdstr: hello where?\n" "u64: 5000000000\n" "u32: 4000000000\n" "u16: 65000\n" @@ -211,6 +221,7 @@ TEST(YAMLIO, TestReadBuiltInTypes) { EXPECT_FALSE(yin.error()); EXPECT_TRUE(map.str.equals("hello there")); + EXPECT_TRUE(map.stdstr == "hello where?"); EXPECT_EQ(map.u64, 5000000000ULL); EXPECT_EQ(map.u32, 4000000000U); EXPECT_EQ(map.u16, 65000); @@ -237,6 +248,7 @@ TEST(YAMLIO, TestReadWriteBuiltInTypes) { { BuiltInTypes map; map.str = "one two"; + map.stdstr = "three four"; map.u64 = 6000000000ULL; map.u32 = 3000000000U; map.u16 = 50000; @@ -265,6 +277,7 @@ TEST(YAMLIO, TestReadWriteBuiltInTypes) { EXPECT_FALSE(yin.error()); EXPECT_TRUE(map.str.equals("one two")); + EXPECT_TRUE(map.stdstr == "three four"); EXPECT_EQ(map.u64, 6000000000ULL); EXPECT_EQ(map.u32, 3000000000U); EXPECT_EQ(map.u16, 50000); @@ -289,6 +302,11 @@ struct StringTypes { llvm::StringRef str3; llvm::StringRef str4; llvm::StringRef str5; + std::string stdstr1; + std::string stdstr2; + std::string stdstr3; + std::string stdstr4; + std::string stdstr5; }; namespace llvm { @@ -301,6 +319,11 @@ namespace yaml { io.mapRequired("str3", st.str3); io.mapRequired("str4", st.str4); io.mapRequired("str5", st.str5); + io.mapRequired("stdstr1", st.stdstr1); + io.mapRequired("stdstr2", st.stdstr2); + io.mapRequired("stdstr3", st.stdstr3); + io.mapRequired("stdstr4", st.stdstr4); + io.mapRequired("stdstr5", st.stdstr5); } }; } @@ -315,6 +338,11 @@ TEST(YAMLIO, TestReadWriteStringTypes) { map.str3 = "`ccc"; map.str4 = "@ddd"; map.str5 = ""; + map.stdstr1 = "'eee"; + map.stdstr2 = "\"fff"; + map.stdstr3 = "`ggg"; + map.stdstr4 = "@hhh"; + map.stdstr5 = ""; llvm::raw_string_ostream ostr(intermediate); Output yout(ostr); @@ -327,6 +355,11 @@ TEST(YAMLIO, TestReadWriteStringTypes) { EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'")); EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'")); EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n")); + EXPECT_NE(std::string::npos, flowOut.find("'''eee")); + EXPECT_NE(std::string::npos, flowOut.find("'\"fff'")); + EXPECT_NE(std::string::npos, flowOut.find("'`ggg'")); + EXPECT_NE(std::string::npos, flowOut.find("'@hhh'")); + EXPECT_NE(std::string::npos, flowOut.find("''\n")); { Input yin(intermediate); @@ -339,6 +372,11 @@ TEST(YAMLIO, TestReadWriteStringTypes) { EXPECT_TRUE(map.str3.equals("`ccc")); EXPECT_TRUE(map.str4.equals("@ddd")); EXPECT_TRUE(map.str5.equals("")); + EXPECT_TRUE(map.stdstr1 == "'eee"); + EXPECT_TRUE(map.stdstr2 == "\"fff"); + EXPECT_TRUE(map.stdstr3 == "`ggg"); + EXPECT_TRUE(map.stdstr4 == "@hhh"); + EXPECT_TRUE(map.stdstr5 == ""); } } @@ -1085,86 +1123,49 @@ TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) { //===----------------------------------------------------------------------===// -// Test dyn_cast<> on IO object +// Test mapping validation //===----------------------------------------------------------------------===// -struct DynCast { - int value; +struct MyValidation { + double value; }; -typedef std::vector<DynCast> DynCastSequence; -LLVM_YAML_IS_SEQUENCE_VECTOR(DynCast) +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation) namespace llvm { namespace yaml { template <> - struct MappingTraits<DynCast> { - static void mapping(IO &io, DynCast& info) { - // Change 10 to 13 when writing yaml. - if (Output *output = dyn_cast<Output>(&io)) { - (void)output; - if (info.value == 10) - info.value = 13; - } - io.mapRequired("value", info.value); - // Change 20 to 23 when parsing yaml. - if (Input *input = dyn_cast<Input>(&io)) { - (void)input; - if (info.value == 20) - info.value = 23; - } + struct MappingTraits<MyValidation> { + static void mapping(IO &io, MyValidation &d) { + io.mapRequired("value", d.value); + } + static StringRef validate(IO &io, MyValidation &d) { + if (d.value < 0) + return "negative value"; + return StringRef(); } }; -} + } } + // -// Test writing then reading back a sequence of mappings +// Test that validate() is called and complains about the negative value. // -TEST(YAMLIO, TestDynCast) { - std::string intermediate; - { - DynCast entry1; - entry1.value = 10; - DynCast entry2; - entry2.value = 20; - DynCast entry3; - entry3.value = 30; - DynCastSequence seq; - seq.push_back(entry1); - seq.push_back(entry2); - seq.push_back(entry3); - - llvm::raw_string_ostream ostr(intermediate); - Output yout(ostr); - yout << seq; - } - - { - Input yin(intermediate); - DynCastSequence seq2; - yin >> seq2; - - EXPECT_FALSE(yin.error()); - EXPECT_EQ(seq2.size(), 3UL); - EXPECT_EQ(seq2[0].value, 13); // Verify changed to 13. - EXPECT_EQ(seq2[1].value, 23); // Verify changed to 23. - EXPECT_EQ(seq2[2].value, 30); // Verify stays same. - } +TEST(YAMLIO, TestValidatingInput) { + std::vector<MyValidation> docList; + Input yin("--- \nvalue: 3.0\n" + "--- \nvalue: -1.0\n...\n", + NULL, suppressErrorMessages); + yin >> docList; + EXPECT_TRUE(yin.error()); } - //===----------------------------------------------------------------------===// // Test error handling //===----------------------------------------------------------------------===// - - -static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) { -} - - // // Test error handling of unknown enumerated scalar // diff --git a/unittests/Transforms/DebugIR/CMakeLists.txt b/unittests/Transforms/DebugIR/CMakeLists.txt index 4b47193..88734d2 100644 --- a/unittests/Transforms/DebugIR/CMakeLists.txt +++ b/unittests/Transforms/DebugIR/CMakeLists.txt @@ -1,5 +1,7 @@ set(LLVM_LINK_COMPONENTS + Core Instrumentation + Support ) add_llvm_unittest(DebugIRTests diff --git a/unittests/Transforms/DebugIR/DebugIR.cpp b/unittests/Transforms/DebugIR/DebugIR.cpp index 7d213fd..9b89c15 100644 --- a/unittests/Transforms/DebugIR/DebugIR.cpp +++ b/unittests/Transforms/DebugIR/DebugIR.cpp @@ -13,17 +13,16 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/Triple.h" +#include "../lib/Transforms/Instrumentation/DebugIR.h" #include "llvm/Config/config.h" -#include "llvm/DebugInfo.h" -#include "llvm/DIBuilder.h" +#include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/Module.h" -#include "llvm/Support/Host.h" #include "llvm/Support/FileSystem.h" +#include "llvm/Support/Host.h" #include "llvm/Support/Path.h" #include "llvm/Transforms/Instrumentation.h" -#include "../lib/Transforms/Instrumentation/DebugIR.h" - // These tests do not depend on MCJIT, but we use the TrivialModuleBuilder // helper class to construct some trivial Modules. #include "../unittests/ExecutionEngine/MCJIT/MCJITTestBase.h" @@ -56,9 +55,10 @@ void insertCUDescriptor(Module *M, StringRef File, StringRef Dir, /// Attempts to remove file at Path and returns true if it existed, or false if /// it did not. bool removeIfExists(StringRef Path) { - bool existed = false; - sys::fs::remove(Path, existed); - return existed; + // This is an approximation, on error we don't know in general if the file + // existed or not. + llvm::error_code EC = sys::fs::remove(Path, false); + return EC != llvm::errc::no_such_file_or_directory; } char * current_dir() { @@ -90,8 +90,8 @@ protected: LLVMContext Context; char *cwd; - OwningPtr<Module> M; - OwningPtr<DebugIR> D; + std::unique_ptr<Module> M; + std::unique_ptr<DebugIR> D; }; // Test empty named Module that is not supposed to be output to disk. @@ -278,7 +278,7 @@ TEST_F(TestDebugIR, ExistingMetadataRetained) { // verify DebugIR did not generate a file ASSERT_FALSE(removeIfExists(Path)) << "Unexpected file " << Path; - DICompileUnit CU(*Finder.compile_unit_begin()); + DICompileUnit CU(*Finder.compile_units().begin()); // Verify original CU information is retained ASSERT_EQ(Filename, CU.getFilename()); diff --git a/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp b/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp new file mode 100644 index 0000000..0d3a239 --- /dev/null +++ b/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp @@ -0,0 +1,102 @@ +//===- ASanStackFrameLayoutTest.cpp - Tests for ComputeASanStackFrameLayout===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "llvm/Transforms/Utils/ASanStackFrameLayout.h" +#include "llvm/ADT/ArrayRef.h" +#include "gtest/gtest.h" +#include <sstream> + +using namespace llvm; + +static std::string +ShadowBytesToString(ArrayRef<uint8_t> ShadowBytes) { + std::ostringstream os; + for (size_t i = 0, n = ShadowBytes.size(); i < n; i++) { + switch (ShadowBytes[i]) { + case kAsanStackLeftRedzoneMagic: os << "L"; break; + case kAsanStackRightRedzoneMagic: os << "R"; break; + case kAsanStackMidRedzoneMagic: os << "M"; break; + default: os << (unsigned)ShadowBytes[i]; + } + } + return os.str(); +} + +static void TestLayout(SmallVector<ASanStackVariableDescription, 10> Vars, + size_t Granularity, size_t MinHeaderSize, + const std::string &ExpectedDescr, + const std::string &ExpectedShadow) { + ASanStackFrameLayout L; + ComputeASanStackFrameLayout(Vars, Granularity, MinHeaderSize, &L); + EXPECT_EQ(ExpectedDescr, L.DescriptionString); + EXPECT_EQ(ExpectedShadow, ShadowBytesToString(L.ShadowBytes)); +} + +TEST(ASanStackFrameLayout, Test) { +#define VEC1(a) SmallVector<ASanStackVariableDescription, 10>(1, a) +#define VEC(a) \ + SmallVector<ASanStackVariableDescription, 10>(a, a + sizeof(a) / sizeof(a[0])) + +#define VAR(name, size, alignment) \ + ASanStackVariableDescription name##size##_##alignment = { \ + #name #size "_" #alignment, \ + size, \ + alignment, \ + 0, \ + 0 \ + } + + VAR(a, 1, 1); + VAR(p, 1, 32); + VAR(p, 1, 256); + VAR(a, 2, 1); + VAR(a, 3, 1); + VAR(a, 4, 1); + VAR(a, 7, 1); + VAR(a, 8, 1); + VAR(a, 9, 1); + VAR(a, 16, 1); + VAR(a, 41, 1); + VAR(a, 105, 1); + + TestLayout(VEC1(a1_1), 8, 16, "1 16 1 4 a1_1", "LL1R"); + TestLayout(VEC1(a1_1), 64, 64, "1 64 1 4 a1_1", "L1"); + TestLayout(VEC1(p1_32), 8, 32, "1 32 1 5 p1_32", "LLLL1RRR"); + TestLayout(VEC1(p1_32), 8, 64, "1 64 1 5 p1_32", "LLLLLLLL1RRRRRRR"); + + TestLayout(VEC1(a1_1), 8, 32, "1 32 1 4 a1_1", "LLLL1RRR"); + TestLayout(VEC1(a2_1), 8, 32, "1 32 2 4 a2_1", "LLLL2RRR"); + TestLayout(VEC1(a3_1), 8, 32, "1 32 3 4 a3_1", "LLLL3RRR"); + TestLayout(VEC1(a4_1), 8, 32, "1 32 4 4 a4_1", "LLLL4RRR"); + TestLayout(VEC1(a7_1), 8, 32, "1 32 7 4 a7_1", "LLLL7RRR"); + TestLayout(VEC1(a8_1), 8, 32, "1 32 8 4 a8_1", "LLLL0RRR"); + TestLayout(VEC1(a9_1), 8, 32, "1 32 9 4 a9_1", "LLLL01RR"); + TestLayout(VEC1(a16_1), 8, 32, "1 32 16 5 a16_1", "LLLL00RR"); + TestLayout(VEC1(p1_256), 8, 32, "1 256 1 6 p1_256", + "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1RRR"); + TestLayout(VEC1(a41_1), 8, 32, "1 32 41 5 a41_1", "LLLL000001RRRRRR"); + TestLayout(VEC1(a105_1), 8, 32, "1 32 105 6 a105_1", + "LLLL00000000000001RRRRRR"); + + { + ASanStackVariableDescription t[] = {a1_1, p1_256}; + TestLayout(VEC(t), 8, 32, + "2 256 1 6 p1_256 272 1 4 a1_1", + "LLLLLLLL" "LLLLLLLL" "LLLLLLLL" "LLLLLLLL" "1M1R"); + } + + { + ASanStackVariableDescription t[] = {a1_1, a16_1, a41_1}; + TestLayout(VEC(t), 8, 32, + "3 32 1 4 a1_1 48 16 5 a16_1 80 41 5 a41_1", + "LLLL" "1M00" "MM00" "0001" "RRRR"); + } +#undef VEC1 +#undef VEC +#undef VAR +} diff --git a/unittests/Transforms/Utils/CMakeLists.txt b/unittests/Transforms/Utils/CMakeLists.txt index 0656390..60447bb 100644 --- a/unittests/Transforms/Utils/CMakeLists.txt +++ b/unittests/Transforms/Utils/CMakeLists.txt @@ -1,8 +1,11 @@ set(LLVM_LINK_COMPONENTS + Core + Support TransformUtils ) add_llvm_unittest(UtilsTests + ASanStackFrameLayoutTest.cpp Cloning.cpp IntegerDivision.cpp Local.cpp diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index e19ae5b..fb27dc1 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -7,15 +7,22 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Constant.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/Function.h" +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/InstIterator.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/Transforms/Utils/Cloning.h" #include "gtest/gtest.h" using namespace llvm; @@ -173,4 +180,230 @@ TEST_F(CloneInstruction, Attributes) { delete F2; } +TEST_F(CloneInstruction, CallingConvention) { + Type *ArgTy1[] = { Type::getInt32PtrTy(context) }; + FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false); + + Function *F1 = Function::Create(FT1, Function::ExternalLinkage); + F1->setCallingConv(CallingConv::Cold); + BasicBlock *BB = BasicBlock::Create(context, "", F1); + IRBuilder<> Builder(BB); + Builder.CreateRetVoid(); + + Function *F2 = Function::Create(FT1, Function::ExternalLinkage); + + SmallVector<ReturnInst*, 4> Returns; + ValueToValueMapTy VMap; + VMap[F1->arg_begin()] = F2->arg_begin(); + + CloneFunctionInto(F2, F1, VMap, false, Returns); + EXPECT_EQ(CallingConv::Cold, F2->getCallingConv()); + + delete F1; + delete F2; +} + +class CloneFunc : public ::testing::Test { +protected: + virtual void SetUp() { + SetupModule(); + CreateOldFunc(); + CreateNewFunc(); + SetupFinder(); + } + + virtual void TearDown() { + delete Finder; + } + + void SetupModule() { + M = new Module("", C); + } + + void CreateOldFunc() { + FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false); + OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M); + CreateOldFunctionBodyAndDI(); + } + + void CreateOldFunctionBodyAndDI() { + DIBuilder DBuilder(*M); + IRBuilder<> IBuilder(C); + + // Function DI + DIFile File = DBuilder.createFile("filename.c", "/file/dir/"); + DIArray ParamTypes = DBuilder.getOrCreateArray(ArrayRef<Value*>()); + DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes); + DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99, + "filename.c", "/file/dir", "CloneFunc", false, "", 0); + + DISubprogram Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4, + FuncType, true, true, 3, 0, false, OldFunc); + + // Function body + BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc); + IBuilder.SetInsertPoint(Entry); + DebugLoc Loc = DebugLoc::get(3, 2, Subprogram); + IBuilder.SetCurrentDebugLocation(Loc); + AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C)); + IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram)); + Value* AllocaContent = IBuilder.getInt32(1); + Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca); + IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram)); + Instruction* Terminator = IBuilder.CreateRetVoid(); + + // Create a local variable around the alloca + DIType IntType = DBuilder.createBasicType("int", 32, 0, + dwarf::DW_ATE_signed); + 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); + // Finalize the debug info + DBuilder.finalize(); + + + // Create another, empty, compile unit + DIBuilder DBuilder2(*M); + DBuilder2.createCompileUnit(dwarf::DW_LANG_C99, + "extra.c", "/file/dir", "CloneFunc", false, "", 0); + DBuilder2.finalize(); + } + + void CreateNewFunc() { + ValueToValueMapTy VMap; + NewFunc = CloneFunction(OldFunc, VMap, true, NULL); + M->getFunctionList().push_back(NewFunc); + } + + void SetupFinder() { + Finder = new DebugInfoFinder(); + Finder->processModule(*M); + } + + LLVMContext C; + Function* OldFunc; + Function* NewFunc; + Module* M; + DebugInfoFinder* Finder; +}; + +// Test that a new, distinct function was created. +TEST_F(CloneFunc, NewFunctionCreated) { + EXPECT_NE(OldFunc, NewFunc); +} + +// Test that a new subprogram entry was added and is pointing to the new +// function, while the original subprogram still points to the old one. +TEST_F(CloneFunc, Subprogram) { + unsigned SubprogramCount = Finder->subprogram_count(); + EXPECT_EQ(2U, SubprogramCount); + + auto Iter = Finder->subprograms().begin(); + DISubprogram Sub1(*Iter); + EXPECT_TRUE(Sub1.Verify()); + Iter++; + DISubprogram Sub2(*Iter); + EXPECT_TRUE(Sub2.Verify()); + + EXPECT_TRUE((Sub1.getFunction() == OldFunc && Sub2.getFunction() == NewFunc) + || (Sub1.getFunction() == NewFunc && Sub2.getFunction() == OldFunc)); +} + +// Test that the new subprogram entry was not added to the CU which doesn't +// contain the old subprogram entry. +TEST_F(CloneFunc, SubprogramInRightCU) { + EXPECT_EQ(2U, Finder->compile_unit_count()); + + auto Iter = Finder->compile_units().begin(); + DICompileUnit CU1(*Iter); + EXPECT_TRUE(CU1.Verify()); + Iter++; + DICompileUnit CU2(*Iter); + EXPECT_TRUE(CU2.Verify()); + EXPECT_TRUE(CU1.getSubprograms().getNumElements() == 0 + || CU2.getSubprograms().getNumElements() == 0); +} + +// Test that instructions in the old function still belong to it in the +// metadata, while instruction in the new function belong to the new one. +TEST_F(CloneFunc, InstructionOwnership) { + inst_iterator OldIter = inst_begin(OldFunc); + inst_iterator OldEnd = inst_end(OldFunc); + inst_iterator NewIter = inst_begin(NewFunc); + inst_iterator NewEnd = inst_end(NewFunc); + while (OldIter != OldEnd && NewIter != NewEnd) { + Instruction& OldI = *OldIter; + Instruction& NewI = *NewIter; + EXPECT_NE(&OldI, &NewI); + + EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata()); + if (OldI.hasMetadata()) { + const DebugLoc& OldDL = OldI.getDebugLoc(); + const DebugLoc& NewDL = NewI.getDebugLoc(); + + // Verify that the debug location data is the same + EXPECT_EQ(OldDL.getLine(), NewDL.getLine()); + EXPECT_EQ(OldDL.getCol(), NewDL.getCol()); + + // But that they belong to different functions + DISubprogram OldSubprogram(OldDL.getScope(C)); + DISubprogram NewSubprogram(NewDL.getScope(C)); + EXPECT_TRUE(OldSubprogram.Verify()); + EXPECT_TRUE(NewSubprogram.Verify()); + EXPECT_EQ(OldFunc, OldSubprogram.getFunction()); + EXPECT_EQ(NewFunc, NewSubprogram.getFunction()); + } + + ++OldIter; + ++NewIter; + } + EXPECT_EQ(OldEnd, OldIter); + EXPECT_EQ(NewEnd, NewIter); +} + +// Test that the arguments for debug intrinsics in the new function were +// properly cloned +TEST_F(CloneFunc, DebugIntrinsics) { + inst_iterator OldIter = inst_begin(OldFunc); + inst_iterator OldEnd = inst_end(OldFunc); + inst_iterator NewIter = inst_begin(NewFunc); + inst_iterator NewEnd = inst_end(NewFunc); + while (OldIter != OldEnd && NewIter != NewEnd) { + Instruction& OldI = *OldIter; + Instruction& NewI = *NewIter; + if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) { + DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI); + EXPECT_TRUE(NewIntrin); + + // Old address must belong to the old function + EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())-> + getParent()->getParent()); + // New address must belong to the new function + EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())-> + getParent()->getParent()); + + // Old variable must belong to the old function + EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable()) + .getContext()).getFunction()); + // New variable must belong to the New function + EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable()) + .getContext()).getFunction()); + } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) { + DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI); + EXPECT_TRUE(NewIntrin); + + // Old variable must belong to the old function + EXPECT_EQ(OldFunc, DISubprogram(DIVariable(OldIntrin->getVariable()) + .getContext()).getFunction()); + // New variable must belong to the New function + EXPECT_EQ(NewFunc, DISubprogram(DIVariable(NewIntrin->getVariable()) + .getContext()).getFunction()); + } + + ++OldIter; + ++NewIter; + } +} + } diff --git a/unittests/Transforms/Utils/IntegerDivision.cpp b/unittests/Transforms/Utils/IntegerDivision.cpp index 44c2328..f7318a2 100644 --- a/unittests/Transforms/Utils/IntegerDivision.cpp +++ b/unittests/Transforms/Utils/IntegerDivision.cpp @@ -19,6 +19,7 @@ using namespace llvm; namespace { + TEST(IntegerDivision, SDiv) { LLVMContext &C(getGlobalContext()); Module M("test division", C); @@ -139,4 +140,125 @@ TEST(IntegerDivision, URem) { EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub); } + +TEST(IntegerDivision, SDiv64) { + LLVMContext &C(getGlobalContext()); + Module M("test division", C); + IRBuilder<> Builder(C); + + SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty()); + Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(), + ArgTys, false), + GlobalValue::ExternalLinkage, "F", &M); + assert(F->getArgumentList().size() == 2); + + BasicBlock *BB = BasicBlock::Create(C, "", F); + Builder.SetInsertPoint(BB); + + Function::arg_iterator AI = F->arg_begin(); + Value *A = AI++; + Value *B = AI++; + + Value *Div = Builder.CreateSDiv(A, B); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv); + + Value *Ret = Builder.CreateRet(Div); + + expandDivision(cast<BinaryOperator>(Div)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr); + + Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0)); + EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub); +} + +TEST(IntegerDivision, UDiv64) { + LLVMContext &C(getGlobalContext()); + Module M("test division", C); + IRBuilder<> Builder(C); + + SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty()); + Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(), + ArgTys, false), + GlobalValue::ExternalLinkage, "F", &M); + assert(F->getArgumentList().size() == 2); + + BasicBlock *BB = BasicBlock::Create(C, "", F); + Builder.SetInsertPoint(BB); + + Function::arg_iterator AI = F->arg_begin(); + Value *A = AI++; + Value *B = AI++; + + Value *Div = Builder.CreateUDiv(A, B); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv); + + Value *Ret = Builder.CreateRet(Div); + + expandDivision(cast<BinaryOperator>(Div)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp); + + Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0)); + EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI); +} + +TEST(IntegerDivision, SRem64) { + LLVMContext &C(getGlobalContext()); + Module M("test remainder", C); + IRBuilder<> Builder(C); + + SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty()); + Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(), + ArgTys, false), + GlobalValue::ExternalLinkage, "F", &M); + assert(F->getArgumentList().size() == 2); + + BasicBlock *BB = BasicBlock::Create(C, "", F); + Builder.SetInsertPoint(BB); + + Function::arg_iterator AI = F->arg_begin(); + Value *A = AI++; + Value *B = AI++; + + Value *Rem = Builder.CreateSRem(A, B); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem); + + Value *Ret = Builder.CreateRet(Rem); + + expandRemainder(cast<BinaryOperator>(Rem)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr); + + Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0)); + EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub); +} + +TEST(IntegerDivision, URem64) { + LLVMContext &C(getGlobalContext()); + Module M("test remainder", C); + IRBuilder<> Builder(C); + + SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty()); + Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(), + ArgTys, false), + GlobalValue::ExternalLinkage, "F", &M); + assert(F->getArgumentList().size() == 2); + + BasicBlock *BB = BasicBlock::Create(C, "", F); + Builder.SetInsertPoint(BB); + + Function::arg_iterator AI = F->arg_begin(); + Value *A = AI++; + Value *B = AI++; + + Value *Rem = Builder.CreateURem(A, B); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem); + + Value *Ret = Builder.CreateRet(Rem); + + expandRemainder(cast<BinaryOperator>(Rem)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp); + + Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0)); + EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub); +} + } diff --git a/unittests/Transforms/Utils/SpecialCaseList.cpp b/unittests/Transforms/Utils/SpecialCaseList.cpp index 07ac908..748834f 100644 --- a/unittests/Transforms/Utils/SpecialCaseList.cpp +++ b/unittests/Transforms/Utils/SpecialCaseList.cpp @@ -40,7 +40,7 @@ protected: } SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) { - OwningPtr<MemoryBuffer> MB(MemoryBuffer::getMemBuffer(List)); + std::unique_ptr<MemoryBuffer> MB(MemoryBuffer::getMemBuffer(List)); return SpecialCaseList::create(MB.get(), Error); } @@ -60,9 +60,10 @@ TEST_F(SpecialCaseListTest, ModuleIsIn) { Function *F = makeFunction("foo", M); GlobalVariable *GV = makeGlobal("bar", "t", M); - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("# This is a comment.\n" - "\n" - "src:hello\n")); + std::unique_ptr<SpecialCaseList> SCL( + makeSpecialCaseList("# This is a comment.\n" + "\n" + "src:hello\n")); EXPECT_TRUE(SCL->isIn(M)); EXPECT_TRUE(SCL->isIn(*F)); EXPECT_TRUE(SCL->isIn(*GV)); @@ -83,7 +84,7 @@ TEST_F(SpecialCaseListTest, FunctionIsIn) { Function *Foo = makeFunction("foo", M); Function *Bar = makeFunction("bar", M); - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n")); + std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n")); EXPECT_TRUE(SCL->isIn(*Foo)); EXPECT_FALSE(SCL->isIn(*Bar)); @@ -107,7 +108,7 @@ TEST_F(SpecialCaseListTest, GlobalIsIn) { GlobalVariable *Foo = makeGlobal("foo", "t1", M); GlobalVariable *Bar = makeGlobal("bar", "t2", M); - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("global:foo\n")); + std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("global:foo\n")); EXPECT_TRUE(SCL->isIn(*Foo)); EXPECT_FALSE(SCL->isIn(*Bar)); EXPECT_FALSE(SCL->isIn(*Foo, "init")); @@ -157,7 +158,7 @@ TEST_F(SpecialCaseListTest, AliasIsIn) { GlobalAlias *FooAlias = makeAlias("fooalias", Foo); GlobalAlias *BarAlias = makeAlias("baralias", Bar); - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n")); + std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("fun:foo\n")); EXPECT_FALSE(SCL->isIn(*FooAlias)); EXPECT_FALSE(SCL->isIn(*BarAlias)); @@ -193,9 +194,9 @@ TEST_F(SpecialCaseListTest, Substring) { GlobalAlias *GA1 = makeAlias("buffoonery", F); GlobalAlias *GA2 = makeAlias("foobar", GV); - OwningPtr<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->isIn(M)); EXPECT_FALSE(SCL->isIn(*F)); EXPECT_FALSE(SCL->isIn(*GV)); @@ -224,7 +225,7 @@ TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) { } TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { - OwningPtr<SpecialCaseList> SCL(makeSpecialCaseList("")); + std::unique_ptr<SpecialCaseList> SCL(makeSpecialCaseList("")); Module M("foo", Ctx); EXPECT_FALSE(SCL->isIn(M)); } |