mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
Add verification for align, dereferenceable, dereferenceable_or_null load metadata
Reviewed By: reames Differential Revision: http://reviews.llvm.org/D13428 llvm-svn: 249856
This commit is contained in:
parent
349c2d6fbd
commit
694f6d1578
@ -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(Instruction &I, unsigned i) {
|
||||
"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(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);
|
||||
|
59
test/Verifier/align-md.ll
Normal file
59
test/Verifier/align-md.ll
Normal file
@ -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
|
86
test/Verifier/dereferenceable-md.ll
Normal file
86
test/Verifier/dereferenceable-md.ll
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user