diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -461,6 +461,8 @@ void visitDereferenceableMetadata(Instruction &I, MDNode *MD); void visitProfMetadata(Instruction &I, MDNode *MD); void visitAnnotationMetadata(MDNode *Annotation); + void visitAliasScopeMetadata(const MDNode *MD); + void visitAliasScopeListMetadata(const MDNode *MD); template bool isValidMetadataArray(const MDTuple &N); #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N); @@ -4343,6 +4345,38 @@ Assert(isa(Op.get()), "operands must be strings"); } +void Verifier::visitAliasScopeMetadata(const MDNode *MD) { + unsigned NumOps = MD->getNumOperands(); + Assert(NumOps >= 2 && NumOps <= 3, "scope must have two or three operands", + MD); + Assert(MD->getOperand(0) == MD || isa(MD->getOperand(0)), + "first scope operand must be self-referential or string", MD); + if (NumOps == 3) + Assert(isa(MD->getOperand(2)), + "third scope operand must be string (if used)", MD); + + MDNode *Domain = dyn_cast(MD->getOperand(1)); + Assert(Domain != nullptr, "second scope operand must be MDNode", MD); + + unsigned NumDomainOps = Domain->getNumOperands(); + Assert(NumDomainOps >= 1 && NumDomainOps <= 2, + "domain must have one or two operands", Domain); + Assert(Domain->getOperand(0) == Domain || + isa(Domain->getOperand(0)), + "first domain operand must be self-referential or string", Domain); + if (NumDomainOps == 2) + Assert(isa(Domain->getOperand(1)), + "second domain operand must be string (if used)", Domain); +} + +void Verifier::visitAliasScopeListMetadata(const MDNode *MD) { + for (const MDOperand &Op : MD->operands()) { + const MDNode *OpMD = dyn_cast(Op); + Assert(OpMD != nullptr, "scope list must consist of MDNodes", MD); + visitAliasScopeMetadata(OpMD); + } +} + /// verifyInstruction - Verify that an instruction is well formed. /// void Verifier::visitInstruction(Instruction &I) { @@ -4502,6 +4536,11 @@ if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa)) TBAAVerifyHelper.visitTBAAMetadata(I, TBAA); + if (MDNode *MD = I.getMetadata(LLVMContext::MD_noalias)) + visitAliasScopeListMetadata(MD); + if (MDNode *MD = I.getMetadata(LLVMContext::MD_alias_scope)) + visitAliasScopeListMetadata(MD); + if (MDNode *AlignMD = I.getMetadata(LLVMContext::MD_align)) { Assert(I.getType()->isPointerTy(), "align applies only to pointer types", &I); @@ -5719,6 +5758,7 @@ II); Assert(ScopeListMD->getNumOperands() == 1, "!id.scope.list must point to a list with a single scope", II); + visitAliasScopeListMetadata(ScopeListMD); } // Only check the domination rule when requested. Once all passes have been diff --git a/llvm/test/Verifier/alias-scope-metadata.ll b/llvm/test/Verifier/alias-scope-metadata.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/alias-scope-metadata.ll @@ -0,0 +1,61 @@ +; RUN: not llvm-as %s -o /dev/null 2>&1 | FileCheck %s + +define void @test(i8* %p) { + load i8, i8* %p, !noalias !0 + load i8, i8* %p, !noalias !1 + load i8, i8* %p, !noalias !3 + load i8, i8* %p, !noalias !5 + load i8, i8* %p, !noalias !7 + load i8, i8* %p, !noalias !9 + load i8, i8* %p, !noalias !11 + load i8, i8* %p, !noalias !14 + load i8, i8* %p, !alias.scope !17 + call void @llvm.experimental.noalias.scope.decl(metadata !20) + ret void +} + +declare void @llvm.experimental.noalias.scope.decl(metadata) + +; CHECK: scope list must consist of MDNodes +!0 = !{!"str"} + +; CHECK: scope must have two or three operands +!1 = !{!2} +!2 = !{!2} + +; CHECK: scope must have two or three operands +!3 = !{!4} +!4 = !{!4, !5, !6, !7} + +; CHECK: first scope operand must be self-referential or string +!5 = !{!6} +!6 = !{!7, !8} + +; CHECK: third scope operand must be string (if used) +!7 = !{!8} +!8 = !{!8, !9, !10} + +; CHECK: second scope operand must be MDNode +!9 = !{!10} +!10 = !{!10, !"str"} + +; CHECK: domain must have one or two operands +!11 = !{!12} +!12 = !{!12, !13} +!13 = !{} + +; CHECK: domain must have one or two operands +!14 = !{!15} +!15 = !{!15, !16} +!16 = !{!17, !18, !19} + +; CHECK: first domain operand must be self-referential or string +!17 = !{!18} +!18 = !{!18, !19} +!19 = !{!20} + +; CHECK: second domain operand must be string (if used) +!20 = !{!21} +!21 = !{!21, !22} +!22 = !{!22, !23} +!23 = !{}