summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/Verifier.cpp
diff options
context:
space:
mode:
authorKeno Fischer <kfischer@college.harvard.edu>2016-01-14 22:20:56 +0000
committerKeno Fischer <kfischer@college.harvard.edu>2016-01-14 22:20:56 +0000
commit60f82a269f975c7cd45b1dfd2721b28db75e905e (patch)
tree8bb1933b8a60930c39a9fd4c181a5d1734009317 /llvm/lib/IR/Verifier.cpp
parent565b30138032d23efb95887dfc2a49ceac4f2d9c (diff)
downloadbcm5719-llvm-60f82a269f975c7cd45b1dfd2721b28db75e905e.tar.gz
bcm5719-llvm-60f82a269f975c7cd45b1dfd2721b28db75e905e.zip
[Verifier] Verify that a GlobalValue is only used in this Module
Summary: We already have the inverse verification that we only use globals that are defined in this module. This essentially catches the same mistake, but when verifying the module that contains the definition. Reviewers: rafael Differential Revision: http://reviews.llvm.org/D15272 llvm-svn: 257823
Diffstat (limited to 'llvm/lib/IR/Verifier.cpp')
-rw-r--r--llvm/lib/IR/Verifier.cpp36
1 files changed, 36 insertions, 0 deletions
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index c4519c48ab5..cbd0bee054b 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -462,6 +462,18 @@ void Verifier::visit(Instruction &I) {
InstVisitor<Verifier>::visit(I);
}
+// Helper to recursively iterate over indirect users. By
+// returning false, the callback can ask to stop recursing
+// further.
+static void forEachUser(const Value *User,
+ SmallPtrSet<const Value *, 32> &Visited,
+ llvm::function_ref<bool(const Value *)> Callback) {
+ if (!Visited.insert(User).second)
+ return;
+ for (const Value *TheNextUser : User->users())
+ if (Callback(TheNextUser))
+ forEachUser(TheNextUser, Visited, Callback);
+}
void Verifier::visitGlobalValue(const GlobalValue &GV) {
Assert(!GV.isDeclaration() || GV.hasExternalLinkage() ||
@@ -481,6 +493,30 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) {
if (GV.isDeclarationForLinker())
Assert(!GV.hasComdat(), "Declaration may not be in a Comdat!", &GV);
+
+ // Verify that this GlobalValue is only used in this module.
+ // This map is used to avoid visiting uses twice. We can arrive at a user
+ // twice, if they have multiple operands. In particular for very large
+ // constant expressions, we can arrive at a particular user many times.
+ SmallPtrSet<const Value *, 32> Visited;
+ forEachUser(&GV, Visited, [&](const Value *V) -> bool {
+ if (const Instruction *I = dyn_cast<Instruction>(V)) {
+ if (!I->getParent() || !I->getParent()->getParent())
+ CheckFailed("Global is referenced by parentless instruction!", &GV,
+ M, I);
+ else if (I->getParent()->getParent()->getParent() != M)
+ CheckFailed("Global is referenced in a different module!", &GV,
+ M, I, I->getParent()->getParent(),
+ I->getParent()->getParent()->getParent());
+ return false;
+ } else if (const Function *F = dyn_cast<Function>(V)) {
+ if (F->getParent() != M)
+ CheckFailed("Global is used by function in a different module", &GV,
+ M, F, F->getParent());
+ return false;
+ }
+ return true;
+ });
}
void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
OpenPOWER on IntegriCloud