mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-28 14:10:55 +00:00
add the 'alloc' metadata node to represent the size of offset of buffers pointed to by pointers.
This metadata can be attached to any instruction returning a pointer git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158660 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
96ef284da4
commit
fa7494306b
@ -105,6 +105,7 @@
|
||||
<li><a href="#tbaa">'<tt>tbaa</tt>' Metadata</a></li>
|
||||
<li><a href="#fpmath">'<tt>fpmath</tt>' Metadata</a></li>
|
||||
<li><a href="#range">'<tt>range</tt>' Metadata</a></li>
|
||||
<li><a href="#alloc">'<tt>alloc</tt>' Metadata</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
</ol>
|
||||
@ -3077,6 +3078,49 @@ call void @llvm.dbg.value(metadata !24, i64 0, metadata !25)
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<h4>
|
||||
<a name="alloc">'<tt>alloc</tt>' Metadata</a>
|
||||
</h4>
|
||||
|
||||
<div>
|
||||
|
||||
<p><tt>alloc</tt> metadata may be attached to any instruction returning a
|
||||
pointer. It can be used to express the size and offset relative to the
|
||||
beginning of the buffer pointed by.</p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>The first parameter is a function that returns the size of the buffer, and
|
||||
the second (optional) parameter is a function that returns the offset from
|
||||
the beginning of the buffer. If the second parameter is not present or null,
|
||||
the offset is assumed to be null. Both functions must be either readonly or
|
||||
readnone.</p>
|
||||
<p><tt>alloc</tt> metadata can have additional parameters, which are passed to
|
||||
the size and offset functions when they are evaluated. Therefore the size and
|
||||
offset functions must have the same signature.</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
|
||||
<p>Examples:</p>
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
; size of buffer allocated by this call is my_malloc_size(%s), and offset=0
|
||||
%a = call my_malloc(%s), !alloc !{i32 (i32)* @my_malloc_size, null, i32 %s}
|
||||
|
||||
; size of the buffer pointed by *ptr is size(%x), and offset=offset(%x)
|
||||
%b = load i8** %foo, !alloc !{i32 (i32)* @size, i32 (i32)* @offset, i32 %x}
|
||||
|
||||
; size of buffer allocated by this call is foo_size(), and offset=0
|
||||
%a = call alloc_foo(%s), !alloc !0
|
||||
...
|
||||
!0 = metadata {i32 ()* @foo_size}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -43,7 +43,8 @@ public:
|
||||
MD_tbaa = 1, // "tbaa"
|
||||
MD_prof = 2, // "prof"
|
||||
MD_fpmath = 3, // "fpmath"
|
||||
MD_range = 4 // "range"
|
||||
MD_range = 4, // "range"
|
||||
MD_alloc = 5 // "alloc"
|
||||
};
|
||||
|
||||
/// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
|
||||
|
@ -53,6 +53,11 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
|
||||
unsigned RangeID = getMDKindID("range");
|
||||
assert(RangeID == MD_range && "range kind id drifted");
|
||||
(void)RangeID;
|
||||
|
||||
// Create the 'alloc' metadata kind.
|
||||
unsigned AllocID = getMDKindID("alloc");
|
||||
assert(AllocID == MD_alloc && "alloc kind id drifted");
|
||||
(void)AllocID;
|
||||
}
|
||||
LLVMContext::~LLVMContext() { delete pImpl; }
|
||||
|
||||
|
@ -1672,6 +1672,39 @@ void Verifier::visitInstruction(Instruction &I) {
|
||||
}
|
||||
}
|
||||
|
||||
if (MDNode *MD = I.getMetadata(LLVMContext::MD_alloc)) {
|
||||
Assert1(I.getType()->isPointerTy(), "alloc requires a pointer result", &I);
|
||||
Assert1(MD->getNumOperands() >= 1, "alloc takes at least one operand", &I);
|
||||
Function *SizeFn = dyn_cast<Function>(MD->getOperand(0));
|
||||
Function *OffsetFn = MD->getNumOperands() >= 2 ?
|
||||
dyn_cast_or_null<Function>(MD->getOperand(1)) : 0;
|
||||
Assert1(SizeFn, "first parameter of alloc must be a function", &I);
|
||||
Assert1(MD->getNumOperands() == 1 || !MD->getOperand(1) || OffsetFn,
|
||||
"second parameter of alloc must be either a function or null", &I);
|
||||
Assert1(SizeFn->onlyReadsMemory(),
|
||||
"size function must be readonly/readnone", &I);
|
||||
Assert1(!OffsetFn || OffsetFn->onlyReadsMemory(),
|
||||
"offset function must be readonly/readnone", &I);
|
||||
Assert1(SizeFn->getReturnType()->isIntegerTy(),
|
||||
"size function must return an integer", &I);
|
||||
Assert1(!OffsetFn || OffsetFn->getReturnType()->isIntegerTy(),
|
||||
"offset function must return an integer", &I);
|
||||
|
||||
FunctionType *SizeFnTy = SizeFn->getFunctionType();
|
||||
FunctionType *OffsetFnTy = OffsetFn ? OffsetFn->getFunctionType() : 0;
|
||||
Assert1(SizeFnTy->getNumParams() == MD->getNumOperands()-2,
|
||||
"size function number of parameters mismatch", &I);
|
||||
Assert1(!OffsetFnTy || OffsetFnTy->getNumParams() == MD->getNumOperands()-2,
|
||||
"offset function number of parameters mismatch", &I);
|
||||
for (unsigned i = 0, e = SizeFnTy->getNumParams(); i != e; ++i) {
|
||||
Assert1(SizeFnTy->getParamType(i) == MD->getOperand(i+2)->getType(),
|
||||
"size function parameter type mismatch", &I);
|
||||
if (OffsetFnTy)
|
||||
Assert1(OffsetFnTy->getParamType(i) == MD->getOperand(i+2)->getType(),
|
||||
"offset function parameter type mismatch", &I);
|
||||
}
|
||||
}
|
||||
|
||||
MDNode *MD = I.getMetadata(LLVMContext::MD_range);
|
||||
Assert1(!MD || isa<LoadInst>(I), "Ranges are only for loads!", &I);
|
||||
|
||||
|
48
test/Verifier/alloc-1.ll
Normal file
48
test/Verifier/alloc-1.ll
Normal file
@ -0,0 +1,48 @@
|
||||
; RUN: not llvm-as < %s -o /dev/null |& FileCheck %s
|
||||
|
||||
declare i32 @size() readonly
|
||||
declare i32 @sizeR()
|
||||
declare i32 @size1(i32) readnone
|
||||
declare i32 @size1i8(i8) readnone
|
||||
declare i32* @sizeptr() readnone
|
||||
|
||||
define void @f1(i8** %x, i32* %y) {
|
||||
entry:
|
||||
%0 = load i8** %x, !alloc !0
|
||||
%1 = load i8** %x, !alloc !1
|
||||
%2 = load i8** %x, !alloc !2
|
||||
%3 = load i8** %x, !alloc !3
|
||||
%4 = load i8** %x, !alloc !4
|
||||
%5 = load i8** %x, !alloc !5
|
||||
%6 = load i8** %x, !alloc !6
|
||||
%7 = load i8** %x, !alloc !7
|
||||
%8 = load i8** %x, !alloc !8
|
||||
%9 = load i32* %y, !alloc !9
|
||||
%10 = load i8** %x, !alloc !10
|
||||
%11 = load i8** %x, !alloc !11
|
||||
ret void
|
||||
}
|
||||
; CHECK: alloc takes at least one operand
|
||||
!0 = metadata !{}
|
||||
; CHECK: first parameter of alloc must be a function
|
||||
!1 = metadata !{i32 0}
|
||||
; CHECK: second parameter of alloc must be either a function or null
|
||||
!2 = metadata !{i32 ()* @size, i32 0}
|
||||
; CHECK: size function number of parameters mismatch
|
||||
!3 = metadata !{i32 ()* @size, null, i32 0}
|
||||
; CHECK: offset function number of parameters mismatch
|
||||
!4 = metadata !{i32 (i32)* @size1, i32 ()* @size, i32 1}
|
||||
; CHECK: size function must be readonly/readnone
|
||||
!5 = metadata !{i32 ()* @sizeR, i32 ()* @size}
|
||||
; CHECK: offset function must be readonly/readnone
|
||||
!6 = metadata !{i32 ()* @size, i32 ()* @sizeR}
|
||||
; CHECK: size function parameter type mismatch
|
||||
!7 = metadata !{i32 (i32)* @size1, i32 (i8)* @size1i8, i8 5}
|
||||
; CHECK: offset function parameter type mismatch
|
||||
!8 = metadata !{i32 (i8)* @size1i8, i32 (i32)* @size1, i8 5}
|
||||
; CHECK: alloc requires a pointer result
|
||||
!9 = metadata !{i32 ()* @size, null}
|
||||
; CHECK: size function must return an integer
|
||||
!10 = metadata !{i32* ()* @sizeptr, null}
|
||||
; CHECK: offset function must return an integer
|
||||
!11 = metadata !{i32 ()* @size, i32* ()* @sizeptr}
|
19
test/Verifier/alloc-2.ll
Normal file
19
test/Verifier/alloc-2.ll
Normal file
@ -0,0 +1,19 @@
|
||||
; RUN: llvm-as < %s -o /dev/null
|
||||
|
||||
declare i32 @size() readonly
|
||||
declare i32 @size1(i32) readnone
|
||||
declare i32 @size1i8(i8) readnone
|
||||
|
||||
define void @ok(i8** %x, i32 %y) {
|
||||
entry:
|
||||
%0 = load i8** %x, !alloc !0
|
||||
%1 = load i8** %x, !alloc !1
|
||||
%2 = load i8** %x, !alloc !2
|
||||
%3 = load i8** %x, !alloc !3
|
||||
%4 = load i8** %x, !alloc !{i32 (i32)* @size1, i32 (i32)* @size1, i32 %y}
|
||||
ret void
|
||||
}
|
||||
!0 = metadata !{i32 ()* @size, i32 ()* @size}
|
||||
!1 = metadata !{i32 ()* @size, null}
|
||||
!2 = metadata !{i32 (i32)* @size1, i32 (i32)* @size1, i32 0}
|
||||
!3 = metadata !{i32 (i8)* @size1i8, i32 (i8)* @size1i8, i8 0}
|
Loading…
Reference in New Issue
Block a user