summaryrefslogtreecommitdiff
path: root/unittests/IR
diff options
context:
space:
mode:
Diffstat (limited to 'unittests/IR')
-rw-r--r--unittests/IR/CMakeLists.txt3
-rw-r--r--unittests/IR/ConstantsTest.cpp73
-rw-r--r--unittests/IR/DebugInfoTest.cpp68
-rw-r--r--unittests/IR/DominatorTreeTest.cpp7
-rw-r--r--unittests/IR/IRBuilderTest.cpp4
-rw-r--r--unittests/IR/LeakDetectorTest.cpp31
-rw-r--r--unittests/IR/LegacyPassManagerTest.cpp52
-rw-r--r--unittests/IR/MDBuilderTest.cpp21
-rw-r--r--unittests/IR/MetadataTest.cpp456
-rw-r--r--unittests/IR/PassManagerTest.cpp35
-rw-r--r--unittests/IR/UseTest.cpp112
-rw-r--r--unittests/IR/UserTest.cpp4
-rw-r--r--unittests/IR/ValueMapTest.cpp4
-rw-r--r--unittests/IR/ValueTest.cpp25
-rw-r--r--unittests/IR/WaymarkTest.cpp5
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);