Skip to content

Commit 42861fa

Browse files
committed
attributes: introduce allockind attr for describing allocator fn behavior
I chose to encode the allockind information in a string constant because otherwise we would get a bit of an explosion of keywords to deal with the possible permutations of allocation function types. I'm not sure that CodeGen.h is the correct place for this enum, but it seemed to kind of match the UWTableKind enum so I put it in the same place. Constructive suggestions on a better location most certainly encouraged. Differential Revision: https://reviews.llvm.org/D123088
1 parent b9443cb commit 42861fa

File tree

16 files changed

+193
-2
lines changed

16 files changed

+193
-2
lines changed

llvm/docs/LangRef.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,27 @@ example:
15841584
"_ZnwmSt11align_val_t" for aligned ``::operator::new`` and
15851585
``::operator::delete``. Matching malloc/realloc/free calls within a family
15861586
can be optimized, but mismatched ones will be left alone.
1587+
``allockind("KIND")``
1588+
Describes the behavior of an allocation function. The KIND string contains comma
1589+
separated entries from the following options:
1590+
* "alloc": the function returns a new block of memory or null.
1591+
* "realloc": the function returns a new block of memory or null. If the
1592+
result is non-null the memory contents from the start of the block up to
1593+
the smaller of the original allocation size and the new allocation size
1594+
will match that of the ``allocptr`` argument and the ``allocptr``
1595+
argument is invalidated, even if the function returns the same address.
1596+
* "free": the function frees the block of memory specified by ``allocptr``.
1597+
* "uninitialized": Any newly-allocated memory (either a new block from
1598+
a "alloc" function or the enlarged capacity from a "realloc" function)
1599+
will be uninitialized.
1600+
* "zeroed": Any newly-allocated memory (either a new block from a "alloc"
1601+
function or the enlarged capacity from a "realloc" function) will be
1602+
zeroed.
1603+
* "aligned": the function returns memory aligned according to the
1604+
``allocalign`` parameter.
1605+
The first three options are mutually exclusive, and the remaining options
1606+
describe more details of how the function behaves. The remaining options
1607+
are invalid for "free"-type functions.
15871608
``allocsize(<EltSizeParam>[, <NumEltsParam>])``
15881609
This attribute indicates that the annotated function will always return at
15891610
least a given number of bytes (or null). Its arguments are zero-indexed

llvm/include/llvm/AsmParser/LLParser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ namespace llvm {
274274
bool AllowParens = false);
275275
bool parseOptionalDerefAttrBytes(lltok::Kind AttrKind, uint64_t &Bytes);
276276
bool parseOptionalUWTableKind(UWTableKind &Kind);
277+
bool parseAllocKind(AllocFnKind &Kind);
277278
bool parseScopeAndOrdering(bool IsAtomic, SyncScope::ID &SSID,
278279
AtomicOrdering &Ordering);
279280
bool parseScope(SyncScope::ID &SSID);

llvm/include/llvm/Bitcode/LLVMBitCodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,7 @@ enum AttributeKindCodes {
684684
ATTR_KIND_NO_SANITIZE_BOUNDS = 79,
685685
ATTR_KIND_ALLOC_ALIGN = 80,
686686
ATTR_KIND_ALLOCATED_POINTER = 81,
687+
ATTR_KIND_ALLOC_KIND = 82,
687688
};
688689

