diff options
author | Stephen Hines <srhines@google.com> | 2014-05-29 02:49:00 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-05-29 02:49:00 -0700 |
commit | dce4a407a24b04eebc6a376f8e62b41aaa7b071f (patch) | |
tree | dcebc53f2b182f145a2e659393bf9a0472cedf23 /unittests | |
parent | 220b921aed042f9e520c26cffd8282a94c66c3d5 (diff) | |
download | external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.zip external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.gz external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.bz2 |
Update LLVM for 3.5 rebase (r209712).
Change-Id: I149556c940fb7dc92d075273c87ff584f400941f
Diffstat (limited to 'unittests')
35 files changed, 1821 insertions, 349 deletions
diff --git a/unittests/ADT/PointerUnionTest.cpp b/unittests/ADT/PointerUnionTest.cpp index 7eb7181..3bfb79c 100644 --- a/unittests/ADT/PointerUnionTest.cpp +++ b/unittests/ADT/PointerUnionTest.cpp @@ -13,22 +13,24 @@ using namespace llvm; namespace { -typedef PointerUnion<int*, float*> PU; +typedef PointerUnion<int *, float *> PU; -// Test fixture -class PointerUnionTest : public testing::Test { -}; +struct PointerUnionTest : public testing::Test { + float f; + int i; -float f = 3.14f; -int i = 42; + PU a, b, c, n; -const PU a(&f); -const PU b(&i); -const PU n; + PointerUnionTest() : f(3.14f), i(42), a(&f), b(&i), c(&i), n() {} +}; TEST_F(PointerUnionTest, Comparison) { + EXPECT_TRUE(a == a); + EXPECT_FALSE(a != a); EXPECT_TRUE(a != b); EXPECT_FALSE(a == b); + EXPECT_TRUE(b == c); + EXPECT_FALSE(b != c); EXPECT_TRUE(b != n); EXPECT_FALSE(b == n); } @@ -44,21 +46,27 @@ TEST_F(PointerUnionTest, Null) { EXPECT_TRUE((bool)a); EXPECT_TRUE((bool)b); EXPECT_FALSE(n); + + EXPECT_NE(n, b); + EXPECT_EQ(b, c); + b = nullptr; + EXPECT_EQ(n, b); + EXPECT_NE(b, c); } TEST_F(PointerUnionTest, Is) { - EXPECT_FALSE(a.is<int*>()); - EXPECT_TRUE(a.is<float*>()); - EXPECT_TRUE(b.is<int*>()); - EXPECT_FALSE(b.is<float*>()); - EXPECT_TRUE(n.is<int*>()); - EXPECT_FALSE(n.is<float*>()); + EXPECT_FALSE(a.is<int *>()); + EXPECT_TRUE(a.is<float *>()); + EXPECT_TRUE(b.is<int *>()); + EXPECT_FALSE(b.is<float *>()); + EXPECT_TRUE(n.is<int *>()); + EXPECT_FALSE(n.is<float *>()); } TEST_F(PointerUnionTest, Get) { - EXPECT_EQ(a.get<float*>(), &f); - EXPECT_EQ(b.get<int*>(), &i); - EXPECT_EQ(n.get<int*>(), (int*)0); + EXPECT_EQ(a.get<float *>(), &f); + EXPECT_EQ(b.get<int *>(), &i); + EXPECT_EQ(n.get<int *>(), (int *)0); } } // end anonymous namespace diff --git a/unittests/ADT/SCCIteratorTest.cpp b/unittests/ADT/SCCIteratorTest.cpp index 92b4b31..8609732 100644 --- a/unittests/ADT/SCCIteratorTest.cpp +++ b/unittests/ADT/SCCIteratorTest.cpp @@ -277,7 +277,7 @@ TEST(SCCIteratorTest, AllSmallGraphs) { GT::NodeSubset NodesInSomeSCC; for (scc_iterator<GT> I = scc_begin(G), E = scc_end(G); I != E; ++I) { - std::vector<GT::NodeType*> &SCC = *I; + const std::vector<GT::NodeType *> &SCC = *I; // Get the nodes in this SCC as a NodeSubset rather than a vector. GT::NodeSubset NodesInThisSCC; diff --git a/unittests/ADT/SmallVectorTest.cpp b/unittests/ADT/SmallVectorTest.cpp index 90c7982..58f5591 100644 --- a/unittests/ADT/SmallVectorTest.cpp +++ b/unittests/ADT/SmallVectorTest.cpp @@ -29,27 +29,43 @@ private: static int numDestructorCalls; static int numAssignmentCalls; + bool constructed; int value; public: - Constructable() : value(0) { + Constructable() : constructed(true), value(0) { ++numConstructorCalls; } - Constructable(int val) : value(val) { + Constructable(int val) : constructed(true), value(val) { ++numConstructorCalls; } - Constructable(const Constructable & src) { + Constructable(const Constructable & src) : constructed(true) { + value = src.value; + ++numConstructorCalls; + } + + Constructable(Constructable && src) : constructed(true) { value = src.value; ++numConstructorCalls; } ~Constructable() { + EXPECT_TRUE(constructed); ++numDestructorCalls; + constructed = false; } Constructable & operator=(const Constructable & src) { + EXPECT_TRUE(constructed); + value = src.value; + ++numAssignmentCalls; + return *this; + } + + Constructable & operator=(Constructable && src) { + EXPECT_TRUE(constructed); value = src.value; ++numAssignmentCalls; return *this; @@ -338,6 +354,36 @@ TYPED_TEST(SmallVectorTest, AssignTest) { this->assertValuesInOrder(this->theVector, 2u, 77, 77); } +// Move-assign test +TYPED_TEST(SmallVectorTest, MoveAssignTest) { + SCOPED_TRACE("MoveAssignTest"); + + // Set up our vector with a single element, but enough capacity for 4. + this->theVector.reserve(4); + this->theVector.push_back(Constructable(1)); + + // Set up the other vector with 2 elements. + this->otherVector.push_back(Constructable(2)); + this->otherVector.push_back(Constructable(3)); + + // Move-assign from the other vector. + this->theVector = std::move(this->otherVector); + + // Make sure we have the right result. + this->assertValuesInOrder(this->theVector, 2u, 2, 3); + + // Make sure the # of constructor/destructor calls line up. There + // are two live objects after clearing the other vector. + this->otherVector.clear(); + EXPECT_EQ(Constructable::getNumConstructorCalls()-2, + Constructable::getNumDestructorCalls()); + + // There shouldn't be any live objects any more. + this->theVector.clear(); + EXPECT_EQ(Constructable::getNumConstructorCalls(), + Constructable::getNumDestructorCalls()); +} + // Erase a single element TYPED_TEST(SmallVectorTest, EraseTest) { SCOPED_TRACE("EraseTest"); @@ -455,13 +501,12 @@ TYPED_TEST(SmallVectorTest, DirectVectorTest) { this->theVector.reserve(4); EXPECT_LE(4u, this->theVector.capacity()); EXPECT_EQ(0, Constructable::getNumConstructorCalls()); - this->theVector.end()[0] = 1; - this->theVector.end()[1] = 2; - this->theVector.end()[2] = 3; - this->theVector.end()[3] = 4; - this->theVector.set_size(4); + this->theVector.push_back(1); + this->theVector.push_back(2); + this->theVector.push_back(3); + this->theVector.push_back(4); EXPECT_EQ(4u, this->theVector.size()); - EXPECT_EQ(4, Constructable::getNumConstructorCalls()); + EXPECT_EQ(8, Constructable::getNumConstructorCalls()); EXPECT_EQ(1, this->theVector[0].getValue()); EXPECT_EQ(2, this->theVector[1].getValue()); EXPECT_EQ(3, this->theVector[2].getValue()); diff --git a/unittests/ADT/StringMapTest.cpp b/unittests/ADT/StringMapTest.cpp index b6d41bc..de18e07 100644 --- a/unittests/ADT/StringMapTest.cpp +++ b/unittests/ADT/StringMapTest.cpp @@ -218,4 +218,92 @@ TEST_F(StringMapTest, NonDefaultConstructable) { ASSERT_EQ(iter->second.i, 123); } +struct MoveOnly { + int i; + MoveOnly(int i) : i(i) {} + MoveOnly(MoveOnly &&RHS) : i(RHS.i) {} + MoveOnly &operator=(MoveOnly &&RHS) { + i = RHS.i; + return *this; + } + +private: + MoveOnly(const MoveOnly &); + MoveOnly &operator=(const MoveOnly &); +}; + +TEST_F(StringMapTest, MoveOnlyKey) { + StringMap<MoveOnly> t; + t.GetOrCreateValue("Test", MoveOnly(42)); + StringRef Key = "Test"; + StringMapEntry<MoveOnly>::Create(Key.begin(), Key.end(), MoveOnly(42)) + ->Destroy(); +} + +TEST_F(StringMapTest, MoveConstruct) { + StringMap<int> A; + A.GetOrCreateValue("x", 42); + StringMap<int> B = std::move(A); + ASSERT_EQ(A.size(), 0u); + ASSERT_EQ(B.size(), 1u); + ASSERT_EQ(B["x"], 42); + ASSERT_EQ(B.count("y"), 0u); +} + +TEST_F(StringMapTest, MoveAssignment) { + StringMap<int> A; + A["x"] = 42; + StringMap<int> B; + B["y"] = 117; + A = std::move(B); + ASSERT_EQ(A.size(), 1u); + ASSERT_EQ(B.size(), 0u); + ASSERT_EQ(A["y"], 117); + ASSERT_EQ(B.count("x"), 0u); +} + +struct Countable { + int &InstanceCount; + int Number; + Countable(int Number, int &InstanceCount) + : InstanceCount(InstanceCount), Number(Number) { + ++InstanceCount; + } + Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) { + ++InstanceCount; + C.Number = -1; + } + Countable(const Countable &C) + : InstanceCount(C.InstanceCount), Number(C.Number) { + ++InstanceCount; + } + Countable &operator=(Countable C) { + Number = C.Number; + return *this; + } + ~Countable() { --InstanceCount; } +}; + +TEST_F(StringMapTest, MoveDtor) { + int InstanceCount = 0; + StringMap<Countable> A; + A.GetOrCreateValue("x", Countable(42, InstanceCount)); + ASSERT_EQ(InstanceCount, 1); + auto I = A.find("x"); + ASSERT_NE(I, A.end()); + ASSERT_EQ(I->second.Number, 42); + + StringMap<Countable> B; + B = std::move(A); + ASSERT_EQ(InstanceCount, 1); + ASSERT_TRUE(A.empty()); + I = B.find("x"); + ASSERT_NE(I, B.end()); + ASSERT_EQ(I->second.Number, 42); + + B = StringMap<Countable>(); + ASSERT_EQ(InstanceCount, 0); + ASSERT_TRUE(B.empty()); +} + } // end anonymous namespace diff --git a/unittests/ADT/StringRefTest.cpp b/unittests/ADT/StringRefTest.cpp index c7fd9d0..d80179b 100644 --- a/unittests/ADT/StringRefTest.cpp +++ b/unittests/ADT/StringRefTest.cpp @@ -9,6 +9,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/Allocator.h" diff --git a/unittests/Analysis/CMakeLists.txt b/unittests/Analysis/CMakeLists.txt index d9f8c0c..8454860 100644 --- a/unittests/Analysis/CMakeLists.txt +++ b/unittests/Analysis/CMakeLists.txt @@ -7,5 +7,7 @@ set(LLVM_LINK_COMPONENTS add_llvm_unittest(AnalysisTests CFGTest.cpp + LazyCallGraphTest.cpp ScalarEvolutionTest.cpp + MixedTBAATest.cpp ) diff --git a/unittests/Analysis/LazyCallGraphTest.cpp b/unittests/Analysis/LazyCallGraphTest.cpp new file mode 100644 index 0000000..d7c7045 --- /dev/null +++ b/unittests/Analysis/LazyCallGraphTest.cpp @@ -0,0 +1,720 @@ +//===- LazyCallGraphTest.cpp - Unit tests for the lazy 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/LazyCallGraph.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SourceMgr.h" +#include "gtest/gtest.h" +#include <memory> + +using namespace llvm; + +namespace { + +std::unique_ptr<Module> parseAssembly(const char *Assembly) { + auto M = make_unique<Module>("Module", getGlobalContext()); + + SMDiagnostic Error; + bool Parsed = + ParseAssemblyString(Assembly, M.get(), Error, M->getContext()) == M.get(); + + std::string ErrMsg; + raw_string_ostream OS(ErrMsg); + Error.print("", OS); + + // A failure here means that the test itself is buggy. + if (!Parsed) + 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. +static const char DiamondOfTriangles[] = + "define void @a1() {\n" + "entry:\n" + " call void @a2()\n" + " call void @b2()\n" + " call void @c3()\n" + " ret void\n" + "}\n" + "define void @a2() {\n" + "entry:\n" + " call void @a3()\n" + " ret void\n" + "}\n" + "define void @a3() {\n" + "entry:\n" + " call void @a1()\n" + " ret void\n" + "}\n" + "define void @b1() {\n" + "entry:\n" + " call void @b2()\n" + " call void @d3()\n" + " ret void\n" + "}\n" + "define void @b2() {\n" + "entry:\n" + " call void @b3()\n" + " ret void\n" + "}\n" + "define void @b3() {\n" + "entry:\n" + " call void @b1()\n" + " ret void\n" + "}\n" + "define void @c1() {\n" + "entry:\n" + " call void @c2()\n" + " call void @d2()\n" + " ret void\n" + "}\n" + "define void @c2() {\n" + "entry:\n" + " call void @c3()\n" + " ret void\n" + "}\n" + "define void @c3() {\n" + "entry:\n" + " call void @c1()\n" + " ret void\n" + "}\n" + "define void @d1() {\n" + "entry:\n" + " call void @d2()\n" + " ret void\n" + "}\n" + "define void @d2() {\n" + "entry:\n" + " call void @d3()\n" + " ret void\n" + "}\n" + "define void @d3() {\n" + "entry:\n" + " call void @d1()\n" + " ret void\n" + "}\n"; + +TEST(LazyCallGraphTest, BasicGraphFormation) { + std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles); + LazyCallGraph CG(*M); + + // The order of the entry nodes should be stable w.r.t. the source order of + // the IR, and everything in our module is an entry node, so just directly + // build variables for each node. + auto I = CG.begin(); + LazyCallGraph::Node &A1 = *I++; + EXPECT_EQ("a1", A1.getFunction().getName()); + LazyCallGraph::Node &A2 = *I++; + EXPECT_EQ("a2", A2.getFunction().getName()); + LazyCallGraph::Node &A3 = *I++; + EXPECT_EQ("a3", A3.getFunction().getName()); + LazyCallGraph::Node &B1 = *I++; + EXPECT_EQ("b1", B1.getFunction().getName()); + LazyCallGraph::Node &B2 = *I++; + EXPECT_EQ("b2", B2.getFunction().getName()); + LazyCallGraph::Node &B3 = *I++; + EXPECT_EQ("b3", B3.getFunction().getName()); + LazyCallGraph::Node &C1 = *I++; + EXPECT_EQ("c1", C1.getFunction().getName()); + LazyCallGraph::Node &C2 = *I++; + EXPECT_EQ("c2", C2.getFunction().getName()); + LazyCallGraph::Node &C3 = *I++; + EXPECT_EQ("c3", C3.getFunction().getName()); + LazyCallGraph::Node &D1 = *I++; + EXPECT_EQ("d1", D1.getFunction().getName()); + LazyCallGraph::Node &D2 = *I++; + EXPECT_EQ("d2", D2.getFunction().getName()); + LazyCallGraph::Node &D3 = *I++; + EXPECT_EQ("d3", D3.getFunction().getName()); + EXPECT_EQ(CG.end(), I); + + // Build vectors and sort them for the rest of the assertions to make them + // independent of order. + std::vector<std::string> Nodes; + + for (LazyCallGraph::Node &N : A1) + Nodes.push_back(N.getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ("a2", Nodes[0]); + EXPECT_EQ("b2", Nodes[1]); + EXPECT_EQ("c3", Nodes[2]); + Nodes.clear(); + + EXPECT_EQ(A2.end(), std::next(A2.begin())); + EXPECT_EQ("a3", A2.begin()->getFunction().getName()); + EXPECT_EQ(A3.end(), std::next(A3.begin())); + EXPECT_EQ("a1", A3.begin()->getFunction().getName()); + + for (LazyCallGraph::Node &N : B1) + Nodes.push_back(N.getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ("b2", Nodes[0]); + EXPECT_EQ("d3", Nodes[1]); + Nodes.clear(); + + EXPECT_EQ(B2.end(), std::next(B2.begin())); + EXPECT_EQ("b3", B2.begin()->getFunction().getName()); + EXPECT_EQ(B3.end(), std::next(B3.begin())); + EXPECT_EQ("b1", B3.begin()->getFunction().getName()); + + for (LazyCallGraph::Node &N : C1) + Nodes.push_back(N.getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ("c2", Nodes[0]); + EXPECT_EQ("d2", Nodes[1]); + Nodes.clear(); + + EXPECT_EQ(C2.end(), std::next(C2.begin())); + EXPECT_EQ("c3", C2.begin()->getFunction().getName()); + EXPECT_EQ(C3.end(), std::next(C3.begin())); + EXPECT_EQ("c1", C3.begin()->getFunction().getName()); + + EXPECT_EQ(D1.end(), std::next(D1.begin())); + EXPECT_EQ("d2", D1.begin()->getFunction().getName()); + EXPECT_EQ(D2.end(), std::next(D2.begin())); + EXPECT_EQ("d3", D2.begin()->getFunction().getName()); + EXPECT_EQ(D3.end(), std::next(D3.begin())); + EXPECT_EQ("d1", D3.begin()->getFunction().getName()); + + // Now lets look at the SCCs. + auto SCCI = CG.postorder_scc_begin(); + + LazyCallGraph::SCC &D = *SCCI++; + for (LazyCallGraph::Node *N : D) + Nodes.push_back(N->getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ(3u, Nodes.size()); + EXPECT_EQ("d1", Nodes[0]); + EXPECT_EQ("d2", Nodes[1]); + EXPECT_EQ("d3", Nodes[2]); + Nodes.clear(); + EXPECT_FALSE(D.isParentOf(D)); + EXPECT_FALSE(D.isChildOf(D)); + EXPECT_FALSE(D.isAncestorOf(D)); + EXPECT_FALSE(D.isDescendantOf(D)); + + LazyCallGraph::SCC &C = *SCCI++; + for (LazyCallGraph::Node *N : C) + Nodes.push_back(N->getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ(3u, Nodes.size()); + EXPECT_EQ("c1", Nodes[0]); + EXPECT_EQ("c2", Nodes[1]); + EXPECT_EQ("c3", Nodes[2]); + Nodes.clear(); + EXPECT_TRUE(C.isParentOf(D)); + EXPECT_FALSE(C.isChildOf(D)); + EXPECT_TRUE(C.isAncestorOf(D)); + EXPECT_FALSE(C.isDescendantOf(D)); + + LazyCallGraph::SCC &B = *SCCI++; + for (LazyCallGraph::Node *N : B) + Nodes.push_back(N->getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ(3u, Nodes.size()); + EXPECT_EQ("b1", Nodes[0]); + EXPECT_EQ("b2", Nodes[1]); + EXPECT_EQ("b3", Nodes[2]); + Nodes.clear(); + EXPECT_TRUE(B.isParentOf(D)); + EXPECT_FALSE(B.isChildOf(D)); + EXPECT_TRUE(B.isAncestorOf(D)); + EXPECT_FALSE(B.isDescendantOf(D)); + EXPECT_FALSE(B.isAncestorOf(C)); + EXPECT_FALSE(C.isAncestorOf(B)); + + LazyCallGraph::SCC &A = *SCCI++; + for (LazyCallGraph::Node *N : A) + Nodes.push_back(N->getFunction().getName()); + std::sort(Nodes.begin(), Nodes.end()); + EXPECT_EQ(3u, Nodes.size()); + EXPECT_EQ("a1", Nodes[0]); + EXPECT_EQ("a2", Nodes[1]); + EXPECT_EQ("a3", Nodes[2]); + Nodes.clear(); + EXPECT_TRUE(A.isParentOf(B)); + EXPECT_TRUE(A.isParentOf(C)); + EXPECT_FALSE(A.isParentOf(D)); + EXPECT_TRUE(A.isAncestorOf(B)); + EXPECT_TRUE(A.isAncestorOf(C)); + EXPECT_TRUE(A.isAncestorOf(D)); + + EXPECT_EQ(CG.postorder_scc_end(), SCCI); +} + +static Function &lookupFunction(Module &M, StringRef Name) { + for (Function &F : M) + if (F.getName() == Name) + return F; + report_fatal_error("Couldn't find function!"); +} + +TEST(LazyCallGraphTest, BasicGraphMutation) { + std::unique_ptr<Module> M = parseAssembly( + "define void @a() {\n" + "entry:\n" + " call void @b()\n" + " call void @c()\n" + " ret void\n" + "}\n" + "define void @b() {\n" + "entry:\n" + " ret void\n" + "}\n" + "define void @c() {\n" + "entry:\n" + " ret void\n" + "}\n"); + LazyCallGraph CG(*M); + + LazyCallGraph::Node &A = CG.get(lookupFunction(*M, "a")); + LazyCallGraph::Node &B = CG.get(lookupFunction(*M, "b")); + EXPECT_EQ(2, std::distance(A.begin(), A.end())); + EXPECT_EQ(0, std::distance(B.begin(), B.end())); + + CG.insertEdge(B, lookupFunction(*M, "c")); + EXPECT_EQ(1, std::distance(B.begin(), B.end())); + LazyCallGraph::Node &C = *B.begin(); + EXPECT_EQ(0, std::distance(C.begin(), C.end())); + + CG.insertEdge(C, B.getFunction()); + EXPECT_EQ(1, std::distance(C.begin(), C.end())); + EXPECT_EQ(&B, &*C.begin()); + + CG.insertEdge(C, C.getFunction()); + EXPECT_EQ(2, std::distance(C.begin(), C.end())); + EXPECT_EQ(&B, &*C.begin()); + EXPECT_EQ(&C, &*std::next(C.begin())); + + CG.removeEdge(C, B.getFunction()); + EXPECT_EQ(1, std::distance(C.begin(), C.end())); + EXPECT_EQ(&C, &*C.begin()); + + CG.removeEdge(C, C.getFunction()); + EXPECT_EQ(0, std::distance(C.begin(), C.end())); + + CG.removeEdge(B, C.getFunction()); + EXPECT_EQ(0, std::distance(B.begin(), B.end())); +} + +TEST(LazyCallGraphTest, MultiArmSCC) { + // Two interlocking cycles. The really useful thing about this SCC is that it + // will require Tarjan's DFS to backtrack and finish processing all of the + // children of each node in the SCC. + std::unique_ptr<Module> M = parseAssembly( + "define void @a() {\n" + "entry:\n" + " call void @b()\n" + " call void @d()\n" + " ret void\n" + "}\n" + "define void @b() {\n" + "entry:\n" + " call void @c()\n" + " ret void\n" + "}\n" + "define void @c() {\n" + "entry:\n" + " call void @a()\n" + " ret void\n" + "}\n" + "define void @d() {\n" + "entry:\n" + " call void @e()\n" + " ret void\n" + "}\n" + "define void @e() {\n" + "entry:\n" + " call void @a()\n" + " ret void\n" + "}\n"); + LazyCallGraph CG(*M); + + // Force the graph to be fully expanded. + auto SCCI = CG.postorder_scc_begin(); + LazyCallGraph::SCC &SCC = *SCCI++; + EXPECT_EQ(CG.postorder_scc_end(), SCCI); + + LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a")); + LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b")); + LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c")); + LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d")); + LazyCallGraph::Node &E = *CG.lookup(lookupFunction(*M, "e")); + EXPECT_EQ(&SCC, CG.lookupSCC(A)); + EXPECT_EQ(&SCC, CG.lookupSCC(B)); + EXPECT_EQ(&SCC, CG.lookupSCC(C)); + EXPECT_EQ(&SCC, CG.lookupSCC(D)); + EXPECT_EQ(&SCC, CG.lookupSCC(E)); +} + +TEST(LazyCallGraphTest, OutgoingSCCEdgeInsertion) { + std::unique_ptr<Module> M = parseAssembly( + "define void @a() {\n" + "entry:\n" + " call void @b()\n" + " call void @c()\n" + " ret void\n" + "}\n" + "define void @b() {\n" + "entry:\n" + " call void @d()\n" + " ret void\n" + "}\n" + "define void @c() {\n" + "entry:\n" + " call void @d()\n" + " ret void\n" + "}\n" + "define void @d() {\n" + "entry:\n" + " ret void\n" + "}\n"); + LazyCallGraph CG(*M); + + // Force the graph to be fully expanded. + for (LazyCallGraph::SCC &C : CG.postorder_sccs()) + (void)C; + + LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a")); + LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b")); + LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c")); + LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d")); + LazyCallGraph::SCC &AC = *CG.lookupSCC(A); + LazyCallGraph::SCC &BC = *CG.lookupSCC(B); + LazyCallGraph::SCC &CC = *CG.lookupSCC(C); + LazyCallGraph::SCC &DC = *CG.lookupSCC(D); + EXPECT_TRUE(AC.isAncestorOf(BC)); + EXPECT_TRUE(AC.isAncestorOf(CC)); + EXPECT_TRUE(AC.isAncestorOf(DC)); + EXPECT_TRUE(DC.isDescendantOf(AC)); + EXPECT_TRUE(DC.isDescendantOf(BC)); + EXPECT_TRUE(DC.isDescendantOf(CC)); + + EXPECT_EQ(2, std::distance(A.begin(), A.end())); + AC.insertOutgoingEdge(A, D); + EXPECT_EQ(3, std::distance(A.begin(), A.end())); + EXPECT_TRUE(AC.isParentOf(DC)); + EXPECT_EQ(&AC, CG.lookupSCC(A)); + EXPECT_EQ(&BC, CG.lookupSCC(B)); + EXPECT_EQ(&CC, CG.lookupSCC(C)); + EXPECT_EQ(&DC, CG.lookupSCC(D)); +} + +TEST(LazyCallGraphTest, IncomingSCCEdgeInsertion) { + // We want to ensure we can add edges even across complex diamond graphs, so + // we use the diamond of triangles graph defined above. The ascii diagram is + // repeated here for easy reference. + // + // d1 | + // / \ | + // d3--d2 | + // / \ | + // b1 c1 | + // / \ / \ | + // b3--b2 c3--c2 | + // \ / | + // a1 | + // / \ | + // a3--a2 | + // + std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles); + LazyCallGraph CG(*M); + + // Force the graph to be fully expanded. + for (LazyCallGraph::SCC &C : CG.postorder_sccs()) + (void)C; + + LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1")); + LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2")); + LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3")); + LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1")); + LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2")); + LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3")); + LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1")); + LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2")); + LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3")); + LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1")); + LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2")); + LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3")); + LazyCallGraph::SCC &AC = *CG.lookupSCC(A1); + LazyCallGraph::SCC &BC = *CG.lookupSCC(B1); + LazyCallGraph::SCC &CC = *CG.lookupSCC(C1); + LazyCallGraph::SCC &DC = *CG.lookupSCC(D1); + ASSERT_EQ(&AC, CG.lookupSCC(A2)); + ASSERT_EQ(&AC, CG.lookupSCC(A3)); + ASSERT_EQ(&BC, CG.lookupSCC(B2)); + ASSERT_EQ(&BC, CG.lookupSCC(B3)); + ASSERT_EQ(&CC, CG.lookupSCC(C2)); + ASSERT_EQ(&CC, CG.lookupSCC(C3)); + ASSERT_EQ(&DC, CG.lookupSCC(D2)); + ASSERT_EQ(&DC, CG.lookupSCC(D3)); + ASSERT_EQ(1, std::distance(D2.begin(), D2.end())); + + // Add an edge to make the graph: + // + // d1 | + // / \ | + // d3--d2---. | + // / \ | | + // b1 c1 | | + // / \ / \ / | + // b3--b2 c3--c2 | + // \ / | + // a1 | + // / \ | + // a3--a2 | + CC.insertIncomingEdge(D2, C2); + // Make sure we connected the nodes. + EXPECT_EQ(2, std::distance(D2.begin(), D2.end())); + + // Make sure we have the correct nodes in the SCC sets. + EXPECT_EQ(&AC, CG.lookupSCC(A1)); + EXPECT_EQ(&AC, CG.lookupSCC(A2)); + EXPECT_EQ(&AC, CG.lookupSCC(A3)); + EXPECT_EQ(&BC, CG.lookupSCC(B1)); + EXPECT_EQ(&BC, CG.lookupSCC(B2)); + EXPECT_EQ(&BC, CG.lookupSCC(B3)); + EXPECT_EQ(&CC, CG.lookupSCC(C1)); + EXPECT_EQ(&CC, CG.lookupSCC(C2)); + EXPECT_EQ(&CC, CG.lookupSCC(C3)); + EXPECT_EQ(&CC, CG.lookupSCC(D1)); + EXPECT_EQ(&CC, CG.lookupSCC(D2)); + EXPECT_EQ(&CC, CG.lookupSCC(D3)); + + // And that ancestry tests have been updated. + EXPECT_TRUE(AC.isParentOf(BC)); + EXPECT_TRUE(AC.isParentOf(CC)); + EXPECT_FALSE(AC.isAncestorOf(DC)); + EXPECT_FALSE(BC.isAncestorOf(DC)); + EXPECT_FALSE(CC.isAncestorOf(DC)); +} + +TEST(LazyCallGraphTest, IncomingSCCEdgeInsertionMidTraversal) { + // This is the same fundamental test as the previous, but we perform it + // having only partially walked the SCCs of the graph. + std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles); + LazyCallGraph CG(*M); + + // Walk the SCCs until we find the one containing 'c1'. + auto SCCI = CG.postorder_scc_begin(), SCCE = CG.postorder_scc_end(); + ASSERT_NE(SCCI, SCCE); + LazyCallGraph::SCC &DC = *SCCI; + ASSERT_NE(&DC, nullptr); + ++SCCI; + ASSERT_NE(SCCI, SCCE); + LazyCallGraph::SCC &CC = *SCCI; + ASSERT_NE(&CC, nullptr); + + ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a1"))); + ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a2"))); + ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a3"))); + ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b1"))); + ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b2"))); + ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b3"))); + LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1")); + LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2")); + LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3")); + LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1")); + LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2")); + LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3")); + ASSERT_EQ(&CC, CG.lookupSCC(C1)); + ASSERT_EQ(&CC, CG.lookupSCC(C2)); + ASSERT_EQ(&CC, CG.lookupSCC(C3)); + ASSERT_EQ(&DC, CG.lookupSCC(D1)); + ASSERT_EQ(&DC, CG.lookupSCC(D2)); + ASSERT_EQ(&DC, CG.lookupSCC(D3)); + ASSERT_EQ(1, std::distance(D2.begin(), D2.end())); + + CC.insertIncomingEdge(D2, C2); + EXPECT_EQ(2, std::distance(D2.begin(), D2.end())); + + // Make sure we have the correct nodes in the SCC sets. + EXPECT_EQ(&CC, CG.lookupSCC(C1)); + EXPECT_EQ(&CC, CG.lookupSCC(C2)); + EXPECT_EQ(&CC, CG.lookupSCC(C3)); + EXPECT_EQ(&CC, CG.lookupSCC(D1)); + EXPECT_EQ(&CC, CG.lookupSCC(D2)); + EXPECT_EQ(&CC, CG.lookupSCC(D3)); + + // Check that we can form the last two SCCs now in a coherent way. + ++SCCI; + EXPECT_NE(SCCI, SCCE); + LazyCallGraph::SCC &BC = *SCCI; + EXPECT_NE(&BC, nullptr); + EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b1")))); + EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b2")))); + EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b3")))); + ++SCCI; + EXPECT_NE(SCCI, SCCE); + LazyCallGraph::SCC &AC = *SCCI; + EXPECT_NE(&AC, nullptr); + EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a1")))); + EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a2")))); + EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a3")))); + ++SCCI; + EXPECT_EQ(SCCI, SCCE); +} + +TEST(LazyCallGraphTest, InterSCCEdgeRemoval) { + std::unique_ptr<Module> M = parseAssembly( + "define void @a() {\n" + "entry:\n" + " call void @b()\n" + " ret void\n" + "}\n" + "define void @b() {\n" + "entry:\n" + " ret void\n" + "}\n"); + LazyCallGraph CG(*M); + + // Force the graph to be fully expanded. + for (LazyCallGraph::SCC &C : CG.postorder_sccs()) + (void)C; + + LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a")); + LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b")); + LazyCallGraph::SCC &AC = *CG.lookupSCC(A); + LazyCallGraph::SCC &BC = *CG.lookupSCC(B); + + EXPECT_EQ("b", A.begin()->getFunction().getName()); + EXPECT_EQ(B.end(), B.begin()); + EXPECT_EQ(&AC, &*BC.parent_begin()); + + AC.removeInterSCCEdge(A, B); + + EXPECT_EQ(A.end(), A.begin()); + EXPECT_EQ(B.end(), B.begin()); + EXPECT_EQ(BC.parent_end(), BC.parent_begin()); +} + +TEST(LazyCallGraphTest, IntraSCCEdgeInsertion) { + std::unique_ptr<Module> M1 = parseAssembly( + "define void @a() {\n" + "entry:\n" + " call void @b()\n" + " ret void\n" + "}\n" + "define void @b() {\n" + "entry:\n" + " call void @c()\n" + " ret void\n" + "}\n" + "define void @c() {\n" + "entry:\n" + " call void @a()\n" + " ret void\n" + "}\n"); + LazyCallGraph CG1(*M1); + + // Force the graph to be fully expanded. + auto SCCI = CG1.postorder_scc_begin(); + LazyCallGraph::SCC &SCC = *SCCI++; + EXPECT_EQ(CG1.postorder_scc_end(), SCCI); + + LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a")); + LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b")); + LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c")); + EXPECT_EQ(&SCC, CG1.lookupSCC(A)); + EXPECT_EQ(&SCC, CG1.lookupSCC(B)); + EXPECT_EQ(&SCC, CG1.lookupSCC(C)); + + // Insert an edge from 'a' to 'c'. Nothing changes about the SCCs. + SCC.insertIntraSCCEdge(A, C); + EXPECT_EQ(2, std::distance(A.begin(), A.end())); + EXPECT_EQ(&SCC, CG1.lookupSCC(A)); + EXPECT_EQ(&SCC, CG1.lookupSCC(B)); + EXPECT_EQ(&SCC, CG1.lookupSCC(C)); + + // Insert a self edge from 'a' back to 'a'. + SCC.insertIntraSCCEdge(A, A); + EXPECT_EQ(3, std::distance(A.begin(), A.end())); + EXPECT_EQ(&SCC, CG1.lookupSCC(A)); + EXPECT_EQ(&SCC, CG1.lookupSCC(B)); + EXPECT_EQ(&SCC, CG1.lookupSCC(C)); +} + +TEST(LazyCallGraphTest, IntraSCCEdgeRemoval) { + // A nice fully connected (including self-edges) SCC. + std::unique_ptr<Module> M1 = parseAssembly( + "define void @a() {\n" + "entry:\n" + " call void @a()\n" + " call void @b()\n" + " call void @c()\n" + " ret void\n" + "}\n" + "define void @b() {\n" + "entry:\n" + " call void @a()\n" + " call void @b()\n" + " call void @c()\n" + " ret void\n" + "}\n" + "define void @c() {\n" + "entry:\n" + " call void @a()\n" + " call void @b()\n" + " call void @c()\n" + " ret void\n" + "}\n"); + LazyCallGraph CG1(*M1); + + // Force the graph to be fully expanded. + auto SCCI = CG1.postorder_scc_begin(); + LazyCallGraph::SCC &SCC = *SCCI++; + EXPECT_EQ(CG1.postorder_scc_end(), SCCI); + + LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a")); + LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b")); + LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c")); + EXPECT_EQ(&SCC, CG1.lookupSCC(A)); + EXPECT_EQ(&SCC, CG1.lookupSCC(B)); + EXPECT_EQ(&SCC, CG1.lookupSCC(C)); + + // Remove the edge from b -> a, which should leave the 3 functions still in + // a single connected component because of a -> b -> c -> a. + SmallVector<LazyCallGraph::SCC *, 1> NewSCCs = SCC.removeIntraSCCEdge(B, A); + EXPECT_EQ(0u, NewSCCs.size()); + EXPECT_EQ(&SCC, CG1.lookupSCC(A)); + EXPECT_EQ(&SCC, CG1.lookupSCC(B)); + EXPECT_EQ(&SCC, CG1.lookupSCC(C)); + + // Remove the edge from c -> a, which should leave 'a' in the original SCC + // and form a new SCC for 'b' and 'c'. + NewSCCs = SCC.removeIntraSCCEdge(C, A); + EXPECT_EQ(1u, NewSCCs.size()); + EXPECT_EQ(&SCC, CG1.lookupSCC(A)); + EXPECT_EQ(1, std::distance(SCC.begin(), SCC.end())); + LazyCallGraph::SCC *SCC2 = CG1.lookupSCC(B); + EXPECT_EQ(SCC2, CG1.lookupSCC(C)); + EXPECT_EQ(SCC2, NewSCCs[0]); +} + +} diff --git a/unittests/Analysis/MixedTBAATest.cpp b/unittests/Analysis/MixedTBAATest.cpp new file mode 100644 index 0000000..2cf7c73 --- /dev/null +++ b/unittests/Analysis/MixedTBAATest.cpp @@ -0,0 +1,77 @@ +//===--- MixedTBAATest.cpp - Mixed TBAA 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/Analysis/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/MDBuilder.h" +#include "llvm/IR/Module.h" +#include "llvm/PassManager.h" +#include "llvm/Support/CommandLine.h" +#include "gtest/gtest.h" + +namespace llvm { +namespace { + +class MixedTBAATest : public testing::Test { +protected: + MixedTBAATest() : M("MixedTBAATest", C), MD(C) {} + + LLVMContext C; + Module M; + MDBuilder MD; + PassManager PM; +}; + +TEST_F(MixedTBAATest, MixedTBAA) { + // Setup function. + FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), + std::vector<Type *>(), false); + auto *F = cast<Function>(M.getOrInsertFunction("f", FTy)); + auto *BB = BasicBlock::Create(C, "entry", F); + auto IntType = Type::getInt32Ty(C); + auto PtrType = Type::getInt32PtrTy(C); + auto *Value = ConstantInt::get(IntType, 42); + auto *Addr = ConstantPointerNull::get(PtrType); + + auto *Store1 = new StoreInst(Value, Addr, BB); + auto *Store2 = new StoreInst(Value, Addr, BB); + ReturnInst::Create(C, 0, BB); + + // New TBAA metadata + { + auto RootMD = MD.createTBAARoot("Simple C/C++ TBAA"); + auto MD1 = MD.createTBAAScalarTypeNode("omnipotent char", RootMD); + auto MD2 = MD.createTBAAScalarTypeNode("int", MD1); + auto MD3 = MD.createTBAAStructTagNode(MD2, MD2, 0); + Store2->setMetadata(LLVMContext::MD_tbaa, MD3); + } + + // Old TBAA metadata + { + auto RootMD = MD.createTBAARoot("Simple C/C++ TBAA"); + auto MD1 = MD.createTBAANode("omnipotent char", RootMD); + auto MD2 = MD.createTBAANode("int", MD1); + Store1->setMetadata(LLVMContext::MD_tbaa, MD2); + } + + // 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" }; + cl::ParseCommandLineOptions(sizeof(args) / sizeof(const char*), args); + PM.add(createTypeBasedAliasAnalysisPass()); + PM.add(createAAEvalPass()); + PM.run(M); +} + +} // end anonymous namspace +} // end llvm namespace + diff --git a/unittests/Bitcode/BitReaderTest.cpp b/unittests/Bitcode/BitReaderTest.cpp index ba03023..b6a3e9a 100644 --- a/unittests/Bitcode/BitReaderTest.cpp +++ b/unittests/Bitcode/BitReaderTest.cpp @@ -59,6 +59,7 @@ TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677 std::unique_ptr<Module> m(ModuleOrErr.get()); PassManager passes; passes.add(createVerifierPass()); + passes.add(createDebugInfoVerifierPass()); passes.run(*m); } diff --git a/unittests/CMakeLists.txt b/unittests/CMakeLists.txt index 9e2f60c..bbab2a1 100644 --- a/unittests/CMakeLists.txt +++ b/unittests/CMakeLists.txt @@ -19,6 +19,7 @@ add_subdirectory(DebugInfo) add_subdirectory(ExecutionEngine) add_subdirectory(IR) add_subdirectory(LineEditor) +add_subdirectory(Linker) add_subdirectory(MC) add_subdirectory(Object) add_subdirectory(Option) diff --git a/unittests/CodeGen/DIEHashTest.cpp b/unittests/CodeGen/DIEHashTest.cpp index c874cef..04c5a8a 100644 --- a/unittests/CodeGen/DIEHashTest.cpp +++ b/unittests/CodeGen/DIEHashTest.cpp @@ -12,6 +12,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Format.h" +#include "llvm/ADT/STLExtras.h" #include "gtest/gtest.h" using namespace llvm; @@ -59,7 +60,7 @@ TEST(DIEHashTest, NamedType) { TEST(DIEHashTest, NamespacedType) { DIE CU(dwarf::DW_TAG_compile_unit); - DIE *Space = new DIE(dwarf::DW_TAG_namespace); + auto Space = make_unique<DIE>(dwarf::DW_TAG_namespace); DIEInteger One(1); DIEString SpaceStr(&One, "space"); Space->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &SpaceStr); @@ -67,15 +68,16 @@ TEST(DIEHashTest, NamespacedType) { Space->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One); // sibling? - DIE *Foo = new DIE(dwarf::DW_TAG_structure_type); + auto Foo = make_unique<DIE>(dwarf::DW_TAG_structure_type); DIEString FooStr(&One, "foo"); Foo->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); Foo->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); - Space->addChild(Foo); - CU.addChild(Space); + DIE &N = *Foo; + Space->addChild(std::move(Foo)); + CU.addChild(std::move(Space)); - uint64_t MD5Res = DIEHash().computeTypeSignature(*Foo); + uint64_t MD5Res = DIEHash().computeTypeSignature(N); // The exact same hash GCC produces for this DIE. ASSERT_EQ(0x7b80381fd17f1e33ULL, MD5Res); @@ -87,15 +89,6 @@ TEST(DIEHashTest, TypeWithMember) { DIEInteger Four(4); Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four); - DIE *Member = new DIE(dwarf::DW_TAG_member); - DIEString MemberStr(&Four, "member"); - Member->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemberStr); - DIEInteger Zero(0); - Member->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, - &Zero); - - Unnamed.addChild(Member); - DIE Int(dwarf::DW_TAG_base_type); DIEString IntStr(&Four, "int"); Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr); @@ -103,9 +96,18 @@ TEST(DIEHashTest, TypeWithMember) { DIEInteger Five(5); Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five); - DIEEntry IntRef(&Int); + DIEEntry IntRef(Int); + + auto Member = make_unique<DIE>(dwarf::DW_TAG_member); + DIEString MemberStr(&Four, "member"); + Member->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemberStr); + DIEInteger Zero(0); + Member->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, + &Zero); Member->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef); + Unnamed.addChild(std::move(Member)); + uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res); @@ -117,35 +119,35 @@ TEST(DIEHashTest, ReusedType) { DIEInteger Eight(8); Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); - DIE *Mem1 = new DIE(dwarf::DW_TAG_member); DIEInteger Four(4); + DIE Int(dwarf::DW_TAG_base_type); + DIEString IntStr(&Four, "int"); + Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr); + Int.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four); + DIEInteger Five(5); + Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five); + + DIEEntry IntRef(Int); + + auto Mem1 = make_unique<DIE>(dwarf::DW_TAG_member); DIEString Mem1Str(&Four, "mem1"); Mem1->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem1Str); DIEInteger Zero(0); Mem1->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); + Mem1->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef); - Unnamed.addChild(Mem1); + Unnamed.addChild(std::move(Mem1)); - DIE *Mem2 = new DIE(dwarf::DW_TAG_member); + auto Mem2 = make_unique<DIE>(dwarf::DW_TAG_member); DIEString Mem2Str(&Four, "mem2"); Mem2->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &Mem2Str); Mem2->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Four); - - Unnamed.addChild(Mem2); - - DIE Int(dwarf::DW_TAG_base_type); - DIEString IntStr(&Four, "int"); - Int.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &IntStr); - Int.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four); - DIEInteger Five(5); - Int.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five); - - DIEEntry IntRef(&Int); - Mem1->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef); Mem2->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntRef); + Unnamed.addChild(std::move(Mem2)); + uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res); @@ -159,14 +161,14 @@ TEST(DIEHashTest, RecursiveType) { DIEString FooStr(&One, "foo"); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); DIEString MemStr(&One, "mem"); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); - DIEEntry FooRef(&Foo); + DIEEntry FooRef(Foo); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRef); // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them. - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); @@ -181,7 +183,7 @@ TEST(DIEHashTest, Pointer) { DIEString FooStr(&Eight, "foo"); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); DIEString MemStr(&Eight, "mem"); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); DIEInteger Zero(0); @@ -189,13 +191,13 @@ TEST(DIEHashTest, Pointer) { DIE FooPtr(dwarf::DW_TAG_pointer_type); FooPtr.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); - DIEEntry FooRef(&Foo); + DIEEntry FooRef(Foo); FooPtr.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRef); - DIEEntry FooPtrRef(&FooPtr); + DIEEntry FooPtrRef(FooPtr); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooPtrRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); @@ -210,7 +212,7 @@ TEST(DIEHashTest, Reference) { DIEString FooStr(&Eight, "foo"); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); DIEString MemStr(&Eight, "mem"); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); DIEInteger Zero(0); @@ -218,17 +220,17 @@ TEST(DIEHashTest, Reference) { DIE FooRef(dwarf::DW_TAG_reference_type); FooRef.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); - DIEEntry FooEntry(&Foo); + DIEEntry FooEntry(Foo); FooRef.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry); DIE FooRefConst(dwarf::DW_TAG_const_type); - DIEEntry FooRefRef(&FooRef); + DIEEntry FooRefRef(FooRef); FooRefConst.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefRef); - DIEEntry FooRefConstRef(&FooRefConst); + DIEEntry FooRefConstRef(FooRefConst); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefConstRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); @@ -243,7 +245,7 @@ TEST(DIEHashTest, RValueReference) { DIEString FooStr(&Eight, "foo"); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); DIEString MemStr(&Eight, "mem"); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); DIEInteger Zero(0); @@ -251,17 +253,17 @@ TEST(DIEHashTest, RValueReference) { DIE FooRef(dwarf::DW_TAG_rvalue_reference_type); FooRef.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); - DIEEntry FooEntry(&Foo); + DIEEntry FooEntry(Foo); FooRef.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry); DIE FooRefConst(dwarf::DW_TAG_const_type); - DIEEntry FooRefRef(&FooRef); + DIEEntry FooRefRef(FooRef); FooRefConst.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefRef); - DIEEntry FooRefConstRef(&FooRefConst); + DIEEntry FooRefConstRef(FooRefConst); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooRefConstRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); @@ -276,22 +278,22 @@ TEST(DIEHashTest, PtrToMember) { DIEString FooStr(&Eight, "foo"); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); DIEString MemStr(&Eight, "mem"); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); DIEInteger Zero(0); Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type); - DIEEntry FooEntry(&Foo); + DIEEntry FooEntry(Foo); PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FooEntry); PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &FooEntry); - DIEEntry PtrToFooMemRef(&PtrToFooMem); + DIEEntry PtrToFooMemRef(PtrToFooMem); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); @@ -320,22 +322,22 @@ TEST(DIEHashTest, PtrToMemberDeclDefMatch) { Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type); - DIEEntry BarEntry(&Bar); + DIEEntry BarEntry(Bar); PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry); - DIEEntry FooEntry(&Foo); + DIEEntry FooEntry(Foo); PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &FooEntry); - DIEEntry PtrToFooMemRef(&PtrToFooMem); + DIEEntry PtrToFooMemRef(PtrToFooMem); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); MD5ResDecl = DIEHash().computeTypeSignature(Foo); } @@ -349,22 +351,22 @@ TEST(DIEHashTest, PtrToMemberDeclDefMatch) { Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type); - DIEEntry BarEntry(&Bar); + DIEEntry BarEntry(Bar); PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry); - DIEEntry FooEntry(&Foo); + DIEEntry FooEntry(Foo); PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &FooEntry); - DIEEntry PtrToFooMemRef(&PtrToFooMem); + DIEEntry PtrToFooMemRef(PtrToFooMem); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); MD5ResDef = DIEHash().computeTypeSignature(Foo); } @@ -393,21 +395,21 @@ TEST(DIEHashTest, PtrToMemberDeclDefMisMatch) { Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type); - DIEEntry BarEntry(&Bar); + DIEEntry BarEntry(Bar); PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry); PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &BarEntry); - DIEEntry PtrToFooMemRef(&PtrToFooMem); + DIEEntry PtrToFooMemRef(PtrToFooMem); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); MD5ResDecl = DIEHash().computeTypeSignature(Foo); } @@ -421,21 +423,21 @@ TEST(DIEHashTest, PtrToMemberDeclDefMisMatch) { Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); DIE PtrToFooMem(dwarf::DW_TAG_ptr_to_member_type); - DIEEntry BarEntry(&Bar); + DIEEntry BarEntry(Bar); PtrToFooMem.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &BarEntry); PtrToFooMem.addValue(dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, &BarEntry); - DIEEntry PtrToFooMemRef(&PtrToFooMem); + DIEEntry PtrToFooMemRef(PtrToFooMem); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &PtrToFooMemRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); MD5ResDef = DIEHash().computeTypeSignature(Foo); } @@ -463,19 +465,19 @@ TEST(DIEHashTest, RefUnnamedType) { Foo.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); Foo.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); - DIE *Mem = new DIE(dwarf::DW_TAG_member); + auto Mem = make_unique<DIE>(dwarf::DW_TAG_member); Mem->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &MemStr); Mem->addValue(dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1, &Zero); DIE UnnamedPtr(dwarf::DW_TAG_pointer_type); UnnamedPtr.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Eight); - DIEEntry UnnamedRef(&Unnamed); + DIEEntry UnnamedRef(Unnamed); UnnamedPtr.addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &UnnamedRef); - DIEEntry UnnamedPtrRef(&UnnamedPtr); + DIEEntry UnnamedPtrRef(UnnamedPtr); Mem->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &UnnamedPtrRef); - Foo.addChild(Mem); + Foo.addChild(std::move(Mem)); uint64_t MD5Res = DIEHash().computeTypeSignature(Foo); @@ -488,12 +490,12 @@ TEST(DIEHashTest, NestedType) { DIEInteger One(1); Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); - DIE *Foo = new DIE(dwarf::DW_TAG_structure_type); + auto Foo = make_unique<DIE>(dwarf::DW_TAG_structure_type); DIEString FooStr(&One, "foo"); Foo->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FooStr); Foo->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); - Unnamed.addChild(Foo); + Unnamed.addChild(std::move(Foo)); uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); @@ -507,11 +509,11 @@ TEST(DIEHashTest, MemberFunc) { DIEInteger One(1); Unnamed.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &One); - DIE *Func = new DIE(dwarf::DW_TAG_subprogram); + auto Func = make_unique<DIE>(dwarf::DW_TAG_subprogram); DIEString FuncStr(&One, "func"); Func->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FuncStr); - Unnamed.addChild(Func); + Unnamed.addChild(std::move(Func)); uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed); @@ -531,7 +533,7 @@ TEST(DIEHashTest, MemberFuncFlag) { A.addValue(dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, &One); A.addValue(dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, &One); - DIE *Func = new DIE(dwarf::DW_TAG_subprogram); + auto Func = make_unique<DIE>(dwarf::DW_TAG_subprogram); DIEString FuncStr(&One, "func"); DIEString FuncLinkage(&One, "_ZN1A4funcEv"); DIEInteger Two(2); @@ -542,7 +544,7 @@ TEST(DIEHashTest, MemberFuncFlag) { Func->addValue(dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp, &FuncLinkage); Func->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One); - A.addChild(Func); + A.addChild(std::move(Func)); uint64_t MD5Res = DIEHash().computeTypeSignature(A); @@ -567,17 +569,17 @@ TEST(DIEHashTest, MemberSdata) { DIEInteger Four(4); DIEInteger Five(5); DIEString FStr(&One, "int"); - DIE *IntTyDIE = new DIE(dwarf::DW_TAG_base_type); - IntTyDIE->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four); - IntTyDIE->addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five); - IntTyDIE->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FStr); + DIE IntTyDIE(dwarf::DW_TAG_base_type); + IntTyDIE.addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four); + IntTyDIE.addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Five); + IntTyDIE.addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FStr); DIEEntry IntTy(IntTyDIE); - DIE *PITyDIE = new DIE(dwarf::DW_TAG_const_type); + auto PITyDIE = make_unique<DIE>(dwarf::DW_TAG_const_type); PITyDIE->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &IntTy); - DIEEntry PITy(PITyDIE); - DIE *PI = new DIE(dwarf::DW_TAG_member); + DIEEntry PITy(*PITyDIE); + auto PI = make_unique<DIE>(dwarf::DW_TAG_member); DIEString PIStr(&One, "PI"); DIEInteger Two(2); DIEInteger NegThree(-3); @@ -589,7 +591,7 @@ TEST(DIEHashTest, MemberSdata) { PI->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One); PI->addValue(dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, &NegThree); - A.addChild(PI); + A.addChild(std::move(PI)); uint64_t MD5Res = DIEHash().computeTypeSignature(A); ASSERT_EQ(0x9a216000dd3788a7ULL, MD5Res); @@ -611,17 +613,17 @@ TEST(DIEHashTest, MemberBlock) { DIEInteger Four(4); DIEString FStr(&One, "float"); - DIE *FloatTyDIE = new DIE(dwarf::DW_TAG_base_type); + auto FloatTyDIE = make_unique<DIE>(dwarf::DW_TAG_base_type); FloatTyDIE->addValue(dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, &Four); FloatTyDIE->addValue(dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, &Four); FloatTyDIE->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &FStr); - DIEEntry FloatTy(FloatTyDIE); - DIE *PITyDIE = new DIE(dwarf::DW_TAG_const_type); + DIEEntry FloatTy(*FloatTyDIE); + auto PITyDIE = make_unique<DIE>(dwarf::DW_TAG_const_type); PITyDIE->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, &FloatTy); - DIEEntry PITy(PITyDIE); - DIE *PI = new DIE(dwarf::DW_TAG_member); + DIEEntry PITy(*PITyDIE); + auto PI = make_unique<DIE>(dwarf::DW_TAG_member); DIEString PIStr(&One, "PI"); DIEInteger Two(2); PI->addValue(dwarf::DW_AT_name, dwarf::DW_FORM_strp, &PIStr); @@ -631,20 +633,20 @@ TEST(DIEHashTest, MemberBlock) { PI->addValue(dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, &One); PI->addValue(dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present, &One); - DIEBlock *PIBlock = new DIEBlock(); + DIEBlock PIBlock; DIEInteger Blk1(0xc3); DIEInteger Blk2(0xf5); DIEInteger Blk3(0x48); DIEInteger Blk4(0x40); - PIBlock->addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk1); - PIBlock->addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk2); - PIBlock->addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk3); - PIBlock->addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk4); + PIBlock.addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk1); + PIBlock.addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk2); + PIBlock.addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk3); + PIBlock.addValue((dwarf::Attribute)0, dwarf::DW_FORM_data1, &Blk4); - PI->addValue(dwarf::DW_AT_const_value, dwarf::DW_FORM_block1, PIBlock); + PI->addValue(dwarf::DW_AT_const_value, dwarf::DW_FORM_block1, &PIBlock); - A.addChild(PI); + A.addChild(std::move(PI)); uint64_t MD5Res = DIEHash().computeTypeSignature(A); ASSERT_EQ(0x493af53ad3d3f651ULL, MD5Res); diff --git a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp b/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp index d3f66a2..db90887 100644 --- a/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp +++ b/unittests/ExecutionEngine/JIT/IntelJITEventListenerTest.cpp @@ -83,7 +83,7 @@ public: EXPECT_TRUE(0 != MockWrapper); Listener.reset(JITEventListener::createIntelJITEventListener( - MockWrapper.take())); + MockWrapper.release())); EXPECT_TRUE(0 != Listener); EE->RegisterJITEventListener(Listener.get()); } diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp index 9e65fee..f438286 100644 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITTest.cpp @@ -114,8 +114,8 @@ public: return Result; } int stubsAllocated; - virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment) { + uint8_t *allocateStub(const GlobalValue *F, unsigned StubSize, + unsigned Alignment) override { stubsAllocated++; return Base->allocateStub(F, StubSize, Alignment); } diff --git a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp index 3813d59..20d3f13 100644 --- a/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp +++ b/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -28,6 +28,7 @@ using namespace llvm; static bool didCallAllocateCodeSection; static bool didAllocateCompactUnwindSection; +static bool didCallYield; static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size, unsigned alignment, @@ -64,6 +65,10 @@ static void roundTripDestroy(void *object) { delete static_cast<SectionMemoryManager*>(object); } +static void yield(LLVMContextRef, void *) { + didCallYield = true; +} + namespace { // memory manager to test reserve allocation space callback @@ -142,6 +147,7 @@ protected: virtual void SetUp() { didCallAllocateCodeSection = false; didAllocateCompactUnwindSection = false; + didCallYield = false; Module = 0; Function = 0; Engine = 0; @@ -429,3 +435,24 @@ TEST_F(MCJITCAPITest, reserve_allocation_space) { EXPECT_TRUE(MM->UsedCodeSize > 0); EXPECT_TRUE(MM->UsedDataSizeRW > 0); } + +TEST_F(MCJITCAPITest, yield) { + SKIP_UNSUPPORTED_PLATFORM; + + buildSimpleFunction(); + buildMCJITOptions(); + buildMCJITEngine(); + LLVMContextRef C = LLVMGetGlobalContext(); + LLVMContextSetYieldCallback(C, yield, NULL); + buildAndRunPasses(); + + union { + void *raw; + int (*usable)(); + } functionPointer; + functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function); + + EXPECT_EQ(42, functionPointer.usable()); + EXPECT_TRUE(didCallYield); +} + diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index 7368a24..b439d59 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -21,6 +21,7 @@ set(IRSources PatternMatch.cpp TypeBuilderTest.cpp TypesTest.cpp + UserTest.cpp ValueHandleTest.cpp ValueMapTest.cpp ValueTest.cpp diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index b3aa810..c11729c 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -254,6 +254,34 @@ TEST(ConstantsTest, AsInstructionsTest) { P6STR ", i32 1"); } +#ifdef GTEST_HAS_DEATH_TEST +#ifndef NDEBUG +TEST(ConstantsTest, ReplaceWithConstantTest) { + std::unique_ptr<Module> M(new Module("MyModule", getGlobalContext())); + + Type *Int32Ty = Type::getInt32Ty(getGlobalContext()); + Constant *One = ConstantInt::get(Int32Ty, 1); + + Constant *Global = + M->getOrInsertGlobal("dummy", PointerType::getUnqual(Int32Ty)); + Constant *GEP = ConstantExpr::getGetElementPtr(Global, One); + EXPECT_DEATH(Global->replaceAllUsesWith(GEP), + "this->replaceAllUsesWith\\(expr\\(this\\)\\) is NOT valid!"); +} + +TEST(ConstantsTest, ReplaceInAliasTest) { + std::unique_ptr<Module> M(new Module("MyModule", getGlobalContext())); + + Type *Int32Ty = Type::getInt32Ty(getGlobalContext()); + auto *Global = cast<GlobalObject>(M->getOrInsertGlobal("dummy", Int32Ty)); + auto *GA = GlobalAlias::create(GlobalValue::ExternalLinkage, "alias", Global); + EXPECT_DEATH(Global->replaceAllUsesWith(GA), + "replaceAliasUseWith cannot form an alias cycle"); +} + +#endif +#endif + #undef CHECK } // end anonymous namespace diff --git a/unittests/IR/InstructionsTest.cpp b/unittests/IR/InstructionsTest.cpp index e76afa8..336f5a2 100644 --- a/unittests/IR/InstructionsTest.cpp +++ b/unittests/IR/InstructionsTest.cpp @@ -483,6 +483,39 @@ TEST(InstructionsTest, isEliminableCastPair) { } +TEST(InstructionsTest, CloneCall) { + LLVMContext &C(getGlobalContext()); + Type *Int32Ty = Type::getInt32Ty(C); + Type *ArgTys[] = {Int32Ty, Int32Ty, Int32Ty}; + Type *FnTy = FunctionType::get(Int32Ty, ArgTys, /*isVarArg=*/false); + Value *Callee = Constant::getNullValue(FnTy->getPointerTo()); + Value *Args[] = { + ConstantInt::get(Int32Ty, 1), + ConstantInt::get(Int32Ty, 2), + ConstantInt::get(Int32Ty, 3) + }; + std::unique_ptr<CallInst> Call(CallInst::Create(Callee, Args, "result")); + + // Test cloning the tail call kind. + CallInst::TailCallKind Kinds[] = {CallInst::TCK_None, CallInst::TCK_Tail, + CallInst::TCK_MustTail}; + for (CallInst::TailCallKind TCK : Kinds) { + Call->setTailCallKind(TCK); + std::unique_ptr<CallInst> Clone(cast<CallInst>(Call->clone())); + EXPECT_EQ(Call->getTailCallKind(), Clone->getTailCallKind()); + } + Call->setTailCallKind(CallInst::TCK_None); + + // Test cloning an attribute. + { + AttrBuilder AB; + AB.addAttribute(Attribute::ReadOnly); + Call->setAttributes(AttributeSet::get(C, AttributeSet::FunctionIndex, AB)); + std::unique_ptr<CallInst> Clone(cast<CallInst>(Call->clone())); + EXPECT_TRUE(Clone->onlyReadsMemory()); + } +} + } // end anonymous namespace } // end namespace llvm diff --git a/unittests/IR/MDBuilderTest.cpp b/unittests/IR/MDBuilderTest.cpp index 665d559..c8b5a09 100644 --- a/unittests/IR/MDBuilderTest.cpp +++ b/unittests/IR/MDBuilderTest.cpp @@ -9,6 +9,7 @@ #include "llvm/IR/MDBuilder.h" #include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Operator.h" #include "gtest/gtest.h" diff --git a/unittests/IR/UserTest.cpp b/unittests/IR/UserTest.cpp new file mode 100644 index 0000000..9c0e7b2 --- /dev/null +++ b/unittests/IR/UserTest.cpp @@ -0,0 +1,96 @@ +//===- llvm/unittest/IR/UserTest.cpp - User 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/SourceMgr.h" +#include "gtest/gtest.h" +using namespace llvm; + +namespace { + +TEST(UserTest, ValueOpIteration) { + LLVMContext C; + + const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n" + "entry:\n" + " switch i32 undef, label %s0\n" + " [ i32 1, label %s1\n" + " i32 2, label %s2\n" + " i32 3, label %s3\n" + " i32 4, label %s4\n" + " i32 5, label %s5\n" + " i32 6, label %s6\n" + " i32 7, label %s7\n" + " i32 8, label %s8\n" + " i32 9, label %s9 ]\n" + "\n" + "s0:\n" + " br label %exit\n" + "s1:\n" + " br label %exit\n" + "s2:\n" + " br label %exit\n" + "s3:\n" + " br label %exit\n" + "s4:\n" + " br label %exit\n" + "s5:\n" + " br label %exit\n" + "s6:\n" + " br label %exit\n" + "s7:\n" + " br label %exit\n" + "s8:\n" + " br label %exit\n" + "s9:\n" + " br label %exit\n" + "\n" + "exit:\n" + " %phi = phi i32 [ 0, %s0 ], [ 1, %s1 ],\n" + " [ 2, %s2 ], [ 3, %s3 ],\n" + " [ 4, %s4 ], [ 5, %s5 ],\n" + " [ 6, %s6 ], [ 7, %s7 ],\n" + " [ 8, %s8 ], [ 9, %s9 ]\n" + " ret void\n" + "}\n"; + SMDiagnostic Err; + Module *M = ParseAssemblyString(ModuleString, NULL, Err, C); + + Function *F = M->getFunction("f"); + BasicBlock &ExitBB = F->back(); + PHINode &P = cast<PHINode>(ExitBB.front()); + EXPECT_TRUE(P.value_op_begin() == P.value_op_begin()); + EXPECT_FALSE(P.value_op_begin() == P.value_op_end()); + EXPECT_TRUE(P.value_op_begin() != P.value_op_end()); + EXPECT_FALSE(P.value_op_end() != P.value_op_end()); + EXPECT_TRUE(P.value_op_begin() < P.value_op_end()); + EXPECT_FALSE(P.value_op_begin() < P.value_op_begin()); + EXPECT_TRUE(P.value_op_end() > P.value_op_begin()); + EXPECT_FALSE(P.value_op_begin() > P.value_op_begin()); + EXPECT_TRUE(P.value_op_begin() <= P.value_op_begin()); + EXPECT_FALSE(P.value_op_end() <= P.value_op_begin()); + EXPECT_TRUE(P.value_op_begin() >= P.value_op_begin()); + EXPECT_FALSE(P.value_op_begin() >= P.value_op_end()); + EXPECT_EQ(10, std::distance(P.value_op_begin(), P.value_op_end())); + + User::value_op_iterator I = P.value_op_begin(); + I += 3; + EXPECT_EQ(std::next(P.value_op_begin(), 3), I); + EXPECT_EQ(P.getOperand(3), *I); + I++; + EXPECT_EQ(P.getOperand(6), I[2]); + EXPECT_EQ(P.value_op_end(), (I - 2) + 8); +} + +} // end anonymous namespace diff --git a/unittests/IR/VerifierTest.cpp b/unittests/IR/VerifierTest.cpp index 0a660a6..252bdd3 100644 --- a/unittests/IR/VerifierTest.cpp +++ b/unittests/IR/VerifierTest.cpp @@ -52,9 +52,7 @@ TEST(VerifierTest, AliasUnnamedAddr) { GlobalVariable *Aliasee = new GlobalVariable(M, Ty, true, GlobalValue::ExternalLinkage, Init, "foo"); - GlobalAlias *GA = new GlobalAlias(Type::getInt8PtrTy(C), - GlobalValue::ExternalLinkage, - "bar", Aliasee, &M); + auto *GA = GlobalAlias::create(GlobalValue::ExternalLinkage, "bar", Aliasee); GA->setUnnamedAddr(true); std::string Error; raw_string_ostream ErrorOS(Error); diff --git a/unittests/LineEditor/LineEditor.cpp b/unittests/LineEditor/LineEditor.cpp index cb115bd..26053c0 100644 --- a/unittests/LineEditor/LineEditor.cpp +++ b/unittests/LineEditor/LineEditor.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "llvm/LineEditor/LineEditor.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "gtest/gtest.h" diff --git a/unittests/Linker/LinkModulesTest.cpp b/unittests/Linker/LinkModulesTest.cpp index 7b40b9f..1d5db36 100644 --- a/unittests/Linker/LinkModulesTest.cpp +++ b/unittests/Linker/LinkModulesTest.cpp @@ -22,11 +22,9 @@ namespace { class LinkModuleTest : public testing::Test { protected: virtual void SetUp() { - LLVMContext &Ctx = getGlobalContext(); M.reset(new Module("MyModule", Ctx)); - FunctionType *FTy = FunctionType::get(Type::getInt8PtrTy(Ctx), - Type::getInt32Ty(Ctx), - false /*=isVarArg*/); + FunctionType *FTy = FunctionType::get( + Type::getInt8PtrTy(Ctx), Type::getInt32Ty(Ctx), false /*=isVarArg*/); F = Function::Create(FTy, Function::ExternalLinkage, "ba_func", M.get()); F->setCallingConv(CallingConv::C); @@ -38,12 +36,10 @@ protected: ArrayType *AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3); GV = new GlobalVariable(*M.get(), AT, false /*=isConstant*/, - GlobalValue::InternalLinkage, - 0, "switch.bas"); - + GlobalValue::InternalLinkage, 0, "switch.bas"); // Global Initializer - std::vector<Constant*> Init; + std::vector<Constant *> Init; Constant *SwitchCase1BA = BlockAddress::get(SwitchCase1BB); Init.push_back(SwitchCase1BA); @@ -51,17 +47,16 @@ protected: Init.push_back(SwitchCase2BA); ConstantInt *One = ConstantInt::get(Type::getInt32Ty(Ctx), 1); - Constant *OnePtr = ConstantExpr::getCast(Instruction::IntToPtr, - One, Type::getInt8PtrTy(Ctx)); + Constant *OnePtr = ConstantExpr::getCast(Instruction::IntToPtr, One, + Type::getInt8PtrTy(Ctx)); Init.push_back(OnePtr); GV->setInitializer(ConstantArray::get(AT, Init)); } - virtual void TearDown() { - M.reset(); - } + virtual void TearDown() { M.reset(); } + LLVMContext Ctx; std::unique_ptr<Module> M; Function *F; GlobalVariable *GV; @@ -72,10 +67,9 @@ protected: }; TEST_F(LinkModuleTest, BlockAddress) { - LLVMContext &Ctx = getGlobalContext(); IRBuilder<> Builder(EntryBB); - std::vector<Value*> GEPIndices; + std::vector<Value *> GEPIndices; GEPIndices.push_back(ConstantInt::get(Type::getInt32Ty(Ctx), 0)); GEPIndices.push_back(F->arg_begin()); @@ -93,7 +87,7 @@ TEST_F(LinkModuleTest, BlockAddress) { Builder.SetInsertPoint(ExitBB); Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx))); - Module *LinkedModule = new Module("MyModuleLinked", getGlobalContext()); + Module *LinkedModule = new Module("MyModuleLinked", Ctx); Linker::LinkModules(LinkedModule, M.get(), Linker::PreserveSource, 0); // Delete the original module. @@ -117,7 +111,7 @@ TEST_F(LinkModuleTest, BlockAddress) { LinkedModule->getFunction("ba_func")); EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(), LinkedModule->getFunction("ba_func")); - + Elem = Init->getOperand(1); ASSERT_TRUE(isa<BlockAddress>(Elem)); EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(), @@ -129,11 +123,9 @@ TEST_F(LinkModuleTest, BlockAddress) { } TEST_F(LinkModuleTest, EmptyModule) { - LLVMContext &Ctx = getGlobalContext(); Module *InternalM = new Module("InternalModule", Ctx); - FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), - Type::getInt8PtrTy(Ctx), - false /*=isVarArgs*/); + FunctionType *FTy = FunctionType::get( + Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/); F = Function::Create(FTy, Function::InternalLinkage, "bar", InternalM); F->setCallingConv(CallingConv::C); @@ -145,12 +137,11 @@ TEST_F(LinkModuleTest, EmptyModule) { StructType *STy = StructType::create(Ctx, PointerType::get(FTy, 0)); GlobalVariable *GV = - new GlobalVariable(*InternalM, STy, false /*=isConstant*/, - GlobalValue::InternalLinkage, 0, "g"); + new GlobalVariable(*InternalM, STy, false /*=isConstant*/, + GlobalValue::InternalLinkage, 0, "g"); GV->setInitializer(ConstantStruct::get(STy, F)); - Module *EmptyM = new Module("EmptyModule1", Ctx); Linker::LinkModules(EmptyM, InternalM, Linker::PreserveSource, 0); diff --git a/unittests/Object/CMakeLists.txt b/unittests/Object/CMakeLists.txt index 6dd66ce..580a894 100644 --- a/unittests/Object/CMakeLists.txt +++ b/unittests/Object/CMakeLists.txt @@ -4,5 +4,6 @@ set(LLVM_LINK_COMPONENTS ) add_llvm_unittest(ObjectTests + StringTableBuilderTest.cpp YAMLTest.cpp ) diff --git a/unittests/Object/StringTableBuilderTest.cpp b/unittests/Object/StringTableBuilderTest.cpp new file mode 100644 index 0000000..130eb4a --- /dev/null +++ b/unittests/Object/StringTableBuilderTest.cpp @@ -0,0 +1,40 @@ +//===----------- StringTableBuilderTest.cpp -------------------------------===// +// +// 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/Object/StringTableBuilder.h" +#include <string> + +using namespace llvm; + +namespace { + +TEST(StringTableBuilderTest, Basic) { + StringTableBuilder B; + + B.add("foo"); + B.add("bar"); + B.add("foobar"); + + B.finalize(); + + std::string Expected; + Expected += '\x00'; + Expected += "foobar"; + Expected += '\x00'; + Expected += "foo"; + Expected += '\x00'; + + EXPECT_EQ(Expected, B.data()); + EXPECT_EQ(1U, B.getOffset("foobar")); + EXPECT_EQ(4U, B.getOffset("bar")); + EXPECT_EQ(8U, B.getOffset("foo")); +} + +} diff --git a/unittests/Option/OptionParsingTest.cpp b/unittests/Option/OptionParsingTest.cpp index 6beb286..aa32da3 100644 --- a/unittests/Option/OptionParsingTest.cpp +++ b/unittests/Option/OptionParsingTest.cpp @@ -68,7 +68,7 @@ TEST(Option, OptionParsing) { TestOptTable T; unsigned MAI, MAC; std::unique_ptr<InputArgList> AL( - T.ParseArgs(Args, array_endof(Args), MAI, MAC)); + T.ParseArgs(std::begin(Args), std::end(Args), MAI, MAC)); // Check they all exist. EXPECT_TRUE(AL->hasArg(OPT_A)); @@ -114,7 +114,7 @@ TEST(Option, ParseWithFlagExclusions) { std::unique_ptr<InputArgList> AL; // Exclude flag3 to avoid parsing as OPT_SLASH_C. - AL.reset(T.ParseArgs(Args, array_endof(Args), MAI, MAC, + AL.reset(T.ParseArgs(std::begin(Args), std::end(Args), MAI, MAC, /*FlagsToInclude=*/0, /*FlagsToExclude=*/OptFlag3)); EXPECT_TRUE(AL->hasArg(OPT_A)); @@ -122,7 +122,7 @@ TEST(Option, ParseWithFlagExclusions) { EXPECT_FALSE(AL->hasArg(OPT_SLASH_C)); // Exclude flag1 to avoid parsing as OPT_C. - AL.reset(T.ParseArgs(Args, array_endof(Args), MAI, MAC, + AL.reset(T.ParseArgs(std::begin(Args), std::end(Args), MAI, MAC, /*FlagsToInclude=*/0, /*FlagsToExclude=*/OptFlag1)); EXPECT_TRUE(AL->hasArg(OPT_B)); @@ -130,7 +130,7 @@ TEST(Option, ParseWithFlagExclusions) { EXPECT_TRUE(AL->hasArg(OPT_SLASH_C)); const char *NewArgs[] = { "/C", "foo", "--C=bar" }; - AL.reset(T.ParseArgs(NewArgs, array_endof(NewArgs), MAI, MAC)); + AL.reset(T.ParseArgs(std::begin(NewArgs), std::end(NewArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_SLASH_C)); EXPECT_TRUE(AL->hasArg(OPT_C)); EXPECT_EQ(AL->getLastArgValue(OPT_SLASH_C), "foo"); @@ -143,7 +143,7 @@ TEST(Option, ParseAliasInGroup) { const char *MyArgs[] = { "-I" }; std::unique_ptr<InputArgList> AL( - T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_H)); } @@ -153,7 +153,7 @@ TEST(Option, AliasArgs) { const char *MyArgs[] = { "-J", "-Joo" }; std::unique_ptr<InputArgList> AL( - T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_B)); EXPECT_EQ(AL->getAllArgValues(OPT_B)[0], "foo"); EXPECT_EQ(AL->getAllArgValues(OPT_B)[1], "bar"); @@ -165,7 +165,7 @@ TEST(Option, IgnoreCase) { const char *MyArgs[] = { "-a", "-joo" }; std::unique_ptr<InputArgList> AL( - T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_A)); EXPECT_TRUE(AL->hasArg(OPT_B)); } @@ -176,7 +176,7 @@ TEST(Option, DoNotIgnoreCase) { const char *MyArgs[] = { "-a", "-joo" }; std::unique_ptr<InputArgList> AL( - T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC)); EXPECT_FALSE(AL->hasArg(OPT_A)); EXPECT_FALSE(AL->hasArg(OPT_B)); } @@ -187,7 +187,7 @@ TEST(Option, SlurpEmpty) { const char *MyArgs[] = { "-A", "-slurp" }; std::unique_ptr<InputArgList> AL( - T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC)); EXPECT_TRUE(AL->hasArg(OPT_A)); EXPECT_TRUE(AL->hasArg(OPT_Slurp)); EXPECT_EQ(AL->getAllArgValues(OPT_Slurp).size(), 0U); @@ -199,7 +199,7 @@ TEST(Option, Slurp) { const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" }; std::unique_ptr<InputArgList> AL( - T.ParseArgs(MyArgs, array_endof(MyArgs), MAI, MAC)); + T.ParseArgs(std::begin(MyArgs), std::end(MyArgs), MAI, MAC)); EXPECT_EQ(AL->size(), 2U); EXPECT_TRUE(AL->hasArg(OPT_A)); EXPECT_FALSE(AL->hasArg(OPT_B)); diff --git a/unittests/Support/AllocatorTest.cpp b/unittests/Support/AllocatorTest.cpp index bcf6bf1..0fc84c7 100644 --- a/unittests/Support/AllocatorTest.cpp +++ b/unittests/Support/AllocatorTest.cpp @@ -29,6 +29,21 @@ TEST(AllocatorTest, Basics) { EXPECT_EQ(2, b[9]); EXPECT_EQ(3, *c); EXPECT_EQ(1U, Alloc.GetNumSlabs()); + + BumpPtrAllocator Alloc2 = std::move(Alloc); + EXPECT_EQ(0U, Alloc.GetNumSlabs()); + EXPECT_EQ(1U, Alloc2.GetNumSlabs()); + + // Make sure the old pointers still work. These are especially interesting + // under ASan or Valgrind. + EXPECT_EQ(1, *a); + EXPECT_EQ(2, b[0]); + EXPECT_EQ(2, b[9]); + EXPECT_EQ(3, *c); + + Alloc = std::move(Alloc2); + EXPECT_EQ(0U, Alloc2.GetNumSlabs()); + EXPECT_EQ(1U, Alloc.GetNumSlabs()); } // Allocate enough bytes to create three slabs. @@ -84,7 +99,7 @@ TEST(AllocatorTest, TestOverflow) { BumpPtrAllocator Alloc; // Fill the slab right up until the end pointer. - Alloc.Allocate(4096 - sizeof(MemSlab), 0); + Alloc.Allocate(4096, 0); EXPECT_EQ(1U, Alloc.GetNumSlabs()); // If we don't allocate a new slab, then we will have overflowed. @@ -102,49 +117,52 @@ TEST(AllocatorTest, TestSmallSlabSize) { // Mock slab allocator that returns slabs aligned on 4096 bytes. There is no // easy portable way to do this, so this is kind of a hack. -class MockSlabAllocator : public SlabAllocator { - MemSlab *LastSlab; +class MockSlabAllocator { + static size_t LastSlabSize; public: - virtual ~MockSlabAllocator() { } + ~MockSlabAllocator() { } - virtual MemSlab *Allocate(size_t Size) { + void *Allocate(size_t Size, size_t /*Alignment*/) { // Allocate space for the alignment, the slab, and a void* that goes right // before the slab. size_t Alignment = 4096; void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*)); - // Make the slab. - MemSlab *Slab = (MemSlab*)(((uintptr_t)MemBase+sizeof(void*)+Alignment-1) & - ~(uintptr_t)(Alignment - 1)); - Slab->Size = Size; - Slab->NextPtr = 0; + // Find the slab start. + void *Slab = alignPtr((char *)MemBase + sizeof(void *), Alignment); // Hold a pointer to the base so we can free the whole malloced block. ((void**)Slab)[-1] = MemBase; - LastSlab = Slab; + LastSlabSize = Size; return Slab; } - virtual void Deallocate(MemSlab *Slab) { + void Deallocate(void *Slab, size_t Size) { free(((void**)Slab)[-1]); } - MemSlab *GetLastSlab() { - return LastSlab; - } + static size_t GetLastSlabSize() { return LastSlabSize; } }; +size_t MockSlabAllocator::LastSlabSize = 0; + // Allocate a large-ish block with a really large alignment so that the // allocator will think that it has space, but after it does the alignment it // will not. TEST(AllocatorTest, TestBigAlignment) { - MockSlabAllocator SlabAlloc; - BumpPtrAllocator Alloc(SlabAlloc); - uintptr_t Ptr = (uintptr_t)Alloc.Allocate(3000, 2048); - MemSlab *Slab = SlabAlloc.GetLastSlab(); - EXPECT_LE(Ptr + 3000, ((uintptr_t)Slab) + Slab->Size); + BumpPtrAllocatorImpl<MockSlabAllocator> Alloc; + + // First allocate a tiny bit to ensure we have to re-align things. + (void)Alloc.Allocate(1, 0); + + // Now the big chunk with a big alignment. + (void)Alloc.Allocate(3000, 2048); + + // We test that the last slab size is not the default 4096 byte slab, but + // rather a custom sized slab that is larger. + EXPECT_GT(MockSlabAllocator::GetLastSlabSize(), 4096u); } } // anonymous namespace diff --git a/unittests/Support/BlockFrequencyTest.cpp b/unittests/Support/BlockFrequencyTest.cpp index c318451..f6e3537 100644 --- a/unittests/Support/BlockFrequencyTest.cpp +++ b/unittests/Support/BlockFrequencyTest.cpp @@ -15,9 +15,8 @@ TEST(BlockFrequencyTest, OneToZero) { EXPECT_EQ(Freq.getFrequency(), 0u); Freq = BlockFrequency(1); - uint32_t Remainder = Freq.scale(Prob); + Freq *= Prob; EXPECT_EQ(Freq.getFrequency(), 0u); - EXPECT_EQ(Remainder, UINT32_MAX - 1); } TEST(BlockFrequencyTest, OneToOne) { @@ -27,9 +26,8 @@ TEST(BlockFrequencyTest, OneToOne) { EXPECT_EQ(Freq.getFrequency(), 1u); Freq = BlockFrequency(1); - uint32_t Remainder = Freq.scale(Prob); + Freq *= Prob; EXPECT_EQ(Freq.getFrequency(), 1u); - EXPECT_EQ(Remainder, 0u); } TEST(BlockFrequencyTest, ThreeToOne) { @@ -39,9 +37,8 @@ TEST(BlockFrequencyTest, ThreeToOne) { EXPECT_EQ(Freq.getFrequency(), 1u); Freq = BlockFrequency(3); - uint32_t Remainder = Freq.scale(Prob); + Freq *= Prob; EXPECT_EQ(Freq.getFrequency(), 1u); - EXPECT_EQ(Remainder, 0u); } TEST(BlockFrequencyTest, MaxToHalfMax) { @@ -51,9 +48,8 @@ TEST(BlockFrequencyTest, MaxToHalfMax) { EXPECT_EQ(Freq.getFrequency(), 9223372034707292159ULL); Freq = BlockFrequency(UINT64_MAX); - uint32_t Remainder = Freq.scale(Prob); + Freq *= Prob; EXPECT_EQ(Freq.getFrequency(), 9223372034707292159ULL); - EXPECT_EQ(Remainder, 0u); } TEST(BlockFrequencyTest, BigToBig) { @@ -65,9 +61,8 @@ TEST(BlockFrequencyTest, BigToBig) { EXPECT_EQ(Freq.getFrequency(), Big); Freq = BlockFrequency(Big); - uint32_t Remainder = Freq.scale(Prob); + Freq *= Prob; EXPECT_EQ(Freq.getFrequency(), Big); - EXPECT_EQ(Remainder, 0u); } TEST(BlockFrequencyTest, MaxToMax) { @@ -80,109 +75,8 @@ TEST(BlockFrequencyTest, MaxToMax) { // value, we do not signal saturation if the result equals said value, but // saturating does not occur. Freq = BlockFrequency(UINT64_MAX); - uint32_t Remainder = Freq.scale(Prob); + Freq *= Prob; EXPECT_EQ(Freq.getFrequency(), UINT64_MAX); - EXPECT_EQ(Remainder, 0u); -} - -TEST(BlockFrequencyTest, ScaleResultRemainderTest) { - struct { - uint64_t Freq; - uint32_t Prob[2]; - uint64_t ExpectedFreq; - uint32_t ExpectedRemainder; - } Tests[80] = { - // Data for scaling that results in <= 64 bit division. - { 0x1423e2a50ULL, { 0x64819521, 0x7765dd13 }, 0x10f418889ULL, 0x92b9d25 }, - { 0x35ef14ceULL, { 0x28ade3c7, 0x304532ae }, 0x2d73c33aULL, 0x2c0fd0b6 }, - { 0xd03dbfbe24ULL, { 0x790079, 0xe419f3 }, 0x6e776fc1fdULL, 0x4a06dd }, - { 0x21d67410bULL, { 0x302a9dc2, 0x3ddb4442 }, 0x1a5948fd6ULL, 0x265d1c2a }, - { 0x8664aeadULL, { 0x3d523513, 0x403523b1 }, 0x805a04cfULL, 0x324c27b8 }, - { 0x201db0cf4ULL, { 0x35112a7b, 0x79fc0c74 }, 0xdf8b07f6ULL, 0x490c1dc4 }, - { 0x13f1e4430aULL, { 0x21c92bf, 0x21e63aae }, 0x13e0cba15ULL, 0x1df47c30 }, - { 0x16c83229ULL, { 0x3793f66f, 0x53180dea }, 0xf3ce7b6ULL, 0x1d0c1b6b }, - { 0xc62415be8ULL, { 0x9cc4a63, 0x4327ae9b }, 0x1ce8b71caULL, 0x3f2c696a }, - { 0x6fac5e434ULL, { 0xe5f9170, 0x1115e10b }, 0x5df23dd4cULL, 0x4dafc7c }, - { 0x1929375f2ULL, { 0x3a851375, 0x76c08456 }, 0xc662b082ULL, 0x343589ee }, - { 0x243c89db6ULL, { 0x354ebfc0, 0x450ef197 }, 0x1bf8c1661ULL, 0x4948e49 }, - { 0x310e9b31aULL, { 0x1b1b8acf, 0x2d3629f0 }, 0x1d69c93f9ULL, 0x73e3b96 }, - { 0xa1fae921dULL, { 0xa7a098c, 0x10469f44 }, 0x684413d6cULL, 0x86a882c }, - { 0xc1582d957ULL, { 0x498e061, 0x59856bc }, 0x9edc5f4e7ULL, 0x29b0653 }, - { 0x57cfee75ULL, { 0x1d061dc3, 0x7c8bfc17 }, 0x1476a220ULL, 0x2383d33f }, - { 0x139220080ULL, { 0x294a6c71, 0x2a2b07c9 }, 0x1329e1c76ULL, 0x7aa5da }, - { 0x1665d353cULL, { 0x7080db5, 0xde0d75c }, 0xb590d9fbULL, 0x7ba8c38 }, - { 0xe8f14541ULL, { 0x5188e8b2, 0x736527ef }, 0xa4971be5ULL, 0x6b612167 }, - { 0x2f4775f29ULL, { 0x254ef0fe, 0x435fcf50 }, 0x1a2e449c1ULL, 0x28bbf5e }, - { 0x27b85d8d7ULL, { 0x304c8220, 0x5de678f2 }, 0x146e3bef9ULL, 0x4b27097e }, - { 0x1d362e36bULL, { 0x36c85b12, 0x37a66f55 }, 0x1cc19b8e6ULL, 0x688e828 }, - { 0x155fd48c7ULL, { 0xf5894d, 0x1256108 }, 0x11e383602ULL, 0x111f0cb }, - { 0xb5db2d15ULL, { 0x39bb26c5, 0x5bdcda3e }, 0x72499259ULL, 0x59c4939b }, - { 0x153990298ULL, { 0x48921c09, 0x706eb817 }, 0xdb3268e8ULL, 0x66bb8a80 }, - { 0x28a7c3ed7ULL, { 0x1f776fd7, 0x349f7a70 }, 0x184f73ae1ULL, 0x28910321 }, - { 0x724dbeabULL, { 0x1bd149f5, 0x253a085e }, 0x5569c0b3ULL, 0xff8e2ed }, - { 0xd8f0c513ULL, { 0x18c8cc4c, 0x1b72bad0 }, 0xc3e30643ULL, 0xd85e134 }, - { 0x17ce3dcbULL, { 0x1e4c6260, 0x233b359e }, 0x1478f4afULL, 0x49ea31e }, - { 0x1ce036ce0ULL, { 0x29e3c8af, 0x5318dd4a }, 0xe8e76196ULL, 0x11d5b9c4 }, - { 0x1473ae2aULL, { 0x29b897ba, 0x2be29378 }, 0x13718185ULL, 0x6f93b2c }, - { 0x1dd41aa68ULL, { 0x3d0a4441, 0x5a0e8f12 }, 0x1437b6bbfULL, 0x54b09ffa }, - { 0x1b49e4a53ULL, { 0x3430c1fe, 0x5a204aed }, 0xfcd6852fULL, 0x15ad6ed7 }, - { 0x217941b19ULL, { 0x12ced2bd, 0x21b68310 }, 0x12aca65b1ULL, 0x1b2a9565 }, - { 0xac6a4dc8ULL, { 0x3ed68da8, 0x6fdca34c }, 0x60da926dULL, 0x22ff53e4 }, - { 0x1c503a4e7ULL, { 0xfcbbd32, 0x11e48d17 }, 0x18fec7d38ULL, 0xa8aa816 }, - { 0x1c885855ULL, { 0x213e919d, 0x25941897 }, 0x193de743ULL, 0x4ea09c }, - { 0x29b9c168eULL, { 0x2b644aea, 0x45725ee7 }, 0x1a122e5d5ULL, 0xbee1099 }, - { 0x806a33f2ULL, { 0x30a80a23, 0x5063733a }, 0x4db9a264ULL, 0x1eaed76e }, - { 0x282afc96bULL, { 0x143ae554, 0x1a9863ff }, 0x1e8de5204ULL, 0x158d9020 }, - // Data for scaling that results in > 64 bit division. - { 0x23ca5f2f672ca41cULL, { 0xecbc641, 0x111373f7 }, 0x1f0301e5e8295ab5ULL, 0xf627f79 }, - { 0x5e4f2468142265e3ULL, { 0x1ddf5837, 0x32189233 }, 0x383ca7ba9fdd2c8cULL, 0x1c8f33e1 }, - { 0x277a1a6f6b266bf6ULL, { 0x415d81a8, 0x61eb5e1e }, 0x1a5a3e1d41b30c0fULL, 0x29cde3ae }, - { 0x1bdbb49a237035cbULL, { 0xea5bf17, 0x1d25ffb3 }, 0xdffc51c53d44b93ULL, 0x5170574 }, - { 0x2bce6d29b64fb8ULL, { 0x3bfd5631, 0x7525c9bb }, 0x166ebedda7ac57ULL, 0x3026dfab }, - { 0x3a02116103df5013ULL, { 0x2ee18a83, 0x3299aea8 }, 0x35be8922ab1e2a84ULL, 0x298d9919 }, - { 0x7b5762390799b18cULL, { 0x12f8e5b9, 0x2563bcd4 }, 0x3e960077aca01209ULL, 0x93afeb8 }, - { 0x69cfd72537021579ULL, { 0x4c35f468, 0x6a40feee }, 0x4be4cb3848be98a3ULL, 0x4ff96b9e }, - { 0x49dfdf835120f1c1ULL, { 0x8cb3759, 0x559eb891 }, 0x79663f7120edadeULL, 0x51b1fb5b }, - { 0x74b5be5c27676381ULL, { 0x47e4c5e0, 0x7c7b19ff }, 0x4367d2dff36a1028ULL, 0x7a7b5608 }, - { 0x4f50f97075e7f431ULL, { 0x9a50a17, 0x11cd1185 }, 0x2af952b34c032df4ULL, 0xfddc6a3 }, - { 0x2f8b0d712e393be4ULL, { 0x1487e386, 0x15aa356e }, 0x2d0df36478a776aaULL, 0x14e2564c }, - { 0x224c1c75999d3deULL, { 0x3b2df0ea, 0x4523b100 }, 0x1d5b481d145f08aULL, 0x15145eec }, - { 0x2bcbcea22a399a76ULL, { 0x28b58212, 0x48dd013e }, 0x187814d084c47cabULL, 0x3a38ebe2 }, - { 0x1dbfca91257cb2d1ULL, { 0x1a8c04d9, 0x5e92502c }, 0x859cf7d00f77545ULL, 0x7431f4d }, - { 0x7f20039b57cda935ULL, { 0xeccf651, 0x323f476e }, 0x25720cd976461a77ULL, 0x202817a3 }, - { 0x40512c6a586aa087ULL, { 0x113b0423, 0x398c9eab }, 0x1341c03de8696a7eULL, 0x1e27284b }, - { 0x63d802693f050a11ULL, { 0xf50cdd6, 0xfce2a44 }, 0x60c0177bb5e46846ULL, 0xf7ad89e }, - { 0x2d956b422838de77ULL, { 0xb2d345b, 0x1321e557 }, 0x1aa0ed16b6aa5319ULL, 0xfe1a5ce }, - { 0x5a1cdf0c1657bc91ULL, { 0x1d77bb0c, 0x1f991ff1 }, 0x54097ee94ff87560ULL, 0x11c4a26c }, - { 0x3801b26d7e00176bULL, { 0xeed25da, 0x1a819d8b }, 0x1f89e96a3a639526ULL, 0xcd51e7c }, - { 0x37655e74338e1e45ULL, { 0x300e170a, 0x5a1595fe }, 0x1d8cfb55fddc0441ULL, 0x3df05434 }, - { 0x7b38703f2a84e6ULL, { 0x66d9053, 0xc79b6b9 }, 0x3f7d4c91774094ULL, 0x26d939e }, - { 0x2245063c0acb3215ULL, { 0x30ce2f5b, 0x610e7271 }, 0x113b916468389235ULL, 0x1b588512 }, - { 0x6bc195877b7b8a7eULL, { 0x392004aa, 0x4a24e60c }, 0x530594fb17db6ba5ULL, 0x35c0a5f0 }, - { 0x40a3fde23c7b43dbULL, { 0x4e712195, 0x6553e56e }, 0x320a799bc76a466aULL, 0x5e23a5eb }, - { 0x1d3dfc2866fbccbaULL, { 0x5075b517, 0x5fc42245 }, 0x18917f0061595bc3ULL, 0x3fcf4527 }, - { 0x19aeb14045a61121ULL, { 0x1bf6edec, 0x707e2f4b }, 0x6626672a070bcc7ULL, 0x3607801f }, - { 0x44ff90486c531e9fULL, { 0x66598a, 0x8a90dc }, 0x32f6f2b0525199b0ULL, 0x5ab576 }, - { 0x3f3e7121092c5bcbULL, { 0x1c754df7, 0x5951a1b9 }, 0x14267f50b7ef375dULL, 0x221220a8 }, - { 0x60e2dafb7e50a67eULL, { 0x4d96c66e, 0x65bd878d }, 0x49e31715ac393f8bULL, 0x4e97b195 }, - { 0x656286667e0e6e29ULL, { 0x9d971a2, 0xacda23b }, 0x5c6ee315ead6cb4fULL, 0x516f5bd }, - { 0x1114e0974255d507ULL, { 0x1c693, 0x2d6ff }, 0xaae42e4b35f6e60ULL, 0x8b65 }, - { 0x508c8baf3a70ff5aULL, { 0x3b26b779, 0x6ad78745 }, 0x2c98387636c4b365ULL, 0x11dc6a51 }, - { 0x5b47bc666bf1f9cfULL, { 0x10a87ed6, 0x187d358a }, 0x3e1767155848368bULL, 0xfb871c }, - { 0x50954e3744460395ULL, { 0x7a42263, 0xcdaa048 }, 0x2fe739f0aee1fee1ULL, 0xb8add57 }, - { 0x20020b406550dd8fULL, { 0x3318539, 0x42eead0 }, 0x186f326325fa346bULL, 0x10d3ae7 }, - { 0x5bcb0b872439ffd5ULL, { 0x6f61fb2, 0x9af7344 }, 0x41fa1e3bec3c1b30ULL, 0x4fee45a }, - { 0x7a670f365db87a53ULL, { 0x417e102, 0x3bb54c67 }, 0x8642a558304fd9eULL, 0x3b65f514 }, - { 0x1ef0db1e7bab1cd0ULL, { 0x2b60cf38, 0x4188f78f }, 0x147ae0d6226b2ee6ULL, 0x336b6106 } - }; - - for (unsigned i = 0; i < 80; i++) { - BlockFrequency Freq(Tests[i].Freq); - uint32_t Remainder = Freq.scale(BranchProbability(Tests[i].Prob[0], - Tests[i].Prob[1])); - EXPECT_EQ(Tests[i].ExpectedFreq, Freq.getFrequency()); - EXPECT_EQ(Tests[i].ExpectedRemainder, Remainder); - } } TEST(BlockFrequency, Divide) { @@ -208,35 +102,6 @@ TEST(BlockFrequencyTest, Saturate) { EXPECT_EQ(33506781356485509ULL, Freq.getFrequency()); } -TEST(BlockFrequencyTest, ProbabilityCompare) { - BranchProbability A(4, 5); - BranchProbability B(4U << 29, 5U << 29); - BranchProbability C(3, 4); - - EXPECT_TRUE(A == B); - EXPECT_FALSE(A != B); - EXPECT_FALSE(A < B); - EXPECT_FALSE(A > B); - EXPECT_TRUE(A <= B); - EXPECT_TRUE(A >= B); - - EXPECT_FALSE(B == C); - EXPECT_TRUE(B != C); - EXPECT_FALSE(B < C); - EXPECT_TRUE(B > C); - EXPECT_FALSE(B <= C); - EXPECT_TRUE(B >= C); - - BranchProbability BigZero(0, UINT32_MAX); - BranchProbability BigOne(UINT32_MAX, UINT32_MAX); - EXPECT_FALSE(BigZero == BigOne); - EXPECT_TRUE(BigZero != BigOne); - EXPECT_TRUE(BigZero < BigOne); - EXPECT_FALSE(BigZero > BigOne); - EXPECT_TRUE(BigZero <= BigOne); - EXPECT_FALSE(BigZero >= BigOne); -} - TEST(BlockFrequencyTest, SaturatingRightShift) { BlockFrequency Freq(0x10080ULL); Freq >>= 2; diff --git a/unittests/Support/BranchProbabilityTest.cpp b/unittests/Support/BranchProbabilityTest.cpp new file mode 100644 index 0000000..bbd4d4e --- /dev/null +++ b/unittests/Support/BranchProbabilityTest.cpp @@ -0,0 +1,282 @@ +//===- unittest/Support/BranchProbabilityTest.cpp - BranchProbability tests -=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/BranchProbability.h" +#include "llvm/Support/raw_ostream.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace llvm { +void PrintTo(const BranchProbability &P, ::std::ostream *os) { + *os << P.getNumerator() << "/" << P.getDenominator(); +} +} +namespace { + +typedef BranchProbability BP; +TEST(BranchProbabilityTest, Accessors) { + EXPECT_EQ(1u, BP(1, 7).getNumerator()); + EXPECT_EQ(7u, BP(1, 7).getDenominator()); + EXPECT_EQ(0u, BP::getZero().getNumerator()); + EXPECT_EQ(1u, BP::getZero().getDenominator()); + EXPECT_EQ(1u, BP::getOne().getNumerator()); + EXPECT_EQ(1u, BP::getOne().getDenominator()); +} + +TEST(BranchProbabilityTest, Operators) { + EXPECT_TRUE(BP(1, 7) < BP(2, 7)); + EXPECT_TRUE(BP(1, 7) < BP(1, 4)); + EXPECT_TRUE(BP(5, 7) < BP(3, 4)); + EXPECT_FALSE(BP(1, 7) < BP(1, 7)); + EXPECT_FALSE(BP(1, 7) < BP(2, 14)); + EXPECT_FALSE(BP(4, 7) < BP(1, 2)); + EXPECT_FALSE(BP(4, 7) < BP(3, 7)); + + EXPECT_FALSE(BP(1, 7) > BP(2, 7)); + EXPECT_FALSE(BP(1, 7) > BP(1, 4)); + EXPECT_FALSE(BP(5, 7) > BP(3, 4)); + EXPECT_FALSE(BP(1, 7) > BP(1, 7)); + EXPECT_FALSE(BP(1, 7) > BP(2, 14)); + EXPECT_TRUE(BP(4, 7) > BP(1, 2)); + EXPECT_TRUE(BP(4, 7) > BP(3, 7)); + + EXPECT_TRUE(BP(1, 7) <= BP(2, 7)); + EXPECT_TRUE(BP(1, 7) <= BP(1, 4)); + EXPECT_TRUE(BP(5, 7) <= BP(3, 4)); + EXPECT_TRUE(BP(1, 7) <= BP(1, 7)); + EXPECT_TRUE(BP(1, 7) <= BP(2, 14)); + EXPECT_FALSE(BP(4, 7) <= BP(1, 2)); + EXPECT_FALSE(BP(4, 7) <= BP(3, 7)); + + EXPECT_FALSE(BP(1, 7) >= BP(2, 7)); + EXPECT_FALSE(BP(1, 7) >= BP(1, 4)); + EXPECT_FALSE(BP(5, 7) >= BP(3, 4)); + EXPECT_TRUE(BP(1, 7) >= BP(1, 7)); + EXPECT_TRUE(BP(1, 7) >= BP(2, 14)); + EXPECT_TRUE(BP(4, 7) >= BP(1, 2)); + EXPECT_TRUE(BP(4, 7) >= BP(3, 7)); + + EXPECT_FALSE(BP(1, 7) == BP(2, 7)); + EXPECT_FALSE(BP(1, 7) == BP(1, 4)); + EXPECT_FALSE(BP(5, 7) == BP(3, 4)); + EXPECT_TRUE(BP(1, 7) == BP(1, 7)); + EXPECT_TRUE(BP(1, 7) == BP(2, 14)); + EXPECT_FALSE(BP(4, 7) == BP(1, 2)); + EXPECT_FALSE(BP(4, 7) == BP(3, 7)); + + EXPECT_TRUE(BP(1, 7) != BP(2, 7)); + EXPECT_TRUE(BP(1, 7) != BP(1, 4)); + EXPECT_TRUE(BP(5, 7) != BP(3, 4)); + EXPECT_FALSE(BP(1, 7) != BP(1, 7)); + EXPECT_FALSE(BP(1, 7) != BP(2, 14)); + EXPECT_TRUE(BP(4, 7) != BP(1, 2)); + EXPECT_TRUE(BP(4, 7) != BP(3, 7)); +} + +TEST(BranchProbabilityTest, MoreOperators) { + BP A(4, 5); + BP B(4U << 29, 5U << 29); + BP C(3, 4); + + EXPECT_TRUE(A == B); + EXPECT_FALSE(A != B); + EXPECT_FALSE(A < B); + EXPECT_FALSE(A > B); + EXPECT_TRUE(A <= B); + EXPECT_TRUE(A >= B); + + EXPECT_FALSE(B == C); + EXPECT_TRUE(B != C); + EXPECT_FALSE(B < C); + EXPECT_TRUE(B > C); + EXPECT_FALSE(B <= C); + EXPECT_TRUE(B >= C); + + BP BigZero(0, UINT32_MAX); + BP BigOne(UINT32_MAX, UINT32_MAX); + EXPECT_FALSE(BigZero == BigOne); + EXPECT_TRUE(BigZero != BigOne); + EXPECT_TRUE(BigZero < BigOne); + EXPECT_FALSE(BigZero > BigOne); + EXPECT_TRUE(BigZero <= BigOne); + EXPECT_FALSE(BigZero >= BigOne); +} + +TEST(BranchProbabilityTest, getCompl) { + EXPECT_EQ(BP(5, 7), BP(2, 7).getCompl()); + EXPECT_EQ(BP(2, 7), BP(5, 7).getCompl()); + EXPECT_EQ(BP::getZero(), BP(7, 7).getCompl()); + EXPECT_EQ(BP::getOne(), BP(0, 7).getCompl()); +} + +TEST(BranchProbabilityTest, scale) { + // Multiply by 1.0. + EXPECT_EQ(UINT64_MAX, BP(1, 1).scale(UINT64_MAX)); + EXPECT_EQ(UINT64_MAX, BP(7, 7).scale(UINT64_MAX)); + EXPECT_EQ(UINT32_MAX, BP(1, 1).scale(UINT32_MAX)); + EXPECT_EQ(UINT32_MAX, BP(7, 7).scale(UINT32_MAX)); + EXPECT_EQ(0u, BP(1, 1).scale(0)); + EXPECT_EQ(0u, BP(7, 7).scale(0)); + + // Multiply by 0.0. + EXPECT_EQ(0u, BP(0, 1).scale(UINT64_MAX)); + EXPECT_EQ(0u, BP(0, 1).scale(UINT64_MAX)); + EXPECT_EQ(0u, BP(0, 1).scale(0)); + + auto Two63 = UINT64_C(1) << 63; + auto Two31 = UINT64_C(1) << 31; + + // Multiply by 0.5. + EXPECT_EQ(Two63 - 1, BP(1, 2).scale(UINT64_MAX)); + + // Big fractions. + EXPECT_EQ(1u, BP(Two31, UINT32_MAX).scale(2)); + EXPECT_EQ(Two31, BP(Two31, UINT32_MAX).scale(Two31 * 2)); + EXPECT_EQ(Two63 + Two31, BP(Two31, UINT32_MAX).scale(UINT64_MAX)); + + // High precision. + EXPECT_EQ(UINT64_C(9223372047592194055), + BP(Two31 + 1, UINT32_MAX - 2).scale(UINT64_MAX)); +} + +TEST(BranchProbabilityTest, scaleByInverse) { + // Divide by 1.0. + EXPECT_EQ(UINT64_MAX, BP(1, 1).scaleByInverse(UINT64_MAX)); + EXPECT_EQ(UINT64_MAX, BP(7, 7).scaleByInverse(UINT64_MAX)); + EXPECT_EQ(UINT32_MAX, BP(1, 1).scaleByInverse(UINT32_MAX)); + EXPECT_EQ(UINT32_MAX, BP(7, 7).scaleByInverse(UINT32_MAX)); + EXPECT_EQ(0u, BP(1, 1).scaleByInverse(0)); + EXPECT_EQ(0u, BP(7, 7).scaleByInverse(0)); + + // Divide by something very small. + EXPECT_EQ(UINT64_MAX, BP(1, UINT32_MAX).scaleByInverse(UINT64_MAX)); + EXPECT_EQ(uint64_t(UINT32_MAX) * UINT32_MAX, + BP(1, UINT32_MAX).scaleByInverse(UINT32_MAX)); + EXPECT_EQ(UINT32_MAX, BP(1, UINT32_MAX).scaleByInverse(1)); + + auto Two63 = UINT64_C(1) << 63; + auto Two31 = UINT64_C(1) << 31; + + // Divide by 0.5. + EXPECT_EQ(UINT64_MAX - 1, BP(1, 2).scaleByInverse(Two63 - 1)); + EXPECT_EQ(UINT64_MAX, BP(1, 2).scaleByInverse(Two63)); + + // Big fractions. + EXPECT_EQ(1u, BP(Two31, UINT32_MAX).scaleByInverse(1)); + EXPECT_EQ(2u, BP(Two31 - 1, UINT32_MAX).scaleByInverse(1)); + EXPECT_EQ(Two31 * 2 - 1, BP(Two31, UINT32_MAX).scaleByInverse(Two31)); + EXPECT_EQ(Two31 * 2 + 1, BP(Two31 - 1, UINT32_MAX).scaleByInverse(Two31)); + EXPECT_EQ(UINT64_MAX, BP(Two31, UINT32_MAX).scaleByInverse(Two63 + Two31)); + + // High precision. The exact answers to these are close to the successors of + // the floor. If we were rounding, these would round up. + EXPECT_EQ(UINT64_C(18446744065119617030), + BP(Two31 + 2, UINT32_MAX - 2) + .scaleByInverse(UINT64_C(9223372047592194055))); + EXPECT_EQ(UINT64_C(18446744065119617026), + BP(Two31 + 1, UINT32_MAX).scaleByInverse(Two63 + Two31)); +} + +TEST(BranchProbabilityTest, scaleBruteForce) { + struct { + uint64_t Num; + uint32_t Prob[2]; + uint64_t Result; + } Tests[] = { + // Data for scaling that results in <= 64 bit division. + { 0x1423e2a50ULL, { 0x64819521, 0x7765dd13 }, 0x10f418889ULL }, + { 0x35ef14ceULL, { 0x28ade3c7, 0x304532ae }, 0x2d73c33aULL }, + { 0xd03dbfbe24ULL, { 0x790079, 0xe419f3 }, 0x6e776fc1fdULL }, + { 0x21d67410bULL, { 0x302a9dc2, 0x3ddb4442 }, 0x1a5948fd6ULL }, + { 0x8664aeadULL, { 0x3d523513, 0x403523b1 }, 0x805a04cfULL }, + { 0x201db0cf4ULL, { 0x35112a7b, 0x79fc0c74 }, 0xdf8b07f6ULL }, + { 0x13f1e4430aULL, { 0x21c92bf, 0x21e63aae }, 0x13e0cba15ULL }, + { 0x16c83229ULL, { 0x3793f66f, 0x53180dea }, 0xf3ce7b6ULL }, + { 0xc62415be8ULL, { 0x9cc4a63, 0x4327ae9b }, 0x1ce8b71caULL }, + { 0x6fac5e434ULL, { 0xe5f9170, 0x1115e10b }, 0x5df23dd4cULL }, + { 0x1929375f2ULL, { 0x3a851375, 0x76c08456 }, 0xc662b082ULL }, + { 0x243c89db6ULL, { 0x354ebfc0, 0x450ef197 }, 0x1bf8c1661ULL }, + { 0x310e9b31aULL, { 0x1b1b8acf, 0x2d3629f0 }, 0x1d69c93f9ULL }, + { 0xa1fae921dULL, { 0xa7a098c, 0x10469f44 }, 0x684413d6cULL }, + { 0xc1582d957ULL, { 0x498e061, 0x59856bc }, 0x9edc5f4e7ULL }, + { 0x57cfee75ULL, { 0x1d061dc3, 0x7c8bfc17 }, 0x1476a220ULL }, + { 0x139220080ULL, { 0x294a6c71, 0x2a2b07c9 }, 0x1329e1c76ULL }, + { 0x1665d353cULL, { 0x7080db5, 0xde0d75c }, 0xb590d9fbULL }, + { 0xe8f14541ULL, { 0x5188e8b2, 0x736527ef }, 0xa4971be5ULL }, + { 0x2f4775f29ULL, { 0x254ef0fe, 0x435fcf50 }, 0x1a2e449c1ULL }, + { 0x27b85d8d7ULL, { 0x304c8220, 0x5de678f2 }, 0x146e3bef9ULL }, + { 0x1d362e36bULL, { 0x36c85b12, 0x37a66f55 }, 0x1cc19b8e6ULL }, + { 0x155fd48c7ULL, { 0xf5894d, 0x1256108 }, 0x11e383602ULL }, + { 0xb5db2d15ULL, { 0x39bb26c5, 0x5bdcda3e }, 0x72499259ULL }, + { 0x153990298ULL, { 0x48921c09, 0x706eb817 }, 0xdb3268e8ULL }, + { 0x28a7c3ed7ULL, { 0x1f776fd7, 0x349f7a70 }, 0x184f73ae1ULL }, + { 0x724dbeabULL, { 0x1bd149f5, 0x253a085e }, 0x5569c0b3ULL }, + { 0xd8f0c513ULL, { 0x18c8cc4c, 0x1b72bad0 }, 0xc3e30643ULL }, + { 0x17ce3dcbULL, { 0x1e4c6260, 0x233b359e }, 0x1478f4afULL }, + { 0x1ce036ce0ULL, { 0x29e3c8af, 0x5318dd4a }, 0xe8e76196ULL }, + { 0x1473ae2aULL, { 0x29b897ba, 0x2be29378 }, 0x13718185ULL }, + { 0x1dd41aa68ULL, { 0x3d0a4441, 0x5a0e8f12 }, 0x1437b6bbfULL }, + { 0x1b49e4a53ULL, { 0x3430c1fe, 0x5a204aed }, 0xfcd6852fULL }, + { 0x217941b19ULL, { 0x12ced2bd, 0x21b68310 }, 0x12aca65b1ULL }, + { 0xac6a4dc8ULL, { 0x3ed68da8, 0x6fdca34c }, 0x60da926dULL }, + { 0x1c503a4e7ULL, { 0xfcbbd32, 0x11e48d17 }, 0x18fec7d38ULL }, + { 0x1c885855ULL, { 0x213e919d, 0x25941897 }, 0x193de743ULL }, + { 0x29b9c168eULL, { 0x2b644aea, 0x45725ee7 }, 0x1a122e5d5ULL }, + { 0x806a33f2ULL, { 0x30a80a23, 0x5063733a }, 0x4db9a264ULL }, + { 0x282afc96bULL, { 0x143ae554, 0x1a9863ff }, 0x1e8de5204ULL }, + // Data for scaling that results in > 64 bit division. + { 0x23ca5f2f672ca41cULL, { 0xecbc641, 0x111373f7 }, 0x1f0301e5e8295ab5ULL }, + { 0x5e4f2468142265e3ULL, { 0x1ddf5837, 0x32189233 }, 0x383ca7ba9fdd2c8cULL }, + { 0x277a1a6f6b266bf6ULL, { 0x415d81a8, 0x61eb5e1e }, 0x1a5a3e1d41b30c0fULL }, + { 0x1bdbb49a237035cbULL, { 0xea5bf17, 0x1d25ffb3 }, 0xdffc51c53d44b93ULL }, + { 0x2bce6d29b64fb8ULL, { 0x3bfd5631, 0x7525c9bb }, 0x166ebedda7ac57ULL }, + { 0x3a02116103df5013ULL, { 0x2ee18a83, 0x3299aea8 }, 0x35be8922ab1e2a84ULL }, + { 0x7b5762390799b18cULL, { 0x12f8e5b9, 0x2563bcd4 }, 0x3e960077aca01209ULL }, + { 0x69cfd72537021579ULL, { 0x4c35f468, 0x6a40feee }, 0x4be4cb3848be98a3ULL }, + { 0x49dfdf835120f1c1ULL, { 0x8cb3759, 0x559eb891 }, 0x79663f7120edadeULL }, + { 0x74b5be5c27676381ULL, { 0x47e4c5e0, 0x7c7b19ff }, 0x4367d2dff36a1028ULL }, + { 0x4f50f97075e7f431ULL, { 0x9a50a17, 0x11cd1185 }, 0x2af952b34c032df4ULL }, + { 0x2f8b0d712e393be4ULL, { 0x1487e386, 0x15aa356e }, 0x2d0df36478a776aaULL }, + { 0x224c1c75999d3deULL, { 0x3b2df0ea, 0x4523b100 }, 0x1d5b481d145f08aULL }, + { 0x2bcbcea22a399a76ULL, { 0x28b58212, 0x48dd013e }, 0x187814d084c47cabULL }, + { 0x1dbfca91257cb2d1ULL, { 0x1a8c04d9, 0x5e92502c }, 0x859cf7d00f77545ULL }, + { 0x7f20039b57cda935ULL, { 0xeccf651, 0x323f476e }, 0x25720cd976461a77ULL }, + { 0x40512c6a586aa087ULL, { 0x113b0423, 0x398c9eab }, 0x1341c03de8696a7eULL }, + { 0x63d802693f050a11ULL, { 0xf50cdd6, 0xfce2a44 }, 0x60c0177bb5e46846ULL }, + { 0x2d956b422838de77ULL, { 0xb2d345b, 0x1321e557 }, 0x1aa0ed16b6aa5319ULL }, + { 0x5a1cdf0c1657bc91ULL, { 0x1d77bb0c, 0x1f991ff1 }, 0x54097ee94ff87560ULL }, + { 0x3801b26d7e00176bULL, { 0xeed25da, 0x1a819d8b }, 0x1f89e96a3a639526ULL }, + { 0x37655e74338e1e45ULL, { 0x300e170a, 0x5a1595fe }, 0x1d8cfb55fddc0441ULL }, + { 0x7b38703f2a84e6ULL, { 0x66d9053, 0xc79b6b9 }, 0x3f7d4c91774094ULL }, + { 0x2245063c0acb3215ULL, { 0x30ce2f5b, 0x610e7271 }, 0x113b916468389235ULL }, + { 0x6bc195877b7b8a7eULL, { 0x392004aa, 0x4a24e60c }, 0x530594fb17db6ba5ULL }, + { 0x40a3fde23c7b43dbULL, { 0x4e712195, 0x6553e56e }, 0x320a799bc76a466aULL }, + { 0x1d3dfc2866fbccbaULL, { 0x5075b517, 0x5fc42245 }, 0x18917f0061595bc3ULL }, + { 0x19aeb14045a61121ULL, { 0x1bf6edec, 0x707e2f4b }, 0x6626672a070bcc7ULL }, + { 0x44ff90486c531e9fULL, { 0x66598a, 0x8a90dc }, 0x32f6f2b0525199b0ULL }, + { 0x3f3e7121092c5bcbULL, { 0x1c754df7, 0x5951a1b9 }, 0x14267f50b7ef375dULL }, + { 0x60e2dafb7e50a67eULL, { 0x4d96c66e, 0x65bd878d }, 0x49e31715ac393f8bULL }, + { 0x656286667e0e6e29ULL, { 0x9d971a2, 0xacda23b }, 0x5c6ee315ead6cb4fULL }, + { 0x1114e0974255d507ULL, { 0x1c693, 0x2d6ff }, 0xaae42e4b35f6e60ULL }, + { 0x508c8baf3a70ff5aULL, { 0x3b26b779, 0x6ad78745 }, 0x2c98387636c4b365ULL }, + { 0x5b47bc666bf1f9cfULL, { 0x10a87ed6, 0x187d358a }, 0x3e1767155848368bULL }, + { 0x50954e3744460395ULL, { 0x7a42263, 0xcdaa048 }, 0x2fe739f0aee1fee1ULL }, + { 0x20020b406550dd8fULL, { 0x3318539, 0x42eead0 }, 0x186f326325fa346bULL }, + { 0x5bcb0b872439ffd5ULL, { 0x6f61fb2, 0x9af7344 }, 0x41fa1e3bec3c1b30ULL }, + { 0x7a670f365db87a53ULL, { 0x417e102, 0x3bb54c67 }, 0x8642a558304fd9eULL }, + { 0x1ef0db1e7bab1cd0ULL, { 0x2b60cf38, 0x4188f78f }, 0x147ae0d6226b2ee6ULL } + }; + + for (const auto &T : Tests) { + EXPECT_EQ(T.Result, BP(T.Prob[0], T.Prob[1]).scale(T.Num)); + } +} + +} diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 4afa4fd..0ea9310 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -7,6 +7,7 @@ add_llvm_unittest(SupportTests AllocatorTest.cpp ArrayRecyclerTest.cpp BlockFrequencyTest.cpp + BranchProbabilityTest.cpp Casting.cpp CommandLineTest.cpp CompressionTest.cpp @@ -15,12 +16,13 @@ add_llvm_unittest(SupportTests EndianTest.cpp ErrorOrTest.cpp FileOutputBufferTest.cpp + IteratorTest.cpp LEB128Test.cpp LineIteratorTest.cpp LockFileManagerTest.cpp + MD5Test.cpp ManagedStatic.cpp MathExtrasTest.cpp - MD5Test.cpp MemoryBufferTest.cpp MemoryTest.cpp Path.cpp diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp index db6a8bb..698ae3a 100644 --- a/unittests/Support/CompressionTest.cpp +++ b/unittests/Support/CompressionTest.cpp @@ -13,8 +13,8 @@ #include "llvm/Support/Compression.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Config/config.h" -#include "llvm/Support/MemoryBuffer.h" #include "gtest/gtest.h" using namespace llvm; @@ -24,20 +24,17 @@ namespace { #if LLVM_ENABLE_ZLIB == 1 && HAVE_LIBZ void TestZlibCompression(StringRef Input, zlib::CompressionLevel Level) { - std::unique_ptr<MemoryBuffer> Compressed; - std::unique_ptr<MemoryBuffer> Uncompressed; + SmallString<32> Compressed; + SmallString<32> Uncompressed; EXPECT_EQ(zlib::StatusOK, zlib::compress(Input, Compressed, Level)); // Check that uncompressed buffer is the same as original. - EXPECT_EQ(zlib::StatusOK, zlib::uncompress(Compressed->getBuffer(), - Uncompressed, Input.size())); - EXPECT_EQ(Input.size(), Uncompressed->getBufferSize()); - EXPECT_EQ(0, - memcmp(Input.data(), Uncompressed->getBufferStart(), Input.size())); + EXPECT_EQ(zlib::StatusOK, + zlib::uncompress(Compressed, Uncompressed, Input.size())); + EXPECT_EQ(Input, Uncompressed); if (Input.size() > 0) { // Uncompression fails if expected length is too short. EXPECT_EQ(zlib::StatusBufferTooShort, - zlib::uncompress(Compressed->getBuffer(), Uncompressed, - Input.size() - 1)); + zlib::uncompress(Compressed, Uncompressed, Input.size() - 1)); } } diff --git a/unittests/Support/FileOutputBufferTest.cpp b/unittests/Support/FileOutputBufferTest.cpp index 6d62999..0801f85 100644 --- a/unittests/Support/FileOutputBufferTest.cpp +++ b/unittests/Support/FileOutputBufferTest.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/FileOutputBuffer.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -38,7 +37,7 @@ TEST(FileOutputBuffer, Test) { SmallString<128> File1(TestDirectory); File1.append("/file1"); { - OwningPtr<FileOutputBuffer> Buffer; + std::unique_ptr<FileOutputBuffer> Buffer; ASSERT_NO_ERROR(FileOutputBuffer::create(File1, 8192, Buffer)); // Start buffer with special header. memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20); @@ -62,7 +61,7 @@ TEST(FileOutputBuffer, Test) { SmallString<128> File2(TestDirectory); File2.append("/file2"); { - OwningPtr<FileOutputBuffer> Buffer2; + std::unique_ptr<FileOutputBuffer> Buffer2; ASSERT_NO_ERROR(FileOutputBuffer::create(File2, 8192, Buffer2)); // Fill buffer with special header. memcpy(Buffer2->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20); @@ -78,7 +77,7 @@ TEST(FileOutputBuffer, Test) { SmallString<128> File3(TestDirectory); File3.append("/file3"); { - OwningPtr<FileOutputBuffer> Buffer; + std::unique_ptr<FileOutputBuffer> Buffer; ASSERT_NO_ERROR(FileOutputBuffer::create(File3, 8192000, Buffer)); // Start buffer with special header. memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20); @@ -102,7 +101,7 @@ TEST(FileOutputBuffer, Test) { SmallString<128> File4(TestDirectory); File4.append("/file4"); { - OwningPtr<FileOutputBuffer> Buffer; + std::unique_ptr<FileOutputBuffer> Buffer; ASSERT_NO_ERROR(FileOutputBuffer::create(File4, 8192, Buffer, FileOutputBuffer::F_executable)); // Start buffer with special header. diff --git a/unittests/Support/IteratorTest.cpp b/unittests/Support/IteratorTest.cpp new file mode 100644 index 0000000..8384832 --- /dev/null +++ b/unittests/Support/IteratorTest.cpp @@ -0,0 +1,101 @@ +//===- IteratorTest.cpp - Unit tests for iterator utilities ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/iterator.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(PointeeIteratorTest, Basic) { + int arr[4] = { 1, 2, 3, 4 }; + SmallVector<int *, 4> V; + V.push_back(&arr[0]); + V.push_back(&arr[1]); + V.push_back(&arr[2]); + V.push_back(&arr[3]); + + typedef pointee_iterator<SmallVectorImpl<int *>::const_iterator> test_iterator; + + test_iterator Begin, End; + Begin = V.begin(); + End = test_iterator(V.end()); + + test_iterator I = Begin; + for (int i = 0; i < 4; ++i) { + EXPECT_EQ(*V[i], *I); + + EXPECT_EQ(I, Begin + i); + EXPECT_EQ(I, std::next(Begin, i)); + test_iterator J = Begin; + J += i; + EXPECT_EQ(I, J); + EXPECT_EQ(*V[i], Begin[i]); + + EXPECT_NE(I, End); + EXPECT_GT(End, I); + EXPECT_LT(I, End); + EXPECT_GE(I, Begin); + EXPECT_LE(Begin, I); + + EXPECT_EQ(i, I - Begin); + EXPECT_EQ(i, std::distance(Begin, I)); + EXPECT_EQ(Begin, I - i); + + test_iterator K = I++; + EXPECT_EQ(K, std::prev(I)); + } + EXPECT_EQ(End, I); +} + +TEST(PointeeIteratorTest, SmartPointer) { + SmallVector<std::unique_ptr<int>, 4> V; + V.push_back(make_unique<int>(1)); + V.push_back(make_unique<int>(2)); + V.push_back(make_unique<int>(3)); + V.push_back(make_unique<int>(4)); + + typedef pointee_iterator< + SmallVectorImpl<std::unique_ptr<int>>::const_iterator> test_iterator; + + test_iterator Begin, End; + Begin = V.begin(); + End = test_iterator(V.end()); + + test_iterator I = Begin; + for (int i = 0; i < 4; ++i) { + EXPECT_EQ(*V[i], *I); + + EXPECT_EQ(I, Begin + i); + EXPECT_EQ(I, std::next(Begin, i)); + test_iterator J = Begin; + J += i; + EXPECT_EQ(I, J); + EXPECT_EQ(*V[i], Begin[i]); + + EXPECT_NE(I, End); + EXPECT_GT(End, I); + EXPECT_LT(I, End); + EXPECT_GE(I, Begin); + EXPECT_LE(Begin, I); + + EXPECT_EQ(i, I - Begin); + EXPECT_EQ(i, std::distance(Begin, I)); + EXPECT_EQ(Begin, I - i); + + test_iterator K = I++; + EXPECT_EQ(K, std::prev(I)); + } + EXPECT_EQ(End, I); +} + +} // anonymous namespace diff --git a/unittests/Support/MemoryBufferTest.cpp b/unittests/Support/MemoryBufferTest.cpp index 43b7e0d..6790d0c 100644 --- a/unittests/Support/MemoryBufferTest.cpp +++ b/unittests/Support/MemoryBufferTest.cpp @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/FileSystem.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" @@ -36,7 +35,7 @@ protected: /// anew before using MemoryBuffer. void testGetOpenFileSlice(bool Reopen); - typedef OwningPtr<MemoryBuffer> OwningBuffer; + typedef std::unique_ptr<MemoryBuffer> OwningBuffer; std::string data; }; diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 52a8f6b..cf95532 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -302,11 +302,23 @@ struct StringTypes { llvm::StringRef str3; llvm::StringRef str4; llvm::StringRef str5; + llvm::StringRef str6; + llvm::StringRef str7; + llvm::StringRef str8; + llvm::StringRef str9; + llvm::StringRef str10; + llvm::StringRef str11; std::string stdstr1; std::string stdstr2; std::string stdstr3; std::string stdstr4; std::string stdstr5; + std::string stdstr6; + std::string stdstr7; + std::string stdstr8; + std::string stdstr9; + std::string stdstr10; + std::string stdstr11; }; namespace llvm { @@ -319,11 +331,23 @@ namespace yaml { io.mapRequired("str3", st.str3); io.mapRequired("str4", st.str4); io.mapRequired("str5", st.str5); + io.mapRequired("str6", st.str6); + io.mapRequired("str7", st.str7); + io.mapRequired("str8", st.str8); + io.mapRequired("str9", st.str9); + io.mapRequired("str10", st.str10); + io.mapRequired("str11", st.str11); io.mapRequired("stdstr1", st.stdstr1); io.mapRequired("stdstr2", st.stdstr2); io.mapRequired("stdstr3", st.stdstr3); io.mapRequired("stdstr4", st.stdstr4); io.mapRequired("stdstr5", st.stdstr5); + io.mapRequired("stdstr6", st.stdstr6); + io.mapRequired("stdstr7", st.stdstr7); + io.mapRequired("stdstr8", st.stdstr8); + io.mapRequired("stdstr9", st.stdstr9); + io.mapRequired("stdstr10", st.stdstr10); + io.mapRequired("stdstr11", st.stdstr11); } }; } @@ -338,11 +362,23 @@ TEST(YAMLIO, TestReadWriteStringTypes) { map.str3 = "`ccc"; map.str4 = "@ddd"; map.str5 = ""; + map.str6 = "0000000004000000"; + map.str7 = "true"; + map.str8 = "FALSE"; + map.str9 = "~"; + map.str10 = "0.2e20"; + map.str11 = "0x30"; map.stdstr1 = "'eee"; map.stdstr2 = "\"fff"; map.stdstr3 = "`ggg"; map.stdstr4 = "@hhh"; map.stdstr5 = ""; + map.stdstr6 = "0000000004000000"; + map.stdstr7 = "true"; + map.stdstr8 = "FALSE"; + map.stdstr9 = "~"; + map.stdstr10 = "0.2e20"; + map.stdstr11 = "0x30"; llvm::raw_string_ostream ostr(intermediate); Output yout(ostr); @@ -355,11 +391,18 @@ TEST(YAMLIO, TestReadWriteStringTypes) { EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'")); EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'")); EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n")); + EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n")); EXPECT_NE(std::string::npos, flowOut.find("'''eee")); EXPECT_NE(std::string::npos, flowOut.find("'\"fff'")); EXPECT_NE(std::string::npos, flowOut.find("'`ggg'")); EXPECT_NE(std::string::npos, flowOut.find("'@hhh'")); EXPECT_NE(std::string::npos, flowOut.find("''\n")); + EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n")); { Input yin(intermediate); @@ -372,11 +415,13 @@ TEST(YAMLIO, TestReadWriteStringTypes) { EXPECT_TRUE(map.str3.equals("`ccc")); EXPECT_TRUE(map.str4.equals("@ddd")); EXPECT_TRUE(map.str5.equals("")); + EXPECT_TRUE(map.str6.equals("0000000004000000")); EXPECT_TRUE(map.stdstr1 == "'eee"); EXPECT_TRUE(map.stdstr2 == "\"fff"); EXPECT_TRUE(map.stdstr3 == "`ggg"); EXPECT_TRUE(map.stdstr4 == "@hhh"); EXPECT_TRUE(map.stdstr5 == ""); + EXPECT_TRUE(map.stdstr6 == "0000000004000000"); } } @@ -602,6 +647,7 @@ namespace yaml { return "malformed by"; } } + static bool mustQuote(StringRef) { return true; } }; } } @@ -663,6 +709,8 @@ namespace yaml { value = n; return StringRef(); } + + static bool mustQuote(StringRef) { return false; } }; } } diff --git a/unittests/Transforms/Utils/SpecialCaseList.cpp b/unittests/Transforms/Utils/SpecialCaseList.cpp index 748834f..fd00687 100644 --- a/unittests/Transforms/Utils/SpecialCaseList.cpp +++ b/unittests/Transforms/Utils/SpecialCaseList.cpp @@ -34,9 +34,8 @@ protected: M, ST, false, GlobalValue::ExternalLinkage, 0, Name); } - GlobalAlias *makeAlias(StringRef Name, GlobalValue *Aliasee) { - return new GlobalAlias(Aliasee->getType(), GlobalValue::ExternalLinkage, - Name, Aliasee, Aliasee->getParent()); + GlobalAlias *makeAlias(StringRef Name, GlobalObject *Aliasee) { + return GlobalAlias::create(GlobalValue::ExternalLinkage, Name, Aliasee); } SpecialCaseList *makeSpecialCaseList(StringRef List, std::string &Error) { |