[llvm] r249856 - Add verification for align, dereferenceable, dereferenceable_or_null load metadata

Artur Pilipenko via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 9 10:41:29 PDT 2015


Author: apilipenko
Date: Fri Oct  9 12:41:29 2015
New Revision: 249856

URL: http://llvm.org/viewvc/llvm-project?rev=249856&view=rev
Log:
Add verification for align, dereferenceable, dereferenceable_or_null load metadata

Reviewed By: reames

Differential Revision: http://reviews.llvm.org/D13428

Added:
    llvm/trunk/test/Verifier/align-md.ll
    llvm/trunk/test/Verifier/dereferenceable-md.ll
Modified:
    llvm/trunk/lib/IR/Verifier.cpp

Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=249856&r1=249855&r2=249856&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Fri Oct  9 12:41:29 2015
@@ -306,6 +306,7 @@ private:
   void visitFunction(const Function &F);
   void visitBasicBlock(BasicBlock &BB);
   void visitRangeMetadata(Instruction& I, MDNode* Range, Type* Ty);
+  void visitDereferenceableMetadata(Instruction& I, MDNode* MD);
 
   template <class Ty> bool isValidMetadataArray(const MDTuple &N);
 #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N);
@@ -3072,6 +3073,19 @@ void Verifier::verifyDominatesUse(Instru
          "Instruction does not dominate all uses!", Op, &I);
 }
 
+void Verifier::visitDereferenceableMetadata(Instruction& I, MDNode* MD) {
+  Assert(I.getType()->isPointerTy(), "dereferenceable, dereferenceable_or_null "
+         "apply only to pointer types", &I);
+  Assert(isa<LoadInst>(I),
+         "dereferenceable, dereferenceable_or_null apply only to load"
+         " instructions, use attributes for calls or invokes", &I);
+  Assert(MD->getNumOperands() == 1, "dereferenceable, dereferenceable_or_null "
+         "take one operand!", &I);
+  ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0));
+  Assert(CI && CI->getType()->isIntegerTy(64), "dereferenceable, "
+         "dereferenceable_or_null metadata value must be an i64!", &I);
+}
+
 /// verifyInstruction - Verify that an instruction is well formed.
 ///
 void Verifier::visitInstruction(Instruction &I) {
@@ -3208,6 +3222,28 @@ void Verifier::visitInstruction(Instruct
            &I);
   }
 
