diff options
Diffstat (limited to 'unittests/IR')
-rw-r--r-- | unittests/IR/CMakeLists.txt | 3 | ||||
-rw-r--r-- | unittests/IR/ConstantsTest.cpp | 73 | ||||
-rw-r--r-- | unittests/IR/DebugInfoTest.cpp | 68 | ||||
-rw-r--r-- | unittests/IR/DominatorTreeTest.cpp | 7 | ||||
-rw-r--r-- | unittests/IR/IRBuilderTest.cpp | 4 | ||||
-rw-r--r-- | unittests/IR/LeakDetectorTest.cpp | 31 | ||||
-rw-r--r-- | unittests/IR/LegacyPassManagerTest.cpp | 52 | ||||
-rw-r--r-- | unittests/IR/MDBuilderTest.cpp | 21 | ||||
-rw-r--r-- | unittests/IR/MetadataTest.cpp | 456 | ||||
-rw-r--r-- | unittests/IR/PassManagerTest.cpp | 35 | ||||
-rw-r--r-- | unittests/IR/UseTest.cpp | 112 | ||||
-rw-r--r-- | unittests/IR/UserTest.cpp | 4 | ||||
-rw-r--r-- | unittests/IR/ValueMapTest.cpp | 4 | ||||
-rw-r--r-- | unittests/IR/ValueTest.cpp | 25 | ||||
-rw-r--r-- | unittests/IR/WaymarkTest.cpp | 5 |
15 files changed, 787 insertions, 113 deletions
diff --git a/unittests/IR/CMakeLists.txt b/unittests/IR/CMakeLists.txt index b439d59dec7b..0c2979632e10 100644 --- a/unittests/IR/CMakeLists.txt +++ b/unittests/IR/CMakeLists.txt @@ -10,10 +10,10 @@ set(IRSources AttributesTest.cpp ConstantRangeTest.cpp ConstantsTest.cpp + DebugInfoTest.cpp DominatorTreeTest.cpp IRBuilderTest.cpp InstructionsTest.cpp - LeakDetectorTest.cpp LegacyPassManagerTest.cpp MDBuilderTest.cpp MetadataTest.cpp @@ -21,6 +21,7 @@ set(IRSources PatternMatch.cpp TypeBuilderTest.cpp TypesTest.cpp + UseTest.cpp UserTest.cpp ValueHandleTest.cpp ValueMapTest.cpp diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index 0cd854998286..5414b25ca3ad 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -274,5 +274,78 @@ TEST(ConstantsTest, ReplaceWithConstantTest) { #undef CHECK +TEST(ConstantsTest, ConstantArrayReplaceWithConstant) { + LLVMContext Context; + std::unique_ptr<Module> M(new Module("MyModule", Context)); + + Type *IntTy = Type::getInt8Ty(Context); + ArrayType *ArrayTy = ArrayType::get(IntTy, 2); + Constant *A01Vals[2] = {ConstantInt::get(IntTy, 0), + ConstantInt::get(IntTy, 1)}; + Constant *A01 = ConstantArray::get(ArrayTy, A01Vals); + + Constant *Global = new GlobalVariable(*M, IntTy, false, + GlobalValue::ExternalLinkage, nullptr); + Constant *GlobalInt = ConstantExpr::getPtrToInt(Global, IntTy); + Constant *A0GVals[2] = {ConstantInt::get(IntTy, 0), GlobalInt}; + Constant *A0G = ConstantArray::get(ArrayTy, A0GVals); + ASSERT_NE(A01, A0G); + + GlobalVariable *RefArray = + new GlobalVariable(*M, ArrayTy, false, GlobalValue::ExternalLinkage, A0G); + ASSERT_EQ(A0G, RefArray->getInitializer()); + + GlobalInt->replaceAllUsesWith(ConstantInt::get(IntTy, 1)); + ASSERT_EQ(A01, RefArray->getInitializer()); +} + +TEST(ConstantsTest, ConstantExprReplaceWithConstant) { + LLVMContext Context; + std::unique_ptr<Module> M(new Module("MyModule", Context)); + + Type *IntTy = Type::getInt8Ty(Context); + Constant *G1 = new GlobalVariable(*M, IntTy, false, + GlobalValue::ExternalLinkage, nullptr); + Constant *G2 = new GlobalVariable(*M, IntTy, false, + GlobalValue::ExternalLinkage, nullptr); + ASSERT_NE(G1, G2); + + Constant *Int1 = ConstantExpr::getPtrToInt(G1, IntTy); + Constant *Int2 = ConstantExpr::getPtrToInt(G2, IntTy); + ASSERT_NE(Int1, Int2); + + GlobalVariable *Ref = + new GlobalVariable(*M, IntTy, false, GlobalValue::ExternalLinkage, Int1); + ASSERT_EQ(Int1, Ref->getInitializer()); + + G1->replaceAllUsesWith(G2); + ASSERT_EQ(Int2, Ref->getInitializer()); +} + +TEST(ConstantsTest, GEPReplaceWithConstant) { + LLVMContext Context; + std::unique_ptr<Module> M(new Module("MyModule", Context)); + + Type *IntTy = Type::getInt32Ty(Context); + Type *PtrTy = PointerType::get(IntTy, 0); + auto *C1 = ConstantInt::get(IntTy, 1); + auto *Placeholder = new GlobalVariable( + *M, IntTy, false, GlobalValue::ExternalWeakLinkage, nullptr); + auto *GEP = ConstantExpr::getGetElementPtr(Placeholder, C1); + ASSERT_EQ(GEP->getOperand(0), Placeholder); + + auto *Ref = + new GlobalVariable(*M, PtrTy, false, GlobalValue::ExternalLinkage, GEP); + ASSERT_EQ(GEP, Ref->getInitializer()); + + auto *Global = new GlobalVariable(*M, PtrTy, false, + GlobalValue::ExternalLinkage, nullptr); + auto *Alias = GlobalAlias::create(IntTy, 0, GlobalValue::ExternalLinkage, + "alias", Global, M.get()); + Placeholder->replaceAllUsesWith(Alias); + ASSERT_EQ(GEP, Ref->getInitializer()); + ASSERT_EQ(GEP->getOperand(0), Alias); +} + } // end anonymous namespace } // end namespace llvm diff --git a/unittests/IR/DebugInfoTest.cpp b/unittests/IR/DebugInfoTest.cpp new file mode 100644 index 000000000000..1fa851e39ae9 --- /dev/null +++ b/unittests/IR/DebugInfoTest.cpp @@ -0,0 +1,68 @@ +//===- llvm/unittest/IR/DebugInfo.cpp - DebugInfo tests -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/DebugInfo.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace llvm { + +static void PrintTo(const StringRef &S, ::std::ostream *os) { + *os << "(" << (const void *)S.data() << "," << S.size() << ") = '"; + for (auto C : S) + if (C) + *os << C; + else + *os << "\\00"; + *os << "'"; +} +static void PrintTo(const DIHeaderFieldIterator &I, ::std::ostream *os) { + PrintTo(I.getCurrent(), os); + *os << " in "; + PrintTo(I.getHeader(), os); +} + +} // end namespace llvm + +namespace { + +#define MAKE_FIELD_ITERATOR(S) \ + DIHeaderFieldIterator(StringRef(S, sizeof(S) - 1)) +TEST(DebugInfoTest, DIHeaderFieldIterator) { + ASSERT_EQ(DIHeaderFieldIterator(), DIHeaderFieldIterator()); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("")); + ASSERT_EQ(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("")); + ASSERT_EQ("", *DIHeaderFieldIterator("")); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("stuff")); + ASSERT_EQ(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("stuff")); + ASSERT_EQ("stuff", *DIHeaderFieldIterator("stuff")); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("st\0uff")); + ASSERT_NE(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("st\0uff")); + ASSERT_EQ(DIHeaderFieldIterator(), ++++MAKE_FIELD_ITERATOR("st\0uff")); + ASSERT_EQ("st", *MAKE_FIELD_ITERATOR("st\0uff")); + ASSERT_EQ("uff", *++MAKE_FIELD_ITERATOR("st\0uff")); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("stuff\0")); + ASSERT_NE(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("stuff\0")); + ASSERT_EQ(DIHeaderFieldIterator(), ++++MAKE_FIELD_ITERATOR("stuff\0")); + ASSERT_EQ("stuff", *MAKE_FIELD_ITERATOR("stuff\0")); + ASSERT_EQ("", *++MAKE_FIELD_ITERATOR("stuff\0")); + + ASSERT_NE(DIHeaderFieldIterator(), MAKE_FIELD_ITERATOR("\0stuff")); + ASSERT_NE(DIHeaderFieldIterator(), ++MAKE_FIELD_ITERATOR("\0stuff")); + ASSERT_EQ(DIHeaderFieldIterator(), ++++MAKE_FIELD_ITERATOR("\0stuff")); + ASSERT_EQ("", *MAKE_FIELD_ITERATOR("\0stuff")); + ASSERT_EQ("stuff", *++MAKE_FIELD_ITERATOR("\0stuff")); +} + +} // end namespace diff --git a/unittests/IR/DominatorTreeTest.cpp b/unittests/IR/DominatorTreeTest.cpp index ab43d1c91fcd..6c43d6fe7c7b 100644 --- a/unittests/IR/DominatorTreeTest.cpp +++ b/unittests/IR/DominatorTreeTest.cpp @@ -186,8 +186,7 @@ namespace llvm { }; char DPass::ID = 0; - - Module* makeLLVMModule(DPass *P) { + std::unique_ptr<Module> makeLLVMModule(DPass *P) { const char *ModuleStrig = "declare i32 @g()\n" \ "define void @f(i32 %x) {\n" \ @@ -213,12 +212,12 @@ namespace llvm { "}\n"; LLVMContext &C = getGlobalContext(); SMDiagnostic Err; - return ParseAssemblyString(ModuleStrig, nullptr, Err, C); + return parseAssemblyString(ModuleStrig, Err, C); } TEST(DominatorTree, Unreachable) { DPass *P = new DPass(); - std::unique_ptr<Module> M(makeLLVMModule(P)); + std::unique_ptr<Module> M = makeLLVMModule(P); PassManager Passes; Passes.add(P); Passes.run(*M); diff --git a/unittests/IR/IRBuilderTest.cpp b/unittests/IR/IRBuilderTest.cpp index 21085755fbad..df5c84064779 100644 --- a/unittests/IR/IRBuilderTest.cpp +++ b/unittests/IR/IRBuilderTest.cpp @@ -189,12 +189,16 @@ TEST_F(IRBuilderTest, FastMathFlags) { Builder.clearFastMathFlags(); + // To test a copy, make sure that a '0' and a '1' change state. F = Builder.CreateFDiv(F, F); ASSERT_TRUE(isa<Instruction>(F)); FDiv = cast<Instruction>(F); EXPECT_FALSE(FDiv->getFastMathFlags().any()); + FDiv->setHasAllowReciprocal(true); + FAdd->setHasAllowReciprocal(false); FDiv->copyFastMathFlags(FAdd); EXPECT_TRUE(FDiv->hasNoNaNs()); + EXPECT_FALSE(FDiv->hasAllowReciprocal()); } diff --git a/unittests/IR/LeakDetectorTest.cpp b/unittests/IR/LeakDetectorTest.cpp deleted file mode 100644 index 94eed4c1432b..000000000000 --- a/unittests/IR/LeakDetectorTest.cpp +++ /dev/null @@ -1,31 +0,0 @@ -//===- LeakDetectorTest.cpp -----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "llvm/IR/LeakDetector.h" -#include "gtest/gtest.h" - -using namespace llvm; - -namespace { - -#ifdef GTEST_HAS_DEATH_TEST -#ifndef NDEBUG -TEST(LeakDetector, Death1) { - LeakDetector::addGarbageObject((void*) 1); - LeakDetector::addGarbageObject((void*) 2); - - EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 1), - ".*Ts.count\\(o\\) == 0 && \"Object already in set!\""); - EXPECT_DEATH(LeakDetector::addGarbageObject((void*) 2), - "Cache != o && \"Object already in set!\""); -} -#endif -#endif - -} diff --git a/unittests/IR/LegacyPassManagerTest.cpp b/unittests/IR/LegacyPassManagerTest.cpp index 9c2a835ca099..4efc2f5b8057 100644 --- a/unittests/IR/LegacyPassManagerTest.cpp +++ b/unittests/IR/LegacyPassManagerTest.cpp @@ -54,11 +54,11 @@ namespace llvm { static char run; static char ID; ModuleNDNM() : ModulePass(ID) { } - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { run++; return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesAll(); } }; @@ -70,7 +70,7 @@ namespace llvm { static char run; static char ID; ModuleNDM() : ModulePass(ID) {} - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { run++; return true; } @@ -83,7 +83,7 @@ namespace llvm { static char run; static char ID; ModuleNDM2() : ModulePass(ID) {} - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { run++; return true; } @@ -98,12 +98,12 @@ namespace llvm { ModuleDNM() : ModulePass(ID) { initializeModuleNDMPass(*PassRegistry::getPassRegistry()); } - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run++; return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired<ModuleNDM>(); AU.setPreservesAll(); } @@ -139,7 +139,7 @@ namespace llvm { runc = 0; } - virtual void releaseMemory() { + void releaseMemory() override { EXPECT_GT(runc, 0); EXPECT_GT(allocated, 0); allocated--; @@ -157,12 +157,12 @@ namespace llvm { using llvm::Pass::doInitialization; using llvm::Pass::doFinalization; #endif - virtual bool doInitialization(T &t) { + bool doInitialization(T &t) override { EXPECT_FALSE(PassTestBase<P>::initialized); PassTestBase<P>::initialized = true; return false; } - virtual bool doFinalization(T &t) { + bool doFinalization(T &t) override { EXPECT_FALSE(PassTestBase<P>::finalized); PassTestBase<P>::finalized = true; EXPECT_EQ(0, PassTestBase<P>::allocated); @@ -175,7 +175,7 @@ namespace llvm { CGPass() { initializeCGPassPass(*PassRegistry::getPassRegistry()); } - virtual bool runOnSCC(CallGraphSCC &SCMM) { + bool runOnSCC(CallGraphSCC &SCMM) override { EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run(); return false; @@ -184,7 +184,7 @@ namespace llvm { struct FPass : public PassTest<Module, FunctionPass> { public: - virtual bool runOnFunction(Function &F) { + bool runOnFunction(Function &F) override { // FIXME: PR4112 // EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>()); run(); @@ -209,17 +209,17 @@ namespace llvm { } using llvm::Pass::doInitialization; using llvm::Pass::doFinalization; - virtual bool doInitialization(Loop* L, LPPassManager &LPM) { + bool doInitialization(Loop* L, LPPassManager &LPM) override { initialized = true; initcount++; return false; } - virtual bool runOnLoop(Loop *L, LPPassManager &LPM) { + bool runOnLoop(Loop *L, LPPassManager &LPM) override { EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run(); return false; } - virtual bool doFinalization() { + bool doFinalization() override { fincount++; finalized = true; return false; @@ -242,25 +242,25 @@ namespace llvm { inited = 0; fin = 0; } - virtual bool doInitialization(Module &M) { + bool doInitialization(Module &M) override { EXPECT_FALSE(initialized); initialized = true; return false; } - virtual bool doInitialization(Function &F) { + bool doInitialization(Function &F) override { inited++; return false; } - virtual bool runOnBasicBlock(BasicBlock &BB) { + bool runOnBasicBlock(BasicBlock &BB) override { EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); run(); return false; } - virtual bool doFinalization(Function &F) { + bool doFinalization(Function &F) override { fin++; return false; } - virtual bool doFinalization(Module &M) { + bool doFinalization(Module &M) override { EXPECT_FALSE(finalized); finalized = true; EXPECT_EQ(0, allocated); @@ -276,7 +276,7 @@ namespace llvm { OnTheFlyTest() : ModulePass(ID) { initializeFPassPass(*PassRegistry::getPassRegistry()); } - virtual bool runOnModule(Module &M) { + bool runOnModule(Module &M) override { EXPECT_TRUE(getAnalysisIfAvailable<DataLayoutPass>()); for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) { Function &F = *I; @@ -287,7 +287,7 @@ namespace llvm { } return false; } - virtual void getAnalysisUsage(AnalysisUsage &AU) const { + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired<FPass>(); } }; @@ -303,7 +303,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; PassManager Passes; - Passes.add(new DataLayoutPass(&M)); + Passes.add(new DataLayoutPass()); Passes.add(mNDM2); Passes.add(mNDM); Passes.add(mNDNM); @@ -327,7 +327,7 @@ namespace llvm { mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0; PassManager Passes; - Passes.add(new DataLayoutPass(&M)); + Passes.add(new DataLayoutPass()); Passes.add(mNDM); Passes.add(mNDNM); Passes.add(mNDM2);// invalidates mNDM needed by mDNM @@ -349,7 +349,7 @@ namespace llvm { std::unique_ptr<Module> M(makeLLVMModule()); T *P = new T(); PassManager Passes; - Passes.add(new DataLayoutPass(M.get())); + Passes.add(new DataLayoutPass()); Passes.add(P); Passes.run(*M); T::finishedOK(run); @@ -360,7 +360,7 @@ namespace llvm { Module *M = makeLLVMModule(); T *P = new T(); PassManager Passes; - Passes.add(new DataLayoutPass(M)); + Passes.add(new DataLayoutPass()); Passes.add(P); Passes.run(*M); T::finishedOK(run, N); @@ -398,7 +398,7 @@ namespace llvm { SCOPED_TRACE("Running OnTheFlyTest"); struct OnTheFlyTest *O = new OnTheFlyTest(); PassManager Passes; - Passes.add(new DataLayoutPass(M)); + Passes.add(new DataLayoutPass()); Passes.add(O); Passes.run(*M); diff --git a/unittests/IR/MDBuilderTest.cpp b/unittests/IR/MDBuilderTest.cpp index fc4674ea1357..ab2d34e89db6 100644 --- a/unittests/IR/MDBuilderTest.cpp +++ b/unittests/IR/MDBuilderTest.cpp @@ -36,10 +36,10 @@ TEST_F(MDBuilderTest, createFPMath) { EXPECT_EQ(MD0, (MDNode *)nullptr); EXPECT_NE(MD1, (MDNode *)nullptr); EXPECT_EQ(MD1->getNumOperands(), 1U); - Value *Op = MD1->getOperand(0); - EXPECT_TRUE(isa<ConstantFP>(Op)); - EXPECT_TRUE(Op->getType()->isFloatingPointTy()); - ConstantFP *Val = cast<ConstantFP>(Op); + Metadata *Op = MD1->getOperand(0); + EXPECT_TRUE(mdconst::hasa<ConstantFP>(Op)); + ConstantFP *Val = mdconst::extract<ConstantFP>(Op); + EXPECT_TRUE(Val->getType()->isFloatingPointTy()); EXPECT_TRUE(Val->isExactlyValue(1.0)); } TEST_F(MDBuilderTest, createRangeMetadata) { @@ -50,10 +50,10 @@ TEST_F(MDBuilderTest, createRangeMetadata) { EXPECT_EQ(R0, (MDNode *)nullptr); EXPECT_NE(R1, (MDNode *)nullptr); EXPECT_EQ(R1->getNumOperands(), 2U); - EXPECT_TRUE(isa<ConstantInt>(R1->getOperand(0))); - EXPECT_TRUE(isa<ConstantInt>(R1->getOperand(1))); - ConstantInt *C0 = cast<ConstantInt>(R1->getOperand(0)); - ConstantInt *C1 = cast<ConstantInt>(R1->getOperand(1)); + EXPECT_TRUE(mdconst::hasa<ConstantInt>(R1->getOperand(0))); + EXPECT_TRUE(mdconst::hasa<ConstantInt>(R1->getOperand(1))); + ConstantInt *C0 = mdconst::extract<ConstantInt>(R1->getOperand(0)); + ConstantInt *C1 = mdconst::extract<ConstantInt>(R1->getOperand(1)); EXPECT_EQ(C0->getValue(), A); EXPECT_EQ(C1->getValue(), B); } @@ -101,7 +101,8 @@ TEST_F(MDBuilderTest, createTBAANode) { EXPECT_EQ(N0->getOperand(1), R); EXPECT_EQ(N1->getOperand(1), R); EXPECT_EQ(N2->getOperand(1), R); - EXPECT_TRUE(isa<ConstantInt>(N2->getOperand(2))); - EXPECT_EQ(cast<ConstantInt>(N2->getOperand(2))->getZExtValue(), 1U); + EXPECT_TRUE(mdconst::hasa<ConstantInt>(N2->getOperand(2))); + EXPECT_EQ(mdconst::extract<ConstantInt>(N2->getOperand(2))->getZExtValue(), + 1U); } } diff --git a/unittests/IR/MetadataTest.cpp b/unittests/IR/MetadataTest.cpp index 4f7bd720d1c3..f862f049fccc 100644 --- a/unittests/IR/MetadataTest.cpp +++ b/unittests/IR/MetadataTest.cpp @@ -7,13 +7,13 @@ // //===----------------------------------------------------------------------===// -#include "llvm/IR/Metadata.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/Type.h" -#include "llvm/IR/ValueHandle.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" using namespace llvm; @@ -23,6 +23,12 @@ namespace { class MetadataTest : public testing::Test { protected: LLVMContext Context; + MDNode *getNode() { return MDNode::get(Context, None); } + MDNode *getNode(Metadata *MD) { return MDNode::get(Context, MD); } + MDNode *getNode(Metadata *MD1, Metadata *MD2) { + Metadata *MDs[] = {MD1, MD2}; + return MDNode::get(Context, MDs); + } }; typedef MetadataTest MDStringTest; @@ -58,7 +64,7 @@ TEST_F(MDStringTest, PrintingSimple) { std::string Str; raw_string_ostream oss(Str); s->print(oss); - EXPECT_STREQ("metadata !\"testing 1 2 3\"", oss.str().c_str()); + EXPECT_STREQ("!\"testing 1 2 3\"", oss.str().c_str()); } // Test printing of MDString with non-printable characters. @@ -68,7 +74,7 @@ TEST_F(MDStringTest, PrintingComplex) { std::string Str; raw_string_ostream oss(Str); s->print(oss); - EXPECT_STREQ("metadata !\"\\00\\0A\\22\\5C\\FF\"", oss.str().c_str()); + EXPECT_STREQ("!\"\\00\\0A\\22\\5C\\FF\"", oss.str().c_str()); } typedef MetadataTest MDNodeTest; @@ -80,30 +86,27 @@ TEST_F(MDNodeTest, Simple) { MDString *s1 = MDString::get(Context, StringRef(&x[0], 3)); MDString *s2 = MDString::get(Context, StringRef(&y[0], 3)); - ConstantInt *CI = ConstantInt::get(getGlobalContext(), APInt(8, 0)); + ConstantAsMetadata *CI = ConstantAsMetadata::get( + ConstantInt::get(getGlobalContext(), APInt(8, 0))); - std::vector<Value *> V; + std::vector<Metadata *> V; V.push_back(s1); V.push_back(CI); V.push_back(s2); MDNode *n1 = MDNode::get(Context, V); - Value *const c1 = n1; + Metadata *const c1 = n1; MDNode *n2 = MDNode::get(Context, c1); - Value *const c2 = n2; + Metadata *const c2 = n2; MDNode *n3 = MDNode::get(Context, V); MDNode *n4 = MDNode::getIfExists(Context, V); MDNode *n5 = MDNode::getIfExists(Context, c1); MDNode *n6 = MDNode::getIfExists(Context, c2); EXPECT_NE(n1, n2); -#ifdef ENABLE_MDNODE_UNIQUING EXPECT_EQ(n1, n3); -#else - (void) n3; -#endif EXPECT_EQ(n4, n1); EXPECT_EQ(n5, n2); - EXPECT_EQ(n6, (Value*)nullptr); + EXPECT_EQ(n6, (Metadata *)nullptr); EXPECT_EQ(3u, n1->getNumOperands()); EXPECT_EQ(s1, n1->getOperand(0)); @@ -118,22 +121,437 @@ TEST_F(MDNodeTest, Delete) { Constant *C = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 1); Instruction *I = new BitCastInst(C, Type::getInt32Ty(getGlobalContext())); - Value *const V = I; + Metadata *const V = LocalAsMetadata::get(I); MDNode *n = MDNode::get(Context, V); - WeakVH wvh = n; + TrackingMDRef wvh(n); EXPECT_EQ(n, wvh); delete I; } +TEST_F(MDNodeTest, DeleteMDNodeFwdDecl) { + delete MDNode::getTemporary(Context, None); +} + +TEST_F(MDNodeTest, SelfReference) { + // !0 = !{!0} + // !1 = !{!0} + { + MDNode *Temp = MDNode::getTemporary(Context, None); + Metadata *Args[] = {Temp}; + MDNode *Self = MDNode::get(Context, Args); + Self->replaceOperandWith(0, Self); + MDNode::deleteTemporary(Temp); + ASSERT_EQ(Self, Self->getOperand(0)); + + // Self-references should be distinct, so MDNode::get() should grab a + // uniqued node that references Self, not Self. + Args[0] = Self; + MDNode *Ref1 = MDNode::get(Context, Args); + MDNode *Ref2 = MDNode::get(Context, Args); + EXPECT_NE(Self, Ref1); + EXPECT_EQ(Ref1, Ref2); + } + + // !0 = !{!0, !{}} + // !1 = !{!0, !{}} + { + MDNode *Temp = MDNode::getTemporary(Context, None); + Metadata *Args[] = {Temp, MDNode::get(Context, None)}; + MDNode *Self = MDNode::get(Context, Args); + Self->replaceOperandWith(0, Self); + MDNode::deleteTemporary(Temp); + ASSERT_EQ(Self, Self->getOperand(0)); + + // Self-references should be distinct, so MDNode::get() should grab a + // uniqued node that references Self, not Self itself. + Args[0] = Self; + MDNode *Ref1 = MDNode::get(Context, Args); + MDNode *Ref2 = MDNode::get(Context, Args); + EXPECT_NE(Self, Ref1); + EXPECT_EQ(Ref1, Ref2); + } +} + +TEST_F(MDNodeTest, Print) { + Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 7); + MDString *S = MDString::get(Context, "foo"); + MDNode *N0 = getNode(); + MDNode *N1 = getNode(N0); + MDNode *N2 = getNode(N0, N1); + + Metadata *Args[] = {ConstantAsMetadata::get(C), S, nullptr, N0, N1, N2}; + MDNode *N = MDNode::get(Context, Args); + + std::string Expected; + { + raw_string_ostream OS(Expected); + OS << "!{"; + C->printAsOperand(OS); + OS << ", "; + S->printAsOperand(OS); + OS << ", null"; + MDNode *Nodes[] = {N0, N1, N2}; + for (auto *Node : Nodes) + OS << ", <" << (void *)Node << ">"; + OS << "}\n"; + } + + std::string Actual; + { + raw_string_ostream OS(Actual); + N->print(OS); + } + + EXPECT_EQ(Expected, Actual); +} + +TEST_F(MDNodeTest, NullOperand) { + // metadata !{} + MDNode *Empty = MDNode::get(Context, None); + + // metadata !{metadata !{}} + Metadata *Ops[] = {Empty}; + MDNode *N = MDNode::get(Context, Ops); + ASSERT_EQ(Empty, N->getOperand(0)); + + // metadata !{metadata !{}} => metadata !{null} + N->replaceOperandWith(0, nullptr); + ASSERT_EQ(nullptr, N->getOperand(0)); + + // metadata !{null} + Ops[0] = nullptr; + MDNode *NullOp = MDNode::get(Context, Ops); + ASSERT_EQ(nullptr, NullOp->getOperand(0)); + EXPECT_EQ(N, NullOp); +} + +TEST_F(MDNodeTest, DistinctOnUniquingCollision) { + // !{} + MDNode *Empty = MDNode::get(Context, None); + ASSERT_TRUE(Empty->isResolved()); + EXPECT_FALSE(Empty->isDistinct()); + + // !{!{}} + Metadata *Wrapped1Ops[] = {Empty}; + MDNode *Wrapped1 = MDNode::get(Context, Wrapped1Ops); + ASSERT_EQ(Empty, Wrapped1->getOperand(0)); + ASSERT_TRUE(Wrapped1->isResolved()); + EXPECT_FALSE(Wrapped1->isDistinct()); + + // !{!{!{}}} + Metadata *Wrapped2Ops[] = {Wrapped1}; + MDNode *Wrapped2 = MDNode::get(Context, Wrapped2Ops); + ASSERT_EQ(Wrapped1, Wrapped2->getOperand(0)); + ASSERT_TRUE(Wrapped2->isResolved()); + EXPECT_FALSE(Wrapped2->isDistinct()); + + // !{!{!{}}} => !{!{}} + Wrapped2->replaceOperandWith(0, Empty); + ASSERT_EQ(Empty, Wrapped2->getOperand(0)); + EXPECT_TRUE(Wrapped2->isDistinct()); + EXPECT_FALSE(Wrapped1->isDistinct()); +} + +TEST_F(MDNodeTest, getDistinct) { + // !{} + MDNode *Empty = MDNode::get(Context, None); + ASSERT_TRUE(Empty->isResolved()); + ASSERT_FALSE(Empty->isDistinct()); + ASSERT_EQ(Empty, MDNode::get(Context, None)); + + // distinct !{} + MDNode *Distinct1 = MDNode::getDistinct(Context, None); + MDNode *Distinct2 = MDNode::getDistinct(Context, None); + EXPECT_TRUE(Distinct1->isResolved()); + EXPECT_TRUE(Distinct2->isDistinct()); + EXPECT_NE(Empty, Distinct1); + EXPECT_NE(Empty, Distinct2); + EXPECT_NE(Distinct1, Distinct2); + + // !{} + ASSERT_EQ(Empty, MDNode::get(Context, None)); +} + +TEST_F(MDNodeTest, TempIsDistinct) { + MDNode *T = MDNode::getTemporary(Context, None); + EXPECT_TRUE(T->isDistinct()); + MDNode::deleteTemporary(T); +} + +TEST_F(MDNodeTest, getDistinctWithUnresolvedOperands) { + // temporary !{} + MDNodeFwdDecl *Temp = MDNode::getTemporary(Context, None); + ASSERT_FALSE(Temp->isResolved()); + + // distinct !{temporary !{}} + Metadata *Ops[] = {Temp}; + MDNode *Distinct = MDNode::getDistinct(Context, Ops); + EXPECT_TRUE(Distinct->isResolved()); + EXPECT_EQ(Temp, Distinct->getOperand(0)); + + // temporary !{} => !{} + MDNode *Empty = MDNode::get(Context, None); + Temp->replaceAllUsesWith(Empty); + MDNode::deleteTemporary(Temp); + EXPECT_EQ(Empty, Distinct->getOperand(0)); +} + +TEST_F(MDNodeTest, handleChangedOperandRecursion) { + // !0 = !{} + MDNode *N0 = MDNode::get(Context, None); + + // !1 = !{!3, null} + std::unique_ptr<MDNodeFwdDecl> Temp3(MDNode::getTemporary(Context, None)); + Metadata *Ops1[] = {Temp3.get(), nullptr}; + MDNode *N1 = MDNode::get(Context, Ops1); + + // !2 = !{!3, !0} + Metadata *Ops2[] = {Temp3.get(), N0}; + MDNode *N2 = MDNode::get(Context, Ops2); + + // !3 = !{!2} + Metadata *Ops3[] = {N2}; + MDNode *N3 = MDNode::get(Context, Ops3); + Temp3->replaceAllUsesWith(N3); + + // !4 = !{!1} + Metadata *Ops4[] = {N1}; + MDNode *N4 = MDNode::get(Context, Ops4); + + // Confirm that the cycle prevented RAUW from getting dropped. + EXPECT_TRUE(N0->isResolved()); + EXPECT_FALSE(N1->isResolved()); + EXPECT_FALSE(N2->isResolved()); + EXPECT_FALSE(N3->isResolved()); + EXPECT_FALSE(N4->isResolved()); + + // Create a couple of distinct nodes to observe what's going on. + // + // !5 = distinct !{!2} + // !6 = distinct !{!3} + Metadata *Ops5[] = {N2}; + MDNode *N5 = MDNode::getDistinct(Context, Ops5); + Metadata *Ops6[] = {N3}; + MDNode *N6 = MDNode::getDistinct(Context, Ops6); + + // Mutate !2 to look like !1, causing a uniquing collision (and an RAUW). + // This will ripple up, with !3 colliding with !4, and RAUWing. Since !2 + // references !3, this can cause a re-entry of handleChangedOperand() when !3 + // is not ready for it. + // + // !2->replaceOperandWith(1, nullptr) + // !2: !{!3, !0} => !{!3, null} + // !2->replaceAllUsesWith(!1) + // !3: !{!2] => !{!1} + // !3->replaceAllUsesWith(!4) + N2->replaceOperandWith(1, nullptr); + + // If all has gone well, N2 and N3 will have been RAUW'ed and deleted from + // under us. Just check that the other nodes are sane. + // + // !1 = !{!4, null} + // !4 = !{!1} + // !5 = distinct !{!1} + // !6 = distinct !{!4} + EXPECT_EQ(N4, N1->getOperand(0)); + EXPECT_EQ(N1, N4->getOperand(0)); + EXPECT_EQ(N1, N5->getOperand(0)); + EXPECT_EQ(N4, N6->getOperand(0)); +} + +TEST_F(MDNodeTest, replaceResolvedOperand) { + // Check code for replacing one resolved operand with another. If doing this + // directly (via replaceOperandWith()) becomes illegal, change the operand to + // a global value that gets RAUW'ed. + // + // Use a temporary node to keep N from being resolved. + std::unique_ptr<MDNodeFwdDecl> Temp(MDNodeFwdDecl::get(Context, None)); + Metadata *Ops[] = {nullptr, Temp.get()}; + + MDNode *Empty = MDTuple::get(Context, ArrayRef<Metadata *>()); + MDNode *N = MDTuple::get(Context, Ops); + EXPECT_EQ(nullptr, N->getOperand(0)); + ASSERT_FALSE(N->isResolved()); + + // Check code for replacing resolved nodes. + N->replaceOperandWith(0, Empty); + EXPECT_EQ(Empty, N->getOperand(0)); + + // Check code for adding another unresolved operand. + N->replaceOperandWith(0, Temp.get()); + EXPECT_EQ(Temp.get(), N->getOperand(0)); + + // Remove the references to Temp; required for teardown. + Temp->replaceAllUsesWith(nullptr); +} + +typedef MetadataTest MDLocationTest; + +TEST_F(MDLocationTest, Overflow) { + MDNode *N = MDNode::get(Context, None); + { + MDLocation *L = MDLocation::get(Context, 2, 7, N); + EXPECT_EQ(2u, L->getLine()); + EXPECT_EQ(7u, L->getColumn()); + } + unsigned U24 = 1u << 24; + unsigned U8 = 1u << 8; + { + MDLocation *L = MDLocation::get(Context, U24 - 1, U8 - 1, N); + EXPECT_EQ(U24 - 1, L->getLine()); + EXPECT_EQ(U8 - 1, L->getColumn()); + } + { + MDLocation *L = MDLocation::get(Context, U24, U8, N); + EXPECT_EQ(0u, L->getLine()); + EXPECT_EQ(0u, L->getColumn()); + } + { + MDLocation *L = MDLocation::get(Context, U24 + 1, U8 + 1, N); + EXPECT_EQ(0u, L->getLine()); + EXPECT_EQ(0u, L->getColumn()); + } +} + +TEST_F(MDLocationTest, getDistinct) { + MDNode *N = MDNode::get(Context, None); + MDLocation *L0 = MDLocation::getDistinct(Context, 2, 7, N); + EXPECT_TRUE(L0->isDistinct()); + MDLocation *L1 = MDLocation::get(Context, 2, 7, N); + EXPECT_FALSE(L1->isDistinct()); + EXPECT_EQ(L1, MDLocation::get(Context, 2, 7, N)); +} + +typedef MetadataTest MetadataAsValueTest; + +TEST_F(MetadataAsValueTest, MDNode) { + MDNode *N = MDNode::get(Context, None); + auto *V = MetadataAsValue::get(Context, N); + EXPECT_TRUE(V->getType()->isMetadataTy()); + EXPECT_EQ(N, V->getMetadata()); + + auto *V2 = MetadataAsValue::get(Context, N); + EXPECT_EQ(V, V2); +} + +TEST_F(MetadataAsValueTest, MDNodeMDNode) { + MDNode *N = MDNode::get(Context, None); + Metadata *Ops[] = {N}; + MDNode *N2 = MDNode::get(Context, Ops); + auto *V = MetadataAsValue::get(Context, N2); + EXPECT_TRUE(V->getType()->isMetadataTy()); + EXPECT_EQ(N2, V->getMetadata()); + + auto *V2 = MetadataAsValue::get(Context, N2); + EXPECT_EQ(V, V2); + + auto *V3 = MetadataAsValue::get(Context, N); + EXPECT_TRUE(V3->getType()->isMetadataTy()); + EXPECT_NE(V, V3); + EXPECT_EQ(N, V3->getMetadata()); +} + +TEST_F(MetadataAsValueTest, MDNodeConstant) { + auto *C = ConstantInt::getTrue(Context); + auto *MD = ConstantAsMetadata::get(C); + Metadata *Ops[] = {MD}; + auto *N = MDNode::get(Context, Ops); + + auto *V = MetadataAsValue::get(Context, MD); + EXPECT_TRUE(V->getType()->isMetadataTy()); + EXPECT_EQ(MD, V->getMetadata()); + + auto *V2 = MetadataAsValue::get(Context, N); + EXPECT_EQ(MD, V2->getMetadata()); + EXPECT_EQ(V, V2); +} + +typedef MetadataTest ValueAsMetadataTest; + +TEST_F(ValueAsMetadataTest, UpdatesOnRAUW) { + Type *Ty = Type::getInt1PtrTy(Context); + std::unique_ptr<GlobalVariable> GV0( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + auto *MD = ValueAsMetadata::get(GV0.get()); + EXPECT_TRUE(MD->getValue() == GV0.get()); + ASSERT_TRUE(GV0->use_empty()); + + std::unique_ptr<GlobalVariable> GV1( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + GV0->replaceAllUsesWith(GV1.get()); + EXPECT_TRUE(MD->getValue() == GV1.get()); +} + +TEST_F(ValueAsMetadataTest, CollidingDoubleUpdates) { + // Create a constant. + ConstantAsMetadata *CI = ConstantAsMetadata::get( + ConstantInt::get(getGlobalContext(), APInt(8, 0))); + + // Create a temporary to prevent nodes from resolving. + std::unique_ptr<MDNodeFwdDecl> Temp(MDNode::getTemporary(Context, None)); + + // When the first operand of N1 gets reset to nullptr, it'll collide with N2. + Metadata *Ops1[] = {CI, CI, Temp.get()}; + Metadata *Ops2[] = {nullptr, CI, Temp.get()}; + + auto *N1 = MDTuple::get(Context, Ops1); + auto *N2 = MDTuple::get(Context, Ops2); + ASSERT_NE(N1, N2); + + // Tell metadata that the constant is getting deleted. + // + // After this, N1 will be invalid, so don't touch it. + ValueAsMetadata::handleDeletion(CI->getValue()); + EXPECT_EQ(nullptr, N2->getOperand(0)); + EXPECT_EQ(nullptr, N2->getOperand(1)); + EXPECT_EQ(Temp.get(), N2->getOperand(2)); + + // Clean up Temp for teardown. + Temp->replaceAllUsesWith(nullptr); +} + +typedef MetadataTest TrackingMDRefTest; + +TEST_F(TrackingMDRefTest, UpdatesOnRAUW) { + Type *Ty = Type::getInt1PtrTy(Context); + std::unique_ptr<GlobalVariable> GV0( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + TypedTrackingMDRef<ValueAsMetadata> MD(ValueAsMetadata::get(GV0.get())); + EXPECT_TRUE(MD->getValue() == GV0.get()); + ASSERT_TRUE(GV0->use_empty()); + + std::unique_ptr<GlobalVariable> GV1( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + GV0->replaceAllUsesWith(GV1.get()); + EXPECT_TRUE(MD->getValue() == GV1.get()); + + // Reset it, so we don't inadvertently test deletion. + MD.reset(); +} + +TEST_F(TrackingMDRefTest, UpdatesOnDeletion) { + Type *Ty = Type::getInt1PtrTy(Context); + std::unique_ptr<GlobalVariable> GV( + new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage)); + TypedTrackingMDRef<ValueAsMetadata> MD(ValueAsMetadata::get(GV.get())); + EXPECT_TRUE(MD->getValue() == GV.get()); + ASSERT_TRUE(GV->use_empty()); + + GV.reset(); + EXPECT_TRUE(!MD); +} + TEST(NamedMDNodeTest, Search) { LLVMContext Context; - Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 1); - Constant *C2 = ConstantInt::get(Type::getInt32Ty(Context), 2); + ConstantAsMetadata *C = + ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Context), 1)); + ConstantAsMetadata *C2 = + ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Context), 2)); - Value *const V = C; - Value *const V2 = C2; + Metadata *const V = C; + Metadata *const V2 = C2; MDNode *n = MDNode::get(Context, V); MDNode *n2 = MDNode::get(Context, V2); diff --git a/unittests/IR/PassManagerTest.cpp b/unittests/IR/PassManagerTest.cpp index 25037a773cfc..41af0b0bd25c 100644 --- a/unittests/IR/PassManagerTest.cpp +++ b/unittests/IR/PassManagerTest.cpp @@ -29,13 +29,16 @@ public: /// \brief Returns an opaque, unique ID for this pass type. static void *ID() { return (void *)&PassID; } + /// \brief Returns the name of the analysis. + static StringRef name() { return "TestFunctionAnalysis"; } + TestFunctionAnalysis(int &Runs) : Runs(Runs) {} /// \brief Run the analysis pass over the function and return a result. - Result run(Function *F, FunctionAnalysisManager *AM) { + Result run(Function &F, FunctionAnalysisManager *AM) { ++Runs; int Count = 0; - for (Function::iterator BBI = F->begin(), BBE = F->end(); BBI != BBE; ++BBI) + for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; ++II) ++Count; @@ -60,12 +63,14 @@ public: static void *ID() { return (void *)&PassID; } + static StringRef name() { return "TestModuleAnalysis"; } + TestModuleAnalysis(int &Runs) : Runs(Runs) {} - Result run(Module *M, ModuleAnalysisManager *AM) { + Result run(Module &M, ModuleAnalysisManager *AM) { ++Runs; int Count = 0; - for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) ++Count; return Result(Count); } @@ -81,7 +86,7 @@ char TestModuleAnalysis::PassID; struct TestModulePass { TestModulePass(int &RunCount) : RunCount(RunCount) {} - PreservedAnalyses run(Module *M) { + PreservedAnalyses run(Module &M) { ++RunCount; return PreservedAnalyses::none(); } @@ -92,13 +97,13 @@ struct TestModulePass { }; struct TestPreservingModulePass { - PreservedAnalyses run(Module *M) { return PreservedAnalyses::all(); } + PreservedAnalyses run(Module &M) { return PreservedAnalyses::all(); } static StringRef name() { return "TestPreservingModulePass"; } }; struct TestMinPreservingModulePass { - PreservedAnalyses run(Module *M, ModuleAnalysisManager *AM) { + PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) { PreservedAnalyses PA; // Force running an analysis. @@ -119,13 +124,13 @@ struct TestFunctionPass { AnalyzedFunctionCount(AnalyzedFunctionCount), OnlyUseCachedResults(OnlyUseCachedResults) {} - PreservedAnalyses run(Function *F, FunctionAnalysisManager *AM) { + PreservedAnalyses run(Function &F, FunctionAnalysisManager *AM) { ++RunCount; const ModuleAnalysisManager &MAM = AM->getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager(); if (TestModuleAnalysis::Result *TMA = - MAM.getCachedResult<TestModuleAnalysis>(F->getParent())) + MAM.getCachedResult<TestModuleAnalysis>(*F.getParent())) AnalyzedFunctionCount += TMA->FunctionCount; if (OnlyUseCachedResults) { @@ -155,9 +160,9 @@ struct TestFunctionPass { struct TestInvalidationFunctionPass { TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {} - PreservedAnalyses run(Function *F) { - return F->getName() == Name ? PreservedAnalyses::none() - : PreservedAnalyses::all(); + PreservedAnalyses run(Function &F) { + return F.getName() == Name ? PreservedAnalyses::none() + : PreservedAnalyses::all(); } static StringRef name() { return "TestInvalidationFunctionPass"; } @@ -165,10 +170,10 @@ struct TestInvalidationFunctionPass { StringRef Name; }; -Module *parseIR(const char *IR) { +std::unique_ptr<Module> parseIR(const char *IR) { LLVMContext &C = getGlobalContext(); SMDiagnostic Err; - return ParseAssemblyString(IR, nullptr, Err, C); + return parseAssemblyString(IR, Err, C); } class PassManagerTest : public ::testing::Test { @@ -310,7 +315,7 @@ TEST_F(PassManagerTest, Basic) { MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } - MPM.run(M.get(), &MAM); + MPM.run(*M, &MAM); // Validate module pass counters. EXPECT_EQ(1, ModulePassRunCount); diff --git a/unittests/IR/UseTest.cpp b/unittests/IR/UseTest.cpp new file mode 100644 index 000000000000..b575a5978408 --- /dev/null +++ b/unittests/IR/UseTest.cpp @@ -0,0 +1,112 @@ +//===- llvm/unittest/IR/UseTest.cpp - Use unit tests ----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/AsmParser/Parser.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/User.h" +#include "llvm/Support/Format.h" +#include "llvm/Support/SourceMgr.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +TEST(UseTest, sort) { + LLVMContext C; + + const char *ModuleString = "define void @f(i32 %x) {\n" + "entry:\n" + " %v0 = add i32 %x, 0\n" + " %v2 = add i32 %x, 2\n" + " %v5 = add i32 %x, 5\n" + " %v1 = add i32 %x, 1\n" + " %v3 = add i32 %x, 3\n" + " %v7 = add i32 %x, 7\n" + " %v6 = add i32 %x, 6\n" + " %v4 = add i32 %x, 4\n" + " ret void\n" + "}\n"; + SMDiagnostic Err; + char vnbuf[8]; + std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C); + Function *F = M->getFunction("f"); + ASSERT_TRUE(F); + ASSERT_TRUE(F->arg_begin() != F->arg_end()); + Argument &X = *F->arg_begin(); + ASSERT_EQ("x", X.getName()); + + X.sortUseList([](const Use &L, const Use &R) { + return L.getUser()->getName() < R.getUser()->getName(); + }); + unsigned I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", I++); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); + + X.sortUseList([](const Use &L, const Use &R) { + return L.getUser()->getName() > R.getUser()->getName(); + }); + I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", (7 - I++)); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); +} + +TEST(UseTest, reverse) { + LLVMContext C; + + const char *ModuleString = "define void @f(i32 %x) {\n" + "entry:\n" + " %v0 = add i32 %x, 0\n" + " %v2 = add i32 %x, 2\n" + " %v5 = add i32 %x, 5\n" + " %v1 = add i32 %x, 1\n" + " %v3 = add i32 %x, 3\n" + " %v7 = add i32 %x, 7\n" + " %v6 = add i32 %x, 6\n" + " %v4 = add i32 %x, 4\n" + " ret void\n" + "}\n"; + SMDiagnostic Err; + char vnbuf[8]; + std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C); + Function *F = M->getFunction("f"); + ASSERT_TRUE(F); + ASSERT_TRUE(F->arg_begin() != F->arg_end()); + Argument &X = *F->arg_begin(); + ASSERT_EQ("x", X.getName()); + + X.sortUseList([](const Use &L, const Use &R) { + return L.getUser()->getName() < R.getUser()->getName(); + }); + unsigned I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", I++); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); + + X.reverseUseList(); + I = 0; + for (User *U : X.users()) { + snprintf(vnbuf, sizeof(vnbuf), "v%u", (7 - I++)); + EXPECT_EQ(vnbuf, U->getName()); + } + ASSERT_EQ(8u, I); +} + +} // end anonymous namespace diff --git a/unittests/IR/UserTest.cpp b/unittests/IR/UserTest.cpp index eb07e824d8b8..56b054b68359 100644 --- a/unittests/IR/UserTest.cpp +++ b/unittests/IR/UserTest.cpp @@ -9,10 +9,10 @@ #include "llvm/AsmParser/Parser.h" #include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.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; @@ -65,7 +65,7 @@ TEST(UserTest, ValueOpIteration) { " ret void\n" "}\n"; SMDiagnostic Err; - Module *M = ParseAssemblyString(ModuleString, nullptr, Err, C); + std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C); Function *F = M->getFunction("f"); BasicBlock &ExitBB = F->back(); diff --git a/unittests/IR/ValueMapTest.cpp b/unittests/IR/ValueMapTest.cpp index 0b7198fc6ecb..a6bad71cf630 100644 --- a/unittests/IR/ValueMapTest.cpp +++ b/unittests/IR/ValueMapTest.cpp @@ -186,11 +186,11 @@ struct LockMutex : ValueMapConfig<KeyT, MutexT> { }; static void onRAUW(const ExtraData &Data, KeyT Old, KeyT New) { *Data.CalledRAUW = true; - EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked."; + EXPECT_FALSE(Data.M->try_lock()) << "Mutex should already be locked."; } static void onDelete(const ExtraData &Data, KeyT Old) { *Data.CalledDeleted = true; - EXPECT_FALSE(Data.M->tryacquire()) << "Mutex should already be locked."; + EXPECT_FALSE(Data.M->try_lock()) << "Mutex should already be locked."; } static MutexT *getMutex(const ExtraData &Data) { return Data.M; } }; diff --git a/unittests/IR/ValueTest.cpp b/unittests/IR/ValueTest.cpp index 61e44a908d4e..4dd0c2c36cf0 100644 --- a/unittests/IR/ValueTest.cpp +++ b/unittests/IR/ValueTest.cpp @@ -34,7 +34,7 @@ TEST(ValueTest, UsedInBasicBlock) { " ret void\n" "}\n"; SMDiagnostic Err; - Module *M = ParseAssemblyString(ModuleString, nullptr, Err, C); + std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C); Function *F = M->getFunction("f"); @@ -60,6 +60,10 @@ TEST(GlobalTest, CreateAddressSpace) { GlobalVariable::NotThreadLocal, 1); + EXPECT_TRUE(Value::MaximumAlignment == 536870912U); + Dummy0->setAlignment(536870912U); + EXPECT_EQ(Dummy0->getAlignment(), 536870912U); + // Make sure the address space isn't dropped when returning this. Constant *Dummy1 = M->getOrInsertGlobal("dummy", Int32Ty); EXPECT_EQ(Dummy0, Dummy1); @@ -83,4 +87,23 @@ TEST(GlobalTest, CreateAddressSpace) { EXPECT_EQ(1u, DummyCast1->getType()->getPointerAddressSpace()); EXPECT_NE(DummyCast0, DummyCast1) << *DummyCast1; } + +#ifdef GTEST_HAS_DEATH_TEST +#ifndef NDEBUG +TEST(GlobalTest, AlignDeath) { + LLVMContext &Ctx = getGlobalContext(); + std::unique_ptr<Module> M(new Module("TestModule", Ctx)); + Type *Int32Ty = Type::getInt32Ty(Ctx); + GlobalVariable *Var = + new GlobalVariable(*M, Int32Ty, true, GlobalValue::ExternalLinkage, + Constant::getAllOnesValue(Int32Ty), "var", nullptr, + GlobalVariable::NotThreadLocal, 1); + + EXPECT_DEATH(Var->setAlignment(536870913U), "Alignment is not a power of 2"); + EXPECT_DEATH(Var->setAlignment(1073741824U), + "Alignment is greater than MaximumAlignment"); +} +#endif +#endif + } // end anonymous namespace diff --git a/unittests/IR/WaymarkTest.cpp b/unittests/IR/WaymarkTest.cpp index 8e3cd45808f8..a8924efed3f5 100644 --- a/unittests/IR/WaymarkTest.cpp +++ b/unittests/IR/WaymarkTest.cpp @@ -29,8 +29,9 @@ TEST(WaymarkTest, NativeArray) { Value * values[22]; std::transform(tail, tail + 22, values, char2constant); FunctionType *FT = FunctionType::get(Type::getVoidTy(getGlobalContext()), true); - Function *F = Function::Create(FT, GlobalValue::ExternalLinkage); - const CallInst *A = CallInst::Create(F, makeArrayRef(values)); + std::unique_ptr<Function> F( + Function::Create(FT, GlobalValue::ExternalLinkage)); + const CallInst *A = CallInst::Create(F.get(), makeArrayRef(values)); ASSERT_NE(A, (const CallInst*)nullptr); ASSERT_EQ(1U + 22, A->getNumOperands()); const Use *U = &A->getOperandUse(0); |