Index: llvm/trunk/lib/IR/Verifier.cpp =================================================================== --- llvm/trunk/lib/IR/Verifier.cpp +++ llvm/trunk/lib/IR/Verifier.cpp @@ -306,6 +306,7 @@ void visitFunction(const Function &F); void visitBasicBlock(BasicBlock &BB); void visitRangeMetadata(Instruction& I, MDNode* Range, Type* Ty); + void visitDereferenceableMetadata(Instruction& I, MDNode* MD); template bool isValidMetadataArray(const MDTuple &N); #define HANDLE_SPECIALIZED_MDNODE_LEAF(CLASS) void visit##CLASS(const CLASS &N); @@ -3072,6 +3073,19 @@ "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(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(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 @@ &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(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(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(N), "invalid !dbg metadata attachment", &I, N); visitMDNode(*N); Index: llvm/trunk/test/Verifier/align-md.ll =================================================================== --- llvm/trunk/test/Verifier/align-md.ll +++ llvm/trunk/test/Verifier/align-md.ll @@ -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 Index: llvm/trunk/test/Verifier/dereferenceable-md.ll =================================================================== --- llvm/trunk/test/Verifier/dereferenceable-md.ll +++ llvm/trunk/test/Verifier/dereferenceable-md.ll @@ -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