From 37ed9c199ca639565f6ce88105f9e39e898d82d0 Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Mon, 1 Dec 2014 14:51:49 -0800 Subject: Update aosp/master LLVM for rebase to r222494. Change-Id: Ic787f5e0124df789bd26f3f24680f45e678eef2d --- unittests/ADT/APFloatTest.cpp | 164 +++++ unittests/ADT/APIntTest.cpp | 25 +- unittests/ADT/ArrayRefTest.cpp | 53 ++ unittests/ADT/CMakeLists.txt | 2 + unittests/ADT/DenseMapTest.cpp | 5 + unittests/ADT/DenseSetTest.cpp | 38 ++ unittests/ADT/FunctionRefTest.cpp | 28 + unittests/ADT/MapVectorTest.cpp | 69 ++ unittests/ADT/OptionalTest.cpp | 99 +++ unittests/ADT/PostOrderIteratorTest.cpp | 37 ++ unittests/ADT/StringMapTest.cpp | 22 +- unittests/ADT/TripleTest.cpp | 102 ++- unittests/Analysis/CFGTest.cpp | 10 +- unittests/Analysis/CMakeLists.txt | 2 + unittests/Analysis/CallGraphTest.cpp | 59 ++ unittests/Analysis/LazyCallGraphTest.cpp | 40 +- unittests/Analysis/Makefile | 2 +- unittests/Analysis/MixedTBAATest.cpp | 2 +- unittests/Bitcode/BitReaderTest.cpp | 160 ++++- unittests/Bitcode/BitstreamReaderTest.cpp | 56 ++ unittests/Bitcode/CMakeLists.txt | 2 + unittests/Bitcode/Makefile | 2 +- unittests/ExecutionEngine/CMakeLists.txt | 4 +- unittests/ExecutionEngine/ExecutionEngineTest.cpp | 48 +- unittests/ExecutionEngine/JIT/CMakeLists.txt | 64 -- .../JIT/IntelJITEventListenerTest.cpp | 113 ---- .../ExecutionEngine/JIT/JITEventListenerTest.cpp | 237 ------- .../JIT/JITEventListenerTestCommon.h | 207 ------ .../ExecutionEngine/JIT/JITMemoryManagerTest.cpp | 302 --------- unittests/ExecutionEngine/JIT/JITTest.cpp | 728 --------------------- unittests/ExecutionEngine/JIT/JITTests.def | 4 - unittests/ExecutionEngine/JIT/Makefile | 52 -- unittests/ExecutionEngine/JIT/MultiJITTest.cpp | 190 ------ .../JIT/OProfileJITEventListenerTest.cpp | 165 ----- unittests/ExecutionEngine/MCJIT/CMakeLists.txt | 2 +- unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp | 2 - .../MCJIT/MCJITMemoryManagerTest.cpp | 1 - .../MCJIT/MCJITMultipleModuleTest.cpp | 60 +- .../ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp | 39 +- unittests/ExecutionEngine/MCJIT/MCJITTest.cpp | 22 +- .../ExecutionEngine/MCJIT/MCJITTestAPICommon.h | 6 +- unittests/ExecutionEngine/MCJIT/MCJITTestBase.h | 22 +- unittests/ExecutionEngine/MCJIT/Makefile | 2 +- unittests/ExecutionEngine/Makefile | 2 +- unittests/IR/CMakeLists.txt | 2 + unittests/IR/ConstantsTest.cpp | 73 +++ unittests/IR/DebugInfoTest.cpp | 68 ++ unittests/IR/DominatorTreeTest.cpp | 7 +- unittests/IR/IRBuilderTest.cpp | 4 + unittests/IR/LegacyPassManagerTest.cpp | 52 +- unittests/IR/PassManagerTest.cpp | 2 +- unittests/IR/UseTest.cpp | 112 ++++ unittests/IR/UserTest.cpp | 2 +- unittests/IR/ValueMapTest.cpp | 4 +- unittests/IR/ValueTest.cpp | 25 +- unittests/LineEditor/CMakeLists.txt | 1 + unittests/Linker/CMakeLists.txt | 1 + unittests/Linker/LinkModulesTest.cpp | 44 +- unittests/Linker/Makefile | 2 +- unittests/MC/CMakeLists.txt | 13 +- unittests/MC/Disassembler.cpp | 64 ++ unittests/MC/Hexagon/CMakeLists.txt | 14 + unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp | 53 ++ unittests/MC/MCAtomTest.cpp | 31 - unittests/MC/Makefile | 2 +- unittests/MC/StringTableBuilderTest.cpp | 35 +- unittests/Support/AllocatorTest.cpp | 43 +- unittests/Support/CMakeLists.txt | 5 + unittests/Support/CommandLineTest.cpp | 25 +- unittests/Support/ConvertUTFTest.cpp | 16 +- unittests/Support/ErrorOrTest.cpp | 31 + unittests/Support/FileOutputBufferTest.cpp | 6 +- unittests/Support/LEB128Test.cpp | 37 ++ unittests/Support/LineIteratorTest.cpp | 130 +++- unittests/Support/LockFileManagerTest.cpp | 4 +- unittests/Support/MD5Test.cpp | 16 +- unittests/Support/MemoryBufferTest.cpp | 50 ++ unittests/Support/Path.cpp | 129 +++- unittests/Support/ProcessTest.cpp | 12 +- unittests/Support/ProgramTest.cpp | 50 ++ unittests/Support/SourceMgrTest.cpp | 5 +- unittests/Support/SpecialCaseListTest.cpp | 51 +- unittests/Support/YAMLIOTest.cpp | 7 + unittests/Support/YAMLParserTest.cpp | 7 +- unittests/Support/raw_ostream_test.cpp | 37 ++ unittests/Transforms/Utils/Cloning.cpp | 7 +- 86 files changed, 2086 insertions(+), 2444 deletions(-) create mode 100644 unittests/ADT/FunctionRefTest.cpp create mode 100644 unittests/ADT/PostOrderIteratorTest.cpp create mode 100644 unittests/Analysis/CallGraphTest.cpp create mode 100644 unittests/Bitcode/BitstreamReaderTest.cpp delete mode 100644 unittests/ExecutionEngine/JIT/CMakeLists.txt delete mode 100644 unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp delete mode 100644 unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp delete mode 100644 unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h delete mode 100644 unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp delete mode 100644 unittests/ExecutionEngine/JIT/JITTest.cpp delete mode 100644 unittests/ExecutionEngine/JIT/JITTests.def delete mode 100644 unittests/ExecutionEngine/JIT/Makefile delete mode 100644 unittests/ExecutionEngine/JIT/MultiJITTest.cpp delete mode 100644 unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp create mode 100644 unittests/IR/DebugInfoTest.cpp create mode 100644 unittests/IR/UseTest.cpp create mode 100644 unittests/MC/Disassembler.cpp create mode 100644 unittests/MC/Hexagon/CMakeLists.txt create mode 100644 unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp delete mode 100644 unittests/MC/MCAtomTest.cpp (limited to 'unittests') diff --git a/unittests/ADT/APFloatTest.cpp b/unittests/ADT/APFloatTest.cpp index 8f298cd..c7ec16b 100644 --- a/unittests/ADT/APFloatTest.cpp +++ b/unittests/ADT/APFloatTest.cpp @@ -474,6 +474,40 @@ TEST(APFloatTest, FMA) { f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven); EXPECT_EQ(12.0f, f1.convertToFloat()); } + + { + APFloat M1(APFloat::x87DoubleExtended, 1.0); + APFloat M2(APFloat::x87DoubleExtended, 1.0); + APFloat A(APFloat::x87DoubleExtended, 3.0); + + bool losesInfo = false; + M1.fusedMultiplyAdd(M1, A, APFloat::rmNearestTiesToEven); + M1.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &losesInfo); + EXPECT_FALSE(losesInfo); + EXPECT_EQ(4.0f, M1.convertToFloat()); + } +} + +TEST(APFloatTest, MinNum) { + APFloat f1(1.0); + APFloat f2(2.0); + APFloat nan = APFloat::getNaN(APFloat::IEEEdouble); + + EXPECT_EQ(1.0, minnum(f1, f2).convertToDouble()); + EXPECT_EQ(1.0, minnum(f2, f1).convertToDouble()); + EXPECT_EQ(1.0, minnum(f1, nan).convertToDouble()); + EXPECT_EQ(1.0, minnum(nan, f1).convertToDouble()); +} + +TEST(APFloatTest, MaxNum) { + APFloat f1(1.0); + APFloat f2(2.0); + APFloat nan = APFloat::getNaN(APFloat::IEEEdouble); + + EXPECT_EQ(2.0, maxnum(f1, f2).convertToDouble()); + EXPECT_EQ(2.0, maxnum(f2, f1).convertToDouble()); + EXPECT_EQ(1.0, maxnum(f1, nan).convertToDouble()); + EXPECT_EQ(1.0, minnum(nan, f1).convertToDouble()); } TEST(APFloatTest, Denormal) { @@ -1342,6 +1376,17 @@ TEST(APFloatTest, getZero) { } } +TEST(APFloatTest, copySign) { + EXPECT_TRUE(APFloat(-42.0).bitwiseIsEqual( + APFloat::copySign(APFloat(42.0), APFloat(-1.0)))); + EXPECT_TRUE(APFloat(42.0).bitwiseIsEqual( + APFloat::copySign(APFloat(-42.0), APFloat(1.0)))); + EXPECT_TRUE(APFloat(-42.0).bitwiseIsEqual( + APFloat::copySign(APFloat(-42.0), APFloat(-1.0)))); + EXPECT_TRUE(APFloat(42.0).bitwiseIsEqual( + APFloat::copySign(APFloat(42.0), APFloat(1.0)))); +} + TEST(APFloatTest, convert) { bool losesInfo; APFloat test(APFloat::IEEEdouble, "1.0"); @@ -2671,4 +2716,123 @@ TEST(APFloatTest, divide) { } } +TEST(APFloatTest, operatorOverloads) { + // This is mostly testing that these operator overloads compile. + APFloat One = APFloat(APFloat::IEEEsingle, "0x1p+0"); + APFloat Two = APFloat(APFloat::IEEEsingle, "0x2p+0"); + EXPECT_TRUE(Two.bitwiseIsEqual(One + One)); + EXPECT_TRUE(One.bitwiseIsEqual(Two - One)); + EXPECT_TRUE(Two.bitwiseIsEqual(One * Two)); + EXPECT_TRUE(One.bitwiseIsEqual(Two / Two)); +} + +TEST(APFloatTest, abs) { + APFloat PInf = APFloat::getInf(APFloat::IEEEsingle, false); + APFloat MInf = APFloat::getInf(APFloat::IEEEsingle, true); + APFloat PZero = APFloat::getZero(APFloat::IEEEsingle, false); + APFloat MZero = APFloat::getZero(APFloat::IEEEsingle, true); + APFloat PQNaN = APFloat::getNaN(APFloat::IEEEsingle, false); + APFloat MQNaN = APFloat::getNaN(APFloat::IEEEsingle, true); + APFloat PSNaN = APFloat::getSNaN(APFloat::IEEEsingle, false); + APFloat MSNaN = APFloat::getSNaN(APFloat::IEEEsingle, true); + APFloat PNormalValue = APFloat(APFloat::IEEEsingle, "0x1p+0"); + APFloat MNormalValue = APFloat(APFloat::IEEEsingle, "-0x1p+0"); + APFloat PLargestValue = APFloat::getLargest(APFloat::IEEEsingle, false); + APFloat MLargestValue = APFloat::getLargest(APFloat::IEEEsingle, true); + APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle, false); + APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle, true); + APFloat PSmallestNormalized = + APFloat::getSmallestNormalized(APFloat::IEEEsingle, false); + APFloat MSmallestNormalized = + APFloat::getSmallestNormalized(APFloat::IEEEsingle, true); + + EXPECT_TRUE(PInf.bitwiseIsEqual(abs(PInf))); + EXPECT_TRUE(PInf.bitwiseIsEqual(abs(MInf))); + EXPECT_TRUE(PZero.bitwiseIsEqual(abs(PZero))); + EXPECT_TRUE(PZero.bitwiseIsEqual(abs(MZero))); + EXPECT_TRUE(PQNaN.bitwiseIsEqual(abs(PQNaN))); + EXPECT_TRUE(PQNaN.bitwiseIsEqual(abs(MQNaN))); + EXPECT_TRUE(PSNaN.bitwiseIsEqual(abs(PSNaN))); + EXPECT_TRUE(PSNaN.bitwiseIsEqual(abs(MSNaN))); + EXPECT_TRUE(PNormalValue.bitwiseIsEqual(abs(PNormalValue))); + EXPECT_TRUE(PNormalValue.bitwiseIsEqual(abs(MNormalValue))); + EXPECT_TRUE(PLargestValue.bitwiseIsEqual(abs(PLargestValue))); + EXPECT_TRUE(PLargestValue.bitwiseIsEqual(abs(MLargestValue))); + EXPECT_TRUE(PSmallestValue.bitwiseIsEqual(abs(PSmallestValue))); + EXPECT_TRUE(PSmallestValue.bitwiseIsEqual(abs(MSmallestValue))); + EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(PSmallestNormalized))); + EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(MSmallestNormalized))); +} + +TEST(APFloatTest, ilogb) { + EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle, "0x1p+0"))); + EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle, "-0x1p+0"))); + EXPECT_EQ(42, ilogb(APFloat(APFloat::IEEEsingle, "0x1p+42"))); + EXPECT_EQ(-42, ilogb(APFloat(APFloat::IEEEsingle, "0x1p-42"))); + + EXPECT_EQ(APFloat::IEK_Inf, + ilogb(APFloat::getInf(APFloat::IEEEsingle, false))); + EXPECT_EQ(APFloat::IEK_Inf, + ilogb(APFloat::getInf(APFloat::IEEEsingle, true))); + EXPECT_EQ(APFloat::IEK_Zero, + ilogb(APFloat::getZero(APFloat::IEEEsingle, false))); + EXPECT_EQ(APFloat::IEK_Zero, + ilogb(APFloat::getZero(APFloat::IEEEsingle, true))); + EXPECT_EQ(APFloat::IEK_NaN, + ilogb(APFloat::getNaN(APFloat::IEEEsingle, false))); + EXPECT_EQ(APFloat::IEK_NaN, + ilogb(APFloat::getSNaN(APFloat::IEEEsingle, false))); + + EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle, false))); + EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle, true))); + EXPECT_EQ(-126, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, false))); + EXPECT_EQ(-126, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, true))); + EXPECT_EQ(-126, + ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle, false))); + EXPECT_EQ(-126, + ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle, true))); +} + +TEST(APFloatTest, scalbn) { + EXPECT_TRUE( + APFloat(APFloat::IEEEsingle, "0x1p+0") + .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 0))); + EXPECT_TRUE( + APFloat(APFloat::IEEEsingle, "0x1p+42") + .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 42))); + EXPECT_TRUE( + APFloat(APFloat::IEEEsingle, "0x1p-42") + .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), -42))); + + APFloat PInf = APFloat::getInf(APFloat::IEEEsingle, false); + APFloat MInf = APFloat::getInf(APFloat::IEEEsingle, true); + APFloat PZero = APFloat::getZero(APFloat::IEEEsingle, false); + APFloat MZero = APFloat::getZero(APFloat::IEEEsingle, true); + APFloat QPNaN = APFloat::getNaN(APFloat::IEEEsingle, false); + APFloat QMNaN = APFloat::getNaN(APFloat::IEEEsingle, true); + APFloat SNaN = APFloat::getSNaN(APFloat::IEEEsingle, false); + + EXPECT_TRUE(PInf.bitwiseIsEqual(scalbn(PInf, 0))); + EXPECT_TRUE(MInf.bitwiseIsEqual(scalbn(MInf, 0))); + EXPECT_TRUE(PZero.bitwiseIsEqual(scalbn(PZero, 0))); + EXPECT_TRUE(MZero.bitwiseIsEqual(scalbn(MZero, 0))); + EXPECT_TRUE(QPNaN.bitwiseIsEqual(scalbn(QPNaN, 0))); + EXPECT_TRUE(QMNaN.bitwiseIsEqual(scalbn(QMNaN, 0))); + EXPECT_TRUE(SNaN.bitwiseIsEqual(scalbn(SNaN, 0))); + + EXPECT_TRUE( + PInf.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 128))); + EXPECT_TRUE(MInf.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "-0x1p+0"), 128))); + EXPECT_TRUE( + PInf.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+127"), 1))); + EXPECT_TRUE(PZero.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), -127))); + EXPECT_TRUE(MZero.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "-0x1p+0"), -127))); + EXPECT_TRUE(PZero.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -1))); + EXPECT_TRUE(PZero.bitwiseIsEqual( + scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -1))); +} } diff --git a/unittests/ADT/APIntTest.cpp b/unittests/ADT/APIntTest.cpp index 19c47ab..8198c71 100644 --- a/unittests/ADT/APIntTest.cpp +++ b/unittests/ADT/APIntTest.cpp @@ -614,7 +614,7 @@ TEST(APIntTest, arrayAccess) { 0x7E7FFA5EADD8846ULL, 0x305F341CA00B613DULL }; - APInt A2(integerPartWidth*4, ArrayRef(E2, 4)); + APInt A2(integerPartWidth*4, E2); for (unsigned i = 0; i < 4; ++i) { for (unsigned j = 0; j < integerPartWidth; ++j) { EXPECT_EQ(bool(E2[i] & (1ULL << j)), @@ -653,17 +653,17 @@ TEST(APIntTest, nearestLogBase2) { // Test round up. integerPart I4[4] = {0x0, 0xF, 0x18, 0x0}; - APInt A4(integerPartWidth*4, ArrayRef(I4, 4)); + APInt A4(integerPartWidth*4, I4); EXPECT_EQ(A4.nearestLogBase2(), A4.ceilLogBase2()); // Test round down. integerPart I5[4] = {0x0, 0xF, 0x10, 0x0}; - APInt A5(integerPartWidth*4, ArrayRef(I5, 4)); + APInt A5(integerPartWidth*4, I5); EXPECT_EQ(A5.nearestLogBase2(), A5.logBase2()); // Test ties round up. uint64_t I6[4] = {0x0, 0x0, 0x0, 0x18}; - APInt A6(integerPartWidth*4, ArrayRef(I6, 4)); + APInt A6(integerPartWidth*4, I6); EXPECT_EQ(A6.nearestLogBase2(), A6.ceilLogBase2()); // Test BitWidth == 1 special cases. @@ -678,4 +678,21 @@ TEST(APIntTest, nearestLogBase2) { EXPECT_EQ(A9.nearestLogBase2(), UINT32_MAX); } +TEST(APIntTest, SelfMoveAssignment) { + APInt X(32, 0xdeadbeef); + X = std::move(X); + EXPECT_EQ(32u, X.getBitWidth()); + EXPECT_EQ(0xdeadbeefULL, X.getLimitedValue()); + + uint64_t Bits[] = {0xdeadbeefdeadbeefULL, 0xdeadbeefdeadbeefULL}; + APInt Y(128, Bits); + Y = std::move(Y); + EXPECT_EQ(128u, Y.getBitWidth()); + EXPECT_EQ(~0ULL, Y.getLimitedValue()); + const uint64_t *Raw = Y.getRawData(); + EXPECT_EQ(2u, Y.getNumWords()); + EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[0]); + EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[1]); +} + } diff --git a/unittests/ADT/ArrayRefTest.cpp b/unittests/ADT/ArrayRefTest.cpp index 293afc6..f9c98a5 100644 --- a/unittests/ADT/ArrayRefTest.cpp +++ b/unittests/ADT/ArrayRefTest.cpp @@ -13,6 +13,23 @@ #include "gtest/gtest.h" using namespace llvm; +// Check that the ArrayRef-of-pointer converting constructor only allows adding +// cv qualifiers (not removing them, or otherwise changing the type) +static_assert( + std::is_convertible, ArrayRef>::value, + "Adding const"); +static_assert( + std::is_convertible, ArrayRef>::value, + "Adding volatile"); +static_assert(!std::is_convertible, ArrayRef>::value, + "Changing pointer of one type to a pointer of another"); +static_assert( + !std::is_convertible, ArrayRef>::value, + "Removing const"); +static_assert( + !std::is_convertible, ArrayRef>::value, + "Removing volatile"); + namespace llvm { TEST(ArrayRefTest, AllocatorCopy) { @@ -36,5 +53,41 @@ TEST(ArrayRefTest, DropBack) { EXPECT_TRUE(AR1.drop_back().equals(AR2)); } +TEST(ArrayRefTest, Equals) { + static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8}; + ArrayRef AR1(A1); + EXPECT_TRUE(AR1.equals(1, 2, 3, 4, 5, 6, 7, 8)); + EXPECT_FALSE(AR1.equals(8, 1, 2, 4, 5, 6, 6, 7)); + EXPECT_FALSE(AR1.equals(2, 4, 5, 6, 6, 7, 8, 1)); + EXPECT_FALSE(AR1.equals(0, 1, 2, 4, 5, 6, 6, 7)); + EXPECT_FALSE(AR1.equals(1, 2, 42, 4, 5, 6, 7, 8)); + EXPECT_FALSE(AR1.equals(42, 2, 3, 4, 5, 6, 7, 8)); + EXPECT_FALSE(AR1.equals(1, 2, 3, 4, 5, 6, 7, 42)); + EXPECT_FALSE(AR1.equals(1, 2, 3, 4, 5, 6, 7)); + EXPECT_FALSE(AR1.equals(1, 2, 3, 4, 5, 6, 7, 8, 9)); + + ArrayRef AR1a = AR1.drop_back(); + EXPECT_TRUE(AR1a.equals(1, 2, 3, 4, 5, 6, 7)); + EXPECT_FALSE(AR1a.equals(1, 2, 3, 4, 5, 6, 7, 8)); + + ArrayRef AR1b = AR1a.slice(2, 4); + EXPECT_TRUE(AR1b.equals(3, 4, 5, 6)); + EXPECT_FALSE(AR1b.equals(2, 3, 4, 5, 6)); + EXPECT_FALSE(AR1b.equals(3, 4, 5, 6, 7)); +} + +TEST(ArrayRefTest, EmptyEquals) { + EXPECT_TRUE(ArrayRef() == ArrayRef()); +} + +TEST(ArrayRefTest, ConstConvert) { + int buf[4]; + for (int i = 0; i < 4; ++i) + buf[i] = i; + + static int *A[] = {&buf[0], &buf[1], &buf[2], &buf[3]}; + ArrayRef a((ArrayRef(A))); + a = ArrayRef(A); +} } // end anonymous namespace diff --git a/unittests/ADT/CMakeLists.txt b/unittests/ADT/CMakeLists.txt index 0f214f3..d899852 100644 --- a/unittests/ADT/CMakeLists.txt +++ b/unittests/ADT/CMakeLists.txt @@ -13,6 +13,7 @@ set(ADTSources DenseMapTest.cpp DenseSetTest.cpp FoldingSet.cpp + FunctionRefTest.cpp HashingTest.cpp ilistTest.cpp ImmutableMapTest.cpp @@ -26,6 +27,7 @@ set(ADTSources PackedVectorTest.cpp PointerIntPairTest.cpp PointerUnionTest.cpp + PostOrderIteratorTest.cpp SCCIteratorTest.cpp SmallPtrSetTest.cpp SmallStringTest.cpp diff --git a/unittests/ADT/DenseMapTest.cpp b/unittests/ADT/DenseMapTest.cpp index 75a910a..f497983 100644 --- a/unittests/ADT/DenseMapTest.cpp +++ b/unittests/ADT/DenseMapTest.cpp @@ -244,6 +244,11 @@ TYPED_TEST(DenseMapTest, AssignmentTest) { EXPECT_EQ(1u, copyMap.size()); EXPECT_EQ(this->getValue(), copyMap[this->getKey()]); + + // test self-assignment. + copyMap = copyMap; + EXPECT_EQ(1u, copyMap.size()); + EXPECT_EQ(this->getValue(), copyMap[this->getKey()]); } // Test swap method diff --git a/unittests/ADT/DenseSetTest.cpp b/unittests/ADT/DenseSetTest.cpp index 154c589..5952353 100644 --- a/unittests/ADT/DenseSetTest.cpp +++ b/unittests/ADT/DenseSetTest.cpp @@ -27,4 +27,42 @@ TEST_F(DenseSetTest, DoubleEntrySetTest) { EXPECT_EQ(0u, set.count(2)); } +struct TestDenseSetInfo { + static inline unsigned getEmptyKey() { return ~0; } + static inline unsigned getTombstoneKey() { return ~0U - 1; } + static unsigned getHashValue(const unsigned& Val) { return Val * 37U; } + static unsigned getHashValue(const char* Val) { + return (unsigned)(Val[0] - 'a') * 37U; + } + static bool isEqual(const unsigned& LHS, const unsigned& RHS) { + return LHS == RHS; + } + static bool isEqual(const char* LHS, const unsigned& RHS) { + return (unsigned)(LHS[0] - 'a') == RHS; + } +}; + +TEST(DenseSetCustomTest, FindAsTest) { + DenseSet set; + set.insert(0); + set.insert(1); + set.insert(2); + + // Size tests + EXPECT_EQ(3u, set.size()); + + // Normal lookup tests + EXPECT_EQ(1u, set.count(1)); + EXPECT_EQ(0u, *set.find(0)); + EXPECT_EQ(1u, *set.find(1)); + EXPECT_EQ(2u, *set.find(2)); + EXPECT_TRUE(set.find(3) == set.end()); + + // find_as() tests + EXPECT_EQ(0u, *set.find_as("a")); + EXPECT_EQ(1u, *set.find_as("b")); + EXPECT_EQ(2u, *set.find_as("c")); + EXPECT_TRUE(set.find_as("d") == set.end()); +} + } diff --git a/unittests/ADT/FunctionRefTest.cpp b/unittests/ADT/FunctionRefTest.cpp new file mode 100644 index 0000000..075d9a0 --- /dev/null +++ b/unittests/ADT/FunctionRefTest.cpp @@ -0,0 +1,28 @@ +//===- llvm/unittest/ADT/MakeUniqueTest.cpp - make_unique unit tests ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/STLExtras.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +// Ensure that copies of a function_ref copy the underlying state rather than +// causing one function_ref to chain to the next. +TEST(FunctionRefTest, Copy) { + auto A = [] { return 1; }; + auto B = [] { return 2; }; + function_ref X = A; + function_ref Y = X; + X = B; + EXPECT_EQ(1, Y()); +} + +} diff --git a/unittests/ADT/MapVectorTest.cpp b/unittests/ADT/MapVectorTest.cpp index 11178bc..8919799 100644 --- a/unittests/ADT/MapVectorTest.cpp +++ b/unittests/ADT/MapVectorTest.cpp @@ -9,6 +9,7 @@ #include "gtest/gtest.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/iterator_range.h" #include using namespace llvm; @@ -53,3 +54,71 @@ TEST(MapVectorTest, insert_pop) { EXPECT_EQ(MV[1], 2); EXPECT_EQ(MV[4], 7); } + +TEST(MapVectorTest, erase) { + MapVector MV; + + MV.insert(std::make_pair(1, 2)); + MV.insert(std::make_pair(3, 4)); + MV.insert(std::make_pair(5, 6)); + ASSERT_EQ(MV.size(), 3u); + + MV.erase(MV.find(1)); + ASSERT_EQ(MV.size(), 2u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV[3], 4); + ASSERT_EQ(MV[5], 6); + + ASSERT_EQ(MV.erase(3), 1u); + ASSERT_EQ(MV.size(), 1u); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV[5], 6); + + ASSERT_EQ(MV.erase(79), 0u); + ASSERT_EQ(MV.size(), 1u); +} + +TEST(MapVectorTest, remove_if) { + MapVector MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + MV.remove_if([](const std::pair &Val) { return Val.second % 2; }); + ASSERT_EQ(MV.size(), 3u); + ASSERT_EQ(MV.find(1), MV.end()); + ASSERT_EQ(MV.find(3), MV.end()); + ASSERT_EQ(MV.find(5), MV.end()); + ASSERT_EQ(MV[2], 12); + ASSERT_EQ(MV[4], 14); + ASSERT_EQ(MV[6], 16); +} + +TEST(MapVectorTest, iteration_test) { + MapVector MV; + + MV.insert(std::make_pair(1, 11)); + MV.insert(std::make_pair(2, 12)); + MV.insert(std::make_pair(3, 13)); + MV.insert(std::make_pair(4, 14)); + MV.insert(std::make_pair(5, 15)); + MV.insert(std::make_pair(6, 16)); + ASSERT_EQ(MV.size(), 6u); + + int count = 1; + for (auto P : make_range(MV.begin(), MV.end())) { + ASSERT_EQ(P.first, count); + count++; + } + + count = 6; + for (auto P : make_range(MV.rbegin(), MV.rend())) { + ASSERT_EQ(P.first, count); + count--; + } +} diff --git a/unittests/ADT/OptionalTest.cpp b/unittests/ADT/OptionalTest.cpp index 2da408c..cadadce 100644 --- a/unittests/ADT/OptionalTest.cpp +++ b/unittests/ADT/OptionalTest.cpp @@ -169,6 +169,52 @@ TEST_F(OptionalTest, NullCopyConstructionTest) { EXPECT_EQ(0u, NonDefaultConstructible::Destructions); } +TEST_F(OptionalTest, GetValueOr) { + Optional A; + EXPECT_EQ(42, A.getValueOr(42)); + + A = 5; + EXPECT_EQ(5, A.getValueOr(42)); +} + +struct MultiArgConstructor { + int x, y; + MultiArgConstructor(int x, int y) : x(x), y(y) {} + explicit MultiArgConstructor(int x, bool positive) + : x(x), y(positive ? x : -x) {} + + MultiArgConstructor(const MultiArgConstructor &) LLVM_DELETED_FUNCTION; + MultiArgConstructor(MultiArgConstructor &&) LLVM_DELETED_FUNCTION; + MultiArgConstructor &operator=(const MultiArgConstructor &) LLVM_DELETED_FUNCTION; + MultiArgConstructor &operator=(MultiArgConstructor &&) LLVM_DELETED_FUNCTION; + + static unsigned Destructions; + ~MultiArgConstructor() { + ++Destructions; + } + static void ResetCounts() { + Destructions = 0; + } +}; +unsigned MultiArgConstructor::Destructions = 0; + +TEST_F(OptionalTest, Emplace) { + MultiArgConstructor::ResetCounts(); + Optional A; + + A.emplace(1, 2); + EXPECT_TRUE(A.hasValue()); + EXPECT_EQ(1, A->x); + EXPECT_EQ(2, A->y); + EXPECT_EQ(0u, MultiArgConstructor::Destructions); + + A.emplace(5, false); + EXPECT_TRUE(A.hasValue()); + EXPECT_EQ(5, A->x); + EXPECT_EQ(-5, A->y); + EXPECT_EQ(1u, MultiArgConstructor::Destructions); +} + struct MoveOnly { static unsigned MoveConstructions; static unsigned Destructions; @@ -278,5 +324,58 @@ TEST_F(OptionalTest, MoveOnlyAssigningAssignment) { EXPECT_EQ(1u, MoveOnly::Destructions); } +struct Immovable { + static unsigned Constructions; + static unsigned Destructions; + int val; + explicit Immovable(int val) : val(val) { + ++Constructions; + } + ~Immovable() { + ++Destructions; + } + static void ResetCounts() { + Constructions = 0; + Destructions = 0; + } +private: + // This should disable all move/copy operations. + Immovable(Immovable&& other) LLVM_DELETED_FUNCTION; +}; + +unsigned Immovable::Constructions = 0; +unsigned Immovable::Destructions = 0; + +TEST_F(OptionalTest, ImmovableEmplace) { + Optional A; + Immovable::ResetCounts(); + A.emplace(4); + EXPECT_TRUE((bool)A); + EXPECT_EQ(4, A->val); + EXPECT_EQ(1u, Immovable::Constructions); + EXPECT_EQ(0u, Immovable::Destructions); +} + +#if LLVM_HAS_RVALUE_REFERENCE_THIS + +TEST_F(OptionalTest, MoveGetValueOr) { + Optional A; + + MoveOnly::ResetCounts(); + EXPECT_EQ(42, std::move(A).getValueOr(MoveOnly(42)).val); + EXPECT_EQ(1u, MoveOnly::MoveConstructions); + EXPECT_EQ(0u, MoveOnly::MoveAssignments); + EXPECT_EQ(2u, MoveOnly::Destructions); + + A = MoveOnly(5); + MoveOnly::ResetCounts(); + EXPECT_EQ(5, std::move(A).getValueOr(MoveOnly(42)).val); + EXPECT_EQ(1u, MoveOnly::MoveConstructions); + EXPECT_EQ(0u, MoveOnly::MoveAssignments); + EXPECT_EQ(2u, MoveOnly::Destructions); +} + +#endif // LLVM_HAS_RVALUE_REFERENCE_THIS + } // end anonymous namespace diff --git a/unittests/ADT/PostOrderIteratorTest.cpp b/unittests/ADT/PostOrderIteratorTest.cpp new file mode 100644 index 0000000..1da1078 --- /dev/null +++ b/unittests/ADT/PostOrderIteratorTest.cpp @@ -0,0 +1,37 @@ +//===- PostOrderIteratorTest.cpp - PostOrderIterator unit tests -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "gtest/gtest.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/CFG.h" +using namespace llvm; + +namespace { + +// Whether we're able to compile +TEST(PostOrderIteratorTest, Compiles) { + typedef SmallPtrSet ExtSetTy; + + // Tests that template specializations are kept up to date + void *Null = nullptr; + po_iterator_storage, false> PIS; + PIS.insertEdge(Null, Null); + ExtSetTy Ext; + po_iterator_storage PISExt(Ext); + PIS.insertEdge(Null, Null); + + // Test above, but going through po_iterator (which inherits from template + // base) + BasicBlock *NullBB = nullptr; + auto PI = po_end(NullBB); + PI.insertEdge(NullBB, NullBB); + auto PIExt = po_ext_end(NullBB, Ext); + PIExt.insertEdge(NullBB, NullBB); +} +} diff --git a/unittests/ADT/StringMapTest.cpp b/unittests/ADT/StringMapTest.cpp index 028375d..33d668f 100644 --- a/unittests/ADT/StringMapTest.cpp +++ b/unittests/ADT/StringMapTest.cpp @@ -250,15 +250,21 @@ struct StringMapTestStruct { TEST_F(StringMapTest, NonDefaultConstructable) { StringMap t; - t.GetOrCreateValue("Test", StringMapTestStruct(123)); + t.insert(std::make_pair("Test", StringMapTestStruct(123))); StringMap::iterator iter = t.find("Test"); ASSERT_NE(iter, t.end()); ASSERT_EQ(iter->second.i, 123); } +struct Immovable { + Immovable() {} + Immovable(Immovable&&) LLVM_DELETED_FUNCTION; // will disable the other special members +}; + struct MoveOnly { int i; MoveOnly(int i) : i(i) {} + MoveOnly(const Immovable&) : i(0) {} MoveOnly(MoveOnly &&RHS) : i(RHS.i) {} MoveOnly &operator=(MoveOnly &&RHS) { i = RHS.i; @@ -270,17 +276,23 @@ private: MoveOnly &operator=(const MoveOnly &) LLVM_DELETED_FUNCTION; }; -TEST_F(StringMapTest, MoveOnlyKey) { +TEST_F(StringMapTest, MoveOnly) { StringMap t; - t.GetOrCreateValue("Test", MoveOnly(42)); + t.insert(std::make_pair("Test", MoveOnly(42))); StringRef Key = "Test"; StringMapEntry::Create(Key, MoveOnly(42)) ->Destroy(); } +TEST_F(StringMapTest, CtorArg) { + StringRef Key = "Test"; + StringMapEntry::Create(Key, Immovable()) + ->Destroy(); +} + TEST_F(StringMapTest, MoveConstruct) { StringMap A; - A.GetOrCreateValue("x", 42); + A["x"] = 42; StringMap B = std::move(A); ASSERT_EQ(A.size(), 0u); ASSERT_EQ(B.size(), 1u); @@ -325,7 +337,7 @@ struct Countable { TEST_F(StringMapTest, MoveDtor) { int InstanceCount = 0; StringMap A; - A.GetOrCreateValue("x", Countable(42, InstanceCount)); + A.insert(std::make_pair("x", Countable(42, InstanceCount))); ASSERT_EQ(InstanceCount, 1); auto I = A.find("x"); ASSERT_NE(I, A.end()); diff --git a/unittests/ADT/TripleTest.cpp b/unittests/ADT/TripleTest.cpp index 2e9d585..cacbde6 100644 --- a/unittests/ADT/TripleTest.cpp +++ b/unittests/ADT/TripleTest.cpp @@ -129,6 +129,36 @@ TEST(TripleTest, ParsedIDs) { EXPECT_EQ(Triple::UnknownOS, T.getOS()); EXPECT_EQ(Triple::EABI, T.getEnvironment()); + T = Triple("amdil-unknown-unknown"); + EXPECT_EQ(Triple::amdil, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + + T = Triple("amdil64-unknown-unknown"); + EXPECT_EQ(Triple::amdil64, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + + T = Triple("hsail-unknown-unknown"); + EXPECT_EQ(Triple::hsail, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + + T = Triple("hsail64-unknown-unknown"); + EXPECT_EQ(Triple::hsail64, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + + T = Triple("spir-unknown-unknown"); + EXPECT_EQ(Triple::spir, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + + T = Triple("spir64-unknown-unknown"); + EXPECT_EQ(Triple::spir64, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + T = Triple("huh"); EXPECT_EQ(Triple::UnknownArch, T.getArch()); } @@ -190,7 +220,7 @@ TEST(TripleTest, Normalization) { ++Vendor) { C[1] = Triple::getVendorTypeName(Triple::VendorType(Vendor)); for (int OS = 1+Triple::UnknownOS; OS <= Triple::Minix; ++OS) { - if (OS == Triple::Cygwin || OS == Triple::MinGW32 || OS == Triple::Win32) + if (OS == Triple::Win32) continue; C[2] = Triple::getOSTypeName(Triple::OSType(OS)); @@ -341,6 +371,36 @@ TEST(TripleTest, BitWidthPredicates) { EXPECT_FALSE(T.isArch16Bit()); EXPECT_FALSE(T.isArch32Bit()); EXPECT_TRUE(T.isArch64Bit()); + + T.setArch(Triple::amdil); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_TRUE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::amdil64); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); + + T.setArch(Triple::hsail); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_TRUE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::hsail64); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); + + T.setArch(Triple::spir); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_TRUE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); + + T.setArch(Triple::spir64); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); } TEST(TripleTest, BitWidthArchVariants) { @@ -399,6 +459,30 @@ TEST(TripleTest, BitWidthArchVariants) { T.setArch(Triple::x86_64); EXPECT_EQ(Triple::x86, T.get32BitArchVariant().getArch()); EXPECT_EQ(Triple::x86_64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::amdil); + EXPECT_EQ(Triple::amdil, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::amdil64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::amdil64); + EXPECT_EQ(Triple::amdil, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::amdil64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::hsail); + EXPECT_EQ(Triple::hsail, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::hsail64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::hsail64); + EXPECT_EQ(Triple::hsail, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::hsail64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::spir); + EXPECT_EQ(Triple::spir, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::spir64, T.get64BitArchVariant().getArch()); + + T.setArch(Triple::spir64); + EXPECT_EQ(Triple::spir, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::spir64, T.get64BitArchVariant().getArch()); } TEST(TripleTest, getOSVersion) { @@ -564,4 +648,20 @@ TEST(TripleTest, NormalizeWindows) { EXPECT_EQ("i686-pc-windows-elf", Triple::normalize("i686-pc-windows-elf-elf")); } + +TEST(TripleTest, getARMCPUForArch) { + { + llvm::Triple Triple("armv6-unknown-freebsd"); + EXPECT_STREQ("arm1176jzf-s", Triple.getARMCPUForArch()); + } + { + llvm::Triple Triple("armv7s-apple-ios7"); + EXPECT_STREQ("swift", Triple.getARMCPUForArch()); + } + { + llvm::Triple Triple("armv7-apple-ios7"); + EXPECT_STREQ("cortex-a8", Triple.getARMCPUForArch()); + EXPECT_STREQ("swift", Triple.getARMCPUForArch("armv7s")); + } +} } diff --git a/unittests/Analysis/CFGTest.cpp b/unittests/Analysis/CFGTest.cpp index ac5e710..dba9d49 100644 --- a/unittests/Analysis/CFGTest.cpp +++ b/unittests/Analysis/CFGTest.cpp @@ -30,20 +30,16 @@ namespace { class IsPotentiallyReachableTest : public testing::Test { protected: void ParseAssembly(const char *Assembly) { - M.reset(new Module("Module", getGlobalContext())); - SMDiagnostic Error; - bool Parsed = ParseAssemblyString(Assembly, M.get(), - Error, M->getContext()) == M.get(); + M = parseAssemblyString(Assembly, Error, getGlobalContext()); std::string errMsg; raw_string_ostream os(errMsg); Error.print("", os); - if (!Parsed) { - // A failure here means that the test itself is buggy. + // A failure here means that the test itself is buggy. + if (!M) report_fatal_error(os.str().c_str()); - } Function *F = M->getFunction("test"); if (F == nullptr) diff --git a/unittests/Analysis/CMakeLists.txt b/unittests/Analysis/CMakeLists.txt index 8454860..baf0c28 100644 --- a/unittests/Analysis/CMakeLists.txt +++ b/unittests/Analysis/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + IPA Analysis AsmParser Core @@ -6,6 +7,7 @@ set(LLVM_LINK_COMPONENTS ) add_llvm_unittest(AnalysisTests + CallGraphTest.cpp CFGTest.cpp LazyCallGraphTest.cpp ScalarEvolutionTest.cpp diff --git a/unittests/Analysis/CallGraphTest.cpp b/unittests/Analysis/CallGraphTest.cpp new file mode 100644 index 0000000..777907a --- /dev/null +++ b/unittests/Analysis/CallGraphTest.cpp @@ -0,0 +1,59 @@ +//=======- CallGraphTest.cpp - Unit tests for the CG analysis -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/CallGraph.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +template void canSpecializeGraphTraitsIterators(Ty *G) { + typedef typename GraphTraits::NodeType NodeTy; + + auto I = GraphTraits::nodes_begin(G); + auto E = GraphTraits::nodes_end(G); + auto X = ++I; + + // Should be able to iterate over all nodes of the graph. + static_assert(std::is_same::value, + "Node type does not match"); + static_assert(std::is_same::value, + "Node type does not match"); + static_assert(std::is_same::value, + "Node type does not match"); + + NodeTy *N = GraphTraits::getEntryNode(G); + + auto S = GraphTraits::child_begin(N); + auto F = GraphTraits::child_end(N); + + // Should be able to iterate over immediate successors of a node. + static_assert(std::is_same::value, + "Node type does not match"); + static_assert(std::is_same::value, + "Node type does not match"); +} + +TEST(CallGraphTest, GraphTraitsSpecialization) { + Module M("", getGlobalContext()); + CallGraph CG(M); + + canSpecializeGraphTraitsIterators(&CG); +} + +TEST(CallGraphTest, GraphTraitsConstSpecialization) { + Module M("", getGlobalContext()); + CallGraph CG(M); + + canSpecializeGraphTraitsIterators(const_cast(&CG)); +} +} diff --git a/unittests/Analysis/LazyCallGraphTest.cpp b/unittests/Analysis/LazyCallGraphTest.cpp index d7c7045..6caccb8 100644 --- a/unittests/Analysis/LazyCallGraphTest.cpp +++ b/unittests/Analysis/LazyCallGraphTest.cpp @@ -22,38 +22,38 @@ using namespace llvm; namespace { std::unique_ptr parseAssembly(const char *Assembly) { - auto M = make_unique("Module", getGlobalContext()); - SMDiagnostic Error; - bool Parsed = - ParseAssemblyString(Assembly, M.get(), Error, M->getContext()) == M.get(); + std::unique_ptr M = + parseAssemblyString(Assembly, Error, getGlobalContext()); std::string ErrMsg; raw_string_ostream OS(ErrMsg); Error.print("", OS); // A failure here means that the test itself is buggy. - if (!Parsed) + if (!M) report_fatal_error(OS.str().c_str()); return M; } -// IR forming a call graph with a diamond of triangle-shaped SCCs: -// -// d1 -// / \ -// d3--d2 -// / \ -// b1 c1 -// / \ / \ -// b3--b2 c3--c2 -// \ / -// a1 -// / \ -// a3--a2 -// -// All call edges go up between SCCs, and clockwise around the SCC. +/* + IR forming a call graph with a diamond of triangle-shaped SCCs: + + d1 + / \ + d3--d2 + / \ + b1 c1 + / \ / \ + b3--b2 c3--c2 + \ / + a1 + / \ + a3--a2 + + All call edges go up between SCCs, and clockwise around the SCC. + */ static const char DiamondOfTriangles[] = "define void @a1() {\n" "entry:\n" diff --git a/unittests/Analysis/Makefile b/unittests/Analysis/Makefile index 527f452..52296e7 100644 --- a/unittests/Analysis/Makefile +++ b/unittests/Analysis/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TESTNAME = Analysis -LINK_COMPONENTS := analysis asmparser +LINK_COMPONENTS := ipa analysis asmparser include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/Analysis/MixedTBAATest.cpp b/unittests/Analysis/MixedTBAATest.cpp index 142e047..d7935e3 100644 --- a/unittests/Analysis/MixedTBAATest.cpp +++ b/unittests/Analysis/MixedTBAATest.cpp @@ -65,7 +65,7 @@ TEST_F(MixedTBAATest, MixedTBAA) { // Run the TBAA eval pass on a mixture of path-aware and non-path-aware TBAA. // The order of the metadata (path-aware vs non-path-aware) is important, // because the AA eval pass only runs one test per store-pair. - const char* args[] = { "MixedTBAATest", "-evaluate-tbaa" }; + const char* args[] = { "MixedTBAATest", "-evaluate-aa-metadata" }; cl::ParseCommandLineOptions(sizeof(args) / sizeof(const char*), args); PM.add(createTypeBasedAliasAnalysisPass()); PM.add(createAAEvalPass()); diff --git a/unittests/Bitcode/BitReaderTest.cpp b/unittests/Bitcode/BitReaderTest.cpp index b6a3e9a..6eb40d6 100644 --- a/unittests/Bitcode/BitReaderTest.cpp +++ b/unittests/Bitcode/BitReaderTest.cpp @@ -10,58 +10,158 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Bitcode/BitstreamWriter.h" #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" -#include "llvm/PassManager.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" -namespace llvm { -namespace { - -static Module *makeLLVMModule() { - Module* Mod = new Module("test-mem", getGlobalContext()); +using namespace llvm; - FunctionType* FuncTy = - FunctionType::get(Type::getVoidTy(Mod->getContext()), false); - Function* Func = Function::Create(FuncTy,GlobalValue::ExternalLinkage, - "func", Mod); +namespace { - BasicBlock* Entry = BasicBlock::Create(Mod->getContext(), "entry", Func); - new UnreachableInst(Mod->getContext(), Entry); +std::unique_ptr parseAssembly(const char *Assembly) { + SMDiagnostic Error; + std::unique_ptr M = + parseAssemblyString(Assembly, Error, getGlobalContext()); - BasicBlock* BB = BasicBlock::Create(Mod->getContext(), "bb", Func); - new UnreachableInst(Mod->getContext(), BB); + std::string ErrMsg; + raw_string_ostream OS(ErrMsg); + Error.print("", OS); - PointerType* Int8Ptr = Type::getInt8PtrTy(Mod->getContext()); - new GlobalVariable(*Mod, Int8Ptr, /*isConstant=*/true, - GlobalValue::ExternalLinkage, - BlockAddress::get(BB), "table"); + // A failure here means that the test itself is buggy. + if (!M) + report_fatal_error(OS.str().c_str()); - return Mod; + return M; } -static void writeModuleToBuffer(SmallVectorImpl &Buffer) { - std::unique_ptr Mod(makeLLVMModule()); +static void writeModuleToBuffer(std::unique_ptr Mod, + SmallVectorImpl &Buffer) { raw_svector_ostream OS(Buffer); WriteBitcodeToFile(Mod.get(), OS); } +static std::unique_ptr getLazyModuleFromAssembly(LLVMContext &Context, + SmallString<1024> &Mem, + const char *Assembly) { + writeModuleToBuffer(parseAssembly(Assembly), Mem); + std::unique_ptr Buffer = + MemoryBuffer::getMemBuffer(Mem.str(), "test", false); + ErrorOr ModuleOrErr = + getLazyBitcodeModule(std::move(Buffer), Context); + return std::unique_ptr(ModuleOrErr.get()); +} + +TEST(BitReaderTest, DematerializeFunctionPreservesLinkageType) { + SmallString<1024> Mem; + + LLVMContext Context; + std::unique_ptr M = getLazyModuleFromAssembly( + Context, Mem, "define internal i32 @func() {\n" + "ret i32 0\n" + "}\n"); + + EXPECT_FALSE(verifyModule(*M, &dbgs())); + + M->getFunction("func")->materialize(); + EXPECT_FALSE(M->getFunction("func")->empty()); + EXPECT_TRUE(M->getFunction("func")->getLinkage() == + GlobalValue::InternalLinkage); + + // Check that the linkage type is preserved after dematerialization. + M->getFunction("func")->Dematerialize(); + EXPECT_TRUE(M->getFunction("func")->empty()); + EXPECT_TRUE(M->getFunction("func")->getLinkage() == + GlobalValue::InternalLinkage); + EXPECT_FALSE(verifyModule(*M, &dbgs())); +} + TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677 SmallString<1024> Mem; - writeModuleToBuffer(Mem); - MemoryBuffer *Buffer = MemoryBuffer::getMemBuffer(Mem.str(), "test", false); - ErrorOr ModuleOrErr = - getLazyBitcodeModule(Buffer, getGlobalContext()); - std::unique_ptr m(ModuleOrErr.get()); - PassManager passes; - passes.add(createVerifierPass()); - passes.add(createDebugInfoVerifierPass()); - passes.run(*m); + + LLVMContext Context; + std::unique_ptr M = getLazyModuleFromAssembly( + Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n" + "define void @func() {\n" + " unreachable\n" + "bb:\n" + " unreachable\n" + "}\n"); + EXPECT_FALSE(verifyModule(*M, &dbgs())); + + // Try (and fail) to dematerialize @func. + M->getFunction("func")->Dematerialize(); + EXPECT_FALSE(M->getFunction("func")->empty()); } +TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) { + SmallString<1024> Mem; + + LLVMContext Context; + std::unique_ptr M = getLazyModuleFromAssembly( + Context, Mem, "define i8* @before() {\n" + " ret i8* blockaddress(@func, %bb)\n" + "}\n" + "define void @other() {\n" + " unreachable\n" + "}\n" + "define void @func() {\n" + " unreachable\n" + "bb:\n" + " unreachable\n" + "}\n"); + EXPECT_TRUE(M->getFunction("before")->empty()); + EXPECT_TRUE(M->getFunction("func")->empty()); + EXPECT_FALSE(verifyModule(*M, &dbgs())); + + // Materialize @before, pulling in @func. + EXPECT_FALSE(M->getFunction("before")->materialize()); + EXPECT_FALSE(M->getFunction("func")->empty()); + EXPECT_TRUE(M->getFunction("other")->empty()); + EXPECT_FALSE(verifyModule(*M, &dbgs())); + + // Try (and fail) to dematerialize @func. + M->getFunction("func")->Dematerialize(); + EXPECT_FALSE(M->getFunction("func")->empty()); + EXPECT_FALSE(verifyModule(*M, &dbgs())); } + +TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) { + SmallString<1024> Mem; + + LLVMContext Context; + std::unique_ptr M = getLazyModuleFromAssembly( + Context, Mem, "define void @func() {\n" + " unreachable\n" + "bb:\n" + " unreachable\n" + "}\n" + "define void @other() {\n" + " unreachable\n" + "}\n" + "define i8* @after() {\n" + " ret i8* blockaddress(@func, %bb)\n" + "}\n"); + EXPECT_TRUE(M->getFunction("after")->empty()); + EXPECT_TRUE(M->getFunction("func")->empty()); + EXPECT_FALSE(verifyModule(*M, &dbgs())); + + // Materialize @after, pulling in @func. + EXPECT_FALSE(M->getFunction("after")->materialize()); + EXPECT_FALSE(M->getFunction("func")->empty()); + EXPECT_TRUE(M->getFunction("other")->empty()); + EXPECT_FALSE(verifyModule(*M, &dbgs())); + + // Try (and fail) to dematerialize @func. + M->getFunction("func")->Dematerialize(); + EXPECT_FALSE(M->getFunction("func")->empty()); + EXPECT_FALSE(verifyModule(*M, &dbgs())); } + +} // end namespace diff --git a/unittests/Bitcode/BitstreamReaderTest.cpp b/unittests/Bitcode/BitstreamReaderTest.cpp new file mode 100644 index 0000000..b11d7fd --- /dev/null +++ b/unittests/Bitcode/BitstreamReaderTest.cpp @@ -0,0 +1,56 @@ +//===- BitstreamReaderTest.cpp - Tests for BitstreamReader ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Bitcode/BitstreamReader.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(BitstreamReaderTest, AtEndOfStream) { + uint8_t Bytes[4] = { + 0x00, 0x01, 0x02, 0x03 + }; + BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); + BitstreamCursor Cursor(Reader); + + EXPECT_FALSE(Cursor.AtEndOfStream()); + (void)Cursor.Read(8); + EXPECT_FALSE(Cursor.AtEndOfStream()); + (void)Cursor.Read(24); + EXPECT_TRUE(Cursor.AtEndOfStream()); + + Cursor.JumpToBit(0); + EXPECT_FALSE(Cursor.AtEndOfStream()); + + Cursor.JumpToBit(32); + EXPECT_TRUE(Cursor.AtEndOfStream()); +} + +TEST(BitstreamReaderTest, AtEndOfStreamJump) { + uint8_t Bytes[4] = { + 0x00, 0x01, 0x02, 0x03 + }; + BitstreamReader Reader(std::begin(Bytes), std::end(Bytes)); + BitstreamCursor Cursor(Reader); + + Cursor.JumpToBit(32); + EXPECT_TRUE(Cursor.AtEndOfStream()); +} + +TEST(BitstreamReaderTest, AtEndOfStreamEmpty) { + uint8_t Dummy = 0xFF; + BitstreamReader Reader(&Dummy, &Dummy); + BitstreamCursor Cursor(Reader); + + EXPECT_TRUE(Cursor.AtEndOfStream()); +} + +} // end anonymous namespace diff --git a/unittests/Bitcode/CMakeLists.txt b/unittests/Bitcode/CMakeLists.txt index 743ab18..09cbcdc 100644 --- a/unittests/Bitcode/CMakeLists.txt +++ b/unittests/Bitcode/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + AsmParser BitReader BitWriter Core @@ -7,4 +8,5 @@ set(LLVM_LINK_COMPONENTS add_llvm_unittest(BitcodeTests BitReaderTest.cpp + BitstreamReaderTest.cpp ) diff --git a/unittests/Bitcode/Makefile b/unittests/Bitcode/Makefile index fcec879..33b09b9 100644 --- a/unittests/Bitcode/Makefile +++ b/unittests/Bitcode/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TESTNAME = Bitcode -LINK_COMPONENTS := bitreader bitwriter +LINK_COMPONENTS := AsmParser BitReader BitWriter Core Support include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/ExecutionEngine/CMakeLists.txt b/unittests/ExecutionEngine/CMakeLists.txt index 489eaaf..783c9b5 100644 --- a/unittests/ExecutionEngine/CMakeLists.txt +++ b/unittests/ExecutionEngine/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine Interpreter + MC Support ) @@ -9,10 +10,9 @@ add_llvm_unittest(ExecutionEngineTests ExecutionEngineTest.cpp ) -# Include JIT/MCJIT tests only if native arch is a built JIT target. +# Include MCJIT tests only if native arch is a built JIT target. list(FIND LLVM_TARGETS_TO_BUILD "${LLVM_NATIVE_ARCH}" build_idx) list(FIND LLVM_TARGETS_WITH_JIT "${LLVM_NATIVE_ARCH}" jit_idx) if (NOT build_idx LESS 0 AND NOT jit_idx LESS 0) - add_subdirectory(JIT) add_subdirectory(MCJIT) endif() diff --git a/unittests/ExecutionEngine/ExecutionEngineTest.cpp b/unittests/ExecutionEngine/ExecutionEngineTest.cpp index f23745c..19917a4 100644 --- a/unittests/ExecutionEngine/ExecutionEngineTest.cpp +++ b/unittests/ExecutionEngine/ExecutionEngineTest.cpp @@ -8,10 +8,13 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/Interpreter.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/ManagedStatic.h" #include "gtest/gtest.h" using namespace llvm; @@ -19,10 +22,14 @@ using namespace llvm; namespace { class ExecutionEngineTest : public testing::Test { +private: + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + protected: - ExecutionEngineTest() - : M(new Module("
", getGlobalContext())), Error(""), - Engine(EngineBuilder(M).setErrorStr(&Error).create()) { + ExecutionEngineTest() { + auto Owner = make_unique("
", getGlobalContext()); + M = Owner.get(); + Engine.reset(EngineBuilder(std::move(Owner)).setErrorStr(&Error).create()); } virtual void SetUp() { @@ -35,9 +42,9 @@ protected: GlobalValue::ExternalLinkage, nullptr, Name); } - Module *const M; std::string Error; - const std::unique_ptr Engine; + Module *M; // Owned by ExecutionEngine. + std::unique_ptr Engine; }; TEST_F(ExecutionEngineTest, ForwardGlobalMapping) { @@ -127,4 +134,35 @@ TEST_F(ExecutionEngineTest, DestructionRemovesGlobalMapping) { EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1)); } +TEST_F(ExecutionEngineTest, LookupWithMangledName) { + int x; + llvm::sys::DynamicLibrary::AddSymbol("x", &x); + + // Demonstrate that getSymbolAddress accepts mangled names and always strips + // the leading underscore. + EXPECT_EQ(reinterpret_cast(&x), + RTDyldMemoryManager::getSymbolAddressInProcess("_x")); +} + +TEST_F(ExecutionEngineTest, LookupWithMangledAndDemangledSymbol) { + int x; + int _x; + llvm::sys::DynamicLibrary::AddSymbol("x", &x); + llvm::sys::DynamicLibrary::AddSymbol("_x", &_x); + + // Lookup the demangled name first, even if there's a demangled symbol that + // matches the input already. + EXPECT_EQ(reinterpret_cast(&x), + RTDyldMemoryManager::getSymbolAddressInProcess("_x")); +} + +TEST_F(ExecutionEngineTest, LookupwithDemangledName) { + int _x; + llvm::sys::DynamicLibrary::AddSymbol("_x", &_x); + + // But do fallback to looking up a demangled name if there's no ambiguity + EXPECT_EQ(reinterpret_cast(&_x), + RTDyldMemoryManager::getSymbolAddressInProcess("_x")); +} + } diff --git a/unittests/ExecutionEngine/JIT/CMakeLists.txt b/unittests/ExecutionEngine/JIT/CMakeLists.txt deleted file mode 100644 index 72c1df7..0000000 --- a/unittests/ExecutionEngine/JIT/CMakeLists.txt +++ /dev/null @@ -1,64 +0,0 @@ -set(LLVM_LINK_COMPONENTS - AsmParser - BitReader - BitWriter - Core - ExecutionEngine - JIT - Support - nativecodegen - ) - -# HACK: Declare a couple of source files as optionally compiled to satisfy the -# missing-file-checker in LLVM's weird CMake build. -set(LLVM_OPTIONAL_SOURCES - IntelJITEventListenerTest.cpp - OProfileJITEventListenerTest.cpp - ) - -if( LLVM_USE_INTEL_JITEVENTS ) - set(ProfileTestSources - IntelJITEventListenerTest.cpp - ) - set(LLVM_LINK_COMPONENTS - ${LLVM_LINK_COMPONENTS} - DebugInfo - IntelJITEvents - Object - ) -endif( LLVM_USE_INTEL_JITEVENTS ) - -if( LLVM_USE_OPROFILE ) - set(ProfileTestSources - ${ProfileTestSources} - OProfileJITEventListenerTest.cpp - ) - set(LLVM_LINK_COMPONENTS - ${LLVM_LINK_COMPONENTS} - OProfileJIT - ) -endif( LLVM_USE_OPROFILE ) - -set(JITTestsSources - JITEventListenerTest.cpp - JITMemoryManagerTest.cpp - JITTest.cpp - MultiJITTest.cpp - ${ProfileTestSources} - ) - -if(MSVC) - list(APPEND JITTestsSources JITTests.def) -endif() - -# The JIT tests need to dlopen things. -set(LLVM_NO_DEAD_STRIP 1) - -add_llvm_unittest(JITTests - ${JITTestsSources} - ) - -if(MINGW OR CYGWIN) - set_property(TARGET JITTests PROPERTY LINK_FLAGS -Wl,--export-all-symbols) -endif() -set_target_properties(JITTests PROPERTIES ENABLE_EXPORTS 1) diff --git a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp deleted file mode 100644 index db90887..0000000 --- a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp +++ /dev/null @@ -1,113 +0,0 @@ -//===- JITEventListenerTest.cpp - Tests for Intel JITEventListener --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "JITEventListenerTestCommon.h" - -using namespace llvm; - -// Because we want to keep the implementation details of the Intel API used to -// communicate with Amplifier out of the public header files, the header below -// is included from the source tree instead. -#include "../../../lib/ExecutionEngine/IntelJITEvents/IntelJITEventsWrapper.h" - -#include -#include - -namespace { - -// map of function ("method") IDs to source locations -NativeCodeMap ReportedDebugFuncs; - -} // namespace - -/// Mock implementaion of Intel JIT API jitprofiling library -namespace test_jitprofiling { - -int NotifyEvent(iJIT_JVM_EVENT EventType, void *EventSpecificData) { - switch (EventType) { - case iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED: { - EXPECT_TRUE(0 != EventSpecificData); - iJIT_Method_Load* msg = static_cast(EventSpecificData); - - ReportedDebugFuncs[msg->method_id]; - - for(unsigned int i = 0; i < msg->line_number_size; ++i) { - EXPECT_TRUE(0 != msg->line_number_table); - std::pair loc( - std::string(msg->source_file_name), - msg->line_number_table[i].LineNumber); - ReportedDebugFuncs[msg->method_id].push_back(loc); - } - } - break; - case iJVM_EVENT_TYPE_METHOD_UNLOAD_START: { - EXPECT_TRUE(0 != EventSpecificData); - unsigned int UnloadId - = *reinterpret_cast(EventSpecificData); - EXPECT_TRUE(1 == ReportedDebugFuncs.erase(UnloadId)); - } - default: - break; - } - return 0; -} - -iJIT_IsProfilingActiveFlags IsProfilingActive(void) { - // for testing, pretend we have an Intel Parallel Amplifier XE 2011 - // instance attached - return iJIT_SAMPLING_ON; -} - -unsigned int GetNewMethodID(void) { - static unsigned int id = 0; - return ++id; -} - -} //namespace test_jitprofiling - -class IntelJITEventListenerTest - : public JITEventListenerTestBase { -public: - IntelJITEventListenerTest() - : JITEventListenerTestBase( - new IntelJITEventsWrapper(test_jitprofiling::NotifyEvent, 0, - test_jitprofiling::IsProfilingActive, 0, 0, - test_jitprofiling::GetNewMethodID)) - { - EXPECT_TRUE(0 != MockWrapper); - - Listener.reset(JITEventListener::createIntelJITEventListener( - MockWrapper.release())); - EXPECT_TRUE(0 != Listener); - EE->RegisterJITEventListener(Listener.get()); - } -}; - -TEST_F(IntelJITEventListenerTest, NoDebugInfo) { - TestNoDebugInfo(ReportedDebugFuncs); -} - -TEST_F(IntelJITEventListenerTest, SingleLine) { - TestSingleLine(ReportedDebugFuncs); -} - -TEST_F(IntelJITEventListenerTest, MultipleLines) { - TestMultipleLines(ReportedDebugFuncs); -} - -// This testcase is disabled because the Intel JIT API does not support a single -// JITted function with source lines associated with multiple files -/* -TEST_F(IntelJITEventListenerTest, MultipleFiles) { - TestMultipleFiles(ReportedDebugFuncs); -} -*/ - -testing::Environment* const jit_env = - testing::AddGlobalTestEnvironment(new JITEnvironment); diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp deleted file mode 100644 index 175b9fb..0000000 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTest.cpp +++ /dev/null @@ -1,237 +0,0 @@ -//===- JITEventListenerTest.cpp - Unit tests for JITEventListeners --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/CodeGen/MachineCodeInfo.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/TypeBuilder.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" -#include - -using namespace llvm; - -namespace { - -struct FunctionEmittedEvent { - // Indices are local to the RecordingJITEventListener, since the - // JITEventListener interface makes no guarantees about the order of - // calls between Listeners. - unsigned Index; - const Function *F; - void *Code; - size_t Size; - JITEvent_EmittedFunctionDetails Details; -}; -struct FunctionFreedEvent { - unsigned Index; - void *Code; -}; - -struct RecordingJITEventListener : public JITEventListener { - std::vector EmittedEvents; - std::vector FreedEvents; - - unsigned NextIndex; - - RecordingJITEventListener() : NextIndex(0) {} - - virtual void NotifyFunctionEmitted(const Function &F, - void *Code, size_t Size, - const EmittedFunctionDetails &Details) { - FunctionEmittedEvent Event = {NextIndex++, &F, Code, Size, Details}; - EmittedEvents.push_back(Event); - } - - virtual void NotifyFreeingMachineCode(void *OldPtr) { - FunctionFreedEvent Event = {NextIndex++, OldPtr}; - FreedEvents.push_back(Event); - } -}; - -class JITEventListenerTest : public testing::Test { - protected: - JITEventListenerTest() - : M(new Module("module", getGlobalContext())), - EE(EngineBuilder(M) - .setEngineKind(EngineKind::JIT) - .create()) { - } - - Module *M; - const std::unique_ptr EE; -}; - -// Tests on SystemZ disabled as we're running the old JIT -#if !defined(__s390__) && !defined(__aarch64__) -Function *buildFunction(Module *M) { - Function *Result = Function::Create( - TypeBuilder::get(getGlobalContext()), - GlobalValue::ExternalLinkage, "id", M); - Value *Arg = Result->arg_begin(); - BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result); - ReturnInst::Create(M->getContext(), Arg, BB); - return Result; -} - -// Tests that a single JITEventListener follows JIT events accurately. -TEST_F(JITEventListenerTest, Simple) { - RecordingJITEventListener Listener; - EE->RegisterJITEventListener(&Listener); - Function *F1 = buildFunction(M); - Function *F2 = buildFunction(M); - - void *F1_addr = EE->getPointerToFunction(F1); - void *F2_addr = EE->getPointerToFunction(F2); - EE->getPointerToFunction(F1); // Should do nothing. - EE->freeMachineCodeForFunction(F1); - EE->freeMachineCodeForFunction(F2); - - ASSERT_EQ(2U, Listener.EmittedEvents.size()); - ASSERT_EQ(2U, Listener.FreedEvents.size()); - - EXPECT_EQ(0U, Listener.EmittedEvents[0].Index); - EXPECT_EQ(F1, Listener.EmittedEvents[0].F); - EXPECT_EQ(F1_addr, Listener.EmittedEvents[0].Code); - EXPECT_LT(0U, Listener.EmittedEvents[0].Size) - << "We don't know how big the function will be, but it had better" - << " contain some bytes."; - - EXPECT_EQ(1U, Listener.EmittedEvents[1].Index); - EXPECT_EQ(F2, Listener.EmittedEvents[1].F); - EXPECT_EQ(F2_addr, Listener.EmittedEvents[1].Code); - EXPECT_LT(0U, Listener.EmittedEvents[1].Size) - << "We don't know how big the function will be, but it had better" - << " contain some bytes."; - - EXPECT_EQ(2U, Listener.FreedEvents[0].Index); - EXPECT_EQ(F1_addr, Listener.FreedEvents[0].Code); - - EXPECT_EQ(3U, Listener.FreedEvents[1].Index); - EXPECT_EQ(F2_addr, Listener.FreedEvents[1].Code); - - F1->eraseFromParent(); - F2->eraseFromParent(); -} - -// Tests that a single JITEventListener follows JIT events accurately. -TEST_F(JITEventListenerTest, MultipleListenersDontInterfere) { - RecordingJITEventListener Listener1; - RecordingJITEventListener Listener2; - RecordingJITEventListener Listener3; - Function *F1 = buildFunction(M); - Function *F2 = buildFunction(M); - - EE->RegisterJITEventListener(&Listener1); - EE->RegisterJITEventListener(&Listener2); - void *F1_addr = EE->getPointerToFunction(F1); - EE->RegisterJITEventListener(&Listener3); - EE->UnregisterJITEventListener(&Listener1); - void *F2_addr = EE->getPointerToFunction(F2); - EE->UnregisterJITEventListener(&Listener2); - EE->UnregisterJITEventListener(&Listener3); - EE->freeMachineCodeForFunction(F1); - EE->RegisterJITEventListener(&Listener2); - EE->RegisterJITEventListener(&Listener3); - EE->RegisterJITEventListener(&Listener1); - EE->freeMachineCodeForFunction(F2); - EE->UnregisterJITEventListener(&Listener1); - EE->UnregisterJITEventListener(&Listener2); - EE->UnregisterJITEventListener(&Listener3); - - // Listener 1. - ASSERT_EQ(1U, Listener1.EmittedEvents.size()); - ASSERT_EQ(1U, Listener1.FreedEvents.size()); - - EXPECT_EQ(0U, Listener1.EmittedEvents[0].Index); - EXPECT_EQ(F1, Listener1.EmittedEvents[0].F); - EXPECT_EQ(F1_addr, Listener1.EmittedEvents[0].Code); - EXPECT_LT(0U, Listener1.EmittedEvents[0].Size) - << "We don't know how big the function will be, but it had better" - << " contain some bytes."; - - EXPECT_EQ(1U, Listener1.FreedEvents[0].Index); - EXPECT_EQ(F2_addr, Listener1.FreedEvents[0].Code); - - // Listener 2. - ASSERT_EQ(2U, Listener2.EmittedEvents.size()); - ASSERT_EQ(1U, Listener2.FreedEvents.size()); - - EXPECT_EQ(0U, Listener2.EmittedEvents[0].Index); - EXPECT_EQ(F1, Listener2.EmittedEvents[0].F); - EXPECT_EQ(F1_addr, Listener2.EmittedEvents[0].Code); - EXPECT_LT(0U, Listener2.EmittedEvents[0].Size) - << "We don't know how big the function will be, but it had better" - << " contain some bytes."; - - EXPECT_EQ(1U, Listener2.EmittedEvents[1].Index); - EXPECT_EQ(F2, Listener2.EmittedEvents[1].F); - EXPECT_EQ(F2_addr, Listener2.EmittedEvents[1].Code); - EXPECT_LT(0U, Listener2.EmittedEvents[1].Size) - << "We don't know how big the function will be, but it had better" - << " contain some bytes."; - - EXPECT_EQ(2U, Listener2.FreedEvents[0].Index); - EXPECT_EQ(F2_addr, Listener2.FreedEvents[0].Code); - - // Listener 3. - ASSERT_EQ(1U, Listener3.EmittedEvents.size()); - ASSERT_EQ(1U, Listener3.FreedEvents.size()); - - EXPECT_EQ(0U, Listener3.EmittedEvents[0].Index); - EXPECT_EQ(F2, Listener3.EmittedEvents[0].F); - EXPECT_EQ(F2_addr, Listener3.EmittedEvents[0].Code); - EXPECT_LT(0U, Listener3.EmittedEvents[0].Size) - << "We don't know how big the function will be, but it had better" - << " contain some bytes."; - - EXPECT_EQ(1U, Listener3.FreedEvents[0].Index); - EXPECT_EQ(F2_addr, Listener3.FreedEvents[0].Code); - - F1->eraseFromParent(); - F2->eraseFromParent(); -} - -TEST_F(JITEventListenerTest, MatchesMachineCodeInfo) { - RecordingJITEventListener Listener; - MachineCodeInfo MCI; - Function *F = buildFunction(M); - - EE->RegisterJITEventListener(&Listener); - EE->runJITOnFunction(F, &MCI); - void *F_addr = EE->getPointerToFunction(F); - EE->freeMachineCodeForFunction(F); - - ASSERT_EQ(1U, Listener.EmittedEvents.size()); - ASSERT_EQ(1U, Listener.FreedEvents.size()); - - EXPECT_EQ(0U, Listener.EmittedEvents[0].Index); - EXPECT_EQ(F, Listener.EmittedEvents[0].F); - EXPECT_EQ(F_addr, Listener.EmittedEvents[0].Code); - EXPECT_EQ(MCI.address(), Listener.EmittedEvents[0].Code); - EXPECT_EQ(MCI.size(), Listener.EmittedEvents[0].Size); - - EXPECT_EQ(1U, Listener.FreedEvents[0].Index); - EXPECT_EQ(F_addr, Listener.FreedEvents[0].Code); -} -#endif - -class JITEnvironment : public testing::Environment { - virtual void SetUp() { - // Required to create a JIT. - InitializeNativeTarget(); - } -}; -testing::Environment* const jit_env = - testing::AddGlobalTestEnvironment(new JITEnvironment); - -} // anonymous namespace diff --git a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h b/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h deleted file mode 100644 index 61220f5..0000000 --- a/unittests/ExecutionEngine/JIT/JITEventListenerTestCommon.h +++ /dev/null @@ -1,207 +0,0 @@ -//===- JITEventListenerTestCommon.h - Helper for JITEventListener tests ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===-------------------------------------------------------------------------------===// - -#ifndef JIT_EVENT_LISTENER_TEST_COMMON_H -#define JIT_EVENT_LISTENER_TEST_COMMON_H - -#include "llvm/CodeGen/MachineCodeInfo.h" -#include "llvm/Config/config.h" -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ExecutionEngine/JITEventListener.h" -#include "llvm/IR/DIBuilder.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/TypeBuilder.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" -#include -#include -#include - -typedef std::vector > SourceLocations; -typedef std::map NativeCodeMap; - -class JITEnvironment : public testing::Environment { - virtual void SetUp() { - // Required to create a JIT. - llvm::InitializeNativeTarget(); - } -}; - -inline unsigned int getLine() { - return 12; -} - -inline unsigned int getCol() { - return 0; -} - -inline const char* getFilename() { - return "mock_source_file.cpp"; -} - -// Test fixture shared by tests for listener implementations -template -class JITEventListenerTestBase : public testing::Test { -protected: - std::unique_ptr MockWrapper; - std::unique_ptr Listener; - -public: - llvm::Module* M; - llvm::MDNode* Scope; - llvm::ExecutionEngine* EE; - llvm::DIBuilder* DebugBuilder; - llvm::IRBuilder<> Builder; - - JITEventListenerTestBase(WrapperT* w) - : MockWrapper(w) - , M(new llvm::Module("module", llvm::getGlobalContext())) - , EE(llvm::EngineBuilder(M) - .setEngineKind(llvm::EngineKind::JIT) - .setOptLevel(llvm::CodeGenOpt::None) - .create()) - , DebugBuilder(new llvm::DIBuilder(*M)) - , Builder(llvm::getGlobalContext()) - { - DebugBuilder->createCompileUnit(llvm::dwarf::DW_LANG_C_plus_plus, - "JIT", - "JIT", - "JIT", - true, - "", - 1); - - Scope = DebugBuilder->createFile(getFilename(), "."); - } - - llvm::Function *buildFunction(const SourceLocations& DebugLocations) { - using namespace llvm; - - LLVMContext& GlobalContext = getGlobalContext(); - - SourceLocations::const_iterator CurrentDebugLocation - = DebugLocations.begin(); - - if (CurrentDebugLocation != DebugLocations.end()) { - DebugLoc DebugLocation = DebugLoc::get(getLine(), getCol(), - DebugBuilder->createFile(CurrentDebugLocation->first, ".")); - Builder.SetCurrentDebugLocation(DebugLocation); - CurrentDebugLocation++; - } - - Function *Result = Function::Create( - TypeBuilder::get(GlobalContext), - GlobalValue::ExternalLinkage, "id", M); - Value *Arg = Result->arg_begin(); - BasicBlock *BB = BasicBlock::Create(M->getContext(), "entry", Result); - Builder.SetInsertPoint(BB); - Value* one = ConstantInt::get(GlobalContext, APInt(32, 1)); - for(; CurrentDebugLocation != DebugLocations.end(); - ++CurrentDebugLocation) { - Arg = Builder.CreateMul(Arg, Builder.CreateAdd(Arg, one)); - Builder.SetCurrentDebugLocation( - DebugLoc::get(CurrentDebugLocation->second, 0, - DebugBuilder->createFile(CurrentDebugLocation->first, "."))); - } - Builder.CreateRet(Arg); - return Result; - } - - void TestNoDebugInfo(NativeCodeMap& ReportedDebugFuncs) { - SourceLocations DebugLocations; - llvm::Function* f = buildFunction(DebugLocations); - EXPECT_TRUE(0 != f); - - //Cause JITting and callbacks to our listener - EXPECT_TRUE(0 != EE->getPointerToFunction(f)); - EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - - EE->freeMachineCodeForFunction(f); - EXPECT_TRUE(ReportedDebugFuncs.size() == 0); - } - - void TestSingleLine(NativeCodeMap& ReportedDebugFuncs) { - SourceLocations DebugLocations; - DebugLocations.push_back(std::make_pair(std::string(getFilename()), - getLine())); - llvm::Function* f = buildFunction(DebugLocations); - EXPECT_TRUE(0 != f); - - EXPECT_TRUE(0 != EE->getPointerToFunction(f)); - EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - EXPECT_STREQ(ReportedDebugFuncs.begin()->second.begin()->first.c_str(), - getFilename()); - EXPECT_EQ(ReportedDebugFuncs.begin()->second.begin()->second, getLine()); - - EE->freeMachineCodeForFunction(f); - EXPECT_TRUE(ReportedDebugFuncs.size() == 0); - } - - void TestMultipleLines(NativeCodeMap& ReportedDebugFuncs) { - using namespace std; - - SourceLocations DebugLocations; - unsigned int c = 5; - for(unsigned int i = 0; i < c; ++i) { - DebugLocations.push_back(make_pair(string(getFilename()), getLine() + i)); - } - - llvm::Function* f = buildFunction(DebugLocations); - EXPECT_TRUE(0 != f); - - EXPECT_TRUE(0 != EE->getPointerToFunction(f)); - EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second; - EXPECT_EQ(c, FunctionInfo.size()); - - int VerifyCount = 0; - for(SourceLocations::iterator i = FunctionInfo.begin(); - i != FunctionInfo.end(); - ++i) { - EXPECT_STREQ(i->first.c_str(), getFilename()); - EXPECT_EQ(i->second, getLine() + VerifyCount); - VerifyCount++; - } - - EE->freeMachineCodeForFunction(f); - EXPECT_TRUE(ReportedDebugFuncs.size() == 0); - } - - void TestMultipleFiles(NativeCodeMap& ReportedDebugFuncs) { - - std::string secondFilename("another_file.cpp"); - - SourceLocations DebugLocations; - DebugLocations.push_back(std::make_pair(std::string(getFilename()), - getLine())); - DebugLocations.push_back(std::make_pair(secondFilename, getLine())); - llvm::Function* f = buildFunction(DebugLocations); - EXPECT_TRUE(0 != f); - - EXPECT_TRUE(0 != EE->getPointerToFunction(f)); - EXPECT_TRUE(1 == ReportedDebugFuncs.size()); - SourceLocations& FunctionInfo = ReportedDebugFuncs.begin()->second; - EXPECT_TRUE(2 == FunctionInfo.size()); - - EXPECT_STREQ(FunctionInfo.at(0).first.c_str(), getFilename()); - EXPECT_STREQ(FunctionInfo.at(1).first.c_str(), secondFilename.c_str()); - - EXPECT_EQ(FunctionInfo.at(0).second, getLine()); - EXPECT_EQ(FunctionInfo.at(1).second, getLine()); - - EE->freeMachineCodeForFunction(f); - EXPECT_TRUE(ReportedDebugFuncs.size() == 0); - } -}; - -#endif //JIT_EVENT_LISTENER_TEST_COMMON_H diff --git a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp b/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp deleted file mode 100644 index 296838d..0000000 --- a/unittests/ExecutionEngine/JIT/JITMemoryManagerTest.cpp +++ /dev/null @@ -1,302 +0,0 @@ -//===- JITMemoryManagerTest.cpp - Unit tests for the JIT memory manager ---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/LLVMContext.h" -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -Function *makeFakeFunction() { - std::vector params; - FunctionType *FTy = - FunctionType::get(Type::getVoidTy(getGlobalContext()), params, false); - return Function::Create(FTy, GlobalValue::ExternalLinkage); -} - -// Allocate three simple functions that fit in the initial slab. This exercises -// the code in the case that we don't have to allocate more memory to store the -// function bodies. -TEST(JITMemoryManagerTest, NoAllocations) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - uintptr_t size; - std::string Error; - - // Allocate the functions. - 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; - - 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; - - std::unique_ptr F3(makeFakeFunction()); - size = 1024; - uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); - memset(FunctionBody3, 0xFF, 1024); - MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + 1024); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - // Deallocate them out of order, in case that matters. - MemMgr->deallocateFunctionBody(FunctionBody2); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody1); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody3); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -} - -// Make three large functions that take up most of the space in the slab. Then -// try allocating three smaller functions that don't require additional slabs. -TEST(JITMemoryManagerTest, TestCodeAllocation) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - uintptr_t size; - std::string Error; - - // Big functions are a little less than the largest block size. - const uintptr_t smallFuncSize = 1024; - const uintptr_t bigFuncSize = (MemMgr->GetDefaultCodeSlabSize() - - smallFuncSize * 2); - - // Allocate big functions - std::unique_ptr F1(makeFakeFunction()); - size = bigFuncSize; - uint8_t *FunctionBody1 = MemMgr->startFunctionBody(F1.get(), size); - ASSERT_LE(bigFuncSize, size); - memset(FunctionBody1, 0xFF, bigFuncSize); - MemMgr->endFunctionBody(F1.get(), FunctionBody1, FunctionBody1 + bigFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr F2(makeFakeFunction()); - size = bigFuncSize; - uint8_t *FunctionBody2 = MemMgr->startFunctionBody(F2.get(), size); - ASSERT_LE(bigFuncSize, size); - memset(FunctionBody2, 0xFF, bigFuncSize); - MemMgr->endFunctionBody(F2.get(), FunctionBody2, FunctionBody2 + bigFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr F3(makeFakeFunction()); - size = bigFuncSize; - uint8_t *FunctionBody3 = MemMgr->startFunctionBody(F3.get(), size); - ASSERT_LE(bigFuncSize, size); - memset(FunctionBody3, 0xFF, bigFuncSize); - MemMgr->endFunctionBody(F3.get(), FunctionBody3, FunctionBody3 + bigFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - // Check that each large function took it's own slab. - EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); - - // Allocate small functions - std::unique_ptr F4(makeFakeFunction()); - size = smallFuncSize; - uint8_t *FunctionBody4 = MemMgr->startFunctionBody(F4.get(), size); - ASSERT_LE(smallFuncSize, size); - memset(FunctionBody4, 0xFF, smallFuncSize); - MemMgr->endFunctionBody(F4.get(), FunctionBody4, - FunctionBody4 + smallFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr F5(makeFakeFunction()); - size = smallFuncSize; - uint8_t *FunctionBody5 = MemMgr->startFunctionBody(F5.get(), size); - ASSERT_LE(smallFuncSize, size); - memset(FunctionBody5, 0xFF, smallFuncSize); - MemMgr->endFunctionBody(F5.get(), FunctionBody5, - FunctionBody5 + smallFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - std::unique_ptr F6(makeFakeFunction()); - size = smallFuncSize; - uint8_t *FunctionBody6 = MemMgr->startFunctionBody(F6.get(), size); - ASSERT_LE(smallFuncSize, size); - memset(FunctionBody6, 0xFF, smallFuncSize); - MemMgr->endFunctionBody(F6.get(), FunctionBody6, - FunctionBody6 + smallFuncSize); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - - // Check that the small functions didn't allocate any new slabs. - EXPECT_EQ(3U, MemMgr->GetNumCodeSlabs()); - - // Deallocate them out of order, in case that matters. - MemMgr->deallocateFunctionBody(FunctionBody2); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody1); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody4); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody3); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody5); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; - MemMgr->deallocateFunctionBody(FunctionBody6); - EXPECT_TRUE(MemMgr->CheckInvariants(Error)) << Error; -} - -// Allocate five global ints of varying widths and alignment, and check their -// alignment and overlap. -TEST(JITMemoryManagerTest, TestSmallGlobalInts) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - uint8_t *a = (uint8_t *)MemMgr->allocateGlobal(8, 0); - uint16_t *b = (uint16_t*)MemMgr->allocateGlobal(16, 2); - uint32_t *c = (uint32_t*)MemMgr->allocateGlobal(32, 4); - uint64_t *d = (uint64_t*)MemMgr->allocateGlobal(64, 8); - - // Check the alignment. - EXPECT_EQ(0U, ((uintptr_t)b) & 0x1); - EXPECT_EQ(0U, ((uintptr_t)c) & 0x3); - EXPECT_EQ(0U, ((uintptr_t)d) & 0x7); - - // Initialize them each one at a time and make sure they don't overlap. - *a = 0xff; - *b = 0U; - *c = 0U; - *d = 0U; - EXPECT_EQ(0xffU, *a); - EXPECT_EQ(0U, *b); - EXPECT_EQ(0U, *c); - EXPECT_EQ(0U, *d); - *a = 0U; - *b = 0xffffU; - EXPECT_EQ(0U, *a); - EXPECT_EQ(0xffffU, *b); - EXPECT_EQ(0U, *c); - EXPECT_EQ(0U, *d); - *b = 0U; - *c = 0xffffffffU; - EXPECT_EQ(0U, *a); - EXPECT_EQ(0U, *b); - EXPECT_EQ(0xffffffffU, *c); - EXPECT_EQ(0U, *d); - *c = 0U; - *d = 0xffffffffffffffffULL; - EXPECT_EQ(0U, *a); - EXPECT_EQ(0U, *b); - EXPECT_EQ(0U, *c); - EXPECT_EQ(0xffffffffffffffffULL, *d); - - // Make sure we didn't allocate any extra slabs for this tiny amount of data. - EXPECT_EQ(1U, MemMgr->GetNumDataSlabs()); -} - -// Allocate a small global, a big global, and a third global, and make sure we -// only use two slabs for that. -TEST(JITMemoryManagerTest, TestLargeGlobalArray) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - size_t Size = 4 * MemMgr->GetDefaultDataSlabSize(); - uint64_t *a = (uint64_t*)MemMgr->allocateGlobal(64, 8); - uint8_t *g = MemMgr->allocateGlobal(Size, 8); - uint64_t *b = (uint64_t*)MemMgr->allocateGlobal(64, 8); - - // Check the alignment. - EXPECT_EQ(0U, ((uintptr_t)a) & 0x7); - EXPECT_EQ(0U, ((uintptr_t)g) & 0x7); - EXPECT_EQ(0U, ((uintptr_t)b) & 0x7); - - // Initialize them to make sure we don't segfault and make sure they don't - // overlap. - memset(a, 0x1, 8); - memset(g, 0x2, Size); - memset(b, 0x3, 8); - EXPECT_EQ(0x0101010101010101ULL, *a); - // Just check the edges. - EXPECT_EQ(0x02U, g[0]); - EXPECT_EQ(0x02U, g[Size - 1]); - EXPECT_EQ(0x0303030303030303ULL, *b); - - // Check the number of slabs. - EXPECT_EQ(2U, MemMgr->GetNumDataSlabs()); -} - -// Allocate lots of medium globals so that we can test moving the bump allocator -// to a new slab. -TEST(JITMemoryManagerTest, TestManyGlobals) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - size_t SlabSize = MemMgr->GetDefaultDataSlabSize(); - size_t Size = 128; - int Iters = (SlabSize / Size) + 1; - - // We should start with no slabs. - EXPECT_EQ(0U, MemMgr->GetNumDataSlabs()); - - // After allocating a bunch of globals, we should have two. - for (int I = 0; I < Iters; ++I) - MemMgr->allocateGlobal(Size, 8); - EXPECT_EQ(2U, MemMgr->GetNumDataSlabs()); - - // And after much more, we should have three. - for (int I = 0; I < Iters; ++I) - MemMgr->allocateGlobal(Size, 8); - EXPECT_EQ(3U, MemMgr->GetNumDataSlabs()); -} - -// Allocate lots of function stubs so that we can test moving the stub bump -// allocator to a new slab. -TEST(JITMemoryManagerTest, TestManyStubs) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - size_t SlabSize = MemMgr->GetDefaultStubSlabSize(); - size_t Size = 128; - int Iters = (SlabSize / Size) + 1; - - // We should start with no slabs. - EXPECT_EQ(0U, MemMgr->GetNumDataSlabs()); - - // After allocating a bunch of stubs, we should have two. - for (int I = 0; I < Iters; ++I) - MemMgr->allocateStub(nullptr, Size, 8); - EXPECT_EQ(2U, MemMgr->GetNumStubSlabs()); - - // And after much more, we should have three. - for (int I = 0; I < Iters; ++I) - MemMgr->allocateStub(nullptr, Size, 8); - EXPECT_EQ(3U, MemMgr->GetNumStubSlabs()); -} - -// Check section allocation and alignment -TEST(JITMemoryManagerTest, AllocateSection) { - std::unique_ptr MemMgr( - JITMemoryManager::CreateDefaultMemManager()); - uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1, StringRef()); - uint8_t *data1 = MemMgr->allocateDataSection(256, 16, 2, StringRef(), true); - uint8_t *code2 = MemMgr->allocateCodeSection(257, 32, 3, StringRef()); - uint8_t *data2 = MemMgr->allocateDataSection(256, 64, 4, StringRef(), false); - uint8_t *code3 = MemMgr->allocateCodeSection(258, 64, 5, StringRef()); - - EXPECT_NE((uint8_t*)nullptr, code1); - EXPECT_NE((uint8_t*)nullptr, code2); - EXPECT_NE((uint8_t*)nullptr, data1); - EXPECT_NE((uint8_t*)nullptr, data2); - - // Check alignment - EXPECT_EQ((uint64_t)code1 & 0xf, 0u); - EXPECT_EQ((uint64_t)code2 & 0x1f, 0u); - EXPECT_EQ((uint64_t)code3 & 0x3f, 0u); - EXPECT_EQ((uint64_t)data1 & 0xf, 0u); - EXPECT_EQ((uint64_t)data2 & 0x3f, 0u); -} - -} diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp deleted file mode 100644 index 817d207..0000000 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ /dev/null @@ -1,728 +0,0 @@ -//===- JITTest.cpp - Unit tests for the JIT -------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/AsmParser/Parser.h" -#include "llvm/Bitcode/ReaderWriter.h" -#include "llvm/ExecutionEngine/JITMemoryManager.h" -#include "llvm/IR/BasicBlock.h" -#include "llvm/IR/Constant.h" -#include "llvm/IR/Constants.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GlobalValue.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/IR/Type.h" -#include "llvm/IR/TypeBuilder.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetSelect.h" -#include "gtest/gtest.h" -#include - -using namespace llvm; - -// This variable is intentionally defined differently in the statically-compiled -// program from the IR input to the JIT to assert that the JIT doesn't use its -// definition. Note that this variable must be defined even on platforms where -// JIT tests are disabled as it is referenced from the .def file. -extern "C" int32_t JITTest_AvailableExternallyGlobal; -int32_t JITTest_AvailableExternallyGlobal LLVM_ATTRIBUTE_USED = 42; - -// This function is intentionally defined differently in the statically-compiled -// program from the IR input to the JIT to assert that the JIT doesn't use its -// definition. Note that this function must be defined even on platforms where -// JIT tests are disabled as it is referenced from the .def file. -extern "C" int32_t JITTest_AvailableExternallyFunction() LLVM_ATTRIBUTE_USED; -extern "C" int32_t JITTest_AvailableExternallyFunction() { - return 42; -} - -namespace { - -// Tests on ARM, PowerPC and SystemZ disabled as we're running the old jit -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \ - && !defined(__aarch64__) - -Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) { - std::vector params; - FunctionType *FTy = FunctionType::get(G->getType()->getElementType(), - params, false); - Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, Name, M); - BasicBlock *Entry = BasicBlock::Create(M->getContext(), "entry", F); - IRBuilder<> builder(Entry); - Value *Load = builder.CreateLoad(G); - Type *GTy = G->getType()->getElementType(); - Value *Add = builder.CreateAdd(Load, ConstantInt::get(GTy, 1LL)); - builder.CreateStore(Add, G); - builder.CreateRet(Add); - return F; -} - -std::string DumpFunction(const Function *F) { - std::string Result; - raw_string_ostream(Result) << "" << *F; - return Result; -} - -class RecordingJITMemoryManager : public JITMemoryManager { - const std::unique_ptr Base; - -public: - RecordingJITMemoryManager() - : Base(JITMemoryManager::CreateDefaultMemManager()) { - stubsAllocated = 0; - } - virtual void *getPointerToNamedFunction(const std::string &Name, - bool AbortOnFailure = true) { - return Base->getPointerToNamedFunction(Name, AbortOnFailure); - } - - virtual void setMemoryWritable() { Base->setMemoryWritable(); } - virtual void setMemoryExecutable() { Base->setMemoryExecutable(); } - virtual void setPoisonMemory(bool poison) { Base->setPoisonMemory(poison); } - virtual void AllocateGOT() { Base->AllocateGOT(); } - virtual uint8_t *getGOTBase() const { return Base->getGOTBase(); } - struct StartFunctionBodyCall { - StartFunctionBodyCall(uint8_t *Result, const Function *F, - uintptr_t ActualSize, uintptr_t ActualSizeResult) - : Result(Result), F(F), F_dump(DumpFunction(F)), - ActualSize(ActualSize), ActualSizeResult(ActualSizeResult) {} - uint8_t *Result; - const Function *F; - std::string F_dump; - uintptr_t ActualSize; - uintptr_t ActualSizeResult; - }; - std::vector startFunctionBodyCalls; - virtual uint8_t *startFunctionBody(const Function *F, - uintptr_t &ActualSize) { - uintptr_t InitialActualSize = ActualSize; - uint8_t *Result = Base->startFunctionBody(F, ActualSize); - startFunctionBodyCalls.push_back( - StartFunctionBodyCall(Result, F, InitialActualSize, ActualSize)); - return Result; - } - int stubsAllocated; - uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize, - unsigned Alignment) override { - stubsAllocated++; - return Base->allocateStub(F, StubSize, Alignment); - } - struct EndFunctionBodyCall { - EndFunctionBodyCall(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) - : F(F), F_dump(DumpFunction(F)), - FunctionStart(FunctionStart), FunctionEnd(FunctionEnd) {} - const Function *F; - std::string F_dump; - uint8_t *FunctionStart; - uint8_t *FunctionEnd; - }; - std::vector endFunctionBodyCalls; - virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart, - uint8_t *FunctionEnd) { - endFunctionBodyCalls.push_back( - EndFunctionBodyCall(F, FunctionStart, FunctionEnd)); - Base->endFunctionBody(F, FunctionStart, FunctionEnd); - } - virtual uint8_t *allocateDataSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName, bool IsReadOnly) { - return Base->allocateDataSection( - Size, Alignment, SectionID, SectionName, IsReadOnly); - } - virtual uint8_t *allocateCodeSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName) { - return Base->allocateCodeSection( - Size, Alignment, SectionID, SectionName); - } - virtual bool finalizeMemory(std::string *ErrMsg) { return false; } - virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) { - return Base->allocateSpace(Size, Alignment); - } - virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) { - return Base->allocateGlobal(Size, Alignment); - } - struct DeallocateFunctionBodyCall { - DeallocateFunctionBodyCall(const void *Body) : Body(Body) {} - const void *Body; - }; - std::vector deallocateFunctionBodyCalls; - virtual void deallocateFunctionBody(void *Body) { - deallocateFunctionBodyCalls.push_back(DeallocateFunctionBodyCall(Body)); - Base->deallocateFunctionBody(Body); - } -}; - -bool LoadAssemblyInto(Module *M, const char *assembly) { - SMDiagnostic Error; - bool success = - nullptr != ParseAssemblyString(assembly, M, Error, M->getContext()); - std::string errMsg; - raw_string_ostream os(errMsg); - Error.print("", os); - EXPECT_TRUE(success) << os.str(); - return success; -} - -class JITTest : public testing::Test { - protected: - virtual RecordingJITMemoryManager *createMemoryManager() { - return new RecordingJITMemoryManager; - } - - virtual void SetUp() { - M = new Module("
", Context); - RJMM = createMemoryManager(); - RJMM->setPoisonMemory(true); - std::string Error; - TargetOptions Options; - TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT) - .setJITMemoryManager(RJMM) - .setErrorStr(&Error) - .setTargetOptions(Options).create()); - ASSERT_TRUE(TheJIT.get() != nullptr) << Error; - } - - void LoadAssembly(const char *assembly) { - LoadAssemblyInto(M, assembly); - } - - LLVMContext Context; - Module *M; // Owned by ExecutionEngine. - RecordingJITMemoryManager *RJMM; - std::unique_ptr TheJIT; -}; - -// Regression test for a bug. The JIT used to allocate globals inside the same -// memory block used for the function, and when the function code was freed, -// the global was left in the same place. This test allocates a function -// that uses and global, deallocates it, and then makes sure that the global -// stays alive after that. -TEST(JIT, GlobalInFunction) { - LLVMContext context; - Module *M = new Module("
", context); - - JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager(); - // Tell the memory manager to poison freed memory so that accessing freed - // memory is more easily tested. - MemMgr->setPoisonMemory(true); - std::string Error; - std::unique_ptr JIT(EngineBuilder(M) - .setEngineKind(EngineKind::JIT) - .setErrorStr(&Error) - .setJITMemoryManager(MemMgr) - // The next line enables the fix: - .setAllocateGVsWithCode(false) - .create()); - ASSERT_EQ(Error, ""); - - // Create a global variable. - Type *GTy = Type::getInt32Ty(context); - GlobalVariable *G = new GlobalVariable( - *M, - GTy, - false, // Not constant. - GlobalValue::InternalLinkage, - Constant::getNullValue(GTy), - "myglobal"); - - // Make a function that points to a global. - Function *F1 = makeReturnGlobal("F1", G, M); - - // Get the pointer to the native code to force it to JIT the function and - // allocate space for the global. - void (*F1Ptr)() = - reinterpret_cast((intptr_t)JIT->getPointerToFunction(F1)); - - // Since F1 was codegen'd, a pointer to G should be available. - int32_t *GPtr = (int32_t*)JIT->getPointerToGlobalIfAvailable(G); - ASSERT_NE((int32_t*)nullptr, GPtr); - EXPECT_EQ(0, *GPtr); - - // F1() should increment G. - F1Ptr(); - EXPECT_EQ(1, *GPtr); - - // Make a second function identical to the first, referring to the same - // global. - Function *F2 = makeReturnGlobal("F2", G, M); - void (*F2Ptr)() = - reinterpret_cast((intptr_t)JIT->getPointerToFunction(F2)); - - // F2() should increment G. - F2Ptr(); - EXPECT_EQ(2, *GPtr); - - // Deallocate F1. - JIT->freeMachineCodeForFunction(F1); - - // F2() should *still* increment G. - F2Ptr(); - EXPECT_EQ(3, *GPtr); -} - -int PlusOne(int arg) { - return arg + 1; -} - -TEST_F(JITTest, FarCallToKnownFunction) { - // x86-64 can only make direct calls to functions within 32 bits of - // the current PC. To call anything farther away, we have to load - // the address into a register and call through the register. The - // current JIT does this by allocating a stub for any far call. - // There was a bug in which the JIT tried to emit a direct call when - // the target was already in the JIT's global mappings and lazy - // compilation was disabled. - - Function *KnownFunction = Function::Create( - TypeBuilder::get(Context), - GlobalValue::ExternalLinkage, "known", M); - TheJIT->addGlobalMapping(KnownFunction, (void*)(intptr_t)PlusOne); - - // int test() { return known(7); } - Function *TestFunction = Function::Create( - TypeBuilder::get(Context), - GlobalValue::ExternalLinkage, "test", M); - BasicBlock *Entry = BasicBlock::Create(Context, "entry", TestFunction); - IRBuilder<> Builder(Entry); - Value *result = Builder.CreateCall( - KnownFunction, - ConstantInt::get(TypeBuilder::get(Context), 7)); - Builder.CreateRet(result); - - TheJIT->DisableLazyCompilation(true); - int (*TestFunctionPtr)() = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(TestFunction)); - // This used to crash in trying to call PlusOne(). - EXPECT_EQ(8, TestFunctionPtr()); -} - -// Test a function C which calls A and B which call each other. -TEST_F(JITTest, NonLazyCompilationStillNeedsStubs) { - TheJIT->DisableLazyCompilation(true); - - FunctionType *Func1Ty = - cast(TypeBuilder::get(Context)); - std::vector arg_types; - arg_types.push_back(Type::getInt1Ty(Context)); - FunctionType *FuncTy = FunctionType::get( - Type::getVoidTy(Context), arg_types, false); - Function *Func1 = Function::Create(Func1Ty, Function::ExternalLinkage, - "func1", M); - Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage, - "func2", M); - Function *Func3 = Function::Create(FuncTy, Function::InternalLinkage, - "func3", M); - BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1); - BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2); - BasicBlock *True2 = BasicBlock::Create(Context, "cond_true", Func2); - BasicBlock *False2 = BasicBlock::Create(Context, "cond_false", Func2); - BasicBlock *Block3 = BasicBlock::Create(Context, "block3", Func3); - BasicBlock *True3 = BasicBlock::Create(Context, "cond_true", Func3); - BasicBlock *False3 = BasicBlock::Create(Context, "cond_false", Func3); - - // Make Func1 call Func2(0) and Func3(0). - IRBuilder<> Builder(Block1); - Builder.CreateCall(Func2, ConstantInt::getTrue(Context)); - Builder.CreateCall(Func3, ConstantInt::getTrue(Context)); - Builder.CreateRetVoid(); - - // void Func2(bool b) { if (b) { Func3(false); return; } return; } - Builder.SetInsertPoint(Block2); - Builder.CreateCondBr(Func2->arg_begin(), True2, False2); - Builder.SetInsertPoint(True2); - Builder.CreateCall(Func3, ConstantInt::getFalse(Context)); - Builder.CreateRetVoid(); - Builder.SetInsertPoint(False2); - Builder.CreateRetVoid(); - - // void Func3(bool b) { if (b) { Func2(false); return; } return; } - Builder.SetInsertPoint(Block3); - Builder.CreateCondBr(Func3->arg_begin(), True3, False3); - Builder.SetInsertPoint(True3); - Builder.CreateCall(Func2, ConstantInt::getFalse(Context)); - Builder.CreateRetVoid(); - Builder.SetInsertPoint(False3); - Builder.CreateRetVoid(); - - // Compile the function to native code - void (*F1Ptr)() = - reinterpret_cast((intptr_t)TheJIT->getPointerToFunction(Func1)); - - F1Ptr(); -} - -// Regression test for PR5162. This used to trigger an AssertingVH inside the -// JIT's Function to stub mapping. -TEST_F(JITTest, NonLazyLeaksNoStubs) { - TheJIT->DisableLazyCompilation(true); - - // Create two functions with a single basic block each. - FunctionType *FuncTy = - cast(TypeBuilder::get(Context)); - Function *Func1 = Function::Create(FuncTy, Function::ExternalLinkage, - "func1", M); - Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage, - "func2", M); - BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1); - BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2); - - // The first function calls the second and returns the result - IRBuilder<> Builder(Block1); - Value *Result = Builder.CreateCall(Func2); - Builder.CreateRet(Result); - - // The second function just returns a constant - Builder.SetInsertPoint(Block2); - Builder.CreateRet(ConstantInt::get(TypeBuilder::get(Context),42)); - - // Compile the function to native code - (void)TheJIT->getPointerToFunction(Func1); - - // Free the JIT state for the functions - TheJIT->freeMachineCodeForFunction(Func1); - TheJIT->freeMachineCodeForFunction(Func2); - - // Delete the first function (and show that is has no users) - EXPECT_EQ(Func1->getNumUses(), 0u); - Func1->eraseFromParent(); - - // Delete the second function (and show that it has no users - it had one, - // func1 but that's gone now) - EXPECT_EQ(Func2->getNumUses(), 0u); - Func2->eraseFromParent(); -} - -TEST_F(JITTest, ModuleDeletion) { - TheJIT->DisableLazyCompilation(false); - LoadAssembly("define void @main() { " - " call i32 @computeVal() " - " ret void " - "} " - " " - "define internal i32 @computeVal() { " - " ret i32 0 " - "} "); - Function *func = M->getFunction("main"); - TheJIT->getPointerToFunction(func); - TheJIT->removeModule(M); - delete M; - - SmallPtrSet FunctionsDeallocated; - for (unsigned i = 0, e = RJMM->deallocateFunctionBodyCalls.size(); - i != e; ++i) { - FunctionsDeallocated.insert(RJMM->deallocateFunctionBodyCalls[i].Body); - } - for (unsigned i = 0, e = RJMM->startFunctionBodyCalls.size(); i != e; ++i) { - EXPECT_TRUE(FunctionsDeallocated.count( - RJMM->startFunctionBodyCalls[i].Result)) - << "Function leaked: \n" << RJMM->startFunctionBodyCalls[i].F_dump; - } - EXPECT_EQ(RJMM->startFunctionBodyCalls.size(), - RJMM->deallocateFunctionBodyCalls.size()); -} - -// ARM, MIPS and PPC still emit stubs for calls since the target may be -// too far away to call directly. This #if can probably be removed when -// http://llvm.org/PR5201 is fixed. -#if !defined(__arm__) && !defined(__mips__) && \ - !defined(__powerpc__) && !defined(__ppc__) && !defined(__aarch64__) -typedef int (*FooPtr) (); - -TEST_F(JITTest, NoStubs) { - LoadAssembly("define void @bar() {" - "entry: " - "ret void" - "}" - " " - "define i32 @foo() {" - "entry:" - "call void @bar()" - "ret i32 undef" - "}" - " " - "define i32 @main() {" - "entry:" - "%0 = call i32 @foo()" - "call void @bar()" - "ret i32 undef" - "}"); - Function *foo = M->getFunction("foo"); - uintptr_t tmp = (uintptr_t)(TheJIT->getPointerToFunction(foo)); - FooPtr ptr = (FooPtr)(tmp); - - (ptr)(); - - // We should now allocate no more stubs, we have the code to foo - // and the existing stub for bar. - int stubsBefore = RJMM->stubsAllocated; - Function *func = M->getFunction("main"); - TheJIT->getPointerToFunction(func); - - Function *bar = M->getFunction("bar"); - TheJIT->getPointerToFunction(bar); - - ASSERT_EQ(stubsBefore, RJMM->stubsAllocated); -} -#endif // !ARM && !PPC - -TEST_F(JITTest, FunctionPointersOutliveTheirCreator) { - TheJIT->DisableLazyCompilation(true); - LoadAssembly("define i8()* @get_foo_addr() { " - " ret i8()* @foo " - "} " - " " - "define i8 @foo() { " - " ret i8 42 " - "} "); - Function *F_get_foo_addr = M->getFunction("get_foo_addr"); - - typedef char(*fooT)(); - fooT (*get_foo_addr)() = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(F_get_foo_addr)); - fooT foo_addr = get_foo_addr(); - - // Now free get_foo_addr. This should not free the machine code for foo or - // any call stub returned as foo's canonical address. - TheJIT->freeMachineCodeForFunction(F_get_foo_addr); - - // Check by calling the reported address of foo. - EXPECT_EQ(42, foo_addr()); - - // The reported address should also be the same as the result of a subsequent - // getPointerToFunction(foo). -#if 0 - // Fails until PR5126 is fixed: - Function *F_foo = M->getFunction("foo"); - fooT foo = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(F_foo)); - EXPECT_EQ((intptr_t)foo, (intptr_t)foo_addr); -#endif -} - -// ARM does not have an implementation of replaceMachineCodeForFunction(), -// so recompileAndRelinkFunction doesn't work. -#if !defined(__arm__) && !defined(__aarch64__) -TEST_F(JITTest, FunctionIsRecompiledAndRelinked) { - Function *F = Function::Create(TypeBuilder::get(Context), - GlobalValue::ExternalLinkage, "test", M); - BasicBlock *Entry = BasicBlock::Create(Context, "entry", F); - IRBuilder<> Builder(Entry); - Value *Val = ConstantInt::get(TypeBuilder::get(Context), 1); - Builder.CreateRet(Val); - - TheJIT->DisableLazyCompilation(true); - // Compile the function once, and make sure it works. - int (*OrigFPtr)() = reinterpret_cast( - (intptr_t)TheJIT->recompileAndRelinkFunction(F)); - EXPECT_EQ(1, OrigFPtr()); - - // Now change the function to return a different value. - Entry->eraseFromParent(); - BasicBlock *NewEntry = BasicBlock::Create(Context, "new_entry", F); - Builder.SetInsertPoint(NewEntry); - Val = ConstantInt::get(TypeBuilder::get(Context), 2); - Builder.CreateRet(Val); - // Recompile it, which should produce a new function pointer _and_ update the - // old one. - int (*NewFPtr)() = reinterpret_cast( - (intptr_t)TheJIT->recompileAndRelinkFunction(F)); - - EXPECT_EQ(2, NewFPtr()) - << "The new pointer should call the new version of the function"; - EXPECT_EQ(2, OrigFPtr()) - << "The old pointer's target should now jump to the new version"; -} -#endif // !defined(__arm__) - -TEST_F(JITTest, AvailableExternallyGlobalIsntEmitted) { - TheJIT->DisableLazyCompilation(true); - LoadAssembly("@JITTest_AvailableExternallyGlobal = " - " available_externally global i32 7 " - " " - "define i32 @loader() { " - " %result = load i32* @JITTest_AvailableExternallyGlobal " - " ret i32 %result " - "} "); - Function *loaderIR = M->getFunction("loader"); - - int32_t (*loader)() = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(loaderIR)); - EXPECT_EQ(42, loader()) << "func should return 42 from the external global," - << " not 7 from the IR version."; -} - -TEST_F(JITTest, AvailableExternallyFunctionIsntCompiled) { - TheJIT->DisableLazyCompilation(true); - LoadAssembly("define available_externally i32 " - " @JITTest_AvailableExternallyFunction() { " - " ret i32 7 " - "} " - " " - "define i32 @func() { " - " %result = tail call i32 " - " @JITTest_AvailableExternallyFunction() " - " ret i32 %result " - "} "); - Function *funcIR = M->getFunction("func"); - - int32_t (*func)() = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(funcIR)); - EXPECT_EQ(42, func()) << "func should return 42 from the static version," - << " not 7 from the IR version."; -} - -TEST_F(JITTest, EscapedLazyStubStillCallable) { - TheJIT->DisableLazyCompilation(false); - LoadAssembly("define internal i32 @stubbed() { " - " ret i32 42 " - "} " - " " - "define i32()* @get_stub() { " - " ret i32()* @stubbed " - "} "); - typedef int32_t(*StubTy)(); - - // Call get_stub() to get the address of @stubbed without actually JITting it. - Function *get_stubIR = M->getFunction("get_stub"); - StubTy (*get_stub)() = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(get_stubIR)); - StubTy stubbed = get_stub(); - // Now get_stubIR is the only reference to stubbed's stub. - get_stubIR->eraseFromParent(); - // Now there are no references inside the JIT, but we've got a pointer outside - // it. The stub should be callable and return the right value. - EXPECT_EQ(42, stubbed()); -} - -// Converts the LLVM assembly to bitcode and returns it in a std::string. An -// empty string indicates an error. -std::string AssembleToBitcode(LLVMContext &Context, const char *Assembly) { - Module TempModule("TempModule", Context); - if (!LoadAssemblyInto(&TempModule, Assembly)) { - return ""; - } - - std::string Result; - raw_string_ostream OS(Result); - WriteBitcodeToFile(&TempModule, OS); - OS.flush(); - return Result; -} - -// Returns a newly-created ExecutionEngine that reads the bitcode in 'Bitcode' -// lazily. The associated Module (owned by the ExecutionEngine) is returned in -// M. Both will be NULL on an error. Bitcode must live at least as long as the -// ExecutionEngine. -ExecutionEngine *getJITFromBitcode( - LLVMContext &Context, const std::string &Bitcode, Module *&M) { - // c_str() is null-terminated like MemoryBuffer::getMemBuffer requires. - MemoryBuffer *BitcodeBuffer = - MemoryBuffer::getMemBuffer(Bitcode, "Bitcode for test"); - ErrorOr ModuleOrErr = getLazyBitcodeModule(BitcodeBuffer, Context); - if (std::error_code EC = ModuleOrErr.getError()) { - ADD_FAILURE() << EC.message(); - delete BitcodeBuffer; - return nullptr; - } - M = ModuleOrErr.get(); - std::string errMsg; - ExecutionEngine *TheJIT = EngineBuilder(M) - .setEngineKind(EngineKind::JIT) - .setErrorStr(&errMsg) - .create(); - if (TheJIT == nullptr) { - ADD_FAILURE() << errMsg; - delete M; - M = nullptr; - return nullptr; - } - return TheJIT; -} - -TEST(LazyLoadedJITTest, MaterializableAvailableExternallyFunctionIsntCompiled) { - LLVMContext Context; - const std::string Bitcode = - AssembleToBitcode(Context, - "define available_externally i32 " - " @JITTest_AvailableExternallyFunction() { " - " ret i32 7 " - "} " - " " - "define i32 @func() { " - " %result = tail call i32 " - " @JITTest_AvailableExternallyFunction() " - " ret i32 %result " - "} "); - ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; - Module *M; - std::unique_ptr TheJIT( - getJITFromBitcode(Context, Bitcode, M)); - ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; - TheJIT->DisableLazyCompilation(true); - - Function *funcIR = M->getFunction("func"); - Function *availableFunctionIR = - M->getFunction("JITTest_AvailableExternallyFunction"); - - // Double-check that the available_externally function is still unmaterialized - // when getPointerToFunction needs to find out if it's available_externally. - EXPECT_TRUE(availableFunctionIR->isMaterializable()); - - int32_t (*func)() = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(funcIR)); - EXPECT_EQ(42, func()) << "func should return 42 from the static version," - << " not 7 from the IR version."; -} - -TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) { - LLVMContext Context; - const std::string Bitcode = - AssembleToBitcode(Context, - "define i32 @recur1(i32 %a) { " - " %zero = icmp eq i32 %a, 0 " - " br i1 %zero, label %done, label %notdone " - "done: " - " ret i32 3 " - "notdone: " - " %am1 = sub i32 %a, 1 " - " %result = call i32 @recur2(i32 %am1) " - " ret i32 %result " - "} " - " " - "define i32 @recur2(i32 %b) { " - " %result = call i32 @recur1(i32 %b) " - " ret i32 %result " - "} "); - ASSERT_FALSE(Bitcode.empty()) << "Assembling failed"; - Module *M; - std::unique_ptr TheJIT( - getJITFromBitcode(Context, Bitcode, M)); - ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT."; - TheJIT->DisableLazyCompilation(true); - - Function *recur1IR = M->getFunction("recur1"); - Function *recur2IR = M->getFunction("recur2"); - EXPECT_TRUE(recur1IR->isMaterializable()); - EXPECT_TRUE(recur2IR->isMaterializable()); - - int32_t (*recur1)(int32_t) = reinterpret_cast( - (intptr_t)TheJIT->getPointerToFunction(recur1IR)); - EXPECT_EQ(3, recur1(4)); -} -#endif // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) - -} diff --git a/unittests/ExecutionEngine/JIT/JITTests.def b/unittests/ExecutionEngine/JIT/JITTests.def deleted file mode 100644 index 17c91e8..0000000 --- a/unittests/ExecutionEngine/JIT/JITTests.def +++ /dev/null @@ -1,4 +0,0 @@ -EXPORTS -getPointerToNamedFunction -JITTest_AvailableExternallyFunction -JITTest_AvailableExternallyGlobal diff --git a/unittests/ExecutionEngine/JIT/Makefile b/unittests/ExecutionEngine/JIT/Makefile deleted file mode 100644 index d86c03b..0000000 --- a/unittests/ExecutionEngine/JIT/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -##===- unittests/ExecutionEngine/JIT/Makefile --------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -TESTNAME = JIT -LINK_COMPONENTS := asmparser bitreader bitwriter jit native - -# The JIT tests need to dlopen things. -NO_DEAD_STRIP := 1 - -include $(LEVEL)/Makefile.config - -SOURCES := JITEventListenerTest.cpp JITMemoryManagerTest.cpp JITTest.cpp MultiJITTest.cpp - - -ifeq ($(USE_INTEL_JITEVENTS), 1) - # Build the Intel JIT Events interface tests - SOURCES += IntelJITEventListenerTest.cpp - - # Add the Intel JIT Events include directory - CPPFLAGS += -I$(INTEL_JITEVENTS_INCDIR) - - # Link against the LLVM Intel JIT Evens interface library - LINK_COMPONENTS += debuginfo inteljitevents object -endif - -ifeq ($(USE_OPROFILE), 1) - # Build the OProfile JIT interface tests - SOURCES += OProfileJITEventListenerTest.cpp - - # Link against the LLVM oprofile interface library - LINK_COMPONENTS += oprofilejit -endif - -EXPORTED_SYMBOL_FILE = $(PROJ_OBJ_DIR)/JITTests.exports - -include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest - -# Permit these tests to use the JIT's symbolic lookup. -LD.Flags += $(RDYNAMIC) - -# Symbol exports are necessary (at least for now) when building with LTO. -$(LLVMUnitTestExe): $(NativeExportsFile) -$(PROJ_OBJ_DIR)/JITTests.exports: $(PROJ_SRC_DIR)/JITTests.def $(PROJ_OBJ_DIR)/.dir - tail -n +2 $< > $@ - diff --git a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp b/unittests/ExecutionEngine/JIT/MultiJITTest.cpp deleted file mode 100644 index f530e0d..0000000 --- a/unittests/ExecutionEngine/JIT/MultiJITTest.cpp +++ /dev/null @@ -1,190 +0,0 @@ -//===- MultiJITTest.cpp - Unit tests for instantiating multiple JITs ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/JIT.h" -#include "llvm/AsmParser/Parser.h" -#include "llvm/ExecutionEngine/GenericValue.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/SourceMgr.h" -#include "gtest/gtest.h" -#include - -using namespace llvm; - -namespace { - -// ARM, PowerPC and SystemZ tests disabled pending fix for PR10783. -#if !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) \ - && !defined(__aarch64__) - -bool LoadAssemblyInto(Module *M, const char *assembly) { - SMDiagnostic Error; - bool success = - nullptr != ParseAssemblyString(assembly, M, Error, M->getContext()); - std::string errMsg; - raw_string_ostream os(errMsg); - Error.print("", os); - EXPECT_TRUE(success) << os.str(); - return success; -} - -void createModule1(LLVMContext &Context1, Module *&M1, Function *&FooF1) { - M1 = new Module("test1", Context1); - LoadAssemblyInto(M1, - "define i32 @add1(i32 %ArgX1) { " - "entry: " - " %addresult = add i32 1, %ArgX1 " - " ret i32 %addresult " - "} " - " " - "define i32 @foo1() { " - "entry: " - " %add1 = call i32 @add1(i32 10) " - " ret i32 %add1 " - "} "); - FooF1 = M1->getFunction("foo1"); -} - -void createModule2(LLVMContext &Context2, Module *&M2, Function *&FooF2) { - M2 = new Module("test2", Context2); - LoadAssemblyInto(M2, - "define i32 @add2(i32 %ArgX2) { " - "entry: " - " %addresult = add i32 2, %ArgX2 " - " ret i32 %addresult " - "} " - " " - "define i32 @foo2() { " - "entry: " - " %add2 = call i32 @add2(i32 10) " - " ret i32 %add2 " - "} "); - FooF2 = M2->getFunction("foo2"); -} - -TEST(MultiJitTest, EagerMode) { - LLVMContext Context1; - Module *M1 = nullptr; - Function *FooF1 = nullptr; - createModule1(Context1, M1, FooF1); - - LLVMContext Context2; - Module *M2 = nullptr; - Function *FooF2 = nullptr; - createModule2(Context2, M2, FooF2); - - // Now we create the JIT in eager mode - std::unique_ptr EE1(EngineBuilder(M1).create()); - EE1->DisableLazyCompilation(true); - std::unique_ptr EE2(EngineBuilder(M2).create()); - EE2->DisableLazyCompilation(true); - - // Call the `foo' function with no arguments: - std::vector noargs; - GenericValue gv1 = EE1->runFunction(FooF1, noargs); - GenericValue gv2 = EE2->runFunction(FooF2, noargs); - - // Import result of execution: - EXPECT_EQ(gv1.IntVal, 11); - EXPECT_EQ(gv2.IntVal, 12); - - EE1->freeMachineCodeForFunction(FooF1); - EE2->freeMachineCodeForFunction(FooF2); -} - -TEST(MultiJitTest, LazyMode) { - LLVMContext Context1; - Module *M1 = nullptr; - Function *FooF1 = nullptr; - createModule1(Context1, M1, FooF1); - - LLVMContext Context2; - Module *M2 = nullptr; - Function *FooF2 = nullptr; - createModule2(Context2, M2, FooF2); - - // Now we create the JIT in lazy mode - std::unique_ptr EE1(EngineBuilder(M1).create()); - EE1->DisableLazyCompilation(false); - std::unique_ptr EE2(EngineBuilder(M2).create()); - EE2->DisableLazyCompilation(false); - - // Call the `foo' function with no arguments: - std::vector noargs; - GenericValue gv1 = EE1->runFunction(FooF1, noargs); - GenericValue gv2 = EE2->runFunction(FooF2, noargs); - - // Import result of execution: - EXPECT_EQ(gv1.IntVal, 11); - EXPECT_EQ(gv2.IntVal, 12); - - EE1->freeMachineCodeForFunction(FooF1); - EE2->freeMachineCodeForFunction(FooF2); -} - -extern "C" { - extern void *getPointerToNamedFunction(const char *Name); -} - -TEST(MultiJitTest, JitPool) { - LLVMContext Context1; - Module *M1 = nullptr; - Function *FooF1 = nullptr; - createModule1(Context1, M1, FooF1); - - LLVMContext Context2; - Module *M2 = nullptr; - Function *FooF2 = nullptr; - createModule2(Context2, M2, FooF2); - - // Now we create two JITs - std::unique_ptr EE1(EngineBuilder(M1).create()); - std::unique_ptr EE2(EngineBuilder(M2).create()); - - Function *F1 = EE1->FindFunctionNamed("foo1"); - void *foo1 = EE1->getPointerToFunction(F1); - - Function *F2 = EE2->FindFunctionNamed("foo2"); - void *foo2 = EE2->getPointerToFunction(F2); - - // Function in M1 - EXPECT_EQ(getPointerToNamedFunction("foo1"), foo1); - - // Function in M2 - EXPECT_EQ(getPointerToNamedFunction("foo2"), foo2); - - // Symbol search - intptr_t - sa = (intptr_t)getPointerToNamedFunction("getPointerToNamedFunction"); - EXPECT_TRUE(sa != 0); - intptr_t fa = (intptr_t)&getPointerToNamedFunction; - EXPECT_TRUE(fa != 0); -#ifdef __i386__ - // getPointerToNamedFunction might be indirect jump on Win32 --enable-shared. - // FF 25 : jmp *(pointer to IAT) - if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) { - fa = *(intptr_t *)(fa + 2); // Address to IAT - EXPECT_TRUE(fa != 0); - fa = *(intptr_t *)fa; // Bound value of IAT - } -#elif defined(__x86_64__) - // getPointerToNamedFunction might be indirect jump - // on Win32 x64 --enable-shared. - // FF 25 : jmp *(RIP + pointer to IAT) - if (sa != fa && memcmp((char *)fa, "\xFF\x25", 2) == 0) { - fa += *(int32_t *)(fa + 2) + 6; // Address to IAT(RIP) - fa = *(intptr_t *)fa; // Bound value of IAT - } -#endif - EXPECT_TRUE(sa == fa); -} -#endif // !defined(__arm__) && !defined(__powerpc__) && !defined(__s390__) - -} // anonymous namespace diff --git a/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp deleted file mode 100644 index 7057fca..0000000 --- a/unittests/ExecutionEngine/JIT/OProfileJITEventListenerTest.cpp +++ /dev/null @@ -1,165 +0,0 @@ -//===- OProfileJITEventListenerTest.cpp - Unit tests for OProfileJITEventsListener --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--------------------------------------------------------------------------------------===// - -#include "llvm/ExecutionEngine/OProfileWrapper.h" -#include "JITEventListenerTestCommon.h" -#include "llvm/ExecutionEngine/JITEventListener.h" -#include -#include - -using namespace llvm; - -namespace { - -struct OprofileNativeFunction { - const char* Name; - uint64_t Addr; - const void* CodePtr; - unsigned int CodeSize; - - OprofileNativeFunction(const char* name, - uint64_t addr, - const void* code, - unsigned int size) - : Name(name) - , Addr(addr) - , CodePtr(code) - , CodeSize(size) { - } -}; - -typedef std::list NativeFunctionList; -typedef std::list NativeDebugList; -NativeFunctionList NativeFunctions; - -NativeCodeMap ReportedDebugFuncs; - -} // namespace - -/// Mock implementaion of opagent library -namespace test_opagent { - -op_agent_t globalAgent = reinterpret_cast(42); - -op_agent_t open_agent() -{ - // return non-null op_agent_t - return globalAgent; -} - -int close_agent(op_agent_t agent) -{ - EXPECT_EQ(globalAgent, agent); - return 0; -} - -int write_native_code(op_agent_t agent, - const char* name, - uint64_t addr, - void const* code, - unsigned int size) -{ - EXPECT_EQ(globalAgent, agent); - OprofileNativeFunction func(name, addr, code, size); - NativeFunctions.push_back(func); - - // Verify no other registration has take place for the same address - EXPECT_TRUE(ReportedDebugFuncs.find(addr) == ReportedDebugFuncs.end()); - - ReportedDebugFuncs[addr]; - return 0; -} - -int write_debug_line_info(op_agent_t agent, - void const* code, - size_t num_entries, - struct debug_line_info const* info) -{ - EXPECT_EQ(globalAgent, agent); - - //verify code has been loaded first - uint64_t addr = reinterpret_cast(code); - NativeCodeMap::iterator i = ReportedDebugFuncs.find(addr); - EXPECT_TRUE(i != ReportedDebugFuncs.end()); - - NativeDebugList NativeInfo(info, info + num_entries); - - SourceLocations locs; - for(NativeDebugList::iterator i = NativeInfo.begin(); - i != NativeInfo.end(); - ++i) { - locs.push_back(std::make_pair(std::string(i->filename), i->lineno)); - } - ReportedDebugFuncs[addr] = locs; - - return 0; -} - -int unload_native_code(op_agent_t agent, uint64_t addr) { - EXPECT_EQ(globalAgent, agent); - - //verify that something for the given JIT addr has been loaded first - NativeCodeMap::iterator i = ReportedDebugFuncs.find(addr); - EXPECT_TRUE(i != ReportedDebugFuncs.end()); - ReportedDebugFuncs.erase(i); - return 0; -} - -int version() { - return 1; -} - -bool is_oprofile_running() { - return true; -} - -} //namespace test_opagent - -class OProfileJITEventListenerTest -: public JITEventListenerTestBase -{ -public: - OProfileJITEventListenerTest() - : JITEventListenerTestBase( - new OProfileWrapper(test_opagent::open_agent, - test_opagent::close_agent, - test_opagent::write_native_code, - test_opagent::write_debug_line_info, - test_opagent::unload_native_code, - test_opagent::version, - test_opagent::version, - test_opagent::is_oprofile_running)) - { - EXPECT_TRUE(0 != MockWrapper); - - Listener.reset(JITEventListener::createOProfileJITEventListener( - MockWrapper.get())); - EXPECT_TRUE(0 != Listener); - EE->RegisterJITEventListener(Listener.get()); - } -}; - -TEST_F(OProfileJITEventListenerTest, NoDebugInfo) { - TestNoDebugInfo(ReportedDebugFuncs); -} - -TEST_F(OProfileJITEventListenerTest, SingleLine) { - TestSingleLine(ReportedDebugFuncs); -} - -TEST_F(OProfileJITEventListenerTest, MultipleLines) { - TestMultipleLines(ReportedDebugFuncs); -} - -TEST_F(OProfileJITEventListenerTest, MultipleFiles) { - TestMultipleFiles(ReportedDebugFuncs); -} - -testing::Environment* const jit_env = - testing::AddGlobalTestEnvironment(new JITEnvironment); diff --git a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt index afa3f2a..b10cbb4 100644 --- a/unittests/ExecutionEngine/MCJIT/CMakeLists.txt +++ b/unittests/ExecutionEngine/MCJIT/CMakeLists.txt @@ -3,7 +3,7 @@ set(LLVM_LINK_COMPONENTS Core ExecutionEngine IPO - JIT + MC MCJIT ScalarOpts Support diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp index d03de89..c80b88b 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -139,8 +139,6 @@ protected: // The operating systems below are known to be sufficiently incompatible // that they will fail the MCJIT C API tests. - UnsupportedOSs.push_back(Triple::Cygwin); - UnsupportedEnvironments.push_back(Triple::Cygnus); } diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp index 98587f7..0582c92 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/ExecutionEngine/SectionMemoryManager.h" -#include "llvm/ExecutionEngine/JIT.h" #include "gtest/gtest.h" using namespace llvm; diff --git a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp index c5ca36e..b0d1bb3 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp @@ -94,8 +94,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_case) { Function *FA, *FB; createTwoModuleCase(A, FA, B, FB); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -114,8 +114,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) { Function *FA, *FB; createTwoModuleCase(A, FA, B, FB); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -135,8 +135,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) { Function *FA, *FB; createTwoModuleExternCase(A, FA, B, FB); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -156,8 +156,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_extern_case) { Function *FA, *FB; createTwoModuleExternCase(A, FA, B, FB); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -177,8 +177,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) { createTwoModuleExternCase(A, FA1, B, FB); FA2 = insertSimpleCallFunction(A.get(), FA1); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -213,8 +213,8 @@ TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) { FB = startFunction(B.get(), "FB"); endFunctionWithRet(FB, Builder.CreateLoad(GVB)); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str()); TheJIT->finalizeObject(); @@ -241,9 +241,9 @@ TEST_F(MCJITMultipleModuleTest, three_module_case) { Function *FA, *FB, *FC; createThreeModuleCase(A, FA, B, FB, C, FC); - createJIT(A.release()); - TheJIT->addModule(B.release()); - TheJIT->addModule(C.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); + TheJIT->addModule(std::move(C)); uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); checkAdd(ptr); @@ -266,9 +266,9 @@ TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) { Function *FA, *FB, *FC; createThreeModuleCase(A, FA, B, FB, C, FC); - createJIT(A.release()); - TheJIT->addModule(B.release()); - TheJIT->addModule(C.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); + TheJIT->addModule(std::move(C)); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -291,9 +291,9 @@ TEST_F(MCJITMultipleModuleTest, three_module_chain_case) { Function *FA, *FB, *FC; createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); - createJIT(A.release()); - TheJIT->addModule(B.release()); - TheJIT->addModule(C.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); + TheJIT->addModule(std::move(C)); uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str()); checkAdd(ptr); @@ -316,9 +316,9 @@ TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) { Function *FA, *FB, *FC; createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC); - createJIT(A.release()); - TheJIT->addModule(B.release()); - TheJIT->addModule(C.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); + TheJIT->addModule(std::move(C)); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAdd(ptr); @@ -341,8 +341,8 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) { Function *FA, *FB1, *FB2; createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str()); checkAccumulate(ptr); @@ -362,8 +362,8 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) { Function *FA, *FB1, *FB2; createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); checkAccumulate(ptr); @@ -383,8 +383,8 @@ TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) { Function *FA, *FB1, *FB2; createCrossModuleRecursiveCase(A, FA, B, FB1, FB2); - createJIT(A.release()); - TheJIT->addModule(B.release()); + createJIT(std::move(A)); + TheJIT->addModule(std::move(B)); uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str()); checkAccumulate(ptr); diff --git a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp index fbbab42..2736383 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp @@ -11,7 +11,6 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" -#include "llvm/ExecutionEngine/JIT.h" #include "llvm/ExecutionEngine/MCJIT.h" #include "llvm/ExecutionEngine/ObjectCache.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" @@ -25,17 +24,7 @@ class TestObjectCache : public ObjectCache { public: TestObjectCache() : DuplicateInserted(false) { } - virtual ~TestObjectCache() { - // Free any buffers we've allocated. - SmallVectorImpl::iterator it, end; - end = AllocatedBuffers.end(); - for (it = AllocatedBuffers.begin(); it != end; ++it) { - delete *it; - } - AllocatedBuffers.clear(); - } - - virtual void notifyObjectCompiled(const Module *M, const MemoryBuffer *Obj) { + void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override { // If we've seen this module before, note that. const std::string ModuleID = M->getModuleIdentifier(); if (ObjMap.find(ModuleID) != ObjMap.end()) @@ -44,7 +33,7 @@ public: ObjMap[ModuleID] = copyBuffer(Obj); } - virtual MemoryBuffer* getObject(const Module* M) { + virtual std::unique_ptr getObject(const Module* M) override { const MemoryBuffer* BufferFound = getObjectInternal(M); ModulesLookedUp.insert(M->getModuleIdentifier()); if (!BufferFound) @@ -72,16 +61,18 @@ public: } private: - MemoryBuffer *copyBuffer(const MemoryBuffer *Buf) { + MemoryBuffer *copyBuffer(MemoryBufferRef Buf) { // Create a local copy of the buffer. - MemoryBuffer *NewBuffer = MemoryBuffer::getMemBufferCopy(Buf->getBuffer()); - AllocatedBuffers.push_back(NewBuffer); - return NewBuffer; + std::unique_ptr NewBuffer = + MemoryBuffer::getMemBufferCopy(Buf.getBuffer()); + MemoryBuffer *Ret = NewBuffer.get(); + AllocatedBuffers.push_back(std::move(NewBuffer)); + return Ret; } StringMap ObjMap; StringSet<> ModulesLookedUp; - SmallVector AllocatedBuffers; + SmallVector, 2> AllocatedBuffers; bool DuplicateInserted; }; @@ -121,7 +112,7 @@ protected: TEST_F(MCJITObjectCacheTest, SetNullObjectCache) { SKIP_UNSUPPORTED_PLATFORM; - createJIT(M.release()); + createJIT(std::move(M)); TheJIT->setObjectCache(nullptr); @@ -137,7 +128,7 @@ TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) { // Save a copy of the module pointer before handing it off to MCJIT. const Module * SavedModulePointer = M.get(); - createJIT(M.release()); + createJIT(std::move(M)); TheJIT->setObjectCache(Cache.get()); @@ -164,7 +155,7 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { std::unique_ptr Cache(new TestObjectCache); // Compile this module with an MCJIT engine - createJIT(M.release()); + createJIT(std::move(M)); TheJIT->setObjectCache(Cache.get()); TheJIT->finalizeObject(); @@ -181,7 +172,7 @@ TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) { const Module * SecondModulePointer = M.get(); // Create a new MCJIT instance to load this module then execute it. - createJIT(M.release()); + createJIT(std::move(M)); TheJIT->setObjectCache(Cache.get()); compileAndRun(); @@ -198,7 +189,7 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { std::unique_ptr Cache(new TestObjectCache); // Compile this module with an MCJIT engine - createJIT(M.release()); + createJIT(std::move(M)); TheJIT->setObjectCache(Cache.get()); TheJIT->finalizeObject(); @@ -216,7 +207,7 @@ TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) { const Module * SecondModulePointer = M.get(); // Create a new MCJIT instance to load this module then execute it. - createJIT(M.release()); + createJIT(std::move(M)); TheJIT->setObjectCache(Cache.get()); // Verify that our object cache does not contain the module yet. diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp index c37c1d1..64d8c2f 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp @@ -49,7 +49,7 @@ TEST_F(MCJITTest, global_variable) { int initialValue = 5; GlobalValue *Global = insertGlobalInt32(M.get(), "test_global", initialValue); - createJIT(M.release()); + createJIT(std::move(M)); void *globalPtr = TheJIT->getPointerToGlobal(Global); EXPECT_TRUE(nullptr != globalPtr) << "Unable to get pointer to global value from JIT"; @@ -62,7 +62,7 @@ TEST_F(MCJITTest, add_function) { SKIP_UNSUPPORTED_PLATFORM; Function *F = insertAddFunction(M.get()); - createJIT(M.release()); + createJIT(std::move(M)); uint64_t addPtr = TheJIT->getFunctionAddress(F->getName().str()); EXPECT_TRUE(0 != addPtr) << "Unable to get pointer to function from JIT"; @@ -83,7 +83,7 @@ TEST_F(MCJITTest, run_main) { int rc = 6; Function *Main = insertMainFunction(M.get(), 6); - createJIT(M.release()); + createJIT(std::move(M)); uint64_t ptr = TheJIT->getFunctionAddress(Main->getName().str()); EXPECT_TRUE(0 != ptr) << "Unable to get pointer to main() from JIT"; @@ -104,7 +104,7 @@ TEST_F(MCJITTest, return_global) { Value *ReadGlobal = Builder.CreateLoad(GV); endFunctionWithRet(ReturnGlobal, ReadGlobal); - createJIT(M.release()); + createJIT(std::move(M)); uint64_t rgvPtr = TheJIT->getFunctionAddress(ReturnGlobal->getName().str()); EXPECT_TRUE(0 != rgvPtr); @@ -175,7 +175,7 @@ TEST_F(MCJITTest, multiple_functions) { Inner = Outer; } - createJIT(M.release()); + createJIT(std::move(M)); uint64_t ptr = TheJIT->getFunctionAddress(Outer->getName().str()); EXPECT_TRUE(0 != ptr) << "Unable to get pointer to outer function from JIT"; @@ -187,4 +187,16 @@ TEST_F(MCJITTest, multiple_functions) { #endif /*!defined(__arm__)*/ +TEST_F(MCJITTest, multiple_decl_lookups) { + SKIP_UNSUPPORTED_PLATFORM; + + Function *Foo = insertExternalReferenceToFunction(M.get(), "_exit"); + createJIT(std::move(M)); + void *A = TheJIT->getPointerToFunction(Foo); + void *B = TheJIT->getPointerToFunction(Foo); + + EXPECT_TRUE(A != 0) << "Failed lookup - test not correctly configured."; + EXPECT_EQ(A, B) << "Repeat calls to getPointerToFunction fail."; +} + } diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h index a48c071..7d704de 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef MCJIT_TEST_API_COMMON_H -#define MCJIT_TEST_API_COMMON_H +#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTAPICOMMON_H +#define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTAPICOMMON_H #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Triple.h" @@ -93,5 +93,5 @@ protected: } // namespace llvm -#endif // MCJIT_TEST_API_COMMON_H +#endif diff --git a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h index 25de312..eea88bb 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h +++ b/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h @@ -14,8 +14,8 @@ //===----------------------------------------------------------------------===// -#ifndef MCJIT_TEST_BASE_H -#define MCJIT_TEST_BASE_H +#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H +#define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H #include "MCJITTestAPICommon.h" #include "llvm/Config/config.h" @@ -107,6 +107,15 @@ protected: return Result; } + // Inserts a declaration to a function defined elsewhere + template + Function *insertExternalReferenceToFunction(Module *M, StringRef Name) { + Function *Result = Function::Create( + TypeBuilder::get(Context), + GlobalValue::ExternalLinkage, Name, M); + return Result; + } + // Inserts an declaration to a function defined elsewhere Function *insertExternalReferenceToFunction(Module *M, StringRef Name, FunctionType *FuncTy) { @@ -302,26 +311,23 @@ protected: // The operating systems below are known to be incompatible with MCJIT as // they are copied from the test/ExecutionEngine/MCJIT/lit.local.cfg and // should be kept in sync. - UnsupportedOSs.push_back(Triple::Cygwin); UnsupportedOSs.push_back(Triple::Darwin); UnsupportedEnvironments.push_back(Triple::Cygnus); } - void createJIT(Module *M) { + void createJIT(std::unique_ptr M) { // Due to the EngineBuilder constructor, it is required to have a Module // in order to construct an ExecutionEngine (i.e. MCJIT) assert(M != 0 && "a non-null Module must be provided to create MCJIT"); - EngineBuilder EB(M); + EngineBuilder EB(std::move(M)); std::string Error; TheJIT.reset(EB.setEngineKind(EngineKind::JIT) - .setUseMCJIT(true) /* can this be folded into the EngineKind enum? */ .setMCJITMemoryManager(MM) .setErrorStr(&Error) .setOptLevel(CodeGenOpt::None) - .setAllocateGVsWithCode(false) /*does this do anything?*/ .setCodeModel(CodeModel::JITDefault) .setRelocationModel(Reloc::Default) .setMArch(MArch) @@ -345,4 +351,4 @@ protected: } // namespace llvm -#endif // MCJIT_TEST_H +#endif diff --git a/unittests/ExecutionEngine/MCJIT/Makefile b/unittests/ExecutionEngine/MCJIT/Makefile index c4dd740..2822b20 100644 --- a/unittests/ExecutionEngine/MCJIT/Makefile +++ b/unittests/ExecutionEngine/MCJIT/Makefile @@ -9,7 +9,7 @@ LEVEL = ../../.. TESTNAME = MCJIT -LINK_COMPONENTS := core ipo jit mcjit native support +LINK_COMPONENTS := core ipo mcjit native support include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/ExecutionEngine/Makefile b/unittests/ExecutionEngine/Makefile index 38e667f..8ecb883 100644 --- a/unittests/ExecutionEngine/Makefile +++ b/unittests/ExecutionEngine/Makefile @@ -14,7 +14,7 @@ LINK_COMPONENTS :=interpreter include $(LEVEL)/Makefile.config ifeq ($(TARGET_HAS_JIT),1) - PARALLEL_DIRS = JIT MCJIT + PARALLEL_DIRS = MCJIT endif include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index b439d59..a046209 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -10,6 +10,7 @@ set(IRSources AttributesTest.cpp ConstantRangeTest.cpp ConstantsTest.cpp + DebugInfoTest.cpp DominatorTreeTest.cpp IRBuilderTest.cpp InstructionsTest.cpp @@ -21,6 +22,7 @@ set(IRSources PatternMatch.cpp TypeBuilderTest.cpp TypesTest.cpp + UseTest.cpp UserTest.cpp ValueHandleTest.cpp ValueMapTest.cpp diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index 0cd8549..5414b25 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -274,5 +274,78 @@ TEST(ConstantsTest, ReplaceWithConstantTest) { #undef CHECK +TEST(ConstantsTest, ConstantArrayReplaceWithConstant) { + LLVMContext Context; + std::unique_ptr M(new Module("MyModule", Context)); + + Type *IntTy = Type::getInt8Ty(Context); + ArrayType *ArrayTy = ArrayType::get(IntTy, 2); + Constant *A01Vals[2] = {ConstantInt::get(IntTy, 0), + ConstantInt::get(IntTy, 1)}; + Constant *A01 = ConstantArray::get(ArrayTy, A01Vals); + + Constant *Global = new GlobalVariable(*M, IntTy, false, + GlobalValue::ExternalLinkage, nullptr); + Constant *GlobalInt = ConstantExpr::getPtrToInt(Global, IntTy); + Constant *A0GVals[2] = {ConstantInt::get(IntTy, 0), GlobalInt}; + Constant *A0G = ConstantArray::get(ArrayTy, A0GVals); + ASSERT_NE(A01, A0G); + + GlobalVariable *RefArray = + new GlobalVariable(*M, ArrayTy, false, GlobalValue::ExternalLinkage, A0G); + ASSERT_EQ(A0G, RefArray->getInitializer()); + + GlobalInt->replaceAllUsesWith(ConstantInt::get(IntTy, 1)); + ASSERT_EQ(A01, RefArray->getInitializer()); +} + +TEST(ConstantsTest, ConstantExprReplaceWithConstant) { + LLVMContext Context; + std::unique_ptr M(new Module("MyModule", Context)); + + Type *IntTy = Type::getInt8Ty(Context); + Constant *G1 = new GlobalVariable(*M, IntTy, false, + GlobalValue::ExternalLinkage, nullptr); + Constant *G2 = new GlobalVariable(*M, IntTy, false, + GlobalValue::ExternalLinkage, nullptr); + ASSERT_NE(G1, G2); + + Constant *Int1 = ConstantExpr::getPtrToInt(G1, IntTy); + Constant *Int2 = ConstantExpr::getPtrToInt(G2, IntTy); + ASSERT_NE(Int1, Int2); + + GlobalVariable *Ref = + new GlobalVariable(*M, IntTy, false, GlobalValue::ExternalLinkage, Int1); + ASSERT_EQ(Int1, Ref->getInitializer()); + + G1->replaceAllUsesWith(G2); + ASSERT_EQ(Int2, Ref->getInitializer()); +} + +TEST(ConstantsTest, GEPReplaceWithConstant) { + LLVMContext Context; + std::unique_ptr M(new Module("MyModule", Context)); + + Type *IntTy = Type::getInt32Ty(Context); + Type *PtrTy = PointerType::get(IntTy, 0); + auto *C1 = ConstantInt::get(IntTy, 1); + auto *Placeholder = new GlobalVariable( + *M, IntTy, false, GlobalValue::ExternalWeakLinkage, nullptr); + auto *GEP = ConstantExpr::getGetElementPtr(Placeholder, C1); + ASSERT_EQ(GEP->getOperand(0), Placeholder); + + auto *Ref = + new GlobalVariable(*M, PtrTy, false, GlobalValue::ExternalLinkage, GEP); + ASSERT_EQ(GEP, Ref->getInitializer()); + + auto *Global = new GlobalVariable(*M, PtrTy, false, + GlobalValue::ExternalLinkage, nullptr); + auto *Alias = GlobalAlias::create(IntTy, 0, GlobalValue::ExternalLinkage, + "alias", Global, M.get()); + Placeholder->replaceAllUsesWith(Alias); + ASSERT_EQ(GEP, Ref->getInitializer()); + ASSERT_EQ(GEP->getOperand(0), Alias); +} + } // end anonymous namespace } // end namespace llvm diff --git a/unittests/IR/DebugInfoTest.cpp b/unittests/IR/DebugInfoTest.cpp new file mode 100644 index 0000000..1fa851e --- /dev/null +++ b/unittests/IR/DebugInfoTest.cpp @@ -0,0 +1,68 @@ +//===- llvm/unittest/IR/DebugInfo.cpp - DebugInfo tests -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/DebugInfo.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace llvm { + +static void PrintTo(const StringRef &S, ::std::ostream *os) { + *os << "(" << (const void *)S.data() << "," << S.size() << ") = '"; + for (auto C : S) + if (C) + *os << C; + else + *os << "\\00"; + *os << "'"; +} +static void PrintTo(const DIHeaderFieldIterator &I, ::std::ostream *os) { + PrintTo(I.getCurrent(), os); + *os << " in "; + PrintTo(I.getHeader(), os); +} + +} // end namespace llvm + +namespace { + +#define MAKE_FIELD_ITERATOR(S) \ + DIHeaderFieldIterator(StringRef(S, sizeof(S) - 1)) +TEST(DebugInfoTest, DIHeaderFieldIterator) { + ASSERT_EQ(DIHeaderFieldIterator(), DIHeaderFieldIterator()); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("")); + ASSERT_EQ(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("")); + ASSERT_EQ("", *DIHeaderFieldIterator("")); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("stuff")); + ASSERT_EQ(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("stuff")); + ASSERT_EQ("stuff", *DIHeaderFieldIterator("stuff")); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("st\0uff")); + ASSERT_NE(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("st\0uff")); + ASSERT_EQ(DIHeaderFieldIterator(), ++++MAKE_FIELD_ITERATOR("st\0uff")); + ASSERT_EQ("st", *MAKE_FIELD_ITERATOR("st\0uff")); + ASSERT_EQ("uff", *++MAKE_FIELD_ITERATOR("st\0uff")); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("stuff\0")); + ASSERT_NE(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("stuff\0")); + ASSERT_EQ(DIHeaderFieldIterator(), ++++MAKE_FIELD_ITERATOR("stuff\0")); + ASSERT_EQ("stuff", *MAKE_FIELD_ITERATOR("stuff\0")); + ASSERT_EQ("", *++MAKE_FIELD_ITERATOR("stuff\0")); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("\0stuff")); + ASSERT_NE(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("\0stuff")); + ASSERT_EQ(DIHeaderFieldIterator(), ++++MAKE_FIELD_ITERATOR("\0stuff")); + ASSERT_EQ("", *MAKE_FIELD_ITERATOR("\0stuff")); + ASSERT_EQ("stuff", *++MAKE_FIELD_ITERATOR("\0stuff")); +} + +} // end namespace diff --git a/unittests/IR/DominatorTreeTest.cpp b/unittests/IR/DominatorTreeTest.cpp index ab43d1c..6c43d6f 100644 --- a/unittests/IR/DominatorTreeTest.cpp +++ b/unittests/IR/DominatorTreeTest.cpp @@ -186,8 +186,7 @@ namespace llvm { }; char DPass::ID = 0; - - Module* makeLLVMModule(DPass *P) { + std::unique_ptr makeLLVMModule(DPass *P) { const char *ModuleStrig = "declare i32 @g()\n" \ "define void @f(i32 %x) {\n" \ @@ -213,12 +212,12 @@ namespace llvm { "}\n"; LLVMContext &C = getGlobalContext(); SMDiagnostic Err; - return ParseAssemblyString(ModuleStrig, nullptr, Err, C); + return parseAssemblyString(ModuleStrig, Err, C); } TEST(DominatorTree, Unreachable) { DPass *P = new DPass(); - std::unique_ptr M(makeLLVMModule(P)); + std::unique_ptr M = makeLLVMModule(P); PassManager Passes; Passes.add(P); Passes.run(*M); diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp index 2108575..df5c840 100644 --- a/unittests/IR/IRBuilderTest.cpp +++ b/unittests/IR/IRBuilderTest.cpp @@ -189,12 +189,16 @@ TEST_F(IRBuilderTest, FastMathFlags) { Builder.clearFastMathFlags(); + // To test a copy, make sure that a '0' and a '1' change state. F = Builder.CreateFDiv(F, F); ASSERT_TRUE(isa(F)); FDiv = cast(F); EXPECT_FALSE(FDiv->getFastMathFlags().any()); + FDiv->setHasAllowReciprocal(true); + FAdd->setHasAllowReciprocal(false); FDiv->copyFastMathFlags(FAdd); EXPECT_TRUE(FDiv->hasNoNaNs()); + EXPECT_FALSE(FDiv->hasAllowReciprocal()); } diff --git a/unittests/IR/LegacyPassManagerTest.cpp b/unittests/IR/LegacyPassManagerTest.cpp index 9c2a835..4efc2f5 100644 --- a/unittests/IR/LegacyPassManagerTest.cpp +++ b/unittests/IR/LegacyPassManagerTest.cpp @@ -54,11 +54,11 @@ namespace llvm { static char run; static char ID; ModuleNDNM() : ModulePass(ID) { } - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { run++; return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } }; @@ -70,7 +70,7 @@ namespace llvm { static char run; static char ID; ModuleNDM() : ModulePass(ID) {} - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { run++; return true; } @@ -83,7 +83,7 @@ namespace llvm { static char run; static char ID; ModuleNDM2() : ModulePass(ID) {} - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { run++; return true; } @@ -98,12 +98,12 @@ namespace llvm { ModuleDNM() : ModulePass(ID) { initializeModuleNDMPass(*PassRegistry::getPassRegistry()); } - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { EXPECT_TRUE(getAnalysisIfAvailable()); run++; return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); AU.setPreservesAll(); } @@ -139,7 +139,7 @@ namespace llvm { runc = 0; } - virtual void releaseMemory() { + void releaseMemory() override { EXPECT_GT(runc, 0); EXPECT_GT(allocated, 0); allocated--; @@ -157,12 +157,12 @@ namespace llvm { using llvm::Pass::doInitialization; using llvm::Pass::doFinalization; #endif - virtual bool doInitialization(T &t) { + bool doInitialization(T &t) override { EXPECT_FALSE(PassTestBase

::initialized); PassTestBase

