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);
"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) {
&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);
--- /dev/null
+; 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
--- /dev/null
+; 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