aboutsummaryrefslogtreecommitdiffstats
path: root/lib/IR
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2013-01-15 20:52:06 +0000
committerDaniel Dunbar <daniel@zuster.org>2013-01-15 20:52:06 +0000
commit12bfff440700c58bc67e9f9d8f99121632022cf1 (patch)
tree17318e72f917ccb6b8d579165f15fd00d7f34b0f /lib/IR
parent6a459e65c8bd90e8381361379255ebfb9552b5cf (diff)
downloadexternal_llvm-12bfff440700c58bc67e9f9d8f99121632022cf1.zip
external_llvm-12bfff440700c58bc67e9f9d8f99121632022cf1.tar.gz
external_llvm-12bfff440700c58bc67e9f9d8f99121632022cf1.tar.bz2
[IR] Add verification for module flags with the "require" behavior.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172549 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/IR')
-rw-r--r--lib/IR/Verifier.cpp42
1 files changed, 35 insertions, 7 deletions
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index 5a4a5a7..2488a7d 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -243,7 +243,8 @@ namespace {
void visitNamedMDNode(NamedMDNode &NMD);
void visitMDNode(MDNode &MD, Function *F);
void visitModuleFlags(Module &M);
- void visitModuleFlag(MDNode *Op, SmallSetVector<MDString*, 16> &SeenIDs);
+ void visitModuleFlag(MDNode *Op, DenseMap<MDString*, MDNode*> &SeenIDs,
+ SmallVectorImpl<MDNode*> &Requirements);
void visitFunction(Function &F);
void visitBasicBlock(BasicBlock &BB);
using InstVisitor<Verifier>::visit;
@@ -529,15 +530,37 @@ void Verifier::visitModuleFlags(Module &M) {
const NamedMDNode *Flags = M.getModuleFlagsMetadata();
if (!Flags) return;
- // Scan each flag.
- SmallSetVector<MDString*, 16> SeenIDs;
+ // Scan each flag, and track the flags and requirements.
+ DenseMap<MDString*, MDNode*> SeenIDs;
+ SmallVector<MDNode*, 16> Requirements;
for (unsigned I = 0, E = Flags->getNumOperands(); I != E; ++I) {
- visitModuleFlag(Flags->getOperand(I), SeenIDs);
+ visitModuleFlag(Flags->getOperand(I), SeenIDs, Requirements);
+ }
+
+ // Validate that the requirements in the module are valid.
+ for (unsigned I = 0, E = Requirements.size(); I != E; ++I) {
+ MDNode *Requirement = Requirements[I];
+ MDString *Flag = cast<MDString>(Requirement->getOperand(0));
+ Value *ReqValue = Requirement->getOperand(1);
+
+ MDNode *Op = SeenIDs.lookup(Flag);
+ if (!Op) {
+ CheckFailed("invalid requirement on flag, flag is not present in module",
+ Flag);
+ continue;
+ }
+
+ if (Op->getOperand(2) != ReqValue) {
+ CheckFailed(("invalid requirement on flag, "
+ "flag does not have the required value"),
+ Flag);
+ continue;
+ }
}
}
-void Verifier::visitModuleFlag(MDNode *Op,
- SmallSetVector<MDString*, 16> &SeenIDs) {
+void Verifier::visitModuleFlag(MDNode *Op, DenseMap<MDString*, MDNode*>&SeenIDs,
+ SmallVectorImpl<MDNode*> &Requirements) {
// Each module flag should have three arguments, the merge behavior (a
// constant int), the flag ID (an MDString), and the value.
Assert1(Op->getNumOperands() == 3,
@@ -558,7 +581,8 @@ void Verifier::visitModuleFlag(MDNode *Op,
// Unless this is a "requires" flag, check the ID is unique.
if (BehaviorValue != Module::Require) {
- Assert1(SeenIDs.insert(ID),
+ bool Inserted = SeenIDs.insert(std::make_pair(ID, Op)).second;
+ Assert1(Inserted,
"module flag identifiers must be unique (or of 'require' type)",
ID);
}
@@ -575,6 +599,10 @@ void Verifier::visitModuleFlag(MDNode *Op,
("invalid value for 'require' module flag "
"(first value operand should be a string)"),
Value->getOperand(0));
+
+ // Append it to the list of requirements, to check once all module flags are
+ // scanned.
+ Requirements.push_back(Value);
}
}