::initialized = true; return false; } - virtual bool doFinalization(T &t) { + bool doFinalization(T &t) override { EXPECT_FALSE(PassTestBase

::finalized); PassTestBase

::finalized = true; EXPECT_EQ(0, PassTestBase

::allocated); @@ -175,7 +175,7 @@ namespace llvm { CGPass() { initializeCGPassPass(*PassRegistry::getPassRegistry()); } - virtual bool runOnSCC(CallGraphSCC &SCMM) { + bool runOnSCC(CallGraphSCC &SCMM) override { EXPECT_TRUE(getAnalysisIfAvailable()); run(); return false; @@ -184,7 +184,7 @@ namespace llvm { struct FPass : public PassTest { public: - virtual bool runOnFunction(Function &F) { + bool runOnFunction(Function &F) override { // FIXME: PR4112 // EXPECT_TRUE(getAnalysisIfAvailable()); run(); @@ -209,17 +209,17 @@ namespace llvm { } using llvm::Pass::doInitialization; using llvm::Pass::doFinalization; - virtual bool doInitialization(Loop* L, LPPassManager &LPM) { + bool doInitialization(Loop* L, LPPassManager &LPM) override { initialized = true; initcount++; return false; } - virtual bool runOnLoop(Loop *L, LPPassManager &LPM) { + bool runOnLoop(Loop *L, LPPassManager &LPM) override { EXPECT_TRUE(getAnalysisIfAvailable()); run(); return false; } - virtual bool doFinalization() { + bool doFinalization() override { fincount++; finalized = true; return false; @@ -242,25 +242,25 @@ namespace llvm { inited = 0; fin = 0; } - virtual bool doInitialization(Module &M) { + bool doInitialization(Module &M) override { EXPECT_FALSE(initialized); initialized = true; return false; } - virtual bool doInitialization(Function &F) { + bool doInitialization(Function &F) override { inited++; return false; } - virtual bool runOnBasicBlock(BasicBlock &BB) { + bool runOnBasicBlock(BasicBlock &BB) override { EXPECT_TRUE(getAnalysisIfAvailable()); run(); return false; } - virtual bool doFinalization(Function &F) { + bool doFinalization(Function &F) override { fin++; return false; } - virtual bool doFinalization(Module &M) { + bool doFinalization(Module &M) override { EXPECT_FALSE(finalized); finalized = true; EXPECT_EQ(0, allocated); @@ -276,7 +276,7 @@ namespace llvm { OnTheFlyTest() : ModulePass(ID) { initializeFPassPass(*PassRegistry::getPassRegistry()); } - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { EXPECT_TRUE(getAnalysisIfAvailable()); for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) { Function &F = *I; @@ -287,7 +287,7 @@ namespace llvm { } return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired(); } }; @@ -303,7 +303,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; PassManager Passes; - Passes.add(new DataLayoutPass(&M)); + Passes.add(new DataLayoutPass()); Passes.add(mNDM2); Passes.add(mNDM); Passes.add(mNDNM); @@ -327,7 +327,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; PassManager Passes; - Passes.add(new DataLayoutPass(&M)); + Passes.add(new DataLayoutPass()); Passes.add(mNDM); Passes.add(mNDNM); Passes.add(mNDM2);// invalidates mNDM needed by mDNM @@ -349,7 +349,7 @@ namespace llvm { std::unique_ptr M(makeLLVMModule()); T *P = new T(); PassManager Passes; - Passes.add(new DataLayoutPass(M.get())); + Passes.add(new DataLayoutPass()); Passes.add(P); Passes.run(*M); T::finishedOK(run); @@ -360,7 +360,7 @@ namespace llvm { Module *M = makeLLVMModule(); T *P = new T(); PassManager Passes; - Passes.add(new DataLayoutPass(M)); + Passes.add(new DataLayoutPass()); Passes.add(P); Passes.run(*M); T::finishedOK(run, N); @@ -398,7 +398,7 @@ namespace llvm { SCOPED_TRACE("Running OnTheFlyTest"); struct OnTheFlyTest *O = new OnTheFlyTest(); PassManager Passes; - Passes.add(new DataLayoutPass(M)); + Passes.add(new DataLayoutPass()); Passes.add(O); Passes.run(*M); diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp index 25037a7..d493156 100644 --- a/unittests/IR/PassManagerTest.cpp +++ b/unittests/IR/PassManagerTest.cpp @@ -168,7 +168,7 @@ struct TestInvalidationFunctionPass { Module *parseIR(const char *IR) { LLVMContext &C = getGlobalContext(); SMDiagnostic Err; - return ParseAssemblyString(IR, nullptr, Err, C); + return parseAssemblyString(IR, Err, C).release(); } class PassManagerTest : public ::testing::Test { diff --git a/unittests/IR/UseTest.cpp b/unittests/IR/UseTest.cpp new file mode 100644 index 0000000..3f33ca6 --- /dev/null +++ b/unittests/IR/UseTest.cpp @@ -0,0 +1,112 @@ +//===- llvm/unittest/IR/UseTest.cpp - Use unit tests ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/User.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/SourceMgr.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(UseTest, sort) { + LLVMContext C; + + const char *ModuleString = "define void @f(i32 %x) {\n" + "entry:\n" + " %v0 = add i32 %x, 0\n" + " %v2 = add i32 %x, 2\n" + " %v5 = add i32 %x, 5\n" + " %v1 = add i32 %x, 1\n" + " %v3 = add i32 %x, 3\n" + " %v7 = add i32 %x, 7\n" + " %v6 = add i32 %x, 6\n" + " %v4 = add i32 %x, 4\n" + " ret void\n" + "}\n"; + SMDiagnostic Err; + char vnbuf[8]; + std::unique_ptr M = parseAssemblyString(ModuleString, Err, C); + Function *F = M->getFunction("f"); + ASSERT_TRUE(F); + ASSERT_TRUE(F->arg_begin() != F->arg_end()); + Argument &X = *F->arg_begin(); + ASSERT_EQ("x", X.getName()); + + X.sortUseList([](const Use &L, const Use &R) { + return L.getUser()->getName() < R.getUser()->getName(); + }); + unsigned I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", I++); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); + + X.sortUseList([](const Use &L, const Use &R) { + return L.getUser()->getName() > R.getUser()->getName(); + }); + I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", (7 - I++)); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); +} + +TEST(UseTest, reverse) { + LLVMContext C; + + const char *ModuleString = "define void @f(i32 %x) {\n" + "entry:\n" + " %v0 = add i32 %x, 0\n" + " %v2 = add i32 %x, 2\n" + " %v5 = add i32 %x, 5\n" + " %v1 = add i32 %x, 1\n" + " %v3 = add i32 %x, 3\n" + " %v7 = add i32 %x, 7\n" + " %v6 = add i32 %x, 6\n" + " %v4 = add i32 %x, 4\n" + " ret void\n" + "}\n"; + SMDiagnostic Err; + char vnbuf[8]; + std::unique_ptr M = parseAssemblyString(ModuleString, Err, C); + Function *F = M->getFunction("f"); + ASSERT_TRUE(F); + ASSERT_TRUE(F->arg_begin() != F->arg_end()); + Argument &X = *F->arg_begin(); + ASSERT_EQ("x", X.getName()); + + X.sortUseList([](const Use &L, const Use &R) { + return L.getUser()->getName() < R.getUser()->getName(); + }); + unsigned I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", I++); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); + + X.reverseUseList(); + I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", (7 - I++)); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); +} + +} // end anonymous namespace diff --git a/unittests/IR/UserTest.cpp b/unittests/IR/UserTest.cpp index eb07e82..5572424 100644 --- a/unittests/IR/UserTest.cpp +++ b/unittests/IR/UserTest.cpp @@ -65,7 +65,7 @@ TEST(UserTest, ValueOpIteration) { " ret void\n" "}\n"; SMDiagnostic Err; - Module *M = ParseAssemblyString(ModuleString, nullptr, Err, C); + std::unique_ptr M = parseAssemblyString(ModuleString, Err, C); Function *F = M->getFunction("f"); BasicBlock &ExitBB = F->back(); diff --git a/unittests/IR/ValueMapTest.cpp b/unittests/IR/ValueMapTest.cpp index 0b7198f..a6bad71 100644 --- a/unittests/IR/ValueMapTest.cpp +++ b/unittests/IR/ValueMapTest.cpp @@ -186,11 +186,11 @@ struct LockMutex : ValueMapConfig { }; static void onRAUW(const ExtraData &Data, KeyT Old, KeyT New) { *Data.CalledRAUW = true; - EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked."; + EXPECT_FALSE(Data.M->try_lock()) << "Mutex should already be locked."; } static void onDelete(const ExtraData &Data, KeyT Old) { *Data.CalledDeleted = true; - EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked."; + EXPECT_FALSE(Data.M->try_lock()) << "Mutex should already be locked."; } static MutexT *getMutex(const ExtraData &Data) { return Data.M; } }; diff --git a/unittests/IR/ValueTest.cpp b/unittests/IR/ValueTest.cpp index 61e44a9..4dd0c2c 100644 --- a/unittests/IR/ValueTest.cpp +++ b/unittests/IR/ValueTest.cpp @@ -34,7 +34,7 @@ TEST(ValueTest, UsedInBasicBlock) { " ret void\n" "}\n"; SMDiagnostic Err; - Module *M = ParseAssemblyString(ModuleString, nullptr, Err, C); + std::unique_ptr M = parseAssemblyString(ModuleString, Err, C); Function *F = M->getFunction("f"); @@ -60,6 +60,10 @@ TEST(GlobalTest, CreateAddressSpace) { GlobalVariable::NotThreadLocal, 1); + EXPECT_TRUE(Value::MaximumAlignment == 536870912U); + Dummy0->setAlignment(536870912U); + EXPECT_EQ(Dummy0->getAlignment(), 536870912U); + // Make sure the address space isn't dropped when returning this. Constant *Dummy1 = M->getOrInsertGlobal("dummy", Int32Ty); EXPECT_EQ(Dummy0, Dummy1); @@ -83,4 +87,23 @@ TEST(GlobalTest, CreateAddressSpace) { EXPECT_EQ(1u, DummyCast1->getType()->getPointerAddressSpace()); EXPECT_NE(DummyCast0, DummyCast1) << *DummyCast1; } + +#ifdef GTEST_HAS_DEATH_TEST +#ifndef NDEBUG +TEST(GlobalTest, AlignDeath) { + LLVMContext &Ctx = getGlobalContext(); + std::unique_ptr M(new Module("TestModule", Ctx)); + Type *Int32Ty = Type::getInt32Ty(Ctx); + GlobalVariable *Var = + new GlobalVariable(*M, Int32Ty, true, GlobalValue::ExternalLinkage, + Constant::getAllOnesValue(Int32Ty), "var", nullptr, + GlobalVariable::NotThreadLocal, 1); + + EXPECT_DEATH(Var->setAlignment(536870913U), "Alignment is not a power of 2"); + EXPECT_DEATH(Var->setAlignment(1073741824U), + "Alignment is greater than MaximumAlignment"); +} +#endif +#endif + } // end anonymous namespace diff --git a/unittests/LineEditor/CMakeLists.txt b/unittests/LineEditor/CMakeLists.txt index c6823d8..70d7497 100644 --- a/unittests/LineEditor/CMakeLists.txt +++ b/unittests/LineEditor/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS LineEditor + Support ) add_llvm_unittest(LineEditorTests diff --git a/unittests/Linker/CMakeLists.txt b/unittests/Linker/CMakeLists.txt index c3dccb6..05f45c0 100644 --- a/unittests/Linker/CMakeLists.txt +++ b/unittests/Linker/CMakeLists.txt @@ -1,4 +1,5 @@ set(LLVM_LINK_COMPONENTS + AsmParser core linker ) diff --git a/unittests/Linker/LinkModulesTest.cpp b/unittests/Linker/LinkModulesTest.cpp index 4ccced1..b15d180 100644 --- a/unittests/Linker/LinkModulesTest.cpp +++ b/unittests/Linker/LinkModulesTest.cpp @@ -7,12 +7,14 @@ // //===----------------------------------------------------------------------===// +#include "llvm/AsmParser/Parser.h" #include "llvm/Linker/Linker.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" using namespace llvm; @@ -88,7 +90,7 @@ TEST_F(LinkModuleTest, BlockAddress) { Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx))); Module *LinkedModule = new Module("MyModuleLinked", Ctx); - Linker::LinkModules(LinkedModule, M.get(), Linker::PreserveSource, nullptr); + Linker::LinkModules(LinkedModule, M.get()); // Delete the original module. M.reset(); @@ -122,12 +124,13 @@ TEST_F(LinkModuleTest, BlockAddress) { delete LinkedModule; } -TEST_F(LinkModuleTest, EmptyModule) { +static Module *getInternal(LLVMContext &Ctx) { Module *InternalM = new Module("InternalModule", Ctx); FunctionType *FTy = FunctionType::get( Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/); - F = Function::Create(FTy, Function::InternalLinkage, "bar", InternalM); + Function *F = + Function::Create(FTy, Function::InternalLinkage, "bar", InternalM); F->setCallingConv(CallingConv::C); BasicBlock *BB = BasicBlock::Create(Ctx, "", F); @@ -141,16 +144,37 @@ TEST_F(LinkModuleTest, EmptyModule) { GlobalValue::InternalLinkage, nullptr, "g"); GV->setInitializer(ConstantStruct::get(STy, F)); + return InternalM; +} + +TEST_F(LinkModuleTest, EmptyModule) { + std::unique_ptr InternalM(getInternal(Ctx)); + std::unique_ptr EmptyM(new Module("EmptyModule1", Ctx)); + Linker::LinkModules(EmptyM.get(), InternalM.get()); +} + +TEST_F(LinkModuleTest, EmptyModule2) { + std::unique_ptr InternalM(getInternal(Ctx)); + std::unique_ptr EmptyM(new Module("EmptyModule1", Ctx)); + Linker::LinkModules(InternalM.get(), EmptyM.get()); +} + +TEST_F(LinkModuleTest, TypeMerge) { + LLVMContext C; + SMDiagnostic Err; + + const char *M1Str = "%t = type {i32}\n" + "@t1 = weak global %t zeroinitializer\n"; + std::unique_ptr M1 = parseAssemblyString(M1Str, Err, C); - Module *EmptyM = new Module("EmptyModule1", Ctx); - Linker::LinkModules(EmptyM, InternalM, Linker::PreserveSource, nullptr); + const char *M2Str = "%t = type {i32}\n" + "@t2 = weak global %t zeroinitializer\n"; + std::unique_ptr M2 = parseAssemblyString(M2Str, Err, C); - delete EmptyM; - EmptyM = new Module("EmptyModule2", Ctx); - Linker::LinkModules(InternalM, EmptyM, Linker::PreserveSource, nullptr); + Linker::LinkModules(M1.get(), M2.get(), [](const llvm::DiagnosticInfo &){}); - delete EmptyM; - delete InternalM; + EXPECT_EQ(M1->getNamedGlobal("t1")->getType(), + M1->getNamedGlobal("t2")->getType()); } } // end anonymous namespace diff --git a/unittests/Linker/Makefile b/unittests/Linker/Makefile index c6058c4..ddbce07 100644 --- a/unittests/Linker/Makefile +++ b/unittests/Linker/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TESTNAME = Linker -LINK_COMPONENTS := core linker +LINK_COMPONENTS := core linker asmparser include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/MC/CMakeLists.txt b/unittests/MC/CMakeLists.txt index e2beab2..c82bcde 100644 --- a/unittests/MC/CMakeLists.txt +++ b/unittests/MC/CMakeLists.txt @@ -1,9 +1,18 @@ set(LLVM_LINK_COMPONENTS - MCAnalysis + ${LLVM_TARGETS_TO_BUILD} + MC + MCDisassembler + Support ) add_llvm_unittest(MCTests - MCAtomTest.cpp + Disassembler.cpp StringTableBuilderTest.cpp YAMLTest.cpp ) + +foreach(t ${LLVM_TARGETS_TO_BUILD}) + if (IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/${t}") + add_subdirectory(${t}) + endif (IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/${t}") +endforeach() diff --git a/unittests/MC/Disassembler.cpp b/unittests/MC/Disassembler.cpp new file mode 100644 index 0000000..dd0f1ef --- /dev/null +++ b/unittests/MC/Disassembler.cpp @@ -0,0 +1,64 @@ +//===- llvm/unittest/Object/Disassembler.cpp ------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm-c/Disassembler.h" +#include "llvm/Support/TargetSelect.h" +#include "gtest/gtest.h" + +using namespace llvm; + +static const char *symbolLookupCallback(void *DisInfo, uint64_t ReferenceValue, + uint64_t *ReferenceType, + uint64_t ReferencePC, + const char **ReferenceName) { + *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; + return nullptr; +} + +TEST(Disassembler, Test1) { + llvm::InitializeAllTargetInfos(); + llvm::InitializeAllTargetMCs(); + llvm::InitializeAllDisassemblers(); + + uint8_t Bytes[] = {0x90, 0x90, 0xeb, 0xfd}; + uint8_t *BytesP = Bytes; + const char OutStringSize = 100; + char OutString[OutStringSize]; + LLVMDisasmContextRef DCR = LLVMCreateDisasm("x86_64-pc-linux", nullptr, 0, + nullptr, symbolLookupCallback); + if (!DCR) + return; + + size_t InstSize; + unsigned NumBytes = sizeof(Bytes); + unsigned PC = 0; + + InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString, + OutStringSize); + EXPECT_EQ(InstSize, 1U); + EXPECT_EQ(StringRef(OutString), "\tnop"); + PC += InstSize; + BytesP += InstSize; + NumBytes -= InstSize; + + InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString, + OutStringSize); + EXPECT_EQ(InstSize, 1U); + EXPECT_EQ(StringRef(OutString), "\tnop"); + PC += InstSize; + BytesP += InstSize; + NumBytes -= InstSize; + + InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString, + OutStringSize); + EXPECT_EQ(InstSize, 2U); + EXPECT_EQ(StringRef(OutString), "\tjmp\t0x1"); + + LLVMDisasmDispose(DCR); +} diff --git a/unittests/MC/Hexagon/CMakeLists.txt b/unittests/MC/Hexagon/CMakeLists.txt new file mode 100644 index 0000000..6d4ee93 --- /dev/null +++ b/unittests/MC/Hexagon/CMakeLists.txt @@ -0,0 +1,14 @@ +set(LLVM_LINK_COMPONENTS + HexagonCodeGen + HexagonDesc + HexagonInfo + MC + Support + ) + +include_directories (${LLVM_MAIN_SRC_DIR}/lib/Target/Hexagon) +include_directories (${LLVM_BINARY_DIR}/lib/Target/Hexagon) + +add_llvm_unittest(HexagonTests + HexagonMCCodeEmitterTest.cpp + ) diff --git a/unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp b/unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp new file mode 100644 index 0000000..958a21f --- /dev/null +++ b/unittests/MC/Hexagon/HexagonMCCodeEmitterTest.cpp @@ -0,0 +1,53 @@ +#include "gtest/gtest.h" + +#include + +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" + +#include "MCTargetDesc/HexagonMCInst.h" +#include "MCTargetDesc/HexagonMCTargetDesc.h" + +namespace { +class TestEmitter { +public: + TestEmitter() : Triple("hexagon-unknown-elf") { + LLVMInitializeHexagonTargetInfo(); + LLVMInitializeHexagonTarget(); + LLVMInitializeHexagonTargetMC(); + std::string error; + Target = llvm::TargetRegistry::lookupTarget("hexagon", error); + assert(Target != nullptr && "Expected to find target"); + assert(error.empty() && "Error should be empty if we have a target"); + RegisterInfo = Target->createMCRegInfo(Triple); + assert(RegisterInfo != nullptr && "Expecting to find register info"); + AsmInfo = Target->createMCAsmInfo(*RegisterInfo, Triple); + assert(AsmInfo != nullptr && "Expecting to find asm info"); + Context = new llvm::MCContext(AsmInfo, RegisterInfo, nullptr); + assert(Context != nullptr && "Expecting to create a context"); + Subtarget = Target->createMCSubtargetInfo(Triple, "hexagonv4", ""); + assert(Subtarget != nullptr && "Expecting to find a subtarget"); + InstrInfo = Target->createMCInstrInfo(); + assert(InstrInfo != nullptr && "Expecting to find instr info"); + Emitter = Target->createMCCodeEmitter(*InstrInfo, *RegisterInfo, *Subtarget, + *Context); + assert(Emitter != nullptr); + } + std::string Triple; + llvm::Target const *Target; + llvm::MCRegisterInfo *RegisterInfo; + llvm::MCAsmInfo *AsmInfo; + llvm::MCContext *Context; + llvm::MCSubtargetInfo *Subtarget; + llvm::MCInstrInfo *InstrInfo; + llvm::MCCodeEmitter *Emitter; +}; +TestEmitter Emitter; +} + +TEST(HexagonMCCodeEmitter, emitter_creation) { + ASSERT_NE(nullptr, Emitter.Emitter); +} diff --git a/unittests/MC/MCAtomTest.cpp b/unittests/MC/MCAtomTest.cpp deleted file mode 100644 index 16228b5..0000000 --- a/unittests/MC/MCAtomTest.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//===- llvm/unittest/MC/MCAtomTest.cpp - Instructions unit tests ----------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/MC/MCAnalysis/MCAtom.h" -#include "llvm/MC/MCAnalysis/MCModule.h" -#include "gtest/gtest.h" - -namespace llvm { -namespace { - -TEST(MCAtomTest, MCDataSize) { - MCModule M; - MCDataAtom *Atom = M.createDataAtom(0, 0); - EXPECT_EQ(uint64_t(0), Atom->getEndAddr()); - Atom->addData(0); - EXPECT_EQ(uint64_t(0), Atom->getEndAddr()); - Atom->addData(1); - EXPECT_EQ(uint64_t(1), Atom->getEndAddr()); - Atom->addData(2); - EXPECT_EQ(uint64_t(2), Atom->getEndAddr()); - EXPECT_EQ(size_t(3), Atom->getData().size()); -} - -} // end anonymous namespace -} // end namespace llvm diff --git a/unittests/MC/Makefile b/unittests/MC/Makefile index 07a608e..3f8d1ef 100644 --- a/unittests/MC/Makefile +++ b/unittests/MC/Makefile @@ -9,7 +9,7 @@ LEVEL = ../.. TESTNAME = MC -LINK_COMPONENTS := MCAnalysis +LINK_COMPONENTS := all-targets MCDisassembler Object include $(LEVEL)/Makefile.config include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest diff --git a/unittests/MC/StringTableBuilderTest.cpp b/unittests/MC/StringTableBuilderTest.cpp index d30dc62..6b5185c 100644 --- a/unittests/MC/StringTableBuilderTest.cpp +++ b/unittests/MC/StringTableBuilderTest.cpp @@ -9,20 +9,21 @@ #include "llvm/MC/StringTableBuilder.h" #include "gtest/gtest.h" +#include "llvm/Support/Endian.h" #include using namespace llvm; namespace { -TEST(StringTableBuilderTest, Basic) { +TEST(StringTableBuilderTest, BasicELF) { StringTableBuilder B; B.add("foo"); B.add("bar"); B.add("foobar"); - B.finalize(); + B.finalize(StringTableBuilder::ELF); std::string Expected; Expected += '\x00'; @@ -37,4 +38,34 @@ TEST(StringTableBuilderTest, Basic) { EXPECT_EQ(8U, B.getOffset("foo")); } +TEST(StringTableBuilderTest, BasicWinCOFF) { + StringTableBuilder B; + + // Strings must be 9 chars or longer to go in the table. + B.add("hippopotamus"); + B.add("pygmy hippopotamus"); + B.add("river horse"); + + B.finalize(StringTableBuilder::WinCOFF); + + // size_field + "pygmy hippopotamus\0" + "river horse\0" + uint32_t ExpectedSize = 4 + 19 + 12; + EXPECT_EQ(ExpectedSize, B.data().size()); + + std::string Expected; + + ExpectedSize = + support::endian::byte_swap(ExpectedSize); + Expected.append((const char*)&ExpectedSize, 4); + Expected += "pygmy hippopotamus"; + Expected += '\x00'; + Expected += "river horse"; + Expected += '\x00'; + + EXPECT_EQ(Expected, B.data()); + EXPECT_EQ(4U, B.getOffset("pygmy hippopotamus")); + EXPECT_EQ(10U, B.getOffset("hippopotamus")); + EXPECT_EQ(23U, B.getOffset("river horse")); +} + } diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp index 0fc84c7..7f15776 100644 --- a/unittests/Support/AllocatorTest.cpp +++ b/unittests/Support/AllocatorTest.cpp @@ -17,9 +17,9 @@ namespace { TEST(AllocatorTest, Basics) { BumpPtrAllocator Alloc; - int *a = (int*)Alloc.Allocate(sizeof(int), 0); - int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 0); - int *c = (int*)Alloc.Allocate(sizeof(int), 0); + int *a = (int*)Alloc.Allocate(sizeof(int), 1); + int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 1); + int *c = (int*)Alloc.Allocate(sizeof(int), 1); *a = 1; b[0] = 2; b[9] = 2; @@ -49,11 +49,11 @@ TEST(AllocatorTest, Basics) { // Allocate enough bytes to create three slabs. TEST(AllocatorTest, ThreeSlabs) { BumpPtrAllocator Alloc; - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(2U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(3U, Alloc.GetNumSlabs()); } @@ -61,15 +61,15 @@ TEST(AllocatorTest, ThreeSlabs) { // again. TEST(AllocatorTest, TestReset) { BumpPtrAllocator Alloc; - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(2U, Alloc.GetNumSlabs()); Alloc.Reset(); EXPECT_EQ(1U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); - Alloc.Allocate(3000, 0); + Alloc.Allocate(3000, 1); EXPECT_EQ(2U, Alloc.GetNumSlabs()); } @@ -99,11 +99,11 @@ TEST(AllocatorTest, TestOverflow) { BumpPtrAllocator Alloc; // Fill the slab right up until the end pointer. - Alloc.Allocate(4096, 0); + Alloc.Allocate(4096, 1); EXPECT_EQ(1U, Alloc.GetNumSlabs()); // If we don't allocate a new slab, then we will have overflowed. - Alloc.Allocate(1, 0); + Alloc.Allocate(1, 1); EXPECT_EQ(2U, Alloc.GetNumSlabs()); } @@ -111,7 +111,20 @@ TEST(AllocatorTest, TestOverflow) { TEST(AllocatorTest, TestSmallSlabSize) { BumpPtrAllocator Alloc; - Alloc.Allocate(8000, 0); + Alloc.Allocate(8000, 1); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); +} + +// Test requesting alignment that goes past the end of the current slab. +TEST(AllocatorTest, TestAlignmentPastSlab) { + BumpPtrAllocator Alloc; + Alloc.Allocate(4095, 1); + + // Aligning the current slab pointer is likely to move it past the end of the + // slab, which would confuse any unsigned comparisons with the difference of + // the the end pointer and the aligned pointer. + Alloc.Allocate(1024, 8192); + EXPECT_EQ(2U, Alloc.GetNumSlabs()); } @@ -130,7 +143,7 @@ public: void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*)); // Find the slab start. - void *Slab = alignPtr((char *)MemBase + sizeof(void *), Alignment); + void *Slab = (void *)alignAddr((char*)MemBase + sizeof(void *), Alignment); // Hold a pointer to the base so we can free the whole malloced block. ((void**)Slab)[-1] = MemBase; @@ -155,7 +168,7 @@ TEST(AllocatorTest, TestBigAlignment) { BumpPtrAllocatorImpl Alloc; // First allocate a tiny bit to ensure we have to re-align things. - (void)Alloc.Allocate(1, 0); + (void)Alloc.Allocate(1, 1); // Now the big chunk with a big alignment. (void)Alloc.Allocate(3000, 2048); diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 97c5c43..7abdd8a 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -42,3 +42,8 @@ add_llvm_unittest(SupportTests formatted_raw_ostream_test.cpp raw_ostream_test.cpp ) + +# ManagedStatic.cpp uses . +if(LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD) + target_link_libraries(SupportTests pthread) +endif() diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index b2d71ab..ac8d3d8 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -153,14 +153,14 @@ class StrDupSaver : public cl::StringSaver { }; typedef void ParserFunction(StringRef Source, llvm::cl::StringSaver &Saver, - SmallVectorImpl &NewArgv); - + SmallVectorImpl &NewArgv, + bool MarkEOLs); void testCommandLineTokenizer(ParserFunction *parse, const char *Input, const char *const Output[], size_t OutputSize) { SmallVector Actual; StrDupSaver Saver; - parse(Input, Saver, Actual); + parse(Input, Saver, Actual, /*MarkEOLs=*/false); EXPECT_EQ(OutputSize, Actual.size()); for (unsigned I = 0, E = Actual.size(); I != E; ++I) { if (I < OutputSize) @@ -212,4 +212,23 @@ TEST(CommandLineTest, AliasesWithArguments) { } } +void testAliasRequired(int argc, const char *const *argv) { + StackOption Option("option", cl::Required); + cl::alias Alias("o", llvm::cl::aliasopt(Option)); + + cl::ParseCommandLineOptions(argc, argv); + EXPECT_EQ("x", Option); + EXPECT_EQ(1, Option.getNumOccurrences()); + + Alias.removeArgument(); +} + +TEST(CommandLineTest, AliasRequired) { + const char *opts1[] = { "-tool", "-option=x" }; + const char *opts2[] = { "-tool", "-o", "x" }; + testAliasRequired(array_lengthof(opts1), opts1); + testAliasRequired(array_lengthof(opts2), opts2); +} + + } // anonymous namespace diff --git a/unittests/Support/ConvertUTFTest.cpp b/unittests/Support/ConvertUTFTest.cpp index 16c9beb..510b1da 100644 --- a/unittests/Support/ConvertUTFTest.cpp +++ b/unittests/Support/ConvertUTFTest.cpp @@ -39,30 +39,30 @@ TEST(ConvertUTFTest, ConvertUTF16BigEndianToUTF8String) { TEST(ConvertUTFTest, OddLengthInput) { std::string Result; - bool Success = convertUTF16ToUTF8String(ArrayRef("xxxxx", 5), Result); + bool Success = convertUTF16ToUTF8String(makeArrayRef("xxxxx", 5), Result); EXPECT_FALSE(Success); } TEST(ConvertUTFTest, Empty) { std::string Result; - bool Success = convertUTF16ToUTF8String(ArrayRef(), Result); + bool Success = convertUTF16ToUTF8String(None, Result); EXPECT_TRUE(Success); EXPECT_TRUE(Result.empty()); } TEST(ConvertUTFTest, HasUTF16BOM) { - bool HasBOM = hasUTF16ByteOrderMark(ArrayRef("\xff\xfe", 2)); + bool HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xff\xfe", 2)); EXPECT_TRUE(HasBOM); - HasBOM = hasUTF16ByteOrderMark(ArrayRef("\xfe\xff", 2)); + HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff", 2)); EXPECT_TRUE(HasBOM); - HasBOM = hasUTF16ByteOrderMark(ArrayRef("\xfe\xff ", 3)); + HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff ", 3)); EXPECT_TRUE(HasBOM); // Don't care about odd lengths. - HasBOM = hasUTF16ByteOrderMark(ArrayRef("\xfe\xff\x00asdf", 6)); + HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff\x00asdf", 6)); EXPECT_TRUE(HasBOM); - HasBOM = hasUTF16ByteOrderMark(ArrayRef()); + HasBOM = hasUTF16ByteOrderMark(None); EXPECT_FALSE(HasBOM); - HasBOM = hasUTF16ByteOrderMark(ArrayRef("\xfe", 1)); + HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe", 1)); EXPECT_FALSE(HasBOM); } diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp index d76e7d6..82bbe09 100644 --- a/unittests/Support/ErrorOrTest.cpp +++ b/unittests/Support/ErrorOrTest.cpp @@ -60,5 +60,36 @@ TEST(ErrorOr, Covariant) { ErrorOr > b1(ErrorOr >(nullptr)); b1 = ErrorOr >(nullptr); + + ErrorOr> b2(ErrorOr(nullptr)); + ErrorOr b3(nullptr); + ErrorOr> b4(b3); } + +// ErrorOr x(nullptr); +// ErrorOr> y = x; // invalid conversion +static_assert( + !std::is_convertible &, + ErrorOr>>::value, + "do not invoke explicit ctors in implicit conversion from lvalue"); + +// ErrorOr> y = ErrorOr(nullptr); // invalid +// // conversion +static_assert( + !std::is_convertible &&, + ErrorOr>>::value, + "do not invoke explicit ctors in implicit conversion from rvalue"); + +// ErrorOr x(nullptr); +// ErrorOr> y; +// y = x; // invalid conversion +static_assert(!std::is_assignable>, + const ErrorOr &>::value, + "do not invoke explicit ctors in assignment"); + +// ErrorOr> x; +// x = ErrorOr(nullptr); // invalid conversion +static_assert(!std::is_assignable>, + ErrorOr &&>::value, + "do not invoke explicit ctors in assignment"); } // end anon namespace diff --git a/unittests/Support/FileOutputBufferTest.cpp b/unittests/Support/FileOutputBufferTest.cpp index b086f1e..911d516 100644 --- a/unittests/Support/FileOutputBufferTest.cpp +++ b/unittests/Support/FileOutputBufferTest.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Support/Errc.h" #include "llvm/Support/FileOutputBuffer.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" @@ -65,9 +66,8 @@ TEST(FileOutputBuffer, Test) { // Do *not* commit buffer. } // Verify file does not exist (because buffer not committed). - bool Exists = false; - ASSERT_NO_ERROR(fs::exists(Twine(File2), Exists)); - EXPECT_FALSE(Exists); + ASSERT_EQ(fs::access(Twine(File2), fs::AccessMode::Exist), + errc::no_such_file_or_directory); ASSERT_NO_ERROR(fs::remove(File2.str())); // TEST 3: Verify sizing down case. diff --git a/unittests/Support/LEB128Test.cpp b/unittests/Support/LEB128Test.cpp index b1ca13e..76b63e5 100644 --- a/unittests/Support/LEB128Test.cpp +++ b/unittests/Support/LEB128Test.cpp @@ -106,6 +106,7 @@ TEST(LEB128Test, DecodeULEB128) { EXPECT_DECODE_ULEB128_EQ(0xffu, "\xff\x01"); EXPECT_DECODE_ULEB128_EQ(0x100u, "\x80\x02"); EXPECT_DECODE_ULEB128_EQ(0x101u, "\x81\x02"); + EXPECT_DECODE_ULEB128_EQ(4294975616ULL, "\x80\xc1\x80\x80\x10"); // Decode ULEB128 with extra padding bytes EXPECT_DECODE_ULEB128_EQ(0u, "\x80\x00"); @@ -118,6 +119,42 @@ TEST(LEB128Test, DecodeULEB128) { #undef EXPECT_DECODE_ULEB128_EQ } +TEST(LEB128Test, DecodeSLEB128) { +#define EXPECT_DECODE_SLEB128_EQ(EXPECTED, VALUE) \ + do { \ + unsigned ActualSize = 0; \ + int64_t Actual = decodeSLEB128(reinterpret_cast(VALUE), \ + &ActualSize); \ + EXPECT_EQ(sizeof(VALUE) - 1, ActualSize); \ + EXPECT_EQ(EXPECTED, Actual); \ + } while (0) + + // Decode SLEB128 + EXPECT_DECODE_SLEB128_EQ(0L, "\x00"); + EXPECT_DECODE_SLEB128_EQ(1L, "\x01"); + EXPECT_DECODE_SLEB128_EQ(63L, "\x3f"); + EXPECT_DECODE_SLEB128_EQ(-64L, "\x40"); + EXPECT_DECODE_SLEB128_EQ(-63L, "\x41"); + EXPECT_DECODE_SLEB128_EQ(-1L, "\x7f"); + EXPECT_DECODE_SLEB128_EQ(128L, "\x80\x01"); + EXPECT_DECODE_SLEB128_EQ(129L, "\x81\x01"); + EXPECT_DECODE_SLEB128_EQ(-129L, "\xff\x7e"); + EXPECT_DECODE_SLEB128_EQ(-128L, "\x80\x7f"); + EXPECT_DECODE_SLEB128_EQ(-127L, "\x81\x7f"); + EXPECT_DECODE_SLEB128_EQ(64L, "\xc0\x00"); + EXPECT_DECODE_SLEB128_EQ(-12345L, "\xc7\x9f\x7f"); + + // Decode unnormalized SLEB128 with extra padding bytes. + EXPECT_DECODE_SLEB128_EQ(0L, "\x80\x00"); + EXPECT_DECODE_SLEB128_EQ(0L, "\x80\x80\x00"); + EXPECT_DECODE_SLEB128_EQ(0x7fL, "\xff\x00"); + EXPECT_DECODE_SLEB128_EQ(0x7fL, "\xff\x80\x00"); + EXPECT_DECODE_SLEB128_EQ(0x80L, "\x80\x81\x00"); + EXPECT_DECODE_SLEB128_EQ(0x80L, "\x80\x81\x80\x00"); + +#undef EXPECT_DECODE_SLEB128_EQ +} + TEST(LEB128Test, SLEB128Size) { // Positive Value Testing Plan: // (1) 128 ^ n - 1 ........ need (n+1) bytes diff --git a/unittests/Support/LineIteratorTest.cpp b/unittests/Support/LineIteratorTest.cpp index 18f3fa9..67f9d97 100644 --- a/unittests/Support/LineIteratorTest.cpp +++ b/unittests/Support/LineIteratorTest.cpp @@ -17,9 +17,9 @@ using namespace llvm::sys; namespace { TEST(LineIteratorTest, Basic) { - std::unique_ptr Buffer(MemoryBuffer::getMemBuffer("line 1\n" - "line 2\n" - "line 3")); + std::unique_ptr Buffer = MemoryBuffer::getMemBuffer("line 1\n" + "line 2\n" + "line 3"); line_iterator I = line_iterator(*Buffer), E; @@ -40,15 +40,17 @@ TEST(LineIteratorTest, Basic) { EXPECT_EQ(E, I); } -TEST(LineIteratorTest, CommentSkipping) { +TEST(LineIteratorTest, CommentAndBlankSkipping) { std::unique_ptr Buffer( MemoryBuffer::getMemBuffer("line 1\n" "line 2\n" "# Comment 1\n" - "line 4\n" + "\n" + "line 5\n" + "\n" "# Comment 2")); - line_iterator I = line_iterator(*Buffer, '#'), E; + line_iterator I = line_iterator(*Buffer, true, '#'), E; EXPECT_FALSE(I.is_at_eof()); EXPECT_NE(E, I); @@ -59,20 +61,57 @@ TEST(LineIteratorTest, CommentSkipping) { EXPECT_EQ("line 2", *I); EXPECT_EQ(2, I.line_number()); ++I; - EXPECT_EQ("line 4", *I); - EXPECT_EQ(4, I.line_number()); + EXPECT_EQ("line 5", *I); + EXPECT_EQ(5, I.line_number()); + ++I; + + EXPECT_TRUE(I.is_at_eof()); + EXPECT_EQ(E, I); +} + +TEST(LineIteratorTest, CommentSkippingKeepBlanks) { + std::unique_ptr Buffer( + MemoryBuffer::getMemBuffer("line 1\n" + "line 2\n" + "# Comment 1\n" + "# Comment 2\n" + "\n" + "line 6\n" + "\n" + "# Comment 3")); + + line_iterator I = line_iterator(*Buffer, false, '#'), E; + + EXPECT_FALSE(I.is_at_eof()); + EXPECT_NE(E, I); + + EXPECT_EQ("line 1", *I); + EXPECT_EQ(1, I.line_number()); + ++I; + EXPECT_EQ("line 2", *I); + EXPECT_EQ(2, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(5, I.line_number()); + ++I; + EXPECT_EQ("line 6", *I); + EXPECT_EQ(6, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(7, I.line_number()); ++I; EXPECT_TRUE(I.is_at_eof()); EXPECT_EQ(E, I); } + TEST(LineIteratorTest, BlankSkipping) { - std::unique_ptr Buffer(MemoryBuffer::getMemBuffer("\n\n\n" - "line 1\n" - "\n\n\n" - "line 2\n" - "\n\n\n")); + 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; @@ -90,26 +129,65 @@ TEST(LineIteratorTest, BlankSkipping) { EXPECT_EQ(E, I); } +TEST(LineIteratorTest, BlankKeeping) { + std::unique_ptr Buffer = MemoryBuffer::getMemBuffer("\n\n" + "line 3\n" + "\n" + "line 5\n" + "\n\n"); + line_iterator I = line_iterator(*Buffer, false), E; + + EXPECT_FALSE(I.is_at_eof()); + EXPECT_NE(E, I); + + EXPECT_EQ("", *I); + EXPECT_EQ(1, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(2, I.line_number()); + ++I; + EXPECT_EQ("line 3", *I); + EXPECT_EQ(3, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(4, I.line_number()); + ++I; + EXPECT_EQ("line 5", *I); + EXPECT_EQ(5, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(6, I.line_number()); + ++I; + EXPECT_EQ("", *I); + EXPECT_EQ(7, I.line_number()); + ++I; + + EXPECT_TRUE(I.is_at_eof()); + EXPECT_EQ(E, I); +} + TEST(LineIteratorTest, EmptyBuffers) { - std::unique_ptr Buffer(MemoryBuffer::getMemBuffer("")); + std::unique_ptr Buffer = MemoryBuffer::getMemBuffer(""); EXPECT_TRUE(line_iterator(*Buffer).is_at_eof()); EXPECT_EQ(line_iterator(), line_iterator(*Buffer)); + EXPECT_TRUE(line_iterator(*Buffer, false).is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer, false)); - Buffer.reset(MemoryBuffer::getMemBuffer("\n\n\n")); + Buffer = MemoryBuffer::getMemBuffer("\n\n\n"); EXPECT_TRUE(line_iterator(*Buffer).is_at_eof()); EXPECT_EQ(line_iterator(), line_iterator(*Buffer)); - Buffer.reset(MemoryBuffer::getMemBuffer("# foo\n" - "\n" - "# bar")); - EXPECT_TRUE(line_iterator(*Buffer, '#').is_at_eof()); - EXPECT_EQ(line_iterator(), line_iterator(*Buffer, '#')); - - Buffer.reset(MemoryBuffer::getMemBuffer("\n" - "# baz\n" - "\n")); - EXPECT_TRUE(line_iterator(*Buffer, '#').is_at_eof()); - EXPECT_EQ(line_iterator(), line_iterator(*Buffer, '#')); + Buffer = MemoryBuffer::getMemBuffer("# foo\n" + "\n" + "# bar"); + EXPECT_TRUE(line_iterator(*Buffer, true, '#').is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer, true, '#')); + + Buffer = MemoryBuffer::getMemBuffer("\n" + "# baz\n" + "\n"); + EXPECT_TRUE(line_iterator(*Buffer, true, '#').is_at_eof()); + EXPECT_EQ(line_iterator(), line_iterator(*Buffer, true, '#')); } } // anonymous namespace diff --git a/unittests/Support/LockFileManagerTest.cpp b/unittests/Support/LockFileManagerTest.cpp index 885b7d6..efe3c30 100644 --- a/unittests/Support/LockFileManagerTest.cpp +++ b/unittests/Support/LockFileManagerTest.cpp @@ -95,7 +95,7 @@ TEST(LockFileManagerTest, RelativePath) { char PathBuf[1024]; const char *OrigPath = getcwd(PathBuf, 1024); - chdir(TmpDir.c_str()); + ASSERT_FALSE(chdir(TmpDir.c_str())); sys::fs::create_directory("inner"); SmallString<64> LockedFile("inner"); @@ -118,7 +118,7 @@ TEST(LockFileManagerTest, RelativePath) { EC = sys::fs::remove("inner"); ASSERT_FALSE(EC); - chdir(OrigPath); + ASSERT_FALSE(chdir(OrigPath)); EC = sys::fs::remove(StringRef(TmpDir)); ASSERT_FALSE(EC); diff --git a/unittests/Support/MD5Test.cpp b/unittests/Support/MD5Test.cpp index 7c1331b..c4fa5cd 100644 --- a/unittests/Support/MD5Test.cpp +++ b/unittests/Support/MD5Test.cpp @@ -41,19 +41,19 @@ void TestMD5Sum(StringRef Input, StringRef Final) { } TEST(MD5Test, MD5) { - TestMD5Sum(ArrayRef((const uint8_t *)"", (size_t) 0), + TestMD5Sum(makeArrayRef((const uint8_t *)"", (size_t) 0), "d41d8cd98f00b204e9800998ecf8427e"); - TestMD5Sum(ArrayRef((const uint8_t *)"a", (size_t) 1), + TestMD5Sum(makeArrayRef((const uint8_t *)"a", (size_t) 1), "0cc175b9c0f1b6a831c399e269772661"); - TestMD5Sum(ArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz", - (size_t) 26), + TestMD5Sum(makeArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz", + (size_t) 26), "c3fcd3d76192e4007dfb496cca67e13b"); - TestMD5Sum(ArrayRef((const uint8_t *)"\0", (size_t) 1), + TestMD5Sum(makeArrayRef((const uint8_t *)"\0", (size_t) 1), "93b885adfe0da089cdf634904fd59f71"); - TestMD5Sum(ArrayRef((const uint8_t *)"a\0", (size_t) 2), + TestMD5Sum(makeArrayRef((const uint8_t *)"a\0", (size_t) 2), "4144e195f46de78a3623da7364d04f11"); - TestMD5Sum(ArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz\0", - (size_t) 27), + TestMD5Sum(makeArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz\0", + (size_t) 27), "81948d1f1554f58cd1a56ebb01f808cb"); TestMD5Sum("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"); } diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp index 93bf301..1cdd6ad 100644 --- a/unittests/Support/MemoryBufferTest.cpp +++ b/unittests/Support/MemoryBufferTest.cpp @@ -169,4 +169,54 @@ TEST_F(MemoryBufferTest, getOpenFileReopened) { testGetOpenFileSlice(true); } + +TEST_F(MemoryBufferTest, slice) { + // Create a file that is six pages long with different data on each page. + int FD; + SmallString<64> TestPath; + sys::fs::createTemporaryFile("MemoryBufferTest_Slice", "temp", FD, TestPath); + raw_fd_ostream OF(FD, true, /*unbuffered=*/true); + for (unsigned i = 0; i < 0x2000 / 8; ++i) { + OF << "12345678"; + } + for (unsigned i = 0; i < 0x2000 / 8; ++i) { + OF << "abcdefgh"; + } + for (unsigned i = 0; i < 0x2000 / 8; ++i) { + OF << "ABCDEFGH"; + } + OF.close(); + + // Try offset of one page. + ErrorOr MB = MemoryBuffer::getFileSlice(TestPath.str(), + 0x4000, 0x1000); + std::error_code EC = MB.getError(); + ASSERT_FALSE(EC); + EXPECT_EQ(0x4000UL, MB.get()->getBufferSize()); + + StringRef BufData = MB.get()->getBuffer(); + EXPECT_TRUE(BufData.substr(0x0000,8).equals("12345678")); + EXPECT_TRUE(BufData.substr(0x0FF8,8).equals("12345678")); + EXPECT_TRUE(BufData.substr(0x1000,8).equals("abcdefgh")); + EXPECT_TRUE(BufData.substr(0x2FF8,8).equals("abcdefgh")); + EXPECT_TRUE(BufData.substr(0x3000,8).equals("ABCDEFGH")); + EXPECT_TRUE(BufData.substr(0x3FF8,8).equals("ABCDEFGH")); + + // Try non-page aligned. + ErrorOr MB2 = MemoryBuffer::getFileSlice(TestPath.str(), + 0x3000, 0x0800); + EC = MB2.getError(); + ASSERT_FALSE(EC); + EXPECT_EQ(0x3000UL, MB2.get()->getBufferSize()); + + StringRef BufData2 = MB2.get()->getBuffer(); + EXPECT_TRUE(BufData2.substr(0x0000,8).equals("12345678")); + EXPECT_TRUE(BufData2.substr(0x17F8,8).equals("12345678")); + EXPECT_TRUE(BufData2.substr(0x1800,8).equals("abcdefgh")); + EXPECT_TRUE(BufData2.substr(0x2FF8,8).equals("abcdefgh")); + +} + + + } diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index cf2e1ee..502cda2 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -16,6 +16,7 @@ #include "gtest/gtest.h" #ifdef LLVM_ON_WIN32 +#include #include #endif @@ -91,6 +92,7 @@ TEST(Support, Path) { paths.push_back("c:\\foo/"); paths.push_back("c:/foo\\bar"); + SmallVector ComponentStack; for (SmallVector::const_iterator i = paths.begin(), e = paths.end(); i != e; @@ -100,18 +102,17 @@ TEST(Support, Path) { ci != ce; ++ci) { ASSERT_FALSE(ci->empty()); + ComponentStack.push_back(*ci); } -#if 0 // Valgrind is whining about this. - outs() << " Reverse Iteration: ["; for (sys::path::reverse_iterator ci = sys::path::rbegin(*i), ce = sys::path::rend(*i); ci != ce; ++ci) { - outs() << *ci << ','; + ASSERT_TRUE(*ci == ComponentStack.back()); + ComponentStack.pop_back(); } - outs() << "]\n"; -#endif + ASSERT_TRUE(ComponentStack.empty()); path::has_root_path(*i); path::root_path(*i); @@ -141,7 +142,7 @@ TEST(Support, Path) { StringRef filename(temp_store.begin(), temp_store.size()), stem, ext; stem = path::stem(filename); ext = path::extension(filename); - EXPECT_EQ(*(--sys::path::end(filename)), (stem + ext).str()); + EXPECT_EQ(*sys::path::rbegin(filename), (stem + ext).str()); path::native(*i, temp_store); } @@ -227,7 +228,7 @@ TEST(Support, AbsolutePathIteratorEnd) { #endif for (StringRef Path : Paths) { - StringRef LastComponent = *--path::end(Path); + StringRef LastComponent = *path::rbegin(Path); EXPECT_EQ(".", LastComponent); } @@ -239,7 +240,7 @@ TEST(Support, AbsolutePathIteratorEnd) { #endif for (StringRef Path : RootPaths) { - StringRef LastComponent = *--path::end(Path); + StringRef LastComponent = *path::rbegin(Path); EXPECT_EQ(1u, LastComponent.size()); EXPECT_TRUE(path::is_separator(LastComponent[0])); } @@ -261,7 +262,7 @@ TEST(Support, HomeDirectory) { class FileSystemTest : public testing::Test { protected: /// Unique temporary directory in which all created filesystem entities must - /// be placed. It is recursively removed at the end of each test. + /// be placed. It is removed at the end of each test (must be empty). SmallString<128> TestDirectory; virtual void SetUp() { @@ -334,9 +335,7 @@ TEST_F(FileSystemTest, TempFiles) { fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath)); // Make sure it exists. - bool TempFileExists; - ASSERT_NO_ERROR(sys::fs::exists(Twine(TempPath), TempFileExists)); - EXPECT_TRUE(TempFileExists); + ASSERT_TRUE(sys::fs::exists(Twine(TempPath))); // Create another temp tile. int FD2; @@ -363,8 +362,8 @@ TEST_F(FileSystemTest, TempFiles) { EXPECT_EQ(B.type(), fs::file_type::file_not_found); // Make sure Temp2 doesn't exist. - ASSERT_NO_ERROR(fs::exists(Twine(TempPath2), TempFileExists)); - EXPECT_FALSE(TempFileExists); + ASSERT_EQ(fs::access(Twine(TempPath2), sys::fs::AccessMode::Exist), + errc::no_such_file_or_directory); SmallString<64> TempPath3; ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "", TempPath3)); @@ -387,8 +386,8 @@ TEST_F(FileSystemTest, TempFiles) { ASSERT_NO_ERROR(fs::remove(Twine(TempPath2))); // Make sure Temp1 doesn't exist. - ASSERT_NO_ERROR(fs::exists(Twine(TempPath), TempFileExists)); - EXPECT_FALSE(TempFileExists); + ASSERT_EQ(fs::access(Twine(TempPath), sys::fs::AccessMode::Exist), + errc::no_such_file_or_directory); #ifdef LLVM_ON_WIN32 // Path name > 260 chars should get an error. @@ -398,8 +397,16 @@ TEST_F(FileSystemTest, TempFiles) { "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; - EXPECT_EQ(fs::createUniqueFile(Twine(Path270), FileDescriptor, TempPath), - errc::no_such_file_or_directory); + EXPECT_EQ(fs::createUniqueFile(Path270, FileDescriptor, TempPath), + errc::invalid_argument); + // Relative path < 247 chars, no problem. + const char *Path216 = + "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6" + "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4" + "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2" + "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0"; + ASSERT_NO_ERROR(fs::createTemporaryFile(Path216, "", TempPath)); + ASSERT_NO_ERROR(fs::remove(Twine(TempPath))); #endif } @@ -409,6 +416,54 @@ TEST_F(FileSystemTest, CreateDir) { ASSERT_EQ(fs::create_directory(Twine(TestDirectory) + "foo", false), errc::file_exists); ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "foo")); + +#ifdef LLVM_ON_WIN32 + // Prove that create_directories() can handle a pathname > 248 characters, + // which is the documented limit for CreateDirectory(). + // (248 is MAX_PATH subtracting room for an 8.3 filename.) + // Generate a directory path guaranteed to fall into that range. + size_t TmpLen = TestDirectory.size(); + const char *OneDir = "\\123456789"; + size_t OneDirLen = strlen(OneDir); + ASSERT_LT(OneDirLen, 12U); + size_t NLevels = ((248 - TmpLen) / OneDirLen) + 1; + SmallString<260> LongDir(TestDirectory); + for (size_t I = 0; I < NLevels; ++I) + LongDir.append(OneDir); + ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir))); + ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir))); + ASSERT_EQ(fs::create_directories(Twine(LongDir), false), + errc::file_exists); + // Tidy up, "recursively" removing the directories. + StringRef ThisDir(LongDir); + for (size_t J = 0; J < NLevels; ++J) { + ASSERT_NO_ERROR(fs::remove(ThisDir)); + ThisDir = path::parent_path(ThisDir); + } + + // Similarly for a relative pathname. Need to set the current directory to + // TestDirectory so that the one we create ends up in the right place. + char PreviousDir[260]; + size_t PreviousDirLen = ::GetCurrentDirectoryA(260, PreviousDir); + ASSERT_GT(PreviousDirLen, 0U); + ASSERT_LT(PreviousDirLen, 260U); + ASSERT_NE(::SetCurrentDirectoryA(TestDirectory.c_str()), 0); + LongDir.clear(); + // Generate a relative directory name with absolute length > 248. + size_t LongDirLen = 249 - TestDirectory.size(); + LongDir.assign(LongDirLen, 'a'); + ASSERT_NO_ERROR(fs::create_directory(Twine(LongDir))); + // While we're here, prove that .. and . handling works in these long paths. + const char *DotDotDirs = "\\..\\.\\b"; + LongDir.append(DotDotDirs); + ASSERT_NO_ERROR(fs::create_directory("b")); + ASSERT_EQ(fs::create_directory(Twine(LongDir), false), errc::file_exists); + // And clean up. + ASSERT_NO_ERROR(fs::remove("b")); + ASSERT_NO_ERROR(fs::remove( + Twine(LongDir.substr(0, LongDir.size() - strlen(DotDotDirs))))); + ASSERT_NE(::SetCurrentDirectoryA(PreviousDir), 0); +#endif } TEST_F(FileSystemTest, DirectoryIteration) { @@ -485,6 +540,8 @@ TEST_F(FileSystemTest, DirectoryIteration) { const char archive[] = "!\x0A"; const char bitcode[] = "\xde\xc0\x17\x0b"; const char coff_object[] = "\x00\x00......"; +const char coff_bigobj[] = "\x00\x00\xff\xff\x00\x02......" + "\xc7\xa1\xba\xd1\xee\xba\xa9\x4b\xaf\x20\xfa\xf6\x6a\xa4\xdc\xb8"; const char coff_import_library[] = "\x00\x00\xff\xff...."; const char elf_relocatable[] = { 0x7f, 'E', 'L', 'F', 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; @@ -501,6 +558,8 @@ const char macho_dynamic_linker[] = "\xfe\xed\xfa\xce..........\x00\x07"; const char macho_bundle[] = "\xfe\xed\xfa\xce..........\x00\x08"; const char macho_dsym_companion[] = "\xfe\xed\xfa\xce..........\x00\x0a"; const char windows_resource[] = "\x00\x00\x00\x00\x020\x00\x00\x00\xff"; +const char macho_dynamically_linked_shared_lib_stub[] = + "\xfe\xed\xfa\xce..........\x00\x09"; TEST_F(FileSystemTest, Magic) { struct type { @@ -514,6 +573,7 @@ TEST_F(FileSystemTest, Magic) { DEFINE(archive), DEFINE(bitcode), DEFINE(coff_object), + { "coff_bigobj", coff_bigobj, sizeof(coff_bigobj), fs::file_magic::coff_object }, DEFINE(coff_import_library), DEFINE(elf_relocatable), DEFINE(macho_universal_binary), @@ -525,6 +585,7 @@ TEST_F(FileSystemTest, Magic) { DEFINE(macho_dynamically_linked_shared_lib), DEFINE(macho_dynamic_linker), DEFINE(macho_bundle), + DEFINE(macho_dynamically_linked_shared_lib_stub), DEFINE(macho_dsym_companion), DEFINE(windows_resource) #undef DEFINE @@ -535,8 +596,8 @@ TEST_F(FileSystemTest, Magic) { ++i) { SmallString<128> file_pathname(TestDirectory); path::append(file_pathname, i->filename); - std::string ErrMsg; - raw_fd_ostream file(file_pathname.c_str(), ErrMsg, sys::fs::F_None); + std::error_code EC; + raw_fd_ostream file(file_pathname, EC, sys::fs::F_None); ASSERT_FALSE(file.has_error()); StringRef magic(i->magic_str, i->magic_str_len); file << magic; @@ -549,27 +610,27 @@ TEST_F(FileSystemTest, Magic) { #ifdef LLVM_ON_WIN32 TEST_F(FileSystemTest, CarriageReturn) { SmallString<128> FilePathname(TestDirectory); - std::string ErrMsg; + std::error_code EC; path::append(FilePathname, "test"); { - raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_Text); - EXPECT_EQ(ErrMsg, ""); + raw_fd_ostream File(FilePathname, EC, sys::fs::F_Text); + ASSERT_NO_ERROR(EC); File << '\n'; } { - auto Buf = MemoryBuffer::getFile(FilePathname.c_str()); + auto Buf = MemoryBuffer::getFile(FilePathname.str()); EXPECT_TRUE((bool)Buf); EXPECT_EQ(Buf.get()->getBuffer(), "\r\n"); } { - raw_fd_ostream File(FilePathname.c_str(), ErrMsg, sys::fs::F_None); - EXPECT_EQ(ErrMsg, ""); + raw_fd_ostream File(FilePathname, EC, sys::fs::F_None); + ASSERT_NO_ERROR(EC); File << '\n'; } { - auto Buf = MemoryBuffer::getFile(FilePathname.c_str()); + auto Buf = MemoryBuffer::getFile(FilePathname.str()); EXPECT_TRUE((bool)Buf); EXPECT_EQ(Buf.get()->getBuffer(), "\n"); } @@ -640,22 +701,22 @@ TEST(Support, NormalizePath) { SmallString<64> Path5("\\a"); SmallString<64> Path6("a\\"); - ASSERT_NO_ERROR(fs::normalize_separators(Path1)); + path::native(Path1); EXPECT_PATH_IS(Path1, "a", "a"); - ASSERT_NO_ERROR(fs::normalize_separators(Path2)); - EXPECT_PATH_IS(Path2, "a/b", "a/b"); + path::native(Path2); + EXPECT_PATH_IS(Path2, "a\\b", "a/b"); - ASSERT_NO_ERROR(fs::normalize_separators(Path3)); + path::native(Path3); EXPECT_PATH_IS(Path3, "a\\b", "a/b"); - ASSERT_NO_ERROR(fs::normalize_separators(Path4)); + path::native(Path4); EXPECT_PATH_IS(Path4, "a\\\\b", "a\\\\b"); - ASSERT_NO_ERROR(fs::normalize_separators(Path5)); + path::native(Path5); EXPECT_PATH_IS(Path5, "\\a", "/a"); - ASSERT_NO_ERROR(fs::normalize_separators(Path6)); + path::native(Path6); EXPECT_PATH_IS(Path6, "a\\", "a/"); #undef EXPECT_PATH_IS diff --git a/unittests/Support/ProcessTest.cpp b/unittests/Support/ProcessTest.cpp index f406072..3045c30 100644 --- a/unittests/Support/ProcessTest.cpp +++ b/unittests/Support/ProcessTest.cpp @@ -31,12 +31,12 @@ TEST(ProcessTest, SelfProcess) { EXPECT_LT(1u, process::get_self()->page_size()); - EXPECT_LT(TimeValue::MinTime, process::get_self()->get_user_time()); - EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_user_time()); - EXPECT_LT(TimeValue::MinTime, process::get_self()->get_system_time()); - EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_system_time()); - EXPECT_LT(TimeValue::MinTime, process::get_self()->get_wall_time()); - EXPECT_GT(TimeValue::MaxTime, process::get_self()->get_wall_time()); + EXPECT_LT(TimeValue::MinTime(), process::get_self()->get_user_time()); + EXPECT_GT(TimeValue::MaxTime(), process::get_self()->get_user_time()); + EXPECT_LT(TimeValue::MinTime(), process::get_self()->get_system_time()); + EXPECT_GT(TimeValue::MaxTime(), process::get_self()->get_system_time()); + EXPECT_LT(TimeValue::MinTime(), process::get_self()->get_wall_time()); + EXPECT_GT(TimeValue::MaxTime(), process::get_self()->get_wall_time()); } TEST(ProcessTest, GetRandomNumberTest) { diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp index 4e7316f..c0e6e80 100644 --- a/unittests/Support/ProgramTest.cpp +++ b/unittests/Support/ProgramTest.cpp @@ -34,6 +34,16 @@ void sleep_for(unsigned int seconds) { #error sleep_for is not implemented on your platform. #endif +#define ASSERT_NO_ERROR(x) \ + if (std::error_code ASSERT_NO_ERROR_ec = x) { \ + SmallString<128> MessageStorage; \ + raw_svector_ostream Message(MessageStorage); \ + Message << #x ": did not return errc::success.\n" \ + << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ + << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ + GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ + } else { \ + } // From TestMain.cpp. extern const char *TestMainArgv0; @@ -220,4 +230,44 @@ TEST(ProgramTest, TestExecuteNegative) { } +#ifdef LLVM_ON_WIN32 +const char utf16le_text[] = + "\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61\x00"; +const char utf16be_text[] = + "\x00\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61"; +#endif +const char utf8_text[] = "\x6c\x69\x6e\x67\xc3\xbc\x69\xc3\xa7\x61"; + +TEST(ProgramTest, TestWriteWithSystemEncoding) { + SmallString<128> TestDirectory; + ASSERT_NO_ERROR(fs::createUniqueDirectory("program-test", TestDirectory)); + errs() << "Test Directory: " << TestDirectory << '\n'; + errs().flush(); + SmallString<128> file_pathname(TestDirectory); + path::append(file_pathname, "international-file.txt"); + // Only on Windows we should encode in UTF16. For other systems, use UTF8 + ASSERT_NO_ERROR(sys::writeFileWithEncoding(file_pathname.c_str(), utf8_text, + sys::WEM_UTF16)); + int fd = 0; + ASSERT_NO_ERROR(fs::openFileForRead(file_pathname.c_str(), fd)); +#if defined(LLVM_ON_WIN32) + char buf[18]; + ASSERT_EQ(::read(fd, buf, 18), 18); + if (strncmp(buf, "\xfe\xff", 2) == 0) { // UTF16-BE + ASSERT_EQ(strncmp(&buf[2], utf16be_text, 16), 0); + } else if (strncmp(buf, "\xff\xfe", 2) == 0) { // UTF16-LE + ASSERT_EQ(strncmp(&buf[2], utf16le_text, 16), 0); + } else { + FAIL() << "Invalid BOM in UTF-16 file"; + } +#else + char buf[10]; + ASSERT_EQ(::read(fd, buf, 10), 10); + ASSERT_EQ(strncmp(buf, utf8_text, 10), 0); +#endif + ::close(fd); + ASSERT_NO_ERROR(fs::remove(file_pathname.str())); + ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); +} + } // end anonymous namespace diff --git a/unittests/Support/SourceMgrTest.cpp b/unittests/Support/SourceMgrTest.cpp index 2b69fe9..79c2d72 100644 --- a/unittests/Support/SourceMgrTest.cpp +++ b/unittests/Support/SourceMgrTest.cpp @@ -23,8 +23,9 @@ public: std::string Output; void setMainBuffer(StringRef Text, StringRef BufferName) { - MemoryBuffer *MainBuffer = MemoryBuffer::getMemBuffer(Text, BufferName); - MainBufferID = SM.AddNewSourceBuffer(MainBuffer, llvm::SMLoc()); + std::unique_ptr MainBuffer = + MemoryBuffer::getMemBuffer(Text, BufferName); + MainBufferID = SM.AddNewSourceBuffer(std::move(MainBuffer), llvm::SMLoc()); } SMLoc getLoc(unsigned Offset) { diff --git a/unittests/Support/SpecialCaseListTest.cpp b/unittests/Support/SpecialCaseListTest.cpp index bb9c351..740dbfe 100644 --- a/unittests/Support/SpecialCaseListTest.cpp +++ b/unittests/Support/SpecialCaseListTest.cpp @@ -17,14 +17,15 @@ namespace { class SpecialCaseListTest : public ::testing::Test { protected: - SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) { - std::unique_ptr MB(MemoryBuffer::getMemBuffer(List)); + std::unique_ptr makeSpecialCaseList(StringRef List, + std::string &Error) { + std::unique_ptr MB = MemoryBuffer::getMemBuffer(List); return SpecialCaseList::create(MB.get(), Error); } - SpecialCaseList *makeSpecialCaseList(StringRef List) { + std::unique_ptr makeSpecialCaseList(StringRef List) { std::string Error; - SpecialCaseList *SCL = makeSpecialCaseList(List, Error); + auto SCL = makeSpecialCaseList(List, Error); assert(SCL); assert(Error == ""); return SCL; @@ -32,13 +33,13 @@ protected: }; TEST_F(SpecialCaseListTest, Basic) { - std::unique_ptr SCL( + std::unique_ptr SCL = makeSpecialCaseList("# This is a comment.\n" "\n" "src:hello\n" "src:bye\n" "src:hi=category\n" - "src:z*=category\n")); + "src:z*=category\n"); EXPECT_TRUE(SCL->inSection("src", "hello")); EXPECT_TRUE(SCL->inSection("src", "bye")); EXPECT_TRUE(SCL->inSection("src", "hi", "category")); @@ -48,39 +49,21 @@ TEST_F(SpecialCaseListTest, Basic) { EXPECT_FALSE(SCL->inSection("src", "hello", "category")); } -TEST_F(SpecialCaseListTest, GlobalInitCompat) { - std::unique_ptr SCL( - makeSpecialCaseList("global:foo=init\n")); +TEST_F(SpecialCaseListTest, GlobalInit) { + std::unique_ptr SCL = + makeSpecialCaseList("global:foo=init\n"); EXPECT_FALSE(SCL->inSection("global", "foo")); EXPECT_FALSE(SCL->inSection("global", "bar")); EXPECT_TRUE(SCL->inSection("global", "foo", "init")); EXPECT_FALSE(SCL->inSection("global", "bar", "init")); - SCL.reset(makeSpecialCaseList("global-init:foo\n")); - EXPECT_FALSE(SCL->inSection("global", "foo")); - EXPECT_FALSE(SCL->inSection("global", "bar")); - EXPECT_TRUE(SCL->inSection("global", "foo", "init")); - EXPECT_FALSE(SCL->inSection("global", "bar", "init")); - - SCL.reset(makeSpecialCaseList("type:t2=init\n")); + SCL = makeSpecialCaseList("type:t2=init\n"); EXPECT_FALSE(SCL->inSection("type", "t1")); EXPECT_FALSE(SCL->inSection("type", "t2")); EXPECT_FALSE(SCL->inSection("type", "t1", "init")); EXPECT_TRUE(SCL->inSection("type", "t2", "init")); - SCL.reset(makeSpecialCaseList("global-init-type:t2\n")); - EXPECT_FALSE(SCL->inSection("type", "t1")); - EXPECT_FALSE(SCL->inSection("type", "t2")); - EXPECT_FALSE(SCL->inSection("type", "t1", "init")); - EXPECT_TRUE(SCL->inSection("type", "t2", "init")); - - SCL.reset(makeSpecialCaseList("src:hello=init\n")); - EXPECT_FALSE(SCL->inSection("src", "hello")); - EXPECT_FALSE(SCL->inSection("src", "bye")); - EXPECT_TRUE(SCL->inSection("src", "hello", "init")); - EXPECT_FALSE(SCL->inSection("src", "bye", "init")); - - SCL.reset(makeSpecialCaseList("global-init-src:hello\n")); + SCL = makeSpecialCaseList("src:hello=init\n"); EXPECT_FALSE(SCL->inSection("src", "hello")); EXPECT_FALSE(SCL->inSection("src", "bye")); EXPECT_TRUE(SCL->inSection("src", "hello", "init")); @@ -88,14 +71,14 @@ TEST_F(SpecialCaseListTest, GlobalInitCompat) { } TEST_F(SpecialCaseListTest, Substring) { - std::unique_ptr 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->inSection("src", "othello")); EXPECT_FALSE(SCL->inSection("fun", "tomfoolery")); EXPECT_FALSE(SCL->inSection("global", "bartender")); - SCL.reset(makeSpecialCaseList("fun:*foo*\n")); + SCL = makeSpecialCaseList("fun:*foo*\n"); EXPECT_TRUE(SCL->inSection("fun", "tomfoolery")); EXPECT_TRUE(SCL->inSection("fun", "foobar")); } @@ -117,7 +100,7 @@ TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) { } TEST_F(SpecialCaseListTest, EmptySpecialCaseList) { - std::unique_ptr SCL(makeSpecialCaseList("")); + std::unique_ptr SCL = makeSpecialCaseList(""); EXPECT_FALSE(SCL->inSection("foo", "bar")); } diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 8aed980..074e27f 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -84,6 +84,13 @@ TEST(YAMLIO, TestMapRead) { } } +TEST(YAMLIO, TestMalformedMapRead) { + FooBar doc; + Input yin("{foo: 3; bar: 5}", nullptr, suppressErrorMessages); + yin >> doc; + EXPECT_TRUE(!!yin.error()); +} + // // Test the reading of a yaml sequence of mappings // diff --git a/unittests/Support/YAMLParserTest.cpp b/unittests/Support/YAMLParserTest.cpp index e983935..823a0d6 100644 --- a/unittests/Support/YAMLParserTest.cpp +++ b/unittests/Support/YAMLParserTest.cpp @@ -18,7 +18,7 @@ namespace llvm { static void SuppressDiagnosticsOutput(const SMDiagnostic &, void *) { - // Prevent SourceMgr from writing errors to stderr + // Prevent SourceMgr from writing errors to stderr // to reduce noise in unit test runs. } @@ -210,8 +210,9 @@ TEST(YAMLParser, DiagnosticFilenameFromBufferID) { // When we construct a YAML stream over a named buffer, // we get its ID as filename in diagnostics. - MemoryBuffer* Buffer = MemoryBuffer::getMemBuffer("[]", "buffername.yaml"); - yaml::Stream Stream(Buffer, SM); + std::unique_ptr Buffer = + MemoryBuffer::getMemBuffer("[]", "buffername.yaml"); + yaml::Stream Stream(Buffer->getMemBufferRef(), SM); Stream.printError(Stream.begin()->getRoot(), "Hello, World!"); EXPECT_EQ("buffername.yaml", GeneratedDiag.getFilename()); } diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp index 44d27d0..39cfaf0 100644 --- a/unittests/Support/raw_ostream_test.cpp +++ b/unittests/Support/raw_ostream_test.cpp @@ -143,4 +143,41 @@ TEST(raw_ostreamTest, WriteEscaped) { EXPECT_EQ("\\001\\010\\200", Str); } +TEST(raw_ostreamTest, Justify) { + EXPECT_EQ("xyz ", printToString(left_justify("xyz", 6), 6)); + EXPECT_EQ("abc", printToString(left_justify("abc", 3), 3)); + EXPECT_EQ("big", printToString(left_justify("big", 1), 3)); + EXPECT_EQ(" xyz", printToString(right_justify("xyz", 6), 6)); + EXPECT_EQ("abc", printToString(right_justify("abc", 3), 3)); + EXPECT_EQ("big", printToString(right_justify("big", 1), 3)); +} + +TEST(raw_ostreamTest, FormatHex) { + EXPECT_EQ("0x1234", printToString(format_hex(0x1234, 6), 6)); + EXPECT_EQ("0x001234", printToString(format_hex(0x1234, 8), 8)); + EXPECT_EQ("0x00001234", printToString(format_hex(0x1234, 10), 10)); + EXPECT_EQ("0x1234", printToString(format_hex(0x1234, 4), 6)); + EXPECT_EQ("0xff", printToString(format_hex(255, 4), 4)); + EXPECT_EQ("0xFF", printToString(format_hex(255, 4, true), 4)); + EXPECT_EQ("0x1", printToString(format_hex(1, 3), 3)); + EXPECT_EQ("0x12", printToString(format_hex(0x12, 3), 4)); + EXPECT_EQ("0x123", printToString(format_hex(0x123, 3), 5)); + EXPECT_EQ("0xffffffffffffffff", + printToString(format_hex(UINT64_MAX, 18), 18)); + EXPECT_EQ("0x8000000000000000", + printToString(format_hex((INT64_MIN), 18), 18)); +} + +TEST(raw_ostreamTest, FormatDecimal) { + EXPECT_EQ(" 0", printToString(format_decimal(0, 4), 4)); + EXPECT_EQ(" -1", printToString(format_decimal(-1, 4), 4)); + EXPECT_EQ(" -1", printToString(format_decimal(-1, 6), 6)); + EXPECT_EQ("1234567890", printToString(format_decimal(1234567890, 10), 10)); + EXPECT_EQ(" 9223372036854775807", + printToString(format_decimal(INT64_MAX, 21), 21)); + EXPECT_EQ(" -9223372036854775808", + printToString(format_decimal(INT64_MIN, 21), 21)); +} + + } diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index b3a1f5b..c779979 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -232,7 +232,7 @@ protected: // Function DI DIFile File = DBuilder.createFile("filename.c", "/file/dir/"); - DIArray ParamTypes = DBuilder.getOrCreateArray(ArrayRef()); + DITypeArray ParamTypes = DBuilder.getOrCreateTypeArray(None); DICompositeType FuncType = DBuilder.createSubroutineType(File, ParamTypes); DICompileUnit CU = DBuilder.createCompileUnit(dwarf::DW_LANG_C99, "filename.c", "/file/dir", "CloneFunc", false, "", 0); @@ -255,10 +255,11 @@ protected: // Create a local variable around the alloca DIType IntType = DBuilder.createBasicType("int", 32, 0, dwarf::DW_ATE_signed); + DIExpression E = DBuilder.createExpression(); DIVariable Variable = DBuilder.createLocalVariable( dwarf::DW_TAG_auto_variable, Subprogram, "x", File, 5, IntType, true); - DBuilder.insertDeclare(Alloca, Variable, Store); - DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, Terminator); + DBuilder.insertDeclare(Alloca, Variable, E, Store); + DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, Terminator); // Finalize the debug info DBuilder.finalize(); -- cgit v1.1