Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -302,6 +302,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); @@ -3068,6 +3069,22 @@ "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, "dereferenceable, dereferenceable_or_null metadata " + "value must be an integer!", &I); + Assert(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) { @@ -3204,6 +3221,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, "align metadata value must be an integer!", &I); + Assert(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 too big", &I); + } + if (MDNode *N = I.getDebugLoc().getAsMDNode()) { Assert(isa(N), "invalid !dbg metadata attachment", &I, N); visitMDNode(*N); Index: test/Verifier/align-md.ll =================================================================== --- /dev/null +++ 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(), !align !{i64 2} + +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, !align !{i64 2} + +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, !align !{} + +define i8* @f4(i8** %x) { +entry: + %y = load i8*, i8** %x, !align !{!"str"} + ret i8* %y +} +; CHECK: align metadata value must be an integer! +; CHECK-NEXT: load i8*, i8** %x, !align !{!"str"} + +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, !align !{i32 2} + +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, !align !{i32 3} + +define i8* @f7(i8** %x) { +entry: + %y = load i8*, i8** %x, !align !{i64 1073741824} + ret i8* %y +} +; CHECK: alignment is too big +; CHECK-NEXT: load i8*, i8** %x, !align !{i32 1073741824} \ No newline at end of file Index: test/Verifier/dereferenceable-md.ll =================================================================== --- /dev/null +++ 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(), !dereferenceable !{i64 2} + +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(), !dereferenceable !{i64 2} + +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, !dereferenceable !{i64 2} + +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, !dereferenceable_or_null !{i64 2} + +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, !dereferenceable !{} + + +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, !dereferenceable_or_null !{} + +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 integer! +; CHECK-NEXT: load i8*, i8** %x, !dereferenceable !{!"str"} + + +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 integer! +; CHECK-NEXT: load i8*, i8** %x, !dereferenceable_or_null !{!"str"} + +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, !dereferenceable !{i32 2} + + +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, !dereferenceable_or_null !{i32 2} \ No newline at end of file