From 36b56886974eae4f9c5ebc96befd3e7bfe5de338 Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Wed, 23 Apr 2014 16:57:46 -0700 Subject: Update to LLVM 3.5a. Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617 --- unittests/ADT/APIntTest.cpp | 81 ++++ unittests/ADT/APSIntTest.cpp | 44 ++ unittests/ADT/ArrayRefTest.cpp | 33 ++ unittests/ADT/BitVectorTest.cpp | 6 + unittests/ADT/CMakeLists.txt | 15 +- unittests/ADT/DenseMapTest.cpp | 30 +- unittests/ADT/HashingTest.cpp | 2 +- unittests/ADT/MakeUniqueTest.cpp | 76 +++ unittests/ADT/OptionalTest.cpp | 2 - unittests/ADT/OwningPtrTest.cpp | 273 +++++++++++ unittests/ADT/PointerIntPairTest.cpp | 76 +++ unittests/ADT/SmallPtrSetTest.cpp | 87 +++- unittests/ADT/StringMapTest.cpp | 32 +- unittests/ADT/StringRefTest.cpp | 17 +- unittests/ADT/TinyPtrVectorTest.cpp | 118 ++--- unittests/ADT/TripleTest.cpp | 93 +++- unittests/ADT/ilistTest.cpp | 6 +- unittests/ADT/polymorphic_ptr_test.cpp | 129 ------ unittests/Analysis/CFGTest.cpp | 80 ++-- unittests/Analysis/CMakeLists.txt | 2 + unittests/Bitcode/BitReaderTest.cpp | 9 +- unittests/Bitcode/CMakeLists.txt | 2 + unittests/CMakeLists.txt | 7 + unittests/CodeGen/CMakeLists.txt | 5 +- unittests/CodeGen/DIEHashTest.cpp | 147 +++++- unittests/DebugInfo/CMakeLists.txt | 4 +- unittests/ExecutionEngine/CMakeLists.txt | 5 +- unittests/ExecutionEngine/ExecutionEngineTest.cpp | 3 +- unittests/ExecutionEngine/JIT/CMakeLists.txt | 14 +- .../ExecutionEngine/JIT/JITEventListenerTest.cpp | 7 +- .../JIT/JITEventListenerTestCommon.h | 8 +- .../ExecutionEngine/JIT/JITMemoryManagerTest.cpp | 33 +- unittests/ExecutionEngine/JIT/JITTest.cpp | 44 +- unittests/ExecutionEngine/JIT/Makefile | 3 + unittests/ExecutionEngine/JIT/MultiJITTest.cpp | 25 +- unittests/ExecutionEngine/MCJIT/CMakeLists.txt | 13 +- unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp | 239 +++++++++- .../MCJIT/MCJITMemoryManagerTest.cpp | 9 +- .../MCJIT/MCJITMultipleModuleTest.cpp | 86 ++-- .../ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp | 23 +- unittests/ExecutionEngine/MCJIT/MCJITTest.cpp | 10 +- .../ExecutionEngine/MCJIT/MCJITTestAPICommon.h | 10 +- unittests/ExecutionEngine/MCJIT/MCJITTestBase.h | 43 +- unittests/ExecutionEngine/MCJIT/Makefile | 2 +- unittests/IR/CMakeLists.txt | 17 +- unittests/IR/ConstantRangeTest.cpp | 512 +++++++++++++++++++++ unittests/IR/ConstantsTest.cpp | 2 +- unittests/IR/DominatorTreeTest.cpp | 40 +- unittests/IR/IRBuilderTest.cpp | 69 ++- unittests/IR/InstructionsTest.cpp | 79 +++- unittests/IR/LeakDetectorTest.cpp | 31 ++ unittests/IR/LegacyPassManagerTest.cpp | 30 +- unittests/IR/MetadataTest.cpp | 2 +- unittests/IR/PassManagerTest.cpp | 275 +++++++++-- unittests/IR/PatternMatch.cpp | 373 ++++++++------- unittests/IR/ValueHandleTest.cpp | 407 ++++++++++++++++ unittests/IR/ValueMapTest.cpp | 10 +- unittests/IR/ValueTest.cpp | 4 +- unittests/IR/VerifierTest.cpp | 18 +- unittests/LineEditor/CMakeLists.txt | 7 + unittests/LineEditor/LineEditor.cpp | 82 ++++ unittests/LineEditor/Makefile | 15 + unittests/Linker/CMakeLists.txt | 12 + unittests/Linker/LinkModulesTest.cpp | 165 +++++++ unittests/Linker/Makefile | 15 + unittests/Makefile | 5 +- unittests/Makefile.unittest | 21 +- unittests/Object/CMakeLists.txt | 3 +- unittests/Object/YAMLTest.cpp | 2 +- unittests/Option/CMakeLists.txt | 2 - unittests/Option/OptionParsingTest.cpp | 24 +- unittests/Support/AllocatorTest.cpp | 12 +- unittests/Support/BlockFrequencyTest.cpp | 8 + unittests/Support/CMakeLists.txt | 6 +- unittests/Support/Casting.cpp | 14 +- unittests/Support/CommandLineTest.cpp | 59 ++- unittests/Support/CompressionTest.cpp | 5 +- unittests/Support/ConstantRangeTest.cpp | 512 --------------------- unittests/Support/ErrorOrTest.cpp | 17 +- unittests/Support/FileOutputBufferTest.cpp | 9 +- unittests/Support/LEB128Test.cpp | 311 +++++++++++++ unittests/Support/LeakDetectorTest.cpp | 31 -- unittests/Support/LineIteratorTest.cpp | 115 +++++ unittests/Support/LockFileManagerTest.cpp | 85 +++- unittests/Support/MemoryBufferTest.cpp | 4 +- unittests/Support/Path.cpp | 153 ++++-- unittests/Support/ProcessTest.cpp | 9 +- unittests/Support/ProgramTest.cpp | 1 - unittests/Support/RegexTest.cpp | 30 +- unittests/Support/SwapByteOrderTest.cpp | 74 +-- unittests/Support/TimeValueTest.cpp | 5 +- unittests/Support/ValueHandleTest.cpp | 408 ---------------- unittests/Support/YAMLIOTest.cpp | 119 ++--- unittests/Transforms/DebugIR/CMakeLists.txt | 2 + unittests/Transforms/DebugIR/DebugIR.cpp | 22 +- .../Transforms/Utils/ASanStackFrameLayoutTest.cpp | 102 ++++ unittests/Transforms/Utils/CMakeLists.txt | 3 + unittests/Transforms/Utils/Cloning.cpp | 235 +++++++++- unittests/Transforms/Utils/IntegerDivision.cpp | 122 +++++ unittests/Transforms/Utils/SpecialCaseList.cpp | 23 +- 100 files changed, 4785 insertions(+), 1886 deletions(-) create mode 100644 unittests/ADT/APSIntTest.cpp create mode 100644 unittests/ADT/ArrayRefTest.cpp create mode 100644 unittests/ADT/MakeUniqueTest.cpp create mode 100644 unittests/ADT/OwningPtrTest.cpp create mode 100644 unittests/ADT/PointerIntPairTest.cpp delete mode 100644 unittests/ADT/polymorphic_ptr_test.cpp create mode 100644 unittests/IR/ConstantRangeTest.cpp create mode 100644 unittests/IR/LeakDetectorTest.cpp create mode 100644 unittests/IR/ValueHandleTest.cpp create mode 100644 unittests/LineEditor/CMakeLists.txt create mode 100644 unittests/LineEditor/LineEditor.cpp create mode 100644 unittests/LineEditor/Makefile create mode 100644 unittests/Linker/CMakeLists.txt create mode 100644 unittests/Linker/LinkModulesTest.cpp create mode 100644 unittests/Linker/Makefile delete mode 100644 unittests/Support/ConstantRangeTest.cpp create mode 100644 unittests/Support/LEB128Test.cpp delete mode 100644 unittests/Support/LeakDetectorTest.cpp create mode 100644 unittests/Support/LineIteratorTest.cpp delete mode 100644 unittests/Support/ValueHandleTest.cpp create mode 100644 unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp (limited to 'unittests') 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(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(I4, 4)); + EXPECT_EQ(A4.nearestLogBase2(), A4.ceilLogBase2()); + + // Test round down. + integerPart I5[4] = {0x0, 0xF, 0x10, 0x0}; + APInt A5(integerPartWidth*4, ArrayRef(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(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 Array1 = makeArrayRef(Words1, 4); + static const uint16_t Words2[] = { 11, 4003, 67, 64000, 13 }; + ArrayRef Array2 = makeArrayRef(Words2, 5); + ArrayRef Array1c = Array1.copy(Alloc); + ArrayRef 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 : true_type {}; +template <> struct is_hashable_data : 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 +using namespace llvm; + +namespace { + +TEST(MakeUniqueTest, SingleObject) { + auto p0 = make_unique(); + EXPECT_TRUE((bool)p0); + EXPECT_EQ(0, *p0); + + auto p1 = make_unique(5); + EXPECT_TRUE((bool)p1); + EXPECT_EQ(5, *p1); + + auto p2 = make_unique>(0, 1); + EXPECT_TRUE((bool)p2); + EXPECT_EQ(std::make_tuple(0, 1), *p2); + + auto p3 = make_unique>(0, 1, 2); + EXPECT_TRUE((bool)p3); + EXPECT_EQ(std::make_tuple(0, 1, 2), *p3); + + auto p4 = make_unique>(0, 1, 2, 3); + EXPECT_TRUE((bool)p4); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3), *p4); + + auto p5 = make_unique>(0, 1, 2, 3, 4); + EXPECT_TRUE((bool)p5); + EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4), *p5); + + auto p6 = + make_unique>(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>( + 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>( + 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>( + 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>( + 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(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 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 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 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 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 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 A(new TrackDestructor(3)); + OwningPtr 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 A(new TrackDestructor(3)); + OwningPtr 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 A(new TrackDestructor(3)); + OwningPtr 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 A(new TrackDestructor(3)); + OwningPtr 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 A(new TrackDestructor(3)); + OwningPtr 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 A(new TrackDestructor(3)); + OwningPtr 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 A(new TrackDestructor(3)); + std::unique_ptr 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 A(new TrackDestructor(3)); + std::unique_ptr 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 +using namespace llvm; + +namespace { + +// Test fixture +class PointerIntPairTest : public testing::Test { +}; + +TEST_F(PointerIntPairTest, GetSet) { + PointerIntPair 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 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(Num.Value << NumLowBitsAvailable); + } + static inline Fixnum31 getFromVoidPointer(void *P) { + // In real code this would assert that the value is in range. + return { reinterpret_cast(P) >> NumLowBitsAvailable }; + } + enum { NumLowBitsAvailable = std::numeric_limits::digits - 31 }; + }; + + PointerIntPair 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::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 s1; + s1.insert(&buf[0]); + s1.insert(&buf[1]); + + SmallPtrSet 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 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 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 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 { -public: - template - static void Initialize(StringMapEntry &T, InitTy InitVal) { - T.second = InitVal; - } -}; - -} // end llvm namespace - -namespace { - // Test StringMapEntry::Create() method. TEST_F(StringMapTest, StringMapEntryTest) { StringMap::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 t; + t.GetOrCreateValue("Test", StringMapTestStruct(123)); + StringMap::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 class TinyPtrVectorTest : public testing::Test { protected: typedef typename VectorT::value_type PtrT; - typedef typename remove_pointer::type ValueT; + typedef typename std::remove_pointer::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 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 -T dummy_copy(const T &arg) { return arg; } - -TEST(polymorphic_ptr_test, Basic) { - polymorphic_ptr null; - EXPECT_FALSE((bool)null); - EXPECT_TRUE(!null); - EXPECT_EQ((S*)0, null.get()); - - S *s = new S(42); - polymorphic_ptr 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 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 p3 = dummy_copy(polymorphic_ptr(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 null_copy = dummy_copy(polymorphic_ptr(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 a(new DerivedA()); - polymorphic_ptr b(new DerivedB()); - - EXPECT_EQ("DerivedA", a->name()); - EXPECT_EQ("DerivedB", b->name()); - - polymorphic_ptr 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 >(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(); - AU.addRequired(); + AU.addRequired(); } bool runOnFunction(Function &F) { @@ -93,7 +93,8 @@ protected: return false; LoopInfo *LI = &getAnalysis(); - DominatorTree *DT = &getAnalysis(); + DominatorTree *DT = + &getAnalysis().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 M; + + std::unique_ptr 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 &Buffer) { - OwningPtr Mod(makeLLVMModule()); + std::unique_ptr 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 m(getLazyBitcodeModule(Buffer, getGlobalContext(), &errMsg)); + ErrorOr ModuleOrErr = + getLazyBitcodeModule(Buffer, getGlobalContext()); + std::unique_ptr 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 Engine; + const std::unique_ptr 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 EE; + const std::unique_ptr 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::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 class JITEventListenerTestBase : public testing::Test { protected: - llvm::OwningPtr MockWrapper; - llvm::OwningPtr Listener; + std::unique_ptr MockWrapper; + std::unique_ptr 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 MemMgr( + std::unique_ptr MemMgr( JITMemoryManager::CreateDefaultMemManager()); uintptr_t size; std::string Error; // Allocate the functions. - OwningPtr F1(makeFakeFunction()); + std::unique_ptr 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 F2(makeFakeFunction()); + std::unique_ptr 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 F3(makeFakeFunction()); + std::unique_ptr 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 MemMgr( + std::unique_ptr MemMgr( JITMemoryManager::CreateDefaultMemManager()); uintptr_t size; std::string Error; @@ -81,7 +80,7 @@ TEST(JITMemoryManagerTest, TestCodeAllocation) { smallFuncSize * 2); // Allocate big functions - OwningPtr F1(makeFakeFunction()); + std::unique_ptr 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 F2(makeFakeFunction()); + std::unique_ptr 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 F3(makeFakeFunction()); + std::unique_ptr 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 F4(makeFakeFunction()); + std::unique_ptr 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 F5(makeFakeFunction()); + std::unique_ptr 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 F6(makeFakeFunction()); + std::unique_ptr 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 MemMgr( + std::unique_ptr 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 MemMgr( + std::unique_ptr 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 MemMgr( + std::unique_ptr 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 MemMgr( + std::unique_ptr 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 MemMgr( + std::unique_ptr 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 params; @@ -76,7 +76,8 @@ std::string DumpFunction(const Function *F) { } class RecordingJITMemoryManager : public JITMemoryManager { - const OwningPtr Base; + const std::unique_ptr 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 TheJIT; + std::unique_ptr 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 JIT(EngineBuilder(M) - .setEngineKind(EngineKind::JIT) - .setErrorStr(&Error) - .setJITMemoryManager(MemMgr) - // The next line enables the fix: - .setAllocateGVsWithCode(false) - .create()); + std::unique_ptr 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::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 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 TheJIT(getJITFromBitcode(Context, Bitcode, M)); + std::unique_ptr 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 TheJIT(getJITFromBitcode(Context, Bitcode, M)); + std::unique_ptr 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 EE1(EngineBuilder(M1).create()); + std::unique_ptr EE1(EngineBuilder(M1).create()); EE1->DisableLazyCompilation(true); - OwningPtr EE2(EngineBuilder(M2).create()); + std::unique_ptr 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 EE1(EngineBuilder(M1).create()); + std::unique_ptr EE1(EngineBuilder(M1).create()); EE1->DisableLazyCompilation(false); - OwningPtr EE2(EngineBuilder(M2).create()); + std::unique_ptr 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 EE1(EngineBuilder(M1).create()); - OwningPtr EE2(EngineBuilder(M2).create()); + std::unique_ptr EE1(EngineBuilder(M1).create()); + std::unique_ptr 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 : 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(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 MemMgr(new SectionMemoryManager()); + std::unique_ptr 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 MemMgr(new SectionMemoryManager()); + std::unique_ptr 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 MemMgr(new SectionMemoryManager()); + std::unique_ptr MemMgr(new SectionMemoryManager()); uint8_t* code[10000]; uint8_t* data[10000]; @@ -118,7 +117,7 @@ TEST(MCJITMemoryManagerTest, ManyAllocations) { } TEST(MCJITMemoryManagerTest, ManyVariedAllocations) { - OwningPtr MemMgr(new SectionMemoryManager()); + std::unique_ptr 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 A, B; + std::unique_ptr 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 A, B; + std::unique_ptr 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 A, B; + std::unique_ptr 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 A, B; + std::unique_ptr 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 A, B; + std::unique_ptr A, B; Function *FA1, *FA2, *FB; createTwoModuleExternCase(A, FA1, B, FB); FA2 = insertSimpleCallFunction(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 A, B; + std::unique_ptr 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(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 A, B, C; + std::unique_ptr 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 A, B, C; + std::unique_ptr 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 A, B, C; + std::unique_ptr 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 A, B, C; + std::unique_ptr 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 A, B; + std::unique_ptr 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 A, B; + std::unique_ptr 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 A, B; + std::unique_ptr 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 Cache(new TestObjectCache); + std::unique_ptr 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 Cache(new TestObjectCache); + std::unique_ptr 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 Cache(new TestObjectCache); + std::unique_ptr 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 HasSubArchs; SmallVector SupportedSubArchs; // We need to own the memory SmallVector UnsupportedOSs; + SmallVector 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 &A, - Function *&FA, - OwningPtr &B, - Function *&FB1, - Function *&FB2) { + void createCrossModuleRecursiveCase(std::unique_ptr &A, Function *&FA, + std::unique_ptr &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 &A, - Function *&FA, - OwningPtr &B, - Function *&FB, - OwningPtr &C, - Function *&FC) { + void + createThreeModuleChainedCallsCase(std::unique_ptr &A, Function *&FA, + std::unique_ptr &B, Function *&FB, + std::unique_ptr &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 &A, Function *&FA, - OwningPtr &B, Function *&FB) { + void createTwoModuleCase(std::unique_ptr &A, Function *&FA, + std::unique_ptr &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 &A, Function *&FA, - OwningPtr &B, Function *&FB) { + void createTwoModuleExternCase(std::unique_ptr &A, Function *&FA, + std::unique_ptr &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 &A, - Function *&FA, - OwningPtr &B, - Function *&FB, - OwningPtr &C, - Function *&FC) { + void createThreeModuleCase(std::unique_ptr &A, Function *&FA, + std::unique_ptr &B, Function *&FB, + std::unique_ptr &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 MAttrs; - OwningPtr TheJIT; + std::unique_ptr TheJIT; RTDyldMemoryManager *MM; - OwningPtr M; + std::unique_ptr 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/IR/ConstantRangeTest.cpp b/unittests/IR/ConstantRangeTest.cpp new file mode 100644 index 0000000..cdf7378 --- /dev/null +++ b/unittests/IR/ConstantRangeTest.cpp @@ -0,0 +1,512 @@ +//===- ConstantRangeTest.cpp - ConstantRange tests ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/ConstantRange.h" +#include "llvm/IR/Instructions.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +class ConstantRangeTest : public ::testing::Test { +protected: + static ConstantRange Full; + static ConstantRange Empty; + static ConstantRange One; + static ConstantRange Some; + static ConstantRange Wrap; +}; + +ConstantRange ConstantRangeTest::Full(16); +ConstantRange ConstantRangeTest::Empty(16, false); +ConstantRange ConstantRangeTest::One(APInt(16, 0xa)); +ConstantRange ConstantRangeTest::Some(APInt(16, 0xa), APInt(16, 0xaaa)); +ConstantRange ConstantRangeTest::Wrap(APInt(16, 0xaaa), APInt(16, 0xa)); + +TEST_F(ConstantRangeTest, Basics) { + EXPECT_TRUE(Full.isFullSet()); + EXPECT_FALSE(Full.isEmptySet()); + EXPECT_TRUE(Full.inverse().isEmptySet()); + EXPECT_FALSE(Full.isWrappedSet()); + EXPECT_TRUE(Full.contains(APInt(16, 0x0))); + EXPECT_TRUE(Full.contains(APInt(16, 0x9))); + EXPECT_TRUE(Full.contains(APInt(16, 0xa))); + EXPECT_TRUE(Full.contains(APInt(16, 0xaa9))); + EXPECT_TRUE(Full.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(Empty.isFullSet()); + EXPECT_TRUE(Empty.isEmptySet()); + EXPECT_TRUE(Empty.inverse().isFullSet()); + EXPECT_FALSE(Empty.isWrappedSet()); + EXPECT_FALSE(Empty.contains(APInt(16, 0x0))); + EXPECT_FALSE(Empty.contains(APInt(16, 0x9))); + EXPECT_FALSE(Empty.contains(APInt(16, 0xa))); + EXPECT_FALSE(Empty.contains(APInt(16, 0xaa9))); + EXPECT_FALSE(Empty.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(One.isFullSet()); + EXPECT_FALSE(One.isEmptySet()); + EXPECT_FALSE(One.isWrappedSet()); + EXPECT_FALSE(One.contains(APInt(16, 0x0))); + EXPECT_FALSE(One.contains(APInt(16, 0x9))); + EXPECT_TRUE(One.contains(APInt(16, 0xa))); + EXPECT_FALSE(One.contains(APInt(16, 0xaa9))); + EXPECT_FALSE(One.contains(APInt(16, 0xaaa))); + EXPECT_FALSE(One.inverse().contains(APInt(16, 0xa))); + + EXPECT_FALSE(Some.isFullSet()); + EXPECT_FALSE(Some.isEmptySet()); + EXPECT_FALSE(Some.isWrappedSet()); + EXPECT_FALSE(Some.contains(APInt(16, 0x0))); + EXPECT_FALSE(Some.contains(APInt(16, 0x9))); + EXPECT_TRUE(Some.contains(APInt(16, 0xa))); + EXPECT_TRUE(Some.contains(APInt(16, 0xaa9))); + EXPECT_FALSE(Some.contains(APInt(16, 0xaaa))); + + EXPECT_FALSE(Wrap.isFullSet()); + EXPECT_FALSE(Wrap.isEmptySet()); + EXPECT_TRUE(Wrap.isWrappedSet()); + EXPECT_TRUE(Wrap.contains(APInt(16, 0x0))); + EXPECT_TRUE(Wrap.contains(APInt(16, 0x9))); + EXPECT_FALSE(Wrap.contains(APInt(16, 0xa))); + EXPECT_FALSE(Wrap.contains(APInt(16, 0xaa9))); + EXPECT_TRUE(Wrap.contains(APInt(16, 0xaaa))); +} + +TEST_F(ConstantRangeTest, Equality) { + EXPECT_EQ(Full, Full); + EXPECT_EQ(Empty, Empty); + EXPECT_EQ(One, One); + EXPECT_EQ(Some, Some); + EXPECT_EQ(Wrap, Wrap); + EXPECT_NE(Full, Empty); + EXPECT_NE(Full, One); + EXPECT_NE(Full, Some); + EXPECT_NE(Full, Wrap); + EXPECT_NE(Empty, One); + EXPECT_NE(Empty, Some); + EXPECT_NE(Empty, Wrap); + EXPECT_NE(One, Some); + EXPECT_NE(One, Wrap); + EXPECT_NE(Some, Wrap); +} + +TEST_F(ConstantRangeTest, SingleElement) { + EXPECT_EQ(Full.getSingleElement(), static_cast(NULL)); + EXPECT_EQ(Empty.getSingleElement(), static_cast(NULL)); + EXPECT_EQ(*One.getSingleElement(), APInt(16, 0xa)); + EXPECT_EQ(Some.getSingleElement(), static_cast(NULL)); + EXPECT_EQ(Wrap.getSingleElement(), static_cast(NULL)); + + EXPECT_FALSE(Full.isSingleElement()); + EXPECT_FALSE(Empty.isSingleElement()); + EXPECT_TRUE(One.isSingleElement()); + EXPECT_FALSE(Some.isSingleElement()); + EXPECT_FALSE(Wrap.isSingleElement()); +} + +TEST_F(ConstantRangeTest, GetSetSize) { + EXPECT_EQ(Full.getSetSize(), APInt(17, 65536)); + EXPECT_EQ(Empty.getSetSize(), APInt(17, 0)); + EXPECT_EQ(One.getSetSize(), APInt(17, 1)); + EXPECT_EQ(Some.getSetSize(), APInt(17, 0xaa0)); + + ConstantRange Wrap(APInt(4, 7), APInt(4, 3)); + ConstantRange Wrap2(APInt(4, 8), APInt(4, 7)); + EXPECT_EQ(Wrap.getSetSize(), APInt(5, 12)); + EXPECT_EQ(Wrap2.getSetSize(), APInt(5, 15)); +} + +TEST_F(ConstantRangeTest, GetMinsAndMaxes) { + EXPECT_EQ(Full.getUnsignedMax(), APInt(16, UINT16_MAX)); + EXPECT_EQ(One.getUnsignedMax(), APInt(16, 0xa)); + EXPECT_EQ(Some.getUnsignedMax(), APInt(16, 0xaa9)); + EXPECT_EQ(Wrap.getUnsignedMax(), APInt(16, UINT16_MAX)); + + EXPECT_EQ(Full.getUnsignedMin(), APInt(16, 0)); + EXPECT_EQ(One.getUnsignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Some.getUnsignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Wrap.getUnsignedMin(), APInt(16, 0)); + + EXPECT_EQ(Full.getSignedMax(), APInt(16, INT16_MAX)); + EXPECT_EQ(One.getSignedMax(), APInt(16, 0xa)); + EXPECT_EQ(Some.getSignedMax(), APInt(16, 0xaa9)); + EXPECT_EQ(Wrap.getSignedMax(), APInt(16, INT16_MAX)); + + EXPECT_EQ(Full.getSignedMin(), APInt(16, (uint64_t)INT16_MIN)); + EXPECT_EQ(One.getSignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Some.getSignedMin(), APInt(16, 0xa)); + EXPECT_EQ(Wrap.getSignedMin(), APInt(16, (uint64_t)INT16_MIN)); + + // Found by Klee + EXPECT_EQ(ConstantRange(APInt(4, 7), APInt(4, 0)).getSignedMax(), + APInt(4, 7)); +} + +TEST_F(ConstantRangeTest, SignWrapped) { + EXPECT_TRUE(Full.isSignWrappedSet()); + EXPECT_FALSE(Empty.isSignWrappedSet()); + EXPECT_FALSE(One.isSignWrappedSet()); + EXPECT_FALSE(Some.isSignWrappedSet()); + EXPECT_TRUE(Wrap.isSignWrappedSet()); + + EXPECT_FALSE(ConstantRange(APInt(8, 127), APInt(8, 128)).isSignWrappedSet()); + EXPECT_TRUE(ConstantRange(APInt(8, 127), APInt(8, 129)).isSignWrappedSet()); + EXPECT_FALSE(ConstantRange(APInt(8, 128), APInt(8, 129)).isSignWrappedSet()); + EXPECT_TRUE(ConstantRange(APInt(8, 10), APInt(8, 9)).isSignWrappedSet()); + EXPECT_TRUE(ConstantRange(APInt(8, 10), APInt(8, 250)).isSignWrappedSet()); + EXPECT_FALSE(ConstantRange(APInt(8, 250), APInt(8, 10)).isSignWrappedSet()); + EXPECT_FALSE(ConstantRange(APInt(8, 250), APInt(8, 251)).isSignWrappedSet()); +} + +TEST_F(ConstantRangeTest, Trunc) { + ConstantRange TFull = Full.truncate(10); + ConstantRange TEmpty = Empty.truncate(10); + ConstantRange TOne = One.truncate(10); + ConstantRange TSome = Some.truncate(10); + ConstantRange TWrap = Wrap.truncate(10); + EXPECT_TRUE(TFull.isFullSet()); + EXPECT_TRUE(TEmpty.isEmptySet()); + EXPECT_EQ(TOne, ConstantRange(One.getLower().trunc(10), + One.getUpper().trunc(10))); + EXPECT_TRUE(TSome.isFullSet()); +} + +TEST_F(ConstantRangeTest, ZExt) { + ConstantRange ZFull = Full.zeroExtend(20); + ConstantRange ZEmpty = Empty.zeroExtend(20); + ConstantRange ZOne = One.zeroExtend(20); + ConstantRange ZSome = Some.zeroExtend(20); + ConstantRange ZWrap = Wrap.zeroExtend(20); + EXPECT_EQ(ZFull, ConstantRange(APInt(20, 0), APInt(20, 0x10000))); + EXPECT_TRUE(ZEmpty.isEmptySet()); + EXPECT_EQ(ZOne, ConstantRange(One.getLower().zext(20), + One.getUpper().zext(20))); + EXPECT_EQ(ZSome, ConstantRange(Some.getLower().zext(20), + Some.getUpper().zext(20))); + EXPECT_EQ(ZWrap, ConstantRange(APInt(20, 0), APInt(20, 0x10000))); + + // zext([5, 0), 3->7) = [5, 8) + ConstantRange FiveZero(APInt(3, 5), APInt(3, 0)); + EXPECT_EQ(FiveZero.zeroExtend(7), ConstantRange(APInt(7, 5), APInt(7, 8))); +} + +TEST_F(ConstantRangeTest, SExt) { + ConstantRange SFull = Full.signExtend(20); + ConstantRange SEmpty = Empty.signExtend(20); + ConstantRange SOne = One.signExtend(20); + ConstantRange SSome = Some.signExtend(20); + ConstantRange SWrap = Wrap.signExtend(20); + EXPECT_EQ(SFull, ConstantRange(APInt(20, (uint64_t)INT16_MIN, true), + APInt(20, INT16_MAX + 1, true))); + EXPECT_TRUE(SEmpty.isEmptySet()); + EXPECT_EQ(SOne, ConstantRange(One.getLower().sext(20), + One.getUpper().sext(20))); + EXPECT_EQ(SSome, ConstantRange(Some.getLower().sext(20), + Some.getUpper().sext(20))); + EXPECT_EQ(SWrap, ConstantRange(APInt(20, (uint64_t)INT16_MIN, true), + APInt(20, INT16_MAX + 1, true))); + + EXPECT_EQ(ConstantRange(APInt(8, 120), APInt(8, 140)).signExtend(16), + ConstantRange(APInt(16, -128), APInt(16, 128))); + + EXPECT_EQ(ConstantRange(APInt(16, 0x0200), APInt(16, 0x8000)).signExtend(19), + ConstantRange(APInt(19, 0x0200), APInt(19, 0x8000))); +} + +TEST_F(ConstantRangeTest, IntersectWith) { + EXPECT_EQ(Empty.intersectWith(Full), Empty); + EXPECT_EQ(Empty.intersectWith(Empty), Empty); + EXPECT_EQ(Empty.intersectWith(One), Empty); + EXPECT_EQ(Empty.intersectWith(Some), Empty); + EXPECT_EQ(Empty.intersectWith(Wrap), Empty); + EXPECT_EQ(Full.intersectWith(Full), Full); + EXPECT_EQ(Some.intersectWith(Some), Some); + EXPECT_EQ(Some.intersectWith(One), One); + EXPECT_EQ(Full.intersectWith(One), One); + EXPECT_EQ(Full.intersectWith(Some), Some); + EXPECT_EQ(Some.intersectWith(Wrap), Empty); + EXPECT_EQ(One.intersectWith(Wrap), Empty); + EXPECT_EQ(One.intersectWith(Wrap), Wrap.intersectWith(One)); + + // Klee generated testcase from PR4545. + // The intersection of i16 [4, 2) and [6, 5) is disjoint, looking like + // 01..4.6789ABCDEF where the dots represent values not in the intersection. + ConstantRange LHS(APInt(16, 4), APInt(16, 2)); + ConstantRange RHS(APInt(16, 6), APInt(16, 5)); + EXPECT_TRUE(LHS.intersectWith(RHS) == LHS); + + // previous bug: intersection of [min, 3) and [2, max) should be 2 + LHS = ConstantRange(APInt(32, -2147483646), APInt(32, 3)); + RHS = ConstantRange(APInt(32, 2), APInt(32, 2147483646)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 2))); + + // [2, 0) /\ [4, 3) = [2, 0) + LHS = ConstantRange(APInt(32, 2), APInt(32, 0)); + RHS = ConstantRange(APInt(32, 4), APInt(32, 3)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 2), APInt(32, 0))); + + // [2, 0) /\ [4, 2) = [4, 0) + LHS = ConstantRange(APInt(32, 2), APInt(32, 0)); + RHS = ConstantRange(APInt(32, 4), APInt(32, 2)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 4), APInt(32, 0))); + + // [4, 2) /\ [5, 1) = [5, 1) + LHS = ConstantRange(APInt(32, 4), APInt(32, 2)); + RHS = ConstantRange(APInt(32, 5), APInt(32, 1)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 5), APInt(32, 1))); + + // [2, 0) /\ [7, 4) = [7, 4) + LHS = ConstantRange(APInt(32, 2), APInt(32, 0)); + RHS = ConstantRange(APInt(32, 7), APInt(32, 4)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 7), APInt(32, 4))); + + // [4, 2) /\ [1, 0) = [1, 0) + LHS = ConstantRange(APInt(32, 4), APInt(32, 2)); + RHS = ConstantRange(APInt(32, 1), APInt(32, 0)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 4), APInt(32, 2))); + + // [15, 0) /\ [7, 6) = [15, 0) + LHS = ConstantRange(APInt(32, 15), APInt(32, 0)); + RHS = ConstantRange(APInt(32, 7), APInt(32, 6)); + EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 15), APInt(32, 0))); +} + +TEST_F(ConstantRangeTest, UnionWith) { + EXPECT_EQ(Wrap.unionWith(One), + ConstantRange(APInt(16, 0xaaa), APInt(16, 0xb))); + EXPECT_EQ(One.unionWith(Wrap), Wrap.unionWith(One)); + EXPECT_EQ(Empty.unionWith(Empty), Empty); + EXPECT_EQ(Full.unionWith(Full), Full); + EXPECT_EQ(Some.unionWith(Wrap), Full); + + // PR4545 + EXPECT_EQ(ConstantRange(APInt(16, 14), APInt(16, 1)).unionWith( + ConstantRange(APInt(16, 0), APInt(16, 8))), + ConstantRange(APInt(16, 14), APInt(16, 8))); + EXPECT_EQ(ConstantRange(APInt(16, 6), APInt(16, 4)).unionWith( + ConstantRange(APInt(16, 4), APInt(16, 0))), + ConstantRange(16)); + EXPECT_EQ(ConstantRange(APInt(16, 1), APInt(16, 0)).unionWith( + ConstantRange(APInt(16, 2), APInt(16, 1))), + ConstantRange(16)); +} + +TEST_F(ConstantRangeTest, SetDifference) { + EXPECT_EQ(Full.difference(Empty), Full); + EXPECT_EQ(Full.difference(Full), Empty); + EXPECT_EQ(Empty.difference(Empty), Empty); + EXPECT_EQ(Empty.difference(Full), Empty); + + ConstantRange A(APInt(16, 3), APInt(16, 7)); + ConstantRange B(APInt(16, 5), APInt(16, 9)); + ConstantRange C(APInt(16, 3), APInt(16, 5)); + ConstantRange D(APInt(16, 7), APInt(16, 9)); + ConstantRange E(APInt(16, 5), APInt(16, 4)); + ConstantRange F(APInt(16, 7), APInt(16, 3)); + EXPECT_EQ(A.difference(B), C); + EXPECT_EQ(B.difference(A), D); + EXPECT_EQ(E.difference(A), F); +} + +TEST_F(ConstantRangeTest, SubtractAPInt) { + EXPECT_EQ(Full.subtract(APInt(16, 4)), Full); + EXPECT_EQ(Empty.subtract(APInt(16, 4)), Empty); + EXPECT_EQ(Some.subtract(APInt(16, 4)), + ConstantRange(APInt(16, 0x6), APInt(16, 0xaa6))); + EXPECT_EQ(Wrap.subtract(APInt(16, 4)), + ConstantRange(APInt(16, 0xaa6), APInt(16, 0x6))); + EXPECT_EQ(One.subtract(APInt(16, 4)), + ConstantRange(APInt(16, 0x6))); +} + +TEST_F(ConstantRangeTest, Add) { + EXPECT_EQ(Full.add(APInt(16, 4)), Full); + EXPECT_EQ(Full.add(Full), Full); + EXPECT_EQ(Full.add(Empty), Empty); + EXPECT_EQ(Full.add(One), Full); + EXPECT_EQ(Full.add(Some), Full); + EXPECT_EQ(Full.add(Wrap), Full); + EXPECT_EQ(Empty.add(Empty), Empty); + EXPECT_EQ(Empty.add(One), Empty); + EXPECT_EQ(Empty.add(Some), Empty); + EXPECT_EQ(Empty.add(Wrap), Empty); + EXPECT_EQ(Empty.add(APInt(16, 4)), Empty); + EXPECT_EQ(Some.add(APInt(16, 4)), + ConstantRange(APInt(16, 0xe), APInt(16, 0xaae))); + EXPECT_EQ(Wrap.add(APInt(16, 4)), + ConstantRange(APInt(16, 0xaae), APInt(16, 0xe))); + EXPECT_EQ(One.add(APInt(16, 4)), + ConstantRange(APInt(16, 0xe))); +} + +TEST_F(ConstantRangeTest, Sub) { + EXPECT_EQ(Full.sub(APInt(16, 4)), Full); + EXPECT_EQ(Full.sub(Full), Full); + EXPECT_EQ(Full.sub(Empty), Empty); + EXPECT_EQ(Full.sub(One), Full); + EXPECT_EQ(Full.sub(Some), Full); + EXPECT_EQ(Full.sub(Wrap), Full); + EXPECT_EQ(Empty.sub(Empty), Empty); + EXPECT_EQ(Empty.sub(One), Empty); + EXPECT_EQ(Empty.sub(Some), Empty); + EXPECT_EQ(Empty.sub(Wrap), Empty); + EXPECT_EQ(Empty.sub(APInt(16, 4)), Empty); + EXPECT_EQ(Some.sub(APInt(16, 4)), + ConstantRange(APInt(16, 0x6), APInt(16, 0xaa6))); + EXPECT_EQ(Some.sub(Some), + ConstantRange(APInt(16, 0xf561), APInt(16, 0xaa0))); + EXPECT_EQ(Wrap.sub(APInt(16, 4)), + ConstantRange(APInt(16, 0xaa6), APInt(16, 0x6))); + EXPECT_EQ(One.sub(APInt(16, 4)), + ConstantRange(APInt(16, 0x6))); +} + +TEST_F(ConstantRangeTest, Multiply) { + EXPECT_EQ(Full.multiply(Full), Full); + EXPECT_EQ(Full.multiply(Empty), Empty); + EXPECT_EQ(Full.multiply(One), Full); + EXPECT_EQ(Full.multiply(Some), Full); + EXPECT_EQ(Full.multiply(Wrap), Full); + EXPECT_EQ(Empty.multiply(Empty), Empty); + EXPECT_EQ(Empty.multiply(One), Empty); + EXPECT_EQ(Empty.multiply(Some), Empty); + EXPECT_EQ(Empty.multiply(Wrap), Empty); + EXPECT_EQ(One.multiply(One), ConstantRange(APInt(16, 0xa*0xa), + APInt(16, 0xa*0xa + 1))); + EXPECT_EQ(One.multiply(Some), ConstantRange(APInt(16, 0xa*0xa), + APInt(16, 0xa*0xaa9 + 1))); + EXPECT_EQ(One.multiply(Wrap), Full); + EXPECT_EQ(Some.multiply(Some), Full); + EXPECT_EQ(Some.multiply(Wrap), Full); + EXPECT_EQ(Wrap.multiply(Wrap), Full); + + ConstantRange Zero(APInt(16, 0)); + EXPECT_EQ(Zero.multiply(Full), Zero); + EXPECT_EQ(Zero.multiply(Some), Zero); + EXPECT_EQ(Zero.multiply(Wrap), Zero); + EXPECT_EQ(Full.multiply(Zero), Zero); + EXPECT_EQ(Some.multiply(Zero), Zero); + EXPECT_EQ(Wrap.multiply(Zero), Zero); + + // http://llvm.org/PR4545 + EXPECT_EQ(ConstantRange(APInt(4, 1), APInt(4, 6)).multiply( + ConstantRange(APInt(4, 6), APInt(4, 2))), + ConstantRange(4, /*isFullSet=*/true)); +} + +TEST_F(ConstantRangeTest, UMax) { + EXPECT_EQ(Full.umax(Full), Full); + EXPECT_EQ(Full.umax(Empty), Empty); + EXPECT_EQ(Full.umax(Some), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(Full.umax(Wrap), Full); + EXPECT_EQ(Full.umax(Some), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(Empty.umax(Empty), Empty); + EXPECT_EQ(Empty.umax(Some), Empty); + EXPECT_EQ(Empty.umax(Wrap), Empty); + EXPECT_EQ(Empty.umax(One), Empty); + EXPECT_EQ(Some.umax(Some), Some); + EXPECT_EQ(Some.umax(Wrap), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(Some.umax(One), Some); + // TODO: ConstantRange is currently over-conservative here. + EXPECT_EQ(Wrap.umax(Wrap), Full); + EXPECT_EQ(Wrap.umax(One), ConstantRange(APInt(16, 0xa), APInt(16, 0))); + EXPECT_EQ(One.umax(One), One); +} + +TEST_F(ConstantRangeTest, SMax) { + EXPECT_EQ(Full.smax(Full), Full); + EXPECT_EQ(Full.smax(Empty), Empty); + EXPECT_EQ(Full.smax(Some), ConstantRange(APInt(16, 0xa), + APInt::getSignedMinValue(16))); + EXPECT_EQ(Full.smax(Wrap), Full); + EXPECT_EQ(Full.smax(One), ConstantRange(APInt(16, 0xa), + APInt::getSignedMinValue(16))); + EXPECT_EQ(Empty.smax(Empty), Empty); + EXPECT_EQ(Empty.smax(Some), Empty); + EXPECT_EQ(Empty.smax(Wrap), Empty); + EXPECT_EQ(Empty.smax(One), Empty); + EXPECT_EQ(Some.smax(Some), Some); + EXPECT_EQ(Some.smax(Wrap), ConstantRange(APInt(16, 0xa), + APInt(16, (uint64_t)INT16_MIN))); + EXPECT_EQ(Some.smax(One), Some); + EXPECT_EQ(Wrap.smax(One), ConstantRange(APInt(16, 0xa), + APInt(16, (uint64_t)INT16_MIN))); + EXPECT_EQ(One.smax(One), One); +} + +TEST_F(ConstantRangeTest, UDiv) { + EXPECT_EQ(Full.udiv(Full), Full); + EXPECT_EQ(Full.udiv(Empty), Empty); + EXPECT_EQ(Full.udiv(One), ConstantRange(APInt(16, 0), + APInt(16, 0xffff / 0xa + 1))); + EXPECT_EQ(Full.udiv(Some), ConstantRange(APInt(16, 0), + APInt(16, 0xffff / 0xa + 1))); + EXPECT_EQ(Full.udiv(Wrap), Full); + EXPECT_EQ(Empty.udiv(Empty), Empty); + EXPECT_EQ(Empty.udiv(One), Empty); + EXPECT_EQ(Empty.udiv(Some), Empty); + EXPECT_EQ(Empty.udiv(Wrap), Empty); + EXPECT_EQ(One.udiv(One), ConstantRange(APInt(16, 1))); + EXPECT_EQ(One.udiv(Some), ConstantRange(APInt(16, 0), APInt(16, 2))); + EXPECT_EQ(One.udiv(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xb))); + EXPECT_EQ(Some.udiv(Some), ConstantRange(APInt(16, 0), APInt(16, 0x111))); + EXPECT_EQ(Some.udiv(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xaaa))); + EXPECT_EQ(Wrap.udiv(Wrap), Full); +} + +TEST_F(ConstantRangeTest, Shl) { + EXPECT_EQ(Full.shl(Full), Full); + EXPECT_EQ(Full.shl(Empty), Empty); + EXPECT_EQ(Full.shl(One), Full); // TODO: [0, (-1 << 0xa) + 1) + EXPECT_EQ(Full.shl(Some), Full); // TODO: [0, (-1 << 0xa) + 1) + EXPECT_EQ(Full.shl(Wrap), Full); + EXPECT_EQ(Empty.shl(Empty), Empty); + EXPECT_EQ(Empty.shl(One), Empty); + EXPECT_EQ(Empty.shl(Some), Empty); + EXPECT_EQ(Empty.shl(Wrap), Empty); + EXPECT_EQ(One.shl(One), ConstantRange(APInt(16, 0xa << 0xa), + APInt(16, (0xa << 0xa) + 1))); + EXPECT_EQ(One.shl(Some), Full); // TODO: [0xa << 0xa, 0) + EXPECT_EQ(One.shl(Wrap), Full); // TODO: [0xa, 0xa << 14 + 1) + EXPECT_EQ(Some.shl(Some), Full); // TODO: [0xa << 0xa, 0xfc01) + EXPECT_EQ(Some.shl(Wrap), Full); // TODO: [0xa, 0x7ff << 0x5 + 1) + EXPECT_EQ(Wrap.shl(Wrap), Full); +} + +TEST_F(ConstantRangeTest, Lshr) { + EXPECT_EQ(Full.lshr(Full), Full); + EXPECT_EQ(Full.lshr(Empty), Empty); + EXPECT_EQ(Full.lshr(One), ConstantRange(APInt(16, 0), + APInt(16, (0xffff >> 0xa) + 1))); + EXPECT_EQ(Full.lshr(Some), ConstantRange(APInt(16, 0), + APInt(16, (0xffff >> 0xa) + 1))); + EXPECT_EQ(Full.lshr(Wrap), Full); + EXPECT_EQ(Empty.lshr(Empty), Empty); + EXPECT_EQ(Empty.lshr(One), Empty); + EXPECT_EQ(Empty.lshr(Some), Empty); + EXPECT_EQ(Empty.lshr(Wrap), Empty); + EXPECT_EQ(One.lshr(One), ConstantRange(APInt(16, 0))); + EXPECT_EQ(One.lshr(Some), ConstantRange(APInt(16, 0))); + EXPECT_EQ(One.lshr(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xb))); + EXPECT_EQ(Some.lshr(Some), ConstantRange(APInt(16, 0), + APInt(16, (0xaaa >> 0xa) + 1))); + EXPECT_EQ(Some.lshr(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xaaa))); + EXPECT_EQ(Wrap.lshr(Wrap), Full); +} + +TEST(ConstantRange, MakeICmpRegion) { + // PR8250 + ConstantRange SMax = ConstantRange(APInt::getSignedMaxValue(32)); + EXPECT_TRUE(ConstantRange::makeICmpRegion(ICmpInst::ICMP_SGT, + SMax).isEmptySet()); +} + +} // anonymous namespace 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 M(new Module("MyModule", getGlobalContext())); + std::unique_ptr 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 *DT = + &getAnalysis().getDomTree(); + PostDominatorTree *PDT = &getAnalysis(); 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 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(); + AU.addRequired(); + AU.addRequired(); } DPass() : FunctionPass(ID) { initializeDPassPass(*PassRegistry::getPassRegistry()); @@ -191,7 +218,7 @@ namespace llvm { TEST(DominatorTree, Unreachable) { DPass *P = new DPass(); - OwningPtr M(makeLLVMModule(P)); + std::unique_ptr 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 M; + std::unique_ptr 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 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(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(F)); + FAdd = cast(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 Builder(BB); + + // Test instructions. + GlobalVariable *G = new GlobalVariable(*M, Builder.getInt32Ty(), true, + GlobalValue::ExternalLinkage, 0); + Value *V = Builder.CreateLoad(G); + EXPECT_TRUE( + cast(Builder.CreateNSWAdd(V, V))->hasNoSignedWrap()); + EXPECT_TRUE( + cast(Builder.CreateNSWMul(V, V))->hasNoSignedWrap()); + EXPECT_TRUE( + cast(Builder.CreateNSWSub(V, V))->hasNoSignedWrap()); + EXPECT_TRUE(cast( + Builder.CreateShl(V, V, "", /* NUW */ false, /* NSW */ true)) + ->hasNoSignedWrap()); + + EXPECT_TRUE( + cast(Builder.CreateNUWAdd(V, V))->hasNoUnsignedWrap()); + EXPECT_TRUE( + cast(Builder.CreateNUWMul(V, V))->hasNoUnsignedWrap()); + EXPECT_TRUE( + cast(Builder.CreateNUWSub(V, V))->hasNoUnsignedWrap()); + EXPECT_TRUE(cast( + Builder.CreateShl(V, V, "", /* NUW */ true, /* NSW */ false)) + ->hasNoUnsignedWrap()); + + // Test operators created with constants. + Constant *C = Builder.getInt32(42); + EXPECT_TRUE(cast(Builder.CreateNSWAdd(C, C)) + ->hasNoSignedWrap()); + EXPECT_TRUE(cast(Builder.CreateNSWSub(C, C)) + ->hasNoSignedWrap()); + EXPECT_TRUE(cast(Builder.CreateNSWMul(C, C)) + ->hasNoSignedWrap()); + EXPECT_TRUE(cast( + Builder.CreateShl(C, C, "", /* NUW */ false, /* NSW */ true)) + ->hasNoSignedWrap()); + + EXPECT_TRUE(cast(Builder.CreateNUWAdd(C, C)) + ->hasNoUnsignedWrap()); + EXPECT_TRUE(cast(Builder.CreateNUWSub(C, C)) + ->hasNoUnsignedWrap()); + EXPECT_TRUE(cast(Builder.CreateNUWMul(C, C)) + ->hasNoUnsignedWrap()); + EXPECT_TRUE(cast( + 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 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 M; + SmallVector 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 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 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/IR/LeakDetectorTest.cpp b/unittests/IR/LeakDetectorTest.cpp new file mode 100644 index 0000000..94eed4c --- /dev/null +++ b/unittests/IR/LeakDetectorTest.cpp @@ -0,0 +1,31 @@ +//===- LeakDetectorTest.cpp -----------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/LeakDetector.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +#ifdef GTEST_HAS_DEATH_TEST +#ifndef NDEBUG +TEST(LeakDetector, Death1) { + LeakDetector::addGarbageObject((void*) 1); + LeakDetector::addGarbageObject((void*) 2); + + EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 1), + ".*Ts.count\\(o\\) == 0 && \"Object already in set!\""); + EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 2), + "Cache != o && \"Object already in set!\""); +} +#endif +#endif + +} diff --git a/unittests/IR/LegacyPassManagerTest.cpp b/unittests/IR/LegacyPassManagerTest.cpp index 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()); + EXPECT_TRUE(getAnalysisIfAvailable()); run++; return false; } @@ -176,7 +176,7 @@ namespace llvm { initializeCGPassPass(*PassRegistry::getPassRegistry()); } virtual bool runOnSCC(CallGraphSCC &SCMM) { - EXPECT_TRUE(getAnalysisIfAvailable()); + EXPECT_TRUE(getAnalysisIfAvailable()); run(); return false; } @@ -215,7 +215,7 @@ namespace llvm { return false; } virtual bool runOnLoop(Loop *L, LPPassManager &LPM) { - EXPECT_TRUE(getAnalysisIfAvailable()); + EXPECT_TRUE(getAnalysisIfAvailable()); run(); return false; } @@ -252,7 +252,7 @@ namespace llvm { return false; } virtual bool runOnBasicBlock(BasicBlock &BB) { - EXPECT_TRUE(getAnalysisIfAvailable()); + EXPECT_TRUE(getAnalysisIfAvailable()); run(); return false; } @@ -277,7 +277,7 @@ namespace llvm { initializeFPassPass(*PassRegistry::getPassRegistry()); } virtual bool runOnModule(Module &M) { - EXPECT_TRUE(getAnalysisIfAvailable()); + EXPECT_TRUE(getAnalysisIfAvailable()); 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 void MemoryTestHelper(int run) { - OwningPtr M(makeLLVMModule()); + std::unique_ptr 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(M); + + PA.preserve(); + 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(F); - AnalyzedInstrCount += AR.InstructionCount; + const ModuleAnalysisManager &MAM = + AM->getResult(F).getManager(); + if (TestModuleAnalysis::Result *TMA = + MAM.getCachedResult(F->getParent())) + AnalyzedFunctionCount += TMA->FunctionCount; - return true; + if (OnlyUseCachedResults) { + // Hack to force the use of the cached interface. + if (TestFunctionAnalysis::Result *AR = + AM->getCachedResult(F)) + AnalyzedInstrCount += AR->InstructionCount; + } else { + // Typical path just runs the analysis as needed. + TestFunctionAnalysis::Result &AR = AM->getResult(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 M; + std::unique_ptr M; public: PassManagerTest() @@ -105,27 +191,154 @@ public: "}\n")) {} }; +TEST_F(PassManagerTest, BasicPreservedAnalyses) { + PreservedAnalyses PA1 = PreservedAnalyses(); + EXPECT_FALSE(PA1.preserved()); + EXPECT_FALSE(PA1.preserved()); + PreservedAnalyses PA2 = PreservedAnalyses::none(); + EXPECT_FALSE(PA2.preserved()); + EXPECT_FALSE(PA2.preserved()); + PreservedAnalyses PA3 = PreservedAnalyses::all(); + EXPECT_TRUE(PA3.preserved()); + EXPECT_TRUE(PA3.preserved()); + PreservedAnalyses PA4 = PA1; + EXPECT_FALSE(PA4.preserved()); + EXPECT_FALSE(PA4.preserved()); + PA4 = PA3; + EXPECT_TRUE(PA4.preserved()); + EXPECT_TRUE(PA4.preserved()); + PA4 = std::move(PA2); + EXPECT_FALSE(PA4.preserved()); + EXPECT_FALSE(PA4.preserved()); + PA4.preserve(); + EXPECT_TRUE(PA4.preserved()); + EXPECT_FALSE(PA4.preserved()); + PA1.preserve(); + EXPECT_FALSE(PA1.preserved()); + EXPECT_TRUE(PA1.preserved()); + PA1.preserve(); + EXPECT_TRUE(PA1.preserved()); + EXPECT_TRUE(PA1.preserved()); + PA1.intersect(PA4); + EXPECT_TRUE(PA1.preserved()); + EXPECT_FALSE(PA1.preserved()); +} + 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 M; + Function *F; + BasicBlock *BB; + IRBuilder 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 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 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 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 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/IR/ValueHandleTest.cpp b/unittests/IR/ValueHandleTest.cpp new file mode 100644 index 0000000..15a0c22 --- /dev/null +++ b/unittests/IR/ValueHandleTest.cpp @@ -0,0 +1,407 @@ +//===- ValueHandleTest.cpp - ValueHandle tests ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/ValueHandle.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "gtest/gtest.h" +#include + +using namespace llvm; + +namespace { + +class ValueHandle : public testing::Test { +protected: + Constant *ConstantV; + std::auto_ptr BitcastV; + + ValueHandle() : + ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), + BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) { + } +}; + +class ConcreteCallbackVH : public CallbackVH { +public: + ConcreteCallbackVH(Value *V) : CallbackVH(V) {} +}; + +TEST_F(ValueHandle, WeakVH_BasicOperation) { + WeakVH WVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), WVH); + WVH = ConstantV; + EXPECT_EQ(ConstantV, WVH); + + // Make sure I can call a method on the underlying Value. It + // doesn't matter which method. + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), WVH->getType()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType()); +} + +TEST_F(ValueHandle, WeakVH_Comparisons) { + WeakVH BitcastWVH(BitcastV.get()); + WeakVH ConstantWVH(ConstantV); + + EXPECT_TRUE(BitcastWVH == BitcastWVH); + EXPECT_TRUE(BitcastV.get() == BitcastWVH); + EXPECT_TRUE(BitcastWVH == BitcastV.get()); + EXPECT_FALSE(BitcastWVH == ConstantWVH); + + EXPECT_TRUE(BitcastWVH != ConstantWVH); + EXPECT_TRUE(BitcastV.get() != ConstantWVH); + EXPECT_TRUE(BitcastWVH != ConstantV); + EXPECT_FALSE(BitcastWVH != BitcastWVH); + + // Cast to Value* so comparisons work. + Value *BV = BitcastV.get(); + Value *CV = ConstantV; + EXPECT_EQ(BV < CV, BitcastWVH < ConstantWVH); + EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantWVH); + EXPECT_EQ(BV > CV, BitcastWVH > ConstantWVH); + EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantWVH); + + EXPECT_EQ(BV < CV, BitcastV.get() < ConstantWVH); + EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantWVH); + EXPECT_EQ(BV > CV, BitcastV.get() > ConstantWVH); + EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantWVH); + + EXPECT_EQ(BV < CV, BitcastWVH < ConstantV); + EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantV); + EXPECT_EQ(BV > CV, BitcastWVH > ConstantV); + EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantV); +} + +TEST_F(ValueHandle, WeakVH_FollowsRAUW) { + WeakVH WVH(BitcastV.get()); + WeakVH WVH_Copy(WVH); + WeakVH WVH_Recreated(BitcastV.get()); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(ConstantV, WVH); + EXPECT_EQ(ConstantV, WVH_Copy); + EXPECT_EQ(ConstantV, WVH_Recreated); +} + +TEST_F(ValueHandle, WeakVH_NullOnDeletion) { + WeakVH WVH(BitcastV.get()); + WeakVH WVH_Copy(WVH); + WeakVH WVH_Recreated(BitcastV.get()); + BitcastV.reset(); + Value *null_value = NULL; + EXPECT_EQ(null_value, WVH); + EXPECT_EQ(null_value, WVH_Copy); + EXPECT_EQ(null_value, WVH_Recreated); +} + + +TEST_F(ValueHandle, AssertingVH_BasicOperation) { + AssertingVH AVH(BitcastV.get()); + CastInst *implicit_to_exact_type = AVH; + (void)implicit_to_exact_type; // Avoid warning. + + AssertingVH GenericAVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), GenericAVH); + GenericAVH = ConstantV; + EXPECT_EQ(ConstantV, GenericAVH); + + // Make sure I can call a method on the underlying CastInst. It + // doesn't matter which method. + EXPECT_FALSE(AVH->mayWriteToMemory()); + EXPECT_FALSE((*AVH).mayWriteToMemory()); +} + +TEST_F(ValueHandle, AssertingVH_Const) { + const CastInst *ConstBitcast = BitcastV.get(); + AssertingVH AVH(ConstBitcast); + const CastInst *implicit_to_exact_type = AVH; + (void)implicit_to_exact_type; // Avoid warning. +} + +TEST_F(ValueHandle, AssertingVH_Comparisons) { + AssertingVH BitcastAVH(BitcastV.get()); + AssertingVH ConstantAVH(ConstantV); + + EXPECT_TRUE(BitcastAVH == BitcastAVH); + EXPECT_TRUE(BitcastV.get() == BitcastAVH); + EXPECT_TRUE(BitcastAVH == BitcastV.get()); + EXPECT_FALSE(BitcastAVH == ConstantAVH); + + EXPECT_TRUE(BitcastAVH != ConstantAVH); + EXPECT_TRUE(BitcastV.get() != ConstantAVH); + EXPECT_TRUE(BitcastAVH != ConstantV); + EXPECT_FALSE(BitcastAVH != BitcastAVH); + + // Cast to Value* so comparisons work. + Value *BV = BitcastV.get(); + Value *CV = ConstantV; + EXPECT_EQ(BV < CV, BitcastAVH < ConstantAVH); + EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantAVH); + EXPECT_EQ(BV > CV, BitcastAVH > ConstantAVH); + EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantAVH); + + EXPECT_EQ(BV < CV, BitcastV.get() < ConstantAVH); + EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantAVH); + EXPECT_EQ(BV > CV, BitcastV.get() > ConstantAVH); + EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantAVH); + + EXPECT_EQ(BV < CV, BitcastAVH < ConstantV); + EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantV); + EXPECT_EQ(BV > CV, BitcastAVH > ConstantV); + EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantV); +} + +TEST_F(ValueHandle, AssertingVH_DoesNotFollowRAUW) { + AssertingVH AVH(BitcastV.get()); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(BitcastV.get(), AVH); +} + +#ifdef NDEBUG + +TEST_F(ValueHandle, AssertingVH_ReducesToPointer) { + EXPECT_EQ(sizeof(CastInst *), sizeof(AssertingVH)); +} + +#else // !NDEBUG + +#ifdef GTEST_HAS_DEATH_TEST + +TEST_F(ValueHandle, AssertingVH_Asserts) { + AssertingVH AVH(BitcastV.get()); + EXPECT_DEATH({BitcastV.reset();}, + "An asserting value handle still pointed to this value!"); + AssertingVH Copy(AVH); + AVH = NULL; + EXPECT_DEATH({BitcastV.reset();}, + "An asserting value handle still pointed to this value!"); + Copy = NULL; + BitcastV.reset(); +} + +#endif // GTEST_HAS_DEATH_TEST + +#endif // NDEBUG + +TEST_F(ValueHandle, CallbackVH_BasicOperation) { + ConcreteCallbackVH CVH(BitcastV.get()); + EXPECT_EQ(BitcastV.get(), CVH); + CVH = ConstantV; + EXPECT_EQ(ConstantV, CVH); + + // Make sure I can call a method on the underlying Value. It + // doesn't matter which method. + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), CVH->getType()); + EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*CVH).getType()); +} + +TEST_F(ValueHandle, CallbackVH_Comparisons) { + ConcreteCallbackVH BitcastCVH(BitcastV.get()); + ConcreteCallbackVH ConstantCVH(ConstantV); + + EXPECT_TRUE(BitcastCVH == BitcastCVH); + EXPECT_TRUE(BitcastV.get() == BitcastCVH); + EXPECT_TRUE(BitcastCVH == BitcastV.get()); + EXPECT_FALSE(BitcastCVH == ConstantCVH); + + EXPECT_TRUE(BitcastCVH != ConstantCVH); + EXPECT_TRUE(BitcastV.get() != ConstantCVH); + EXPECT_TRUE(BitcastCVH != ConstantV); + EXPECT_FALSE(BitcastCVH != BitcastCVH); + + // Cast to Value* so comparisons work. + Value *BV = BitcastV.get(); + Value *CV = ConstantV; + EXPECT_EQ(BV < CV, BitcastCVH < ConstantCVH); + EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantCVH); + EXPECT_EQ(BV > CV, BitcastCVH > ConstantCVH); + EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantCVH); + + EXPECT_EQ(BV < CV, BitcastV.get() < ConstantCVH); + EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantCVH); + EXPECT_EQ(BV > CV, BitcastV.get() > ConstantCVH); + EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantCVH); + + EXPECT_EQ(BV < CV, BitcastCVH < ConstantV); + EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantV); + EXPECT_EQ(BV > CV, BitcastCVH > ConstantV); + EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantV); +} + +TEST_F(ValueHandle, CallbackVH_CallbackOnDeletion) { + class RecordingVH : public CallbackVH { + public: + int DeletedCalls; + int AURWCalls; + + RecordingVH() : DeletedCalls(0), AURWCalls(0) {} + RecordingVH(Value *V) : CallbackVH(V), DeletedCalls(0), AURWCalls(0) {} + + private: + virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } + virtual void allUsesReplacedWith(Value *) { AURWCalls++; } + }; + + RecordingVH RVH; + RVH = BitcastV.get(); + EXPECT_EQ(0, RVH.DeletedCalls); + EXPECT_EQ(0, RVH.AURWCalls); + BitcastV.reset(); + EXPECT_EQ(1, RVH.DeletedCalls); + EXPECT_EQ(0, RVH.AURWCalls); +} + +TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) { + class RecordingVH : public CallbackVH { + public: + int DeletedCalls; + Value *AURWArgument; + + RecordingVH() : DeletedCalls(0), AURWArgument(NULL) {} + RecordingVH(Value *V) + : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL) {} + + private: + virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } + virtual void allUsesReplacedWith(Value *new_value) { + EXPECT_EQ(NULL, AURWArgument); + AURWArgument = new_value; + } + }; + + RecordingVH RVH; + RVH = BitcastV.get(); + EXPECT_EQ(0, RVH.DeletedCalls); + EXPECT_EQ(NULL, RVH.AURWArgument); + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(0, RVH.DeletedCalls); + EXPECT_EQ(ConstantV, RVH.AURWArgument); +} + +TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) { + class RecoveringVH : public CallbackVH { + public: + int DeletedCalls; + Value *AURWArgument; + LLVMContext *Context; + + RecoveringVH() : DeletedCalls(0), AURWArgument(NULL), + Context(&getGlobalContext()) {} + RecoveringVH(Value *V) + : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL), + Context(&getGlobalContext()) {} + + private: + virtual void deleted() { + getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))); + setValPtr(NULL); + } + virtual void allUsesReplacedWith(Value *new_value) { + ASSERT_TRUE(NULL != getValPtr()); + EXPECT_EQ(1U, getValPtr()->getNumUses()); + EXPECT_EQ(NULL, AURWArgument); + AURWArgument = new_value; + } + }; + + // Normally, if a value has uses, deleting it will crash. However, we can use + // a CallbackVH to remove the uses before the check for no uses. + RecoveringVH RVH; + RVH = BitcastV.get(); + std::auto_ptr BitcastUser( + BinaryOperator::CreateAdd(RVH, + Constant::getNullValue(Type::getInt32Ty(getGlobalContext())))); + EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0)); + BitcastV.reset(); // Would crash without the ValueHandler. + EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), RVH.AURWArgument); + EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), + BitcastUser->getOperand(0)); +} + +TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) { + // When a CallbackVH modifies other ValueHandles in its callbacks, + // that shouldn't interfere with non-modified ValueHandles receiving + // their appropriate callbacks. + // + // We create the active CallbackVH in the middle of a palindromic + // arrangement of other VHs so that the bad behavior would be + // triggered in whichever order callbacks run. + + class DestroyingVH : public CallbackVH { + public: + std::unique_ptr ToClear[2]; + DestroyingVH(Value *V) { + ToClear[0].reset(new WeakVH(V)); + setValPtr(V); + ToClear[1].reset(new WeakVH(V)); + } + virtual void deleted() { + ToClear[0].reset(); + ToClear[1].reset(); + CallbackVH::deleted(); + } + virtual void allUsesReplacedWith(Value *) { + ToClear[0].reset(); + ToClear[1].reset(); + } + }; + + { + WeakVH ShouldBeVisited1(BitcastV.get()); + DestroyingVH C(BitcastV.get()); + WeakVH ShouldBeVisited2(BitcastV.get()); + + BitcastV->replaceAllUsesWith(ConstantV); + EXPECT_EQ(ConstantV, static_cast(ShouldBeVisited1)); + EXPECT_EQ(ConstantV, static_cast(ShouldBeVisited2)); + } + + { + WeakVH ShouldBeVisited1(BitcastV.get()); + DestroyingVH C(BitcastV.get()); + WeakVH ShouldBeVisited2(BitcastV.get()); + + BitcastV.reset(); + EXPECT_EQ(NULL, static_cast(ShouldBeVisited1)); + EXPECT_EQ(NULL, static_cast(ShouldBeVisited2)); + } +} + +TEST_F(ValueHandle, AssertingVHCheckedLast) { + // If a CallbackVH exists to clear out a group of AssertingVHs on + // Value deletion, the CallbackVH should get a chance to do so + // before the AssertingVHs assert. + + class ClearingVH : public CallbackVH { + public: + AssertingVH *ToClear[2]; + ClearingVH(Value *V, + AssertingVH &A0, AssertingVH &A1) + : CallbackVH(V) { + ToClear[0] = &A0; + ToClear[1] = &A1; + } + + virtual void deleted() { + *ToClear[0] = 0; + *ToClear[1] = 0; + CallbackVH::deleted(); + } + }; + + AssertingVH A1, A2; + A1 = BitcastV.get(); + ClearingVH C(BitcastV.get(), A1, A2); + A2 = BitcastV.get(); + // C.deleted() should run first, clearing the two AssertingVHs, + // which should prevent them from asserting. + BitcastV.reset(); +} + +} 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 class ValueMapTest : public testing::Test { protected: Constant *ConstantV; - OwningPtr BitcastV; - OwningPtr AddV; + std::unique_ptr BitcastV; + std::unique_ptr AddV; ValueMapTest() : ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), @@ -117,7 +116,8 @@ TYPED_TEST(ValueMapTest, OperationsWork) { template void CompileAssertHasType(VarType) { - typedef char assert[is_same::value ? 1 : -1]; + static_assert(std::is_same::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 M(new Module("TestModule", Ctx)); + std::unique_ptr 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 Completions; + + TestListCompleter(const std::vector &Completions) + : Completions(Completions) {} + + std::vector operator()(StringRef Buffer, + size_t Pos) const { + EXPECT_TRUE(Buffer.empty()); + EXPECT_EQ(0u, Pos); + return Completions; + } +}; + +TEST_F(LineEditorTest, ListCompleters) { + std::vector 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 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 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 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(Elem)); + EXPECT_EQ(cast(Elem)->getFunction(), + LinkedModule->getFunction("ba_func")); + EXPECT_EQ(cast(Elem)->getBasicBlock()->getParent(), + LinkedModule->getFunction("ba_func")); + + Elem = Init->getOperand(1); + ASSERT_TRUE(isa(Elem)); + EXPECT_EQ(cast(Elem)->getFunction(), + LinkedModule->getFunction("ba_func")); + EXPECT_EQ(cast(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 AL(T.ParseArgs(Args, array_endof(Args), MAI, MAC)); + std::unique_ptr 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 AL; + std::unique_ptr 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 AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr 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 AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr 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 AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr 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 AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr 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 AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr 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 AL(T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + std::unique_ptr 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 @@ -77,12 +77,16 @@ using namespace llvm; // Test the peculiar behavior of Use in simplify_type. -int Check1[is_same::SimpleType, Value *>::value ? 1 : -1]; -int Check2[is_same::SimpleType, Value *>::value ? 1 : -1]; +static_assert(std::is_same::SimpleType, Value *>::value, + "Use doesn't simplify correctly!"); +static_assert(std::is_same::SimpleType, Value *>::value, + "Use doesn't simplify correctly!"); // Test that a regular class behaves as expected. -int Check3[is_same::SimpleType, int>::value ? 1 : -1]; -int Check4[is_same::SimpleType, foo *>::value ? 1 : -1]; +static_assert(std::is_same::SimpleType, int>::value, + "Unexpected simplify_type result!"); +static_assert(std::is_same::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 #include @@ -42,6 +42,33 @@ class TempEnvVar { const char *const name; }; +template +class StackOption : public cl::opt { + typedef cl::opt Base; +public: + // One option... + template + explicit StackOption(const M0t &M0) : Base(M0) {} + + // Two options... + template + StackOption(const M0t &M0, const M1t &M1) : Base(M0, M1) {} + + // Three options... + template + StackOption(const M0t &M0, const M1t &M1, const M2t &M2) : Base(M0, M1, M2) {} + + // Four options... + template + 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 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 EnvironmentTestOptionLocal("env-test-opt-local"); + StackOption 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 TestOption2("test-option", cl::cat(TestCategory)); + StackOption 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 Actual("actual"); + StackOption Extra("extra"); + StackOption 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 Compressed; - OwningPtr Uncompressed; + std::unique_ptr Compressed; + std::unique_ptr 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/ConstantRangeTest.cpp b/unittests/Support/ConstantRangeTest.cpp deleted file mode 100644 index 3e0a085..0000000 --- a/unittests/Support/ConstantRangeTest.cpp +++ /dev/null @@ -1,512 +0,0 @@ -//===- llvm/unittest/Support/ConstantRangeTest.cpp - ConstantRange 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/ConstantRange.h" -#include "llvm/IR/Instructions.h" -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -class ConstantRangeTest : public ::testing::Test { -protected: - static ConstantRange Full; - static ConstantRange Empty; - static ConstantRange One; - static ConstantRange Some; - static ConstantRange Wrap; -}; - -ConstantRange ConstantRangeTest::Full(16); -ConstantRange ConstantRangeTest::Empty(16, false); -ConstantRange ConstantRangeTest::One(APInt(16, 0xa)); -ConstantRange ConstantRangeTest::Some(APInt(16, 0xa), APInt(16, 0xaaa)); -ConstantRange ConstantRangeTest::Wrap(APInt(16, 0xaaa), APInt(16, 0xa)); - -TEST_F(ConstantRangeTest, Basics) { - EXPECT_TRUE(Full.isFullSet()); - EXPECT_FALSE(Full.isEmptySet()); - EXPECT_TRUE(Full.inverse().isEmptySet()); - EXPECT_FALSE(Full.isWrappedSet()); - EXPECT_TRUE(Full.contains(APInt(16, 0x0))); - EXPECT_TRUE(Full.contains(APInt(16, 0x9))); - EXPECT_TRUE(Full.contains(APInt(16, 0xa))); - EXPECT_TRUE(Full.contains(APInt(16, 0xaa9))); - EXPECT_TRUE(Full.contains(APInt(16, 0xaaa))); - - EXPECT_FALSE(Empty.isFullSet()); - EXPECT_TRUE(Empty.isEmptySet()); - EXPECT_TRUE(Empty.inverse().isFullSet()); - EXPECT_FALSE(Empty.isWrappedSet()); - EXPECT_FALSE(Empty.contains(APInt(16, 0x0))); - EXPECT_FALSE(Empty.contains(APInt(16, 0x9))); - EXPECT_FALSE(Empty.contains(APInt(16, 0xa))); - EXPECT_FALSE(Empty.contains(APInt(16, 0xaa9))); - EXPECT_FALSE(Empty.contains(APInt(16, 0xaaa))); - - EXPECT_FALSE(One.isFullSet()); - EXPECT_FALSE(One.isEmptySet()); - EXPECT_FALSE(One.isWrappedSet()); - EXPECT_FALSE(One.contains(APInt(16, 0x0))); - EXPECT_FALSE(One.contains(APInt(16, 0x9))); - EXPECT_TRUE(One.contains(APInt(16, 0xa))); - EXPECT_FALSE(One.contains(APInt(16, 0xaa9))); - EXPECT_FALSE(One.contains(APInt(16, 0xaaa))); - EXPECT_FALSE(One.inverse().contains(APInt(16, 0xa))); - - EXPECT_FALSE(Some.isFullSet()); - EXPECT_FALSE(Some.isEmptySet()); - EXPECT_FALSE(Some.isWrappedSet()); - EXPECT_FALSE(Some.contains(APInt(16, 0x0))); - EXPECT_FALSE(Some.contains(APInt(16, 0x9))); - EXPECT_TRUE(Some.contains(APInt(16, 0xa))); - EXPECT_TRUE(Some.contains(APInt(16, 0xaa9))); - EXPECT_FALSE(Some.contains(APInt(16, 0xaaa))); - - EXPECT_FALSE(Wrap.isFullSet()); - EXPECT_FALSE(Wrap.isEmptySet()); - EXPECT_TRUE(Wrap.isWrappedSet()); - EXPECT_TRUE(Wrap.contains(APInt(16, 0x0))); - EXPECT_TRUE(Wrap.contains(APInt(16, 0x9))); - EXPECT_FALSE(Wrap.contains(APInt(16, 0xa))); - EXPECT_FALSE(Wrap.contains(APInt(16, 0xaa9))); - EXPECT_TRUE(Wrap.contains(APInt(16, 0xaaa))); -} - -TEST_F(ConstantRangeTest, Equality) { - EXPECT_EQ(Full, Full); - EXPECT_EQ(Empty, Empty); - EXPECT_EQ(One, One); - EXPECT_EQ(Some, Some); - EXPECT_EQ(Wrap, Wrap); - EXPECT_NE(Full, Empty); - EXPECT_NE(Full, One); - EXPECT_NE(Full, Some); - EXPECT_NE(Full, Wrap); - EXPECT_NE(Empty, One); - EXPECT_NE(Empty, Some); - EXPECT_NE(Empty, Wrap); - EXPECT_NE(One, Some); - EXPECT_NE(One, Wrap); - EXPECT_NE(Some, Wrap); -} - -TEST_F(ConstantRangeTest, SingleElement) { - EXPECT_EQ(Full.getSingleElement(), static_cast(NULL)); - EXPECT_EQ(Empty.getSingleElement(), static_cast(NULL)); - EXPECT_EQ(*One.getSingleElement(), APInt(16, 0xa)); - EXPECT_EQ(Some.getSingleElement(), static_cast(NULL)); - EXPECT_EQ(Wrap.getSingleElement(), static_cast(NULL)); - - EXPECT_FALSE(Full.isSingleElement()); - EXPECT_FALSE(Empty.isSingleElement()); - EXPECT_TRUE(One.isSingleElement()); - EXPECT_FALSE(Some.isSingleElement()); - EXPECT_FALSE(Wrap.isSingleElement()); -} - -TEST_F(ConstantRangeTest, GetSetSize) { - EXPECT_EQ(Full.getSetSize(), APInt(17, 65536)); - EXPECT_EQ(Empty.getSetSize(), APInt(17, 0)); - EXPECT_EQ(One.getSetSize(), APInt(17, 1)); - EXPECT_EQ(Some.getSetSize(), APInt(17, 0xaa0)); - - ConstantRange Wrap(APInt(4, 7), APInt(4, 3)); - ConstantRange Wrap2(APInt(4, 8), APInt(4, 7)); - EXPECT_EQ(Wrap.getSetSize(), APInt(5, 12)); - EXPECT_EQ(Wrap2.getSetSize(), APInt(5, 15)); -} - -TEST_F(ConstantRangeTest, GetMinsAndMaxes) { - EXPECT_EQ(Full.getUnsignedMax(), APInt(16, UINT16_MAX)); - EXPECT_EQ(One.getUnsignedMax(), APInt(16, 0xa)); - EXPECT_EQ(Some.getUnsignedMax(), APInt(16, 0xaa9)); - EXPECT_EQ(Wrap.getUnsignedMax(), APInt(16, UINT16_MAX)); - - EXPECT_EQ(Full.getUnsignedMin(), APInt(16, 0)); - EXPECT_EQ(One.getUnsignedMin(), APInt(16, 0xa)); - EXPECT_EQ(Some.getUnsignedMin(), APInt(16, 0xa)); - EXPECT_EQ(Wrap.getUnsignedMin(), APInt(16, 0)); - - EXPECT_EQ(Full.getSignedMax(), APInt(16, INT16_MAX)); - EXPECT_EQ(One.getSignedMax(), APInt(16, 0xa)); - EXPECT_EQ(Some.getSignedMax(), APInt(16, 0xaa9)); - EXPECT_EQ(Wrap.getSignedMax(), APInt(16, INT16_MAX)); - - EXPECT_EQ(Full.getSignedMin(), APInt(16, (uint64_t)INT16_MIN)); - EXPECT_EQ(One.getSignedMin(), APInt(16, 0xa)); - EXPECT_EQ(Some.getSignedMin(), APInt(16, 0xa)); - EXPECT_EQ(Wrap.getSignedMin(), APInt(16, (uint64_t)INT16_MIN)); - - // Found by Klee - EXPECT_EQ(ConstantRange(APInt(4, 7), APInt(4, 0)).getSignedMax(), - APInt(4, 7)); -} - -TEST_F(ConstantRangeTest, SignWrapped) { - EXPECT_TRUE(Full.isSignWrappedSet()); - EXPECT_FALSE(Empty.isSignWrappedSet()); - EXPECT_FALSE(One.isSignWrappedSet()); - EXPECT_FALSE(Some.isSignWrappedSet()); - EXPECT_TRUE(Wrap.isSignWrappedSet()); - - EXPECT_FALSE(ConstantRange(APInt(8, 127), APInt(8, 128)).isSignWrappedSet()); - EXPECT_TRUE(ConstantRange(APInt(8, 127), APInt(8, 129)).isSignWrappedSet()); - EXPECT_FALSE(ConstantRange(APInt(8, 128), APInt(8, 129)).isSignWrappedSet()); - EXPECT_TRUE(ConstantRange(APInt(8, 10), APInt(8, 9)).isSignWrappedSet()); - EXPECT_TRUE(ConstantRange(APInt(8, 10), APInt(8, 250)).isSignWrappedSet()); - EXPECT_FALSE(ConstantRange(APInt(8, 250), APInt(8, 10)).isSignWrappedSet()); - EXPECT_FALSE(ConstantRange(APInt(8, 250), APInt(8, 251)).isSignWrappedSet()); -} - -TEST_F(ConstantRangeTest, Trunc) { - ConstantRange TFull = Full.truncate(10); - ConstantRange TEmpty = Empty.truncate(10); - ConstantRange TOne = One.truncate(10); - ConstantRange TSome = Some.truncate(10); - ConstantRange TWrap = Wrap.truncate(10); - EXPECT_TRUE(TFull.isFullSet()); - EXPECT_TRUE(TEmpty.isEmptySet()); - EXPECT_EQ(TOne, ConstantRange(One.getLower().trunc(10), - One.getUpper().trunc(10))); - EXPECT_TRUE(TSome.isFullSet()); -} - -TEST_F(ConstantRangeTest, ZExt) { - ConstantRange ZFull = Full.zeroExtend(20); - ConstantRange ZEmpty = Empty.zeroExtend(20); - ConstantRange ZOne = One.zeroExtend(20); - ConstantRange ZSome = Some.zeroExtend(20); - ConstantRange ZWrap = Wrap.zeroExtend(20); - EXPECT_EQ(ZFull, ConstantRange(APInt(20, 0), APInt(20, 0x10000))); - EXPECT_TRUE(ZEmpty.isEmptySet()); - EXPECT_EQ(ZOne, ConstantRange(One.getLower().zext(20), - One.getUpper().zext(20))); - EXPECT_EQ(ZSome, ConstantRange(Some.getLower().zext(20), - Some.getUpper().zext(20))); - EXPECT_EQ(ZWrap, ConstantRange(APInt(20, 0), APInt(20, 0x10000))); - - // zext([5, 0), 3->7) = [5, 8) - ConstantRange FiveZero(APInt(3, 5), APInt(3, 0)); - EXPECT_EQ(FiveZero.zeroExtend(7), ConstantRange(APInt(7, 5), APInt(7, 8))); -} - -TEST_F(ConstantRangeTest, SExt) { - ConstantRange SFull = Full.signExtend(20); - ConstantRange SEmpty = Empty.signExtend(20); - ConstantRange SOne = One.signExtend(20); - ConstantRange SSome = Some.signExtend(20); - ConstantRange SWrap = Wrap.signExtend(20); - EXPECT_EQ(SFull, ConstantRange(APInt(20, (uint64_t)INT16_MIN, true), - APInt(20, INT16_MAX + 1, true))); - EXPECT_TRUE(SEmpty.isEmptySet()); - EXPECT_EQ(SOne, ConstantRange(One.getLower().sext(20), - One.getUpper().sext(20))); - EXPECT_EQ(SSome, ConstantRange(Some.getLower().sext(20), - Some.getUpper().sext(20))); - EXPECT_EQ(SWrap, ConstantRange(APInt(20, (uint64_t)INT16_MIN, true), - APInt(20, INT16_MAX + 1, true))); - - EXPECT_EQ(ConstantRange(APInt(8, 120), APInt(8, 140)).signExtend(16), - ConstantRange(APInt(16, -128), APInt(16, 128))); - - EXPECT_EQ(ConstantRange(APInt(16, 0x0200), APInt(16, 0x8000)).signExtend(19), - ConstantRange(APInt(19, 0x0200), APInt(19, 0x8000))); -} - -TEST_F(ConstantRangeTest, IntersectWith) { - EXPECT_EQ(Empty.intersectWith(Full), Empty); - EXPECT_EQ(Empty.intersectWith(Empty), Empty); - EXPECT_EQ(Empty.intersectWith(One), Empty); - EXPECT_EQ(Empty.intersectWith(Some), Empty); - EXPECT_EQ(Empty.intersectWith(Wrap), Empty); - EXPECT_EQ(Full.intersectWith(Full), Full); - EXPECT_EQ(Some.intersectWith(Some), Some); - EXPECT_EQ(Some.intersectWith(One), One); - EXPECT_EQ(Full.intersectWith(One), One); - EXPECT_EQ(Full.intersectWith(Some), Some); - EXPECT_EQ(Some.intersectWith(Wrap), Empty); - EXPECT_EQ(One.intersectWith(Wrap), Empty); - EXPECT_EQ(One.intersectWith(Wrap), Wrap.intersectWith(One)); - - // Klee generated testcase from PR4545. - // The intersection of i16 [4, 2) and [6, 5) is disjoint, looking like - // 01..4.6789ABCDEF where the dots represent values not in the intersection. - ConstantRange LHS(APInt(16, 4), APInt(16, 2)); - ConstantRange RHS(APInt(16, 6), APInt(16, 5)); - EXPECT_TRUE(LHS.intersectWith(RHS) == LHS); - - // previous bug: intersection of [min, 3) and [2, max) should be 2 - LHS = ConstantRange(APInt(32, -2147483646), APInt(32, 3)); - RHS = ConstantRange(APInt(32, 2), APInt(32, 2147483646)); - EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 2))); - - // [2, 0) /\ [4, 3) = [2, 0) - LHS = ConstantRange(APInt(32, 2), APInt(32, 0)); - RHS = ConstantRange(APInt(32, 4), APInt(32, 3)); - EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 2), APInt(32, 0))); - - // [2, 0) /\ [4, 2) = [4, 0) - LHS = ConstantRange(APInt(32, 2), APInt(32, 0)); - RHS = ConstantRange(APInt(32, 4), APInt(32, 2)); - EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 4), APInt(32, 0))); - - // [4, 2) /\ [5, 1) = [5, 1) - LHS = ConstantRange(APInt(32, 4), APInt(32, 2)); - RHS = ConstantRange(APInt(32, 5), APInt(32, 1)); - EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 5), APInt(32, 1))); - - // [2, 0) /\ [7, 4) = [7, 4) - LHS = ConstantRange(APInt(32, 2), APInt(32, 0)); - RHS = ConstantRange(APInt(32, 7), APInt(32, 4)); - EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 7), APInt(32, 4))); - - // [4, 2) /\ [1, 0) = [1, 0) - LHS = ConstantRange(APInt(32, 4), APInt(32, 2)); - RHS = ConstantRange(APInt(32, 1), APInt(32, 0)); - EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 4), APInt(32, 2))); - - // [15, 0) /\ [7, 6) = [15, 0) - LHS = ConstantRange(APInt(32, 15), APInt(32, 0)); - RHS = ConstantRange(APInt(32, 7), APInt(32, 6)); - EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 15), APInt(32, 0))); -} - -TEST_F(ConstantRangeTest, UnionWith) { - EXPECT_EQ(Wrap.unionWith(One), - ConstantRange(APInt(16, 0xaaa), APInt(16, 0xb))); - EXPECT_EQ(One.unionWith(Wrap), Wrap.unionWith(One)); - EXPECT_EQ(Empty.unionWith(Empty), Empty); - EXPECT_EQ(Full.unionWith(Full), Full); - EXPECT_EQ(Some.unionWith(Wrap), Full); - - // PR4545 - EXPECT_EQ(ConstantRange(APInt(16, 14), APInt(16, 1)).unionWith( - ConstantRange(APInt(16, 0), APInt(16, 8))), - ConstantRange(APInt(16, 14), APInt(16, 8))); - EXPECT_EQ(ConstantRange(APInt(16, 6), APInt(16, 4)).unionWith( - ConstantRange(APInt(16, 4), APInt(16, 0))), - ConstantRange(16)); - EXPECT_EQ(ConstantRange(APInt(16, 1), APInt(16, 0)).unionWith( - ConstantRange(APInt(16, 2), APInt(16, 1))), - ConstantRange(16)); -} - -TEST_F(ConstantRangeTest, SetDifference) { - EXPECT_EQ(Full.difference(Empty), Full); - EXPECT_EQ(Full.difference(Full), Empty); - EXPECT_EQ(Empty.difference(Empty), Empty); - EXPECT_EQ(Empty.difference(Full), Empty); - - ConstantRange A(APInt(16, 3), APInt(16, 7)); - ConstantRange B(APInt(16, 5), APInt(16, 9)); - ConstantRange C(APInt(16, 3), APInt(16, 5)); - ConstantRange D(APInt(16, 7), APInt(16, 9)); - ConstantRange E(APInt(16, 5), APInt(16, 4)); - ConstantRange F(APInt(16, 7), APInt(16, 3)); - EXPECT_EQ(A.difference(B), C); - EXPECT_EQ(B.difference(A), D); - EXPECT_EQ(E.difference(A), F); -} - -TEST_F(ConstantRangeTest, SubtractAPInt) { - EXPECT_EQ(Full.subtract(APInt(16, 4)), Full); - EXPECT_EQ(Empty.subtract(APInt(16, 4)), Empty); - EXPECT_EQ(Some.subtract(APInt(16, 4)), - ConstantRange(APInt(16, 0x6), APInt(16, 0xaa6))); - EXPECT_EQ(Wrap.subtract(APInt(16, 4)), - ConstantRange(APInt(16, 0xaa6), APInt(16, 0x6))); - EXPECT_EQ(One.subtract(APInt(16, 4)), - ConstantRange(APInt(16, 0x6))); -} - -TEST_F(ConstantRangeTest, Add) { - EXPECT_EQ(Full.add(APInt(16, 4)), Full); - EXPECT_EQ(Full.add(Full), Full); - EXPECT_EQ(Full.add(Empty), Empty); - EXPECT_EQ(Full.add(One), Full); - EXPECT_EQ(Full.add(Some), Full); - EXPECT_EQ(Full.add(Wrap), Full); - EXPECT_EQ(Empty.add(Empty), Empty); - EXPECT_EQ(Empty.add(One), Empty); - EXPECT_EQ(Empty.add(Some), Empty); - EXPECT_EQ(Empty.add(Wrap), Empty); - EXPECT_EQ(Empty.add(APInt(16, 4)), Empty); - EXPECT_EQ(Some.add(APInt(16, 4)), - ConstantRange(APInt(16, 0xe), APInt(16, 0xaae))); - EXPECT_EQ(Wrap.add(APInt(16, 4)), - ConstantRange(APInt(16, 0xaae), APInt(16, 0xe))); - EXPECT_EQ(One.add(APInt(16, 4)), - ConstantRange(APInt(16, 0xe))); -} - -TEST_F(ConstantRangeTest, Sub) { - EXPECT_EQ(Full.sub(APInt(16, 4)), Full); - EXPECT_EQ(Full.sub(Full), Full); - EXPECT_EQ(Full.sub(Empty), Empty); - EXPECT_EQ(Full.sub(One), Full); - EXPECT_EQ(Full.sub(Some), Full); - EXPECT_EQ(Full.sub(Wrap), Full); - EXPECT_EQ(Empty.sub(Empty), Empty); - EXPECT_EQ(Empty.sub(One), Empty); - EXPECT_EQ(Empty.sub(Some), Empty); - EXPECT_EQ(Empty.sub(Wrap), Empty); - EXPECT_EQ(Empty.sub(APInt(16, 4)), Empty); - EXPECT_EQ(Some.sub(APInt(16, 4)), - ConstantRange(APInt(16, 0x6), APInt(16, 0xaa6))); - EXPECT_EQ(Some.sub(Some), - ConstantRange(APInt(16, 0xf561), APInt(16, 0xaa0))); - EXPECT_EQ(Wrap.sub(APInt(16, 4)), - ConstantRange(APInt(16, 0xaa6), APInt(16, 0x6))); - EXPECT_EQ(One.sub(APInt(16, 4)), - ConstantRange(APInt(16, 0x6))); -} - -TEST_F(ConstantRangeTest, Multiply) { - EXPECT_EQ(Full.multiply(Full), Full); - EXPECT_EQ(Full.multiply(Empty), Empty); - EXPECT_EQ(Full.multiply(One), Full); - EXPECT_EQ(Full.multiply(Some), Full); - EXPECT_EQ(Full.multiply(Wrap), Full); - EXPECT_EQ(Empty.multiply(Empty), Empty); - EXPECT_EQ(Empty.multiply(One), Empty); - EXPECT_EQ(Empty.multiply(Some), Empty); - EXPECT_EQ(Empty.multiply(Wrap), Empty); - EXPECT_EQ(One.multiply(One), ConstantRange(APInt(16, 0xa*0xa), - APInt(16, 0xa*0xa + 1))); - EXPECT_EQ(One.multiply(Some), ConstantRange(APInt(16, 0xa*0xa), - APInt(16, 0xa*0xaa9 + 1))); - EXPECT_EQ(One.multiply(Wrap), Full); - EXPECT_EQ(Some.multiply(Some), Full); - EXPECT_EQ(Some.multiply(Wrap), Full); - EXPECT_EQ(Wrap.multiply(Wrap), Full); - - ConstantRange Zero(APInt(16, 0)); - EXPECT_EQ(Zero.multiply(Full), Zero); - EXPECT_EQ(Zero.multiply(Some), Zero); - EXPECT_EQ(Zero.multiply(Wrap), Zero); - EXPECT_EQ(Full.multiply(Zero), Zero); - EXPECT_EQ(Some.multiply(Zero), Zero); - EXPECT_EQ(Wrap.multiply(Zero), Zero); - - // http://llvm.org/PR4545 - EXPECT_EQ(ConstantRange(APInt(4, 1), APInt(4, 6)).multiply( - ConstantRange(APInt(4, 6), APInt(4, 2))), - ConstantRange(4, /*isFullSet=*/true)); -} - -TEST_F(ConstantRangeTest, UMax) { - EXPECT_EQ(Full.umax(Full), Full); - EXPECT_EQ(Full.umax(Empty), Empty); - EXPECT_EQ(Full.umax(Some), ConstantRange(APInt(16, 0xa), APInt(16, 0))); - EXPECT_EQ(Full.umax(Wrap), Full); - EXPECT_EQ(Full.umax(Some), ConstantRange(APInt(16, 0xa), APInt(16, 0))); - EXPECT_EQ(Empty.umax(Empty), Empty); - EXPECT_EQ(Empty.umax(Some), Empty); - EXPECT_EQ(Empty.umax(Wrap), Empty); - EXPECT_EQ(Empty.umax(One), Empty); - EXPECT_EQ(Some.umax(Some), Some); - EXPECT_EQ(Some.umax(Wrap), ConstantRange(APInt(16, 0xa), APInt(16, 0))); - EXPECT_EQ(Some.umax(One), Some); - // TODO: ConstantRange is currently over-conservative here. - EXPECT_EQ(Wrap.umax(Wrap), Full); - EXPECT_EQ(Wrap.umax(One), ConstantRange(APInt(16, 0xa), APInt(16, 0))); - EXPECT_EQ(One.umax(One), One); -} - -TEST_F(ConstantRangeTest, SMax) { - EXPECT_EQ(Full.smax(Full), Full); - EXPECT_EQ(Full.smax(Empty), Empty); - EXPECT_EQ(Full.smax(Some), ConstantRange(APInt(16, 0xa), - APInt::getSignedMinValue(16))); - EXPECT_EQ(Full.smax(Wrap), Full); - EXPECT_EQ(Full.smax(One), ConstantRange(APInt(16, 0xa), - APInt::getSignedMinValue(16))); - EXPECT_EQ(Empty.smax(Empty), Empty); - EXPECT_EQ(Empty.smax(Some), Empty); - EXPECT_EQ(Empty.smax(Wrap), Empty); - EXPECT_EQ(Empty.smax(One), Empty); - EXPECT_EQ(Some.smax(Some), Some); - EXPECT_EQ(Some.smax(Wrap), ConstantRange(APInt(16, 0xa), - APInt(16, (uint64_t)INT16_MIN))); - EXPECT_EQ(Some.smax(One), Some); - EXPECT_EQ(Wrap.smax(One), ConstantRange(APInt(16, 0xa), - APInt(16, (uint64_t)INT16_MIN))); - EXPECT_EQ(One.smax(One), One); -} - -TEST_F(ConstantRangeTest, UDiv) { - EXPECT_EQ(Full.udiv(Full), Full); - EXPECT_EQ(Full.udiv(Empty), Empty); - EXPECT_EQ(Full.udiv(One), ConstantRange(APInt(16, 0), - APInt(16, 0xffff / 0xa + 1))); - EXPECT_EQ(Full.udiv(Some), ConstantRange(APInt(16, 0), - APInt(16, 0xffff / 0xa + 1))); - EXPECT_EQ(Full.udiv(Wrap), Full); - EXPECT_EQ(Empty.udiv(Empty), Empty); - EXPECT_EQ(Empty.udiv(One), Empty); - EXPECT_EQ(Empty.udiv(Some), Empty); - EXPECT_EQ(Empty.udiv(Wrap), Empty); - EXPECT_EQ(One.udiv(One), ConstantRange(APInt(16, 1))); - EXPECT_EQ(One.udiv(Some), ConstantRange(APInt(16, 0), APInt(16, 2))); - EXPECT_EQ(One.udiv(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xb))); - EXPECT_EQ(Some.udiv(Some), ConstantRange(APInt(16, 0), APInt(16, 0x111))); - EXPECT_EQ(Some.udiv(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xaaa))); - EXPECT_EQ(Wrap.udiv(Wrap), Full); -} - -TEST_F(ConstantRangeTest, Shl) { - EXPECT_EQ(Full.shl(Full), Full); - EXPECT_EQ(Full.shl(Empty), Empty); - EXPECT_EQ(Full.shl(One), Full); // TODO: [0, (-1 << 0xa) + 1) - EXPECT_EQ(Full.shl(Some), Full); // TODO: [0, (-1 << 0xa) + 1) - EXPECT_EQ(Full.shl(Wrap), Full); - EXPECT_EQ(Empty.shl(Empty), Empty); - EXPECT_EQ(Empty.shl(One), Empty); - EXPECT_EQ(Empty.shl(Some), Empty); - EXPECT_EQ(Empty.shl(Wrap), Empty); - EXPECT_EQ(One.shl(One), ConstantRange(APInt(16, 0xa << 0xa), - APInt(16, (0xa << 0xa) + 1))); - EXPECT_EQ(One.shl(Some), Full); // TODO: [0xa << 0xa, 0) - EXPECT_EQ(One.shl(Wrap), Full); // TODO: [0xa, 0xa << 14 + 1) - EXPECT_EQ(Some.shl(Some), Full); // TODO: [0xa << 0xa, 0xfc01) - EXPECT_EQ(Some.shl(Wrap), Full); // TODO: [0xa, 0x7ff << 0x5 + 1) - EXPECT_EQ(Wrap.shl(Wrap), Full); -} - -TEST_F(ConstantRangeTest, Lshr) { - EXPECT_EQ(Full.lshr(Full), Full); - EXPECT_EQ(Full.lshr(Empty), Empty); - EXPECT_EQ(Full.lshr(One), ConstantRange(APInt(16, 0), - APInt(16, (0xffff >> 0xa) + 1))); - EXPECT_EQ(Full.lshr(Some), ConstantRange(APInt(16, 0), - APInt(16, (0xffff >> 0xa) + 1))); - EXPECT_EQ(Full.lshr(Wrap), Full); - EXPECT_EQ(Empty.lshr(Empty), Empty); - EXPECT_EQ(Empty.lshr(One), Empty); - EXPECT_EQ(Empty.lshr(Some), Empty); - EXPECT_EQ(Empty.lshr(Wrap), Empty); - EXPECT_EQ(One.lshr(One), ConstantRange(APInt(16, 0))); - EXPECT_EQ(One.lshr(Some), ConstantRange(APInt(16, 0))); - EXPECT_EQ(One.lshr(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xb))); - EXPECT_EQ(Some.lshr(Some), ConstantRange(APInt(16, 0), - APInt(16, (0xaaa >> 0xa) + 1))); - EXPECT_EQ(Some.lshr(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xaaa))); - EXPECT_EQ(Wrap.lshr(Wrap), Full); -} - -TEST(ConstantRange, MakeICmpRegion) { - // PR8250 - ConstantRange SMax = ConstantRange(APInt::getSignedMaxValue(32)); - EXPECT_TRUE(ConstantRange::makeICmpRegion(ICmpInst::ICMP_SGT, - SMax).isEmptySet()); -} - -} // anonymous namespace 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 using namespace llvm; @@ -22,22 +20,25 @@ ErrorOr t2() { return errc::invalid_argument; } TEST(ErrorOr, SimpleValue) { ErrorOr 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 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 > t3() { return std::unique_ptr(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(ErrorOr(0)); b = ErrorOr(0); -#if LLVM_HAS_CXX11_STDLIB ErrorOr > b1(ErrorOr >(0)); b1 = ErrorOr >(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 +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(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(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/LeakDetectorTest.cpp b/unittests/Support/LeakDetectorTest.cpp deleted file mode 100644 index d198c7a..0000000 --- a/unittests/Support/LeakDetectorTest.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//===- llvm/unittest/LeakDetector/LeakDetector.cpp - LeakDetector 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/LeakDetector.h" - -using namespace llvm; - -namespace { - -#ifdef GTEST_HAS_DEATH_TEST -#ifndef NDEBUG -TEST(LeakDetector, Death1) { - LeakDetector::addGarbageObject((void*) 1); - LeakDetector::addGarbageObject((void*) 2); - - EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 1), - ".*Ts.count\\(o\\) == 0 && \"Object already in set!\""); - EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 2), - "Cache != o && \"Object already in set!\""); -} -#endif -#endif - -} diff --git a/unittests/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 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 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 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 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 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 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 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 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 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[] = "!\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 Buf; + std::unique_ptr 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 Buf; + std::unique_ptr 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 #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 #if defined(__APPLE__) # include 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(value); - EXPECT_EQ(origional_uint8, - sys::SwapByteOrder(sys::SwapByteOrder(origional_uint8))); + uint8_t original_uint8 = static_cast(value); + EXPECT_EQ(original_uint8, + sys::SwapByteOrder(sys::SwapByteOrder(original_uint8))); - uint16_t origional_uint16 = static_cast(value); - EXPECT_EQ(origional_uint16, - sys::SwapByteOrder(sys::SwapByteOrder(origional_uint16))); + uint16_t original_uint16 = static_cast(value); + EXPECT_EQ(original_uint16, + sys::SwapByteOrder(sys::SwapByteOrder(original_uint16))); - uint32_t origional_uint32 = static_cast(value); - EXPECT_EQ(origional_uint32, - sys::SwapByteOrder(sys::SwapByteOrder(origional_uint32))); + uint32_t original_uint32 = static_cast(value); + EXPECT_EQ(original_uint32, + sys::SwapByteOrder(sys::SwapByteOrder(original_uint32))); - uint64_t origional_uint64 = static_cast(value); - EXPECT_EQ(origional_uint64, - sys::SwapByteOrder(sys::SwapByteOrder(origional_uint64))); + uint64_t original_uint64 = static_cast(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(value); - EXPECT_EQ(origional_int8, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int8))); + int8_t original_int8 = static_cast(value); + EXPECT_EQ(original_int8, + sys::SwapByteOrder(sys::SwapByteOrder(original_int8))); - int16_t origional_int16 = static_cast(value); - EXPECT_EQ(origional_int16, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int16))); + int16_t original_int16 = static_cast(value); + EXPECT_EQ(original_int16, + sys::SwapByteOrder(sys::SwapByteOrder(original_int16))); - int32_t origional_int32 = static_cast(value); - EXPECT_EQ(origional_int32, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int32))); + int32_t original_int32 = static_cast(value); + EXPECT_EQ(original_int32, + sys::SwapByteOrder(sys::SwapByteOrder(original_int32))); - int64_t origional_int64 = static_cast(value); - EXPECT_EQ(origional_int64, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int64))); + int64_t original_int64 = static_cast(value); + EXPECT_EQ(original_int64, + sys::SwapByteOrder(sys::SwapByteOrder(original_int64))); // Test other sign. value *= -1; - origional_int8 = static_cast(value); - EXPECT_EQ(origional_int8, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int8))); + original_int8 = static_cast(value); + EXPECT_EQ(original_int8, + sys::SwapByteOrder(sys::SwapByteOrder(original_int8))); - origional_int16 = static_cast(value); - EXPECT_EQ(origional_int16, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int16))); + original_int16 = static_cast(value); + EXPECT_EQ(original_int16, + sys::SwapByteOrder(sys::SwapByteOrder(original_int16))); - origional_int32 = static_cast(value); - EXPECT_EQ(origional_int32, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int32))); + original_int32 = static_cast(value); + EXPECT_EQ(original_int32, + sys::SwapByteOrder(sys::SwapByteOrder(original_int32))); - origional_int64 = static_cast(value); - EXPECT_EQ(origional_int64, - sys::SwapByteOrder(sys::SwapByteOrder(origional_int64))); + original_int64 = static_cast(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(now_t - now.toEpochTime())) < 2); + EXPECT_TRUE(std::abs(static_cast(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(epoch.nanoseconds())); // Confirm it reversible. EXPECT_EQ(ft1970, epoch.toWin32Time()); diff --git a/unittests/Support/ValueHandleTest.cpp b/unittests/Support/ValueHandleTest.cpp deleted file mode 100644 index 05aafa2..0000000 --- a/unittests/Support/ValueHandleTest.cpp +++ /dev/null @@ -1,408 +0,0 @@ -//===- llvm/unittest/Support/ValueHandleTest.cpp - ValueHandle 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/ValueHandle.h" -#include "llvm/ADT/OwningPtr.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LLVMContext.h" -#include "gtest/gtest.h" -#include - -using namespace llvm; - -namespace { - -class ValueHandle : public testing::Test { -protected: - Constant *ConstantV; - std::auto_ptr BitcastV; - - ValueHandle() : - ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)), - BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) { - } -}; - -class ConcreteCallbackVH : public CallbackVH { -public: - ConcreteCallbackVH(Value *V) : CallbackVH(V) {} -}; - -TEST_F(ValueHandle, WeakVH_BasicOperation) { - WeakVH WVH(BitcastV.get()); - EXPECT_EQ(BitcastV.get(), WVH); - WVH = ConstantV; - EXPECT_EQ(ConstantV, WVH); - - // Make sure I can call a method on the underlying Value. It - // doesn't matter which method. - EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), WVH->getType()); - EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType()); -} - -TEST_F(ValueHandle, WeakVH_Comparisons) { - WeakVH BitcastWVH(BitcastV.get()); - WeakVH ConstantWVH(ConstantV); - - EXPECT_TRUE(BitcastWVH == BitcastWVH); - EXPECT_TRUE(BitcastV.get() == BitcastWVH); - EXPECT_TRUE(BitcastWVH == BitcastV.get()); - EXPECT_FALSE(BitcastWVH == ConstantWVH); - - EXPECT_TRUE(BitcastWVH != ConstantWVH); - EXPECT_TRUE(BitcastV.get() != ConstantWVH); - EXPECT_TRUE(BitcastWVH != ConstantV); - EXPECT_FALSE(BitcastWVH != BitcastWVH); - - // Cast to Value* so comparisons work. - Value *BV = BitcastV.get(); - Value *CV = ConstantV; - EXPECT_EQ(BV < CV, BitcastWVH < ConstantWVH); - EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantWVH); - EXPECT_EQ(BV > CV, BitcastWVH > ConstantWVH); - EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantWVH); - - EXPECT_EQ(BV < CV, BitcastV.get() < ConstantWVH); - EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantWVH); - EXPECT_EQ(BV > CV, BitcastV.get() > ConstantWVH); - EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantWVH); - - EXPECT_EQ(BV < CV, BitcastWVH < ConstantV); - EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantV); - EXPECT_EQ(BV > CV, BitcastWVH > ConstantV); - EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantV); -} - -TEST_F(ValueHandle, WeakVH_FollowsRAUW) { - WeakVH WVH(BitcastV.get()); - WeakVH WVH_Copy(WVH); - WeakVH WVH_Recreated(BitcastV.get()); - BitcastV->replaceAllUsesWith(ConstantV); - EXPECT_EQ(ConstantV, WVH); - EXPECT_EQ(ConstantV, WVH_Copy); - EXPECT_EQ(ConstantV, WVH_Recreated); -} - -TEST_F(ValueHandle, WeakVH_NullOnDeletion) { - WeakVH WVH(BitcastV.get()); - WeakVH WVH_Copy(WVH); - WeakVH WVH_Recreated(BitcastV.get()); - BitcastV.reset(); - Value *null_value = NULL; - EXPECT_EQ(null_value, WVH); - EXPECT_EQ(null_value, WVH_Copy); - EXPECT_EQ(null_value, WVH_Recreated); -} - - -TEST_F(ValueHandle, AssertingVH_BasicOperation) { - AssertingVH AVH(BitcastV.get()); - CastInst *implicit_to_exact_type = AVH; - (void)implicit_to_exact_type; // Avoid warning. - - AssertingVH GenericAVH(BitcastV.get()); - EXPECT_EQ(BitcastV.get(), GenericAVH); - GenericAVH = ConstantV; - EXPECT_EQ(ConstantV, GenericAVH); - - // Make sure I can call a method on the underlying CastInst. It - // doesn't matter which method. - EXPECT_FALSE(AVH->mayWriteToMemory()); - EXPECT_FALSE((*AVH).mayWriteToMemory()); -} - -TEST_F(ValueHandle, AssertingVH_Const) { - const CastInst *ConstBitcast = BitcastV.get(); - AssertingVH AVH(ConstBitcast); - const CastInst *implicit_to_exact_type = AVH; - (void)implicit_to_exact_type; // Avoid warning. -} - -TEST_F(ValueHandle, AssertingVH_Comparisons) { - AssertingVH BitcastAVH(BitcastV.get()); - AssertingVH ConstantAVH(ConstantV); - - EXPECT_TRUE(BitcastAVH == BitcastAVH); - EXPECT_TRUE(BitcastV.get() == BitcastAVH); - EXPECT_TRUE(BitcastAVH == BitcastV.get()); - EXPECT_FALSE(BitcastAVH == ConstantAVH); - - EXPECT_TRUE(BitcastAVH != ConstantAVH); - EXPECT_TRUE(BitcastV.get() != ConstantAVH); - EXPECT_TRUE(BitcastAVH != ConstantV); - EXPECT_FALSE(BitcastAVH != BitcastAVH); - - // Cast to Value* so comparisons work. - Value *BV = BitcastV.get(); - Value *CV = ConstantV; - EXPECT_EQ(BV < CV, BitcastAVH < ConstantAVH); - EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantAVH); - EXPECT_EQ(BV > CV, BitcastAVH > ConstantAVH); - EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantAVH); - - EXPECT_EQ(BV < CV, BitcastV.get() < ConstantAVH); - EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantAVH); - EXPECT_EQ(BV > CV, BitcastV.get() > ConstantAVH); - EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantAVH); - - EXPECT_EQ(BV < CV, BitcastAVH < ConstantV); - EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantV); - EXPECT_EQ(BV > CV, BitcastAVH > ConstantV); - EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantV); -} - -TEST_F(ValueHandle, AssertingVH_DoesNotFollowRAUW) { - AssertingVH AVH(BitcastV.get()); - BitcastV->replaceAllUsesWith(ConstantV); - EXPECT_EQ(BitcastV.get(), AVH); -} - -#ifdef NDEBUG - -TEST_F(ValueHandle, AssertingVH_ReducesToPointer) { - EXPECT_EQ(sizeof(CastInst *), sizeof(AssertingVH)); -} - -#else // !NDEBUG - -#ifdef GTEST_HAS_DEATH_TEST - -TEST_F(ValueHandle, AssertingVH_Asserts) { - AssertingVH AVH(BitcastV.get()); - EXPECT_DEATH({BitcastV.reset();}, - "An asserting value handle still pointed to this value!"); - AssertingVH Copy(AVH); - AVH = NULL; - EXPECT_DEATH({BitcastV.reset();}, - "An asserting value handle still pointed to this value!"); - Copy = NULL; - BitcastV.reset(); -} - -#endif // GTEST_HAS_DEATH_TEST - -#endif // NDEBUG - -TEST_F(ValueHandle, CallbackVH_BasicOperation) { - ConcreteCallbackVH CVH(BitcastV.get()); - EXPECT_EQ(BitcastV.get(), CVH); - CVH = ConstantV; - EXPECT_EQ(ConstantV, CVH); - - // Make sure I can call a method on the underlying Value. It - // doesn't matter which method. - EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), CVH->getType()); - EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*CVH).getType()); -} - -TEST_F(ValueHandle, CallbackVH_Comparisons) { - ConcreteCallbackVH BitcastCVH(BitcastV.get()); - ConcreteCallbackVH ConstantCVH(ConstantV); - - EXPECT_TRUE(BitcastCVH == BitcastCVH); - EXPECT_TRUE(BitcastV.get() == BitcastCVH); - EXPECT_TRUE(BitcastCVH == BitcastV.get()); - EXPECT_FALSE(BitcastCVH == ConstantCVH); - - EXPECT_TRUE(BitcastCVH != ConstantCVH); - EXPECT_TRUE(BitcastV.get() != ConstantCVH); - EXPECT_TRUE(BitcastCVH != ConstantV); - EXPECT_FALSE(BitcastCVH != BitcastCVH); - - // Cast to Value* so comparisons work. - Value *BV = BitcastV.get(); - Value *CV = ConstantV; - EXPECT_EQ(BV < CV, BitcastCVH < ConstantCVH); - EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantCVH); - EXPECT_EQ(BV > CV, BitcastCVH > ConstantCVH); - EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantCVH); - - EXPECT_EQ(BV < CV, BitcastV.get() < ConstantCVH); - EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantCVH); - EXPECT_EQ(BV > CV, BitcastV.get() > ConstantCVH); - EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantCVH); - - EXPECT_EQ(BV < CV, BitcastCVH < ConstantV); - EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantV); - EXPECT_EQ(BV > CV, BitcastCVH > ConstantV); - EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantV); -} - -TEST_F(ValueHandle, CallbackVH_CallbackOnDeletion) { - class RecordingVH : public CallbackVH { - public: - int DeletedCalls; - int AURWCalls; - - RecordingVH() : DeletedCalls(0), AURWCalls(0) {} - RecordingVH(Value *V) : CallbackVH(V), DeletedCalls(0), AURWCalls(0) {} - - private: - virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } - virtual void allUsesReplacedWith(Value *) { AURWCalls++; } - }; - - RecordingVH RVH; - RVH = BitcastV.get(); - EXPECT_EQ(0, RVH.DeletedCalls); - EXPECT_EQ(0, RVH.AURWCalls); - BitcastV.reset(); - EXPECT_EQ(1, RVH.DeletedCalls); - EXPECT_EQ(0, RVH.AURWCalls); -} - -TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) { - class RecordingVH : public CallbackVH { - public: - int DeletedCalls; - Value *AURWArgument; - - RecordingVH() : DeletedCalls(0), AURWArgument(NULL) {} - RecordingVH(Value *V) - : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL) {} - - private: - virtual void deleted() { DeletedCalls++; CallbackVH::deleted(); } - virtual void allUsesReplacedWith(Value *new_value) { - EXPECT_EQ(NULL, AURWArgument); - AURWArgument = new_value; - } - }; - - RecordingVH RVH; - RVH = BitcastV.get(); - EXPECT_EQ(0, RVH.DeletedCalls); - EXPECT_EQ(NULL, RVH.AURWArgument); - BitcastV->replaceAllUsesWith(ConstantV); - EXPECT_EQ(0, RVH.DeletedCalls); - EXPECT_EQ(ConstantV, RVH.AURWArgument); -} - -TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) { - class RecoveringVH : public CallbackVH { - public: - int DeletedCalls; - Value *AURWArgument; - LLVMContext *Context; - - RecoveringVH() : DeletedCalls(0), AURWArgument(NULL), - Context(&getGlobalContext()) {} - RecoveringVH(Value *V) - : CallbackVH(V), DeletedCalls(0), AURWArgument(NULL), - Context(&getGlobalContext()) {} - - private: - virtual void deleted() { - getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))); - setValPtr(NULL); - } - virtual void allUsesReplacedWith(Value *new_value) { - ASSERT_TRUE(NULL != getValPtr()); - EXPECT_EQ(1U, getValPtr()->getNumUses()); - EXPECT_EQ(NULL, AURWArgument); - AURWArgument = new_value; - } - }; - - // Normally, if a value has uses, deleting it will crash. However, we can use - // a CallbackVH to remove the uses before the check for no uses. - RecoveringVH RVH; - RVH = BitcastV.get(); - std::auto_ptr BitcastUser( - BinaryOperator::CreateAdd(RVH, - Constant::getNullValue(Type::getInt32Ty(getGlobalContext())))); - EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0)); - BitcastV.reset(); // Would crash without the ValueHandler. - EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), RVH.AURWArgument); - EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), - BitcastUser->getOperand(0)); -} - -TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) { - // When a CallbackVH modifies other ValueHandles in its callbacks, - // that shouldn't interfere with non-modified ValueHandles receiving - // their appropriate callbacks. - // - // We create the active CallbackVH in the middle of a palindromic - // arrangement of other VHs so that the bad behavior would be - // triggered in whichever order callbacks run. - - class DestroyingVH : public CallbackVH { - public: - OwningPtr ToClear[2]; - DestroyingVH(Value *V) { - ToClear[0].reset(new WeakVH(V)); - setValPtr(V); - ToClear[1].reset(new WeakVH(V)); - } - virtual void deleted() { - ToClear[0].reset(); - ToClear[1].reset(); - CallbackVH::deleted(); - } - virtual void allUsesReplacedWith(Value *) { - ToClear[0].reset(); - ToClear[1].reset(); - } - }; - - { - WeakVH ShouldBeVisited1(BitcastV.get()); - DestroyingVH C(BitcastV.get()); - WeakVH ShouldBeVisited2(BitcastV.get()); - - BitcastV->replaceAllUsesWith(ConstantV); - EXPECT_EQ(ConstantV, static_cast(ShouldBeVisited1)); - EXPECT_EQ(ConstantV, static_cast(ShouldBeVisited2)); - } - - { - WeakVH ShouldBeVisited1(BitcastV.get()); - DestroyingVH C(BitcastV.get()); - WeakVH ShouldBeVisited2(BitcastV.get()); - - BitcastV.reset(); - EXPECT_EQ(NULL, static_cast(ShouldBeVisited1)); - EXPECT_EQ(NULL, static_cast(ShouldBeVisited2)); - } -} - -TEST_F(ValueHandle, AssertingVHCheckedLast) { - // If a CallbackVH exists to clear out a group of AssertingVHs on - // Value deletion, the CallbackVH should get a chance to do so - // before the AssertingVHs assert. - - class ClearingVH : public CallbackVH { - public: - AssertingVH *ToClear[2]; - ClearingVH(Value *V, - AssertingVH &A0, AssertingVH &A1) - : CallbackVH(V) { - ToClear[0] = &A0; - ToClear[1] = &A1; - } - - virtual void deleted() { - *ToClear[0] = 0; - *ToClear[1] = 0; - CallbackVH::deleted(); - } - }; - - AssertingVH A1, A2; - A1 = BitcastV.get(); - ClearingVH C(BitcastV.get(), A1, A2); - A2 = BitcastV.get(); - // C.deleted() should run first, clearing the two AssertingVHs, - // which should prevent them from asserting. - BitcastV.reset(); -} - -} 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 { 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 DynCastSequence; -LLVM_YAML_IS_SEQUENCE_VECTOR(DynCast) +LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation) namespace llvm { namespace yaml { template <> - struct MappingTraits { - static void mapping(IO &io, DynCast& info) { - // Change 10 to 13 when writing yaml. - if (Output *output = dyn_cast(&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(&io)) { - (void)input; - if (info.value == 20) - info.value = 23; - } + struct MappingTraits { + 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 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 M; - OwningPtr D; + std::unique_ptr M; + std::unique_ptr 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 + +using namespace llvm; + +static std::string +ShadowBytesToString(ArrayRef 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 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(1, a) +#define VEC(a) \ + SmallVector(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 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()); + 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(&OldI)) { + DbgDeclareInst* NewIntrin = dyn_cast(&NewI); + EXPECT_TRUE(NewIntrin); + + // Old address must belong to the old function + EXPECT_EQ(OldFunc, cast(OldIntrin->getAddress())-> + getParent()->getParent()); + // New address must belong to the new function + EXPECT_EQ(NewFunc, cast(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(&OldI)) { + DbgValueInst* NewIntrin = dyn_cast(&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 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(Div)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr); + + Instruction* Quotient = dyn_cast(cast(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 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(Div)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp); + + Instruction* Quotient = dyn_cast(cast(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 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(Rem)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr); + + Instruction* Remainder = dyn_cast(cast(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 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(Rem)); + EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp); + + Instruction* Remainder = dyn_cast(cast(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 MB(MemoryBuffer::getMemBuffer(List)); + std::unique_ptr 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 SCL(makeSpecialCaseList("# This is a comment.\n" - "\n" - "src:hello\n")); + std::unique_ptr 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 SCL(makeSpecialCaseList("fun:foo\n")); + std::unique_ptr 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 SCL(makeSpecialCaseList("global:foo\n")); + std::unique_ptr 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 SCL(makeSpecialCaseList("fun:foo\n")); + std::unique_ptr 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 SCL(makeSpecialCaseList("src:hello\n" - "fun:foo\n" - "global:bar\n")); + std::unique_ptr 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 SCL(makeSpecialCaseList("")); + std::unique_ptr SCL(makeSpecialCaseList("")); Module M("foo", Ctx); EXPECT_FALSE(SCL->isIn(M)); } -- cgit v1.1