llvm.org GIT mirror llvm / fa74943
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 Nuno Lopes 8 years ago
6 changed file(s) with 151 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
104104
  • 'tbaa' Metadata
  • 105105
  • 'fpmath' Metadata
  • 106106
  • 'range' Metadata
  • 107
  • 'alloc' Metadata
  • 107108
    108109
    109110
    30763077
    30773078
    30783079
    3080
    3081
    3082

    3083 'alloc' Metadata
    3084
    3085
    3086
    3087
    3088

    alloc metadata may be attached to any instruction returning a

    3089 pointer. It can be used to express the size and offset relative to the
    3090 beginning of the buffer pointed by.

    3091
    3092
    3093
    3094

    The first parameter is a function that returns the size of the buffer, and

    3095 the second (optional) parameter is a function that returns the offset from
    3096 the beginning of the buffer. If the second parameter is not present or null,
    3097 the offset is assumed to be null. Both functions must be either readonly or
    3098 readnone.

    3099

    alloc metadata can have additional parameters, which are passed to

    3100 the size and offset functions when they are evaluated. Therefore the size and
    3101 offset functions must have the same signature.

    3102
    3103
    3104
    3105
    3106

    Examples:

    3107
    3108
    
                      
                    
    3109 ; size of buffer allocated by this call is my_malloc_size(%s), and offset=0
    3110 %a = call my_malloc(%s), !alloc !{i32 (i32)* @my_malloc_size, null, i32 %s}
    3111
    3112 ; size of the buffer pointed by *ptr is size(%x), and offset=offset(%x)
    3113 %b = load i8** %foo, !alloc !{i32 (i32)* @size, i32 (i32)* @offset, i32 %x}
    3114
    3115 ; size of buffer allocated by this call is foo_size(), and offset=0
    3116 %a = call alloc_foo(%s), !alloc !0
    3117 ...
    3118 !0 = metadata {i32 ()* @foo_size}
    3119
    3120
    3121
    3122
    30793123
    30803124
    30813125
    4242 MD_tbaa = 1, // "tbaa"
    4343 MD_prof = 2, // "prof"
    4444 MD_fpmath = 3, // "fpmath"
    45 MD_range = 4 // "range"
    45 MD_range = 4, // "range"
    46 MD_alloc = 5 // "alloc"
    4647 };
    4748
    4849 /// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
    5252 unsigned RangeID = getMDKindID("range");
    5353 assert(RangeID == MD_range && "range kind id drifted");
    5454 (void)RangeID;
    55
    56 // Create the 'alloc' metadata kind.
    57 unsigned AllocID = getMDKindID("alloc");
    58 assert(AllocID == MD_alloc && "alloc kind id drifted");
    59 (void)AllocID;
    5560 }
    5661 LLVMContext::~LLVMContext() { delete pImpl; }
    5762
    16711671 }
    16721672 }
    16731673
    1674 if (MDNode *MD = I.getMetadata(LLVMContext::MD_alloc)) {
    1675 Assert1(I.getType()->isPointerTy(), "alloc requires a pointer result", &I);
    1676 Assert1(MD->getNumOperands() >= 1, "alloc takes at least one operand", &I);
    1677 Function *SizeFn = dyn_cast(MD->getOperand(0));
    1678 Function *OffsetFn = MD->getNumOperands() >= 2 ?
    1679 dyn_cast_or_null(MD->getOperand(1)) : 0;
    1680 Assert1(SizeFn, "first parameter of alloc must be a function", &I);
    1681 Assert1(MD->getNumOperands() == 1 || !MD->getOperand(1) || OffsetFn,
    1682 "second parameter of alloc must be either a function or null", &I);
    1683 Assert1(SizeFn->onlyReadsMemory(),
    1684 "size function must be readonly/readnone", &I);
    1685 Assert1(!OffsetFn || OffsetFn->onlyReadsMemory(),
    1686 "offset function must be readonly/readnone", &I);
    1687 Assert1(SizeFn->getReturnType()->isIntegerTy(),
    1688 "size function must return an integer", &I);
    1689 Assert1(!OffsetFn || OffsetFn->getReturnType()->isIntegerTy(),
    1690 "offset function must return an integer", &I);
    1691
    1692 FunctionType *SizeFnTy = SizeFn->getFunctionType();
    1693 FunctionType *OffsetFnTy = OffsetFn ? OffsetFn->getFunctionType() : 0;
    1694 Assert1(SizeFnTy->getNumParams() == MD->getNumOperands()-2,
    1695 "size function number of parameters mismatch", &I);
    1696 Assert1(!OffsetFnTy || OffsetFnTy->getNumParams() == MD->getNumOperands()-2,
    1697 "offset function number of parameters mismatch", &I);
    1698 for (unsigned i = 0, e = SizeFnTy->getNumParams(); i != e; ++i) {
    1699 Assert1(SizeFnTy->getParamType(i) == MD->getOperand(i+2)->getType(),
    1700 "size function parameter type mismatch", &I);
    1701 if (OffsetFnTy)
    1702 Assert1(OffsetFnTy->getParamType(i) == MD->getOperand(i+2)->getType(),
    1703 "offset function parameter type mismatch", &I);
    1704 }
    1705 }
    1706
    16741707 MDNode *MD = I.getMetadata(LLVMContext::MD_range);
    16751708 Assert1(!MD || isa(I), "Ranges are only for loads!", &I);
    16761709
    0 ; RUN: not llvm-as < %s -o /dev/null |& FileCheck %s
    1
    2 declare i32 @size() readonly
    3 declare i32 @sizeR()
    4 declare i32 @size1(i32) readnone
    5 declare i32 @size1i8(i8) readnone
    6 declare i32* @sizeptr() readnone
    7
    8 define void @f1(i8** %x, i32* %y) {
    9 entry:
    10 %0 = load i8** %x, !alloc !0
    11 %1 = load i8** %x, !alloc !1
    12 %2 = load i8** %x, !alloc !2
    13 %3 = load i8** %x, !alloc !3
    14 %4 = load i8** %x, !alloc !4
    15 %5 = load i8** %x, !alloc !5
    16 %6 = load i8** %x, !alloc !6
    17 %7 = load i8** %x, !alloc !7
    18 %8 = load i8** %x, !alloc !8
    19 %9 = load i32* %y, !alloc !9
    20 %10 = load i8** %x, !alloc !10
    21 %11 = load i8** %x, !alloc !11
    22 ret void
    23 }
    24 ; CHECK: alloc takes at least one operand
    25 !0 = metadata !{}
    26 ; CHECK: first parameter of alloc must be a function
    27 !1 = metadata !{i32 0}
    28 ; CHECK: second parameter of alloc must be either a function or null
    29 !2 = metadata !{i32 ()* @size, i32 0}
    30 ; CHECK: size function number of parameters mismatch
    31 !3 = metadata !{i32 ()* @size, null, i32 0}
    32 ; CHECK: offset function number of parameters mismatch
    33 !4 = metadata !{i32 (i32)* @size1, i32 ()* @size, i32 1}
    34 ; CHECK: size function must be readonly/readnone
    35 !5 = metadata !{i32 ()* @sizeR, i32 ()* @size}
    36 ; CHECK: offset function must be readonly/readnone
    37 !6 = metadata !{i32 ()* @size, i32 ()* @sizeR}
    38 ; CHECK: size function parameter type mismatch
    39 !7 = metadata !{i32 (i32)* @size1, i32 (i8)* @size1i8, i8 5}
    40 ; CHECK: offset function parameter type mismatch
    41 !8 = metadata !{i32 (i8)* @size1i8, i32 (i32)* @size1, i8 5}
    42 ; CHECK: alloc requires a pointer result
    43 !9 = metadata !{i32 ()* @size, null}
    44 ; CHECK: size function must return an integer
    45 !10 = metadata !{i32* ()* @sizeptr, null}
    46 ; CHECK: offset function must return an integer
    47 !11 = metadata !{i32 ()* @size, i32* ()* @sizeptr}
    0 ; RUN: llvm-as < %s -o /dev/null
    1
    2 declare i32 @size() readonly
    3 declare i32 @size1(i32) readnone
    4 declare i32 @size1i8(i8) readnone
    5
    6 define void @ok(i8** %x, i32 %y) {
    7 entry:
    8 %0 = load i8** %x, !alloc !0
    9 %1 = load i8** %x, !alloc !1
    10 %2 = load i8** %x, !alloc !2
    11 %3 = load i8** %x, !alloc !3
    12 %4 = load i8** %x, !alloc !{i32 (i32)* @size1, i32 (i32)* @size1, i32 %y}
    13 ret void
    14 }
    15 !0 = metadata !{i32 ()* @size, i32 ()* @size}
    16 !1 = metadata !{i32 ()* @size, null}
    17 !2 = metadata !{i32 (i32)* @size1, i32 (i32)* @size1, i32 0}
    18 !3 = metadata !{i32 (i8)* @size1i8, i32 (i8)* @size1i8, i8 0}