689690
enum ComdatSelectionKindCodes {

llvm/include/llvm/IR/Attributes.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "llvm-c/Types.h"
1919
#include "llvm/ADT/ArrayRef.h"
20+
#include "llvm/ADT/BitmaskEnum.h"
2021
#include "llvm/ADT/Optional.h"
2122
#include "llvm/ADT/SmallString.h"
2223
#include "llvm/ADT/StringRef.h"
@@ -43,6 +44,18 @@ class Function;
4344
class LLVMContext;
4445
class Type;
4546

47+
enum class AllocFnKind : uint64_t {
48+
Unknown = 0,
49+
Alloc = 1 << 0, // Allocator function returns a new allocation
50+
Realloc = 1 << 1, // Allocator function resizes the `allocptr` argument
51+
Free = 1 << 2, // Allocator function frees the `allocptr` argument
52+
Uninitialized = 1 << 3, // Allocator function returns uninitialized memory
53+
Zeroed = 1 << 4, // Allocator function returns zeroed memory
54+
Aligned = 1 << 5, // Allocator function aligns allocations per the
55+
// `allocalign` argument
56+
LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Aligned)
57+
};
58+
4659
//===----------------------------------------------------------------------===//
4760
/// \class
4861
/// Functions, function parameters, and return types can have attributes
@@ -228,6 +241,9 @@ class Attribute {
228241
// Returns the unwind table kind.
229242
UWTableKind getUWTableKind() const;
230243

244+
// Returns the allocator function kind.
245+
AllocFnKind getAllocKind() const;
246+
231247
/// The Attribute is converted to a string of equivalent mnemonic. This
232248
/// is, presumably, for writing out the mnemonics for the assembly writer.
233249
std::string getAsString(bool InAttrGrp = false) const;
@@ -359,6 +375,7 @@ class AttributeSet {
359375
unsigned getVScaleRangeMin() const;
360376
Optional<unsigned> getVScaleRangeMax() const;
361377
UWTableKind getUWTableKind() const;
378+
AllocFnKind getAllocKind() const;
362379
std::string getAsString(bool InAttrGrp = false) const;
363380

364381
/// Return true if this attribute set belongs to the LLVMContext.
@@ -850,6 +867,8 @@ class AttributeList {
850867
/// Get the unwind table kind requested for the function.
851868
UWTableKind getUWTableKind() const;
852869

870+
AllocFnKind getAllocKind() const;
871+
853872
/// Return the attributes at the index as a string.
854873
std::string getAsString(unsigned Index, bool InAttrGrp = false) const;
855874

@@ -1203,6 +1222,9 @@ class AttrBuilder {
12031222
/// Attribute.
12041223
AttrBuilder &addUWTableAttr(UWTableKind Kind);
12051224

1225+
// This turns the allocator kind into the form used internally in Attribute.
1226+
AttrBuilder &addAllocKindAttr(AllocFnKind Kind);
1227+
12061228
ArrayRef<Attribute> attrs() const { return Attrs; }
12071229

12081230
bool operator==(const AttrBuilder &B) const;

llvm/include/llvm/IR/Attributes.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ def Alignment : IntAttr<"align", [ParamAttr, RetAttr]>;
5151
/// aligned_alloc and aligned ::operator::new.
5252
def AllocAlign: EnumAttr<"allocalign", [ParamAttr]>;
5353

54+
/// Describes behavior of an allocator function in terms of known properties.
55+
def AllocKind: IntAttr<"allockind", [FnAttr]>;
56+
5457
/// Parameter is the pointer to be manipulated by the allocator function.
5558
def AllocatedPointer : EnumAttr<"allocptr", [ParamAttr]>;
5659

llvm/lib/AsmParser/LLParser.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,13 @@ bool LLParser::parseEnumAttribute(Attribute::AttrKind Attr, AttrBuilder &B,
13621362
B.addUWTableAttr(Kind);
13631363
return false;
13641364
}
1365+
case Attribute::AllocKind: {
1366+
AllocFnKind Kind = AllocFnKind::Unknown;
1367+
if (parseAllocKind(Kind))
1368+
return true;
1369+
B.addAllocKindAttr(Kind);
1370+
return false;
1371+
}
13651372
default:
13661373
B.addAttribute(Attr);
13671374
Lex.Lex();
@@ -2041,6 +2048,40 @@ bool LLParser::parseOptionalUWTableKind(UWTableKind &Kind) {
20412048
return parseToken(lltok::rparen, "expected ')'");
20422049
}
20432050

2051+
bool LLParser::parseAllocKind(AllocFnKind &Kind) {
2052+
Lex.Lex();
2053+
LocTy ParenLoc = Lex.getLoc();
2054+
if (!EatIfPresent(lltok::lparen))
2055+
return error(ParenLoc, "expected '('");
2056+
LocTy KindLoc = Lex.getLoc();
2057+
std::string Arg;
2058+
if (parseStringConstant(Arg))
2059+
return error(KindLoc, "expected allockind value");
2060+
for (StringRef A : llvm::split(Arg, ",")) {
2061+
if (A == "alloc") {
2062+
Kind |= AllocFnKind::Alloc;
2063+
} else if (A == "realloc") {
2064+
Kind |= AllocFnKind::Realloc;
2065+
} else if (A == "free") {
2066+
Kind |= AllocFnKind::Free;
2067+
} else if (A == "uninitialized") {
2068+
Kind |= AllocFnKind::Uninitialized;
2069+
} else if (A == "zeroed") {
2070+
Kind |= AllocFnKind::Zeroed;
2071+
} else if (A == "aligned") {
2072+
Kind |= AllocFnKind::Aligned;
2073+
} else {
2074+
return error(KindLoc, Twine("unknown allockind ") + A);
2075+
}
2076+
}
2077+
ParenLoc = Lex.getLoc();
2078+
if (!EatIfPresent(lltok::rparen))
2079+
return error(ParenLoc, "expected ')'");
2080+
if (Kind == AllocFnKind::Unknown)
2081+
return error(KindLoc, "expected allockind value");
2082+
return false;
2083+
}
2084+
20442085
/// parseOptionalCommaAlign
20452086
/// ::=
20462087
/// ::= ',' align 4

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
15361536
return Attribute::DereferenceableOrNull;
15371537
case bitc::ATTR_KIND_ALLOC_ALIGN:
15381538
return Attribute::AllocAlign;
1539+
case bitc::ATTR_KIND_ALLOC_KIND:
1540+
return Attribute::AllocKind;
15391541
case bitc::ATTR_KIND_ALLOC_SIZE:
15401542
return Attribute::AllocSize;
15411543
case bitc::ATTR_KIND_ALLOCATED_POINTER:
@@ -1736,6 +1738,8 @@ Error BitcodeReader::parseAttributeGroupBlock() {
17361738
B.addVScaleRangeAttrFromRawRepr(Record[++i]);
17371739
else if (Kind == Attribute::UWTable)
17381740
B.addUWTableAttr(UWTableKind(Record[++i]));
1741+
else if (Kind == Attribute::AllocKind)
1742+
B.addAllocKindAttr(static_cast<AllocFnKind>(Record[++i]));
17391743
} else if (Record[i] == 3 || Record[i] == 4) { // String attribute
17401744
bool HasValue = (Record[i++] == 4);
17411745
SmallString<64> KindStr;

llvm/lib/Bitcode/Writer/BitcodeWriter.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,8 @@ static uint64_t getAttrKindEncoding(Attribute::AttrKind Kind) {
650650
return bitc::ATTR_KIND_MIN_SIZE;
651651
case Attribute::AllocatedPointer:
652652
return bitc::ATTR_KIND_ALLOCATED_POINTER;
653+
case Attribute::AllocKind:
654+
return bitc::ATTR_KIND_ALLOC_KIND;
653655
case Attribute::Naked:
654656
return bitc::ATTR_KIND_NAKED;
655657
case Attribute::Nest:

llvm/lib/IR/AttributeImpl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ class AttributeSetNode final
256256
unsigned getVScaleRangeMin() const;
257257
Optional<unsigned> getVScaleRangeMax() const;
258258
UWTableKind getUWTableKind() const;
259+
AllocFnKind getAllocKind() const;
259260
std::string getAsString(bool InAttrGrp) const;
260261
Type *getAttributeType(Attribute::AttrKind Kind) const;
261262

llvm/lib/IR/Attributes.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,12 @@ UWTableKind Attribute::getUWTableKind() const {
376376
return UWTableKind(pImpl->getValueAsInt());
377377
}
378378

379+
AllocFnKind Attribute::getAllocKind() const {
380+
assert(hasAttribute(Attribute::AllocKind) &&
381+
"Trying to get allockind value from non-allockind attribute");
382+
return AllocFnKind(pImpl->getValueAsInt());
383+
}
384+
379385
std::string Attribute::getAsString(bool InAttrGrp) const {
380386
if (!pImpl) return {};
381387

@@ -447,6 +453,26 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
447453
}
448454
}
449455

456+
if (hasAttribute(Attribute::AllocKind)) {
457+
AllocFnKind Kind = getAllocKind();
458+
SmallVector<StringRef> parts;
459+
if ((Kind & AllocFnKind::Alloc) != AllocFnKind::Unknown)
460+
parts.push_back("alloc");
461+
if ((Kind & AllocFnKind::Realloc) != AllocFnKind::Unknown)
462+
parts.push_back("realloc");
463+
if ((Kind & AllocFnKind::Free) != AllocFnKind::Unknown)
464+
parts.push_back("free");
465+
if ((Kind & AllocFnKind::Uninitialized) != AllocFnKind::Unknown)
466+
parts.push_back("uninitialized");
467+
if ((Kind & AllocFnKind::Zeroed) != AllocFnKind::Unknown)
468+
parts.push_back("zeroed");
469+
if ((Kind & AllocFnKind::Aligned) != AllocFnKind::Unknown)
470+
parts.push_back("aligned");
471+
return ("allockind(\"" +
472+
Twine(llvm::join(parts.begin(), parts.end(), ",")) + "\")")
473+
.str();
474+
}
475+
450476
// Convert target-dependent attributes to strings of the form:
451477
//
452478
// "kind"
@@ -735,6 +761,10 @@ UWTableKind AttributeSet::getUWTableKind() const {
735761
return SetNode ? SetNode->getUWTableKind() : UWTableKind::None;
736762
}
737763

764+
AllocFnKind AttributeSet::getAllocKind() const {
765+
return SetNode ? SetNode->getAllocKind() : AllocFnKind::Unknown;
766+
}
767+
738768
std::string AttributeSet::getAsString(bool InAttrGrp) const {
739769
return SetNode ? SetNode->getAsString(InAttrGrp) : "";
740770
}
@@ -907,6 +937,12 @@ UWTableKind AttributeSetNode::getUWTableKind() const {
907937
return UWTableKind::None;
908938
}
909939

940+
AllocFnKind AttributeSetNode::getAllocKind() const {
941+
if (auto A = findEnumAttribute(Attribute::AllocKind))
942+
return A->getAllocKind();
943+
return AllocFnKind::Unknown;
944+
}
945+
910946
std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
911947
std::string Str;
912948
for (iterator I = begin(), E = end(); I != E; ++I) {
@@ -1463,6 +1499,10 @@ UWTableKind AttributeList::getUWTableKind() const {
14631499
return getFnAttrs().getUWTableKind();
14641500
}
14651501

1502+
AllocFnKind AttributeList::getAllocKind() const {
1503+
return getFnAttrs().getAllocKind();
1504+
}
1505+
14661506
std::string AttributeList::getAsString(unsigned Index, bool InAttrGrp) const {
14671507
return getAttributes(Index).getAsString(InAttrGrp);
14681508
}
@@ -1690,6 +1730,10 @@ AttrBuilder &AttrBuilder::addUWTableAttr(UWTableKind Kind) {
16901730
return addRawIntAttr(Attribute::UWTable, uint64_t(Kind));
16911731
}
16921732

1733+
AttrBuilder &AttrBuilder::addAllocKindAttr(AllocFnKind Kind) {
1734+
return addRawIntAttr(Attribute::AllocKind, static_cast<uint64_t>(Kind));
1735+
}
1736+
16931737
Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
16941738
assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
16951739
Attribute A = getAttribute(Kind);

0 commit comments

Comments
 (0)