From 12bfff440700c58bc67e9f9d8f99121632022cf1 Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Tue, 15 Jan 2013 20:52:06 +0000 Subject: [PATCH] [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 --- lib/IR/Verifier.cpp | 42 +++++++++++++++++++++++++++------ test/Verifier/module-flags-1.ll | 18 ++++++++++++-- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 5a4a5a790ed..2488a7de169 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 &SeenIDs); + void visitModuleFlag(MDNode *Op, DenseMap &SeenIDs, + SmallVectorImpl &Requirements); void visitFunction(Function &F); void visitBasicBlock(BasicBlock &BB); using InstVisitor::visit; @@ -529,15 +530,37 @@ void Verifier::visitModuleFlags(Module &M) { const NamedMDNode *Flags = M.getModuleFlagsMetadata(); if (!Flags) return; - // Scan each flag. - SmallSetVector SeenIDs; + // Scan each flag, and track the flags and requirements. + DenseMap SeenIDs; + SmallVector 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(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 &SeenIDs) { +void Verifier::visitModuleFlag(MDNode *Op, DenseMap&SeenIDs, + SmallVectorImpl &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); } } diff --git a/test/Verifier/module-flags-1.ll b/test/Verifier/module-flags-1.ll index eafb1139f21..94e98171153 100644 --- a/test/Verifier/module-flags-1.ll +++ b/test/Verifier/module-flags-1.ll @@ -31,7 +31,21 @@ !8 = metadata !{ i32 2, metadata !"foo", i32 50 } ; CHECK-NOT: module flag identifiers must be unique !9 = metadata !{ i32 2, metadata !"bar", i32 51 } -!10 = metadata !{ i32 3, metadata !"bar", i32 51 } +!10 = metadata !{ i32 3, metadata !"bar", metadata !{ metadata !"bar", i32 51 } } + +; Check that any 'require' module flags are valid. +; CHECK: invalid requirement on flag, flag is not present in module +!11 = metadata !{ i32 3, metadata !"bar", + metadata !{ metadata !"no-such-flag", i32 52 } } +; CHECK: invalid requirement on flag, flag does not have the required value +!12 = metadata !{ i32 1, metadata !"flag-0", i32 53 } +!13 = metadata !{ i32 3, metadata !"bar", + metadata !{ metadata !"flag-0", i32 54 } } +; CHECK-NOT: invalid requirement on flag, flag is not present in module +; CHECK-NOT: invalid requirement on flag, flag does not have the required value +!14 = metadata !{ i32 1, metadata !"flag-1", i32 55 } +!15 = metadata !{ i32 3, metadata !"bar", + metadata !{ metadata !"flag-1", i32 55 } } !llvm.module.flags = !{ - !0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10 } + !0, !1, !2, !3, !4, !5, !6, !7, !8, !9, !10, !11, !12, !13, !14, !15 } -- 2.34.1