+  if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable))
+    visitDereferenceableMetadata(I, MD);
+
+  if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable_or_null))
+    visitDereferenceableMetadata(I, MD);
+
+  if (MDNode *AlignMD = I.getMetadata(LLVMContext::MD_align)) {
+    Assert(I.getType()->isPointerTy(), "align applies only to pointer types",
+           &I);
+    Assert(isa<LoadInst>(I), "align applies only to load instructions, "
+           "use attributes for calls or invokes", &I);
+    Assert(AlignMD->getNumOperands() == 1, "align takes one operand!", &I);
+    ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(AlignMD->getOperand(0));
+    Assert(CI && CI->getType()->isIntegerTy(64),
+           "align metadata value must be an i64!", &I);
+    uint64_t Align = CI->getZExtValue();
+    Assert(isPowerOf2_64(Align),
+           "align metadata value must be a power of 2!", &I);
+    Assert(Align <= Value::MaximumAlignment,
+           "alignment is larger that implementation defined limit", &I);
+  }
+
   if (MDNode *N = I.getDebugLoc().getAsMDNode()) {
     Assert(isa<DILocation>(N), "invalid !dbg metadata attachment", &I, N);
     visitMDNode(*N);

Added: llvm/trunk/test/Verifier/align-md.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/align-md.ll?rev=249856&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/align-md.ll (added)
+++ llvm/trunk/test/Verifier/align-md.ll Fri Oct  9 12:41:29 2015
@@ -0,0 +1,59 @@
+; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
+
+declare i8* @foo()
+
+define void @f1() {
+entry:
+  call i8* @foo(), !align !{i64 2}
+  ret void
+}
+; CHECK: align applies only to load instructions
+; CHECK-NEXT: call i8* @foo()
+
+define i8 @f2(i8* %x) {
+entry:
+  %y = load i8, i8* %x, !align !{i64 2}
+  ret i8 %y
+}
+; CHECK: align applies only to pointer types
+; CHECK-NEXT: load i8, i8* %x
+
+define i8* @f3(i8** %x) {
+entry:
+  %y = load i8*, i8** %x, !align !{}
+  ret i8* %y
+}
+; CHECK: align takes one operand
+; CHECK-NEXT: load i8*, i8** %x
+
+define i8* @f4(i8** %x) {
+entry:
+  %y = load i8*, i8** %x, !align !{!"str"}
+  ret i8* %y
+}
+; CHECK: align metadata value must be an i64!
+; CHECK-NEXT: load i8*, i8** %x
+
+define i8* @f5(i8** %x) {
+entry:
+  %y = load i8*, i8** %x, !align !{i32 2}
+  ret i8* %y
+}
+; CHECK: align metadata value must be an i64!
+; CHECK-NEXT: load i8*, i8** %x
+
+define i8* @f6(i8** %x) {
+entry:
+  %y = load i8*, i8** %x, !align !{i64 3}
+  ret i8* %y
+}
+; CHECK: align metadata value must be a power of 2!
+; CHECK-NEXT: load i8*, i8** %x
+
+define i8* @f7(i8** %x) {
+entry:
+  %y = load i8*, i8** %x, !align !{i64 1073741824}
+  ret i8* %y
+}
+; CHECK: alignment is larger that implementation defined limit
+; CHECK-NEXT: load i8*, i8** %x
\ No newline at end of file

Added: llvm/trunk/test/Verifier/dereferenceable-md.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Verifier/dereferenceable-md.ll?rev=249856&view=auto
==============================================================================
--- llvm/trunk/test/Verifier/dereferenceable-md.ll (added)
+++ llvm/trunk/test/Verifier/dereferenceable-md.ll Fri Oct  9 12:41:29 2015
@@ -0,0 +1,86 @@
+; RUN: not llvm-as < %s -o /dev/null 2>&1 | FileCheck %s
+
+declare i8* @foo()
+
+define void @f1() {
+entry:
+  call i8* @foo(), !dereferenceable !{i64 2}
+  ret void
+}
+; CHECK: dereferenceable, dereferenceable_or_null apply only to load instructions, use attributes for calls or invokes
+; CHECK-NEXT: call i8* @foo()
+
+define void @f2() {
+entry:
+  call i8* @foo(), !dereferenceable_or_null !{i64 2}
+  ret void
+}
+; CHECK: dereferenceable, dereferenceable_or_null apply only to load instructions, use attributes for calls or invokes
+; CHECK-NEXT: call i8* @foo()
+
+define i8 @f3(i8* %x) {
+entry:
+  %y = load i8, i8* %x, !dereferenceable !{i64 2}
+  ret i8 %y
+}
+; CHECK: dereferenceable, dereferenceable_or_null apply only to pointer types
+; CHECK-NEXT: load i8, i8* %x
+
+define i8 @f4(i8* %x) {
+entry:
+  %y = load i8, i8* %x, !dereferenceable_or_null !{i64 2}
+  ret i8 %y
+}
+; CHECK: dereferenceable, dereferenceable_or_null apply only to pointer types
+; CHECK-NEXT: load i8, i8* %x
+
+define i8* @f5(i8** %x) {
+entry:
+  %y = load i8*, i8** %x, !dereferenceable !{}
+  ret i8* %y
+}
+; CHECK: dereferenceable, dereferenceable_or_null take one operand
+; CHECK-NEXT: load i8*, i8** %x
+
+
+define i8* @f6(i8** %x) {
+entry:
+  %y = load i8*, i8** %x, !dereferenceable_or_null !{}
+  ret i8* %y
+}
+; CHECK: dereferenceable, dereferenceable_or_null take one operand
+; CHECK-NEXT: load i8*, i8** %x
+
+define i8* @f7(i8** %x) {
+entry:
+  %y = load i8*, i8** %x, !dereferenceable !{!"str"}
+  ret i8* %y
+}
+; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64!
+; CHECK-NEXT: load i8*, i8** %x
+
+
+define i8* @f8(i8** %x) {
+entry:
+  %y = load i8*, i8** %x, !dereferenceable_or_null !{!"str"}
+  ret i8* %y
+}
+; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64!
+; CHECK-NEXT: load i8*, i8** %x
+
+define i8* @f9(i8** %x) {
+entry:
+  %y = load i8*, i8** %x, !dereferenceable !{i32 2}
+  ret i8* %y
+}
+; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64!
+; CHECK-NEXT: load i8*, i8** %x
+
+
+define i8* @f10(i8** %x) {
+entry:
+  %y = load i8*, i8** %x, !dereferenceable_or_null !{i32 2}
+  ret i8* %y
+}
+; CHECK: dereferenceable, dereferenceable_or_null metadata value must be an i64!
+; CHECK-NEXT: load i8*, i8** %x
\ No newline at end of file




More information about the llvm-commits mailing list