summaryrefslogtreecommitdiff
path: root/lib/IR/Attributes.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:12 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:12 +0000
commite6d1592492a3a379186bfb02bd0f4eda0669c0d5 (patch)
tree599ab169a01f1c86eda9adc774edaedde2f2db5b /lib/IR/Attributes.cpp
parent1a56a5ead7a2e84bee8240f5f6b033b5f1707154 (diff)
Notes
Diffstat (limited to 'lib/IR/Attributes.cpp')
-rw-r--r--lib/IR/Attributes.cpp150
1 files changed, 136 insertions, 14 deletions
diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp
index ff46debb7a9e..bb90bcd7dd74 100644
--- a/lib/IR/Attributes.cpp
+++ b/lib/IR/Attributes.cpp
@@ -1,9 +1,8 @@
//===- Attributes.cpp - Implement AttributesList --------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -122,6 +121,27 @@ Attribute Attribute::get(LLVMContext &Context, StringRef Kind, StringRef Val) {
return Attribute(PA);
}
+Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
+ Type *Ty) {
+ LLVMContextImpl *pImpl = Context.pImpl;
+ FoldingSetNodeID ID;
+ ID.AddInteger(Kind);
+ ID.AddPointer(Ty);
+
+ void *InsertPoint;
+ AttributeImpl *PA = pImpl->AttrsSet.FindNodeOrInsertPos(ID, InsertPoint);
+
+ if (!PA) {
+ // If we didn't find any existing attributes of the same shape then create a
+ // new one and insert it.
+ PA = new TypeAttributeImpl(Kind, Ty);
+ pImpl->AttrsSet.InsertNode(PA, InsertPoint);
+ }
+
+ // Return the Attribute that we found or created.
+ return Attribute(PA);
+}
+
Attribute Attribute::getWithAlignment(LLVMContext &Context, uint64_t Align) {
assert(isPowerOf2_32(Align) && "Alignment must be a power of two.");
assert(Align <= 0x40000000 && "Alignment too large.");
@@ -147,6 +167,10 @@ Attribute Attribute::getWithDereferenceableOrNullBytes(LLVMContext &Context,
return get(Context, DereferenceableOrNull, Bytes);
}
+Attribute Attribute::getWithByValType(LLVMContext &Context, Type *Ty) {
+ return get(Context, ByVal, Ty);
+}
+
Attribute
Attribute::getWithAllocSizeArgs(LLVMContext &Context, unsigned ElemSizeArg,
const Optional<unsigned> &NumElemsArg) {
@@ -171,9 +195,13 @@ bool Attribute::isStringAttribute() const {
return pImpl && pImpl->isStringAttribute();
}
+bool Attribute::isTypeAttribute() const {
+ return pImpl && pImpl->isTypeAttribute();
+}
+
Attribute::AttrKind Attribute::getKindAsEnum() const {
if (!pImpl) return None;
- assert((isEnumAttribute() || isIntAttribute()) &&
+ assert((isEnumAttribute() || isIntAttribute() || isTypeAttribute()) &&
"Invalid attribute type to get the kind as an enum!");
return pImpl->getKindAsEnum();
}
@@ -199,6 +227,14 @@ StringRef Attribute::getValueAsString() const {
return pImpl->getValueAsString();
}
+Type *Attribute::getValueAsType() const {
+ if (!pImpl) return {};
+ assert(isTypeAttribute() &&
+ "Invalid attribute type to get the value as a type!");
+ return pImpl->getValueAsType();
+}
+
+
bool Attribute::hasAttribute(AttrKind Kind) const {
return (pImpl && pImpl->hasAttribute(Kind)) || (!pImpl && Kind == None);
}
@@ -247,14 +283,14 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "sanitize_address";
if (hasAttribute(Attribute::SanitizeHWAddress))
return "sanitize_hwaddress";
+ if (hasAttribute(Attribute::SanitizeMemTag))
+ return "sanitize_memtag";
if (hasAttribute(Attribute::AlwaysInline))
return "alwaysinline";
if (hasAttribute(Attribute::ArgMemOnly))
return "argmemonly";
if (hasAttribute(Attribute::Builtin))
return "builtin";
- if (hasAttribute(Attribute::ByVal))
- return "byval";
if (hasAttribute(Attribute::Convergent))
return "convergent";
if (hasAttribute(Attribute::SwiftError))
@@ -287,6 +323,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "nocapture";
if (hasAttribute(Attribute::NoDuplicate))
return "noduplicate";
+ if (hasAttribute(Attribute::NoFree))
+ return "nofree";
if (hasAttribute(Attribute::NoImplicitFloat))
return "noimplicitfloat";
if (hasAttribute(Attribute::NoInline))
@@ -299,6 +337,10 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "noredzone";
if (hasAttribute(Attribute::NoReturn))
return "noreturn";
+ if (hasAttribute(Attribute::NoSync))
+ return "nosync";
+ if (hasAttribute(Attribute::WillReturn))
+ return "willreturn";
if (hasAttribute(Attribute::NoCfCheck))
return "nocf_check";
if (hasAttribute(Attribute::NoRecurse))
@@ -351,6 +393,21 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "zeroext";
if (hasAttribute(Attribute::Cold))
return "cold";
+ if (hasAttribute(Attribute::ImmArg))
+ return "immarg";
+
+ if (hasAttribute(Attribute::ByVal)) {
+ std::string Result;
+ Result += "byval";
+ if (Type *Ty = getValueAsType()) {
+ raw_string_ostream OS(Result);
+ Result += '(';
+ Ty->print(OS, false, true);
+ OS.flush();
+ Result += ')';
+ }
+ return Result;
+ }
// FIXME: These should be output like this:
//
@@ -450,6 +507,8 @@ void IntAttributeImpl::anchor() {}
void StringAttributeImpl::anchor() {}
+void TypeAttributeImpl::anchor() {}
+
bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
if (isStringAttribute()) return false;
return getKindAsEnum() == A;
@@ -461,7 +520,7 @@ bool AttributeImpl::hasAttribute(StringRef Kind) const {
}
Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
- assert(isEnumAttribute() || isIntAttribute());
+ assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute());
return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
}
@@ -480,6 +539,11 @@ StringRef AttributeImpl::getValueAsString() const {
return static_cast<const StringAttributeImpl *>(this)->getStringValue();
}
+Type *AttributeImpl::getValueAsType() const {
+ assert(isTypeAttribute());
+ return static_cast<const TypeAttributeImpl *>(this)->getTypeValue();
+}
+
bool AttributeImpl::operator<(const AttributeImpl &AI) const {
// This sorts the attributes with Attribute::AttrKinds coming first (sorted
// relative to their enum value) and then strings.
@@ -487,10 +551,23 @@ bool AttributeImpl::operator<(const AttributeImpl &AI) const {
if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum();
if (AI.isIntAttribute()) return true;
if (AI.isStringAttribute()) return true;
+ if (AI.isTypeAttribute()) return true;
+ }
+
+ if (isTypeAttribute()) {
+ if (AI.isEnumAttribute()) return false;
+ if (AI.isTypeAttribute()) {
+ assert(getKindAsEnum() != AI.getKindAsEnum() &&
+ "Comparison of types would be unstable");
+ return getKindAsEnum() < AI.getKindAsEnum();
+ }
+ if (AI.isIntAttribute()) return true;
+ if (AI.isStringAttribute()) return true;
}
if (isIntAttribute()) {
if (AI.isEnumAttribute()) return false;
+ if (AI.isTypeAttribute()) return false;
if (AI.isIntAttribute()) {
if (getKindAsEnum() == AI.getKindAsEnum())
return getValueAsInt() < AI.getValueAsInt();
@@ -499,7 +576,9 @@ bool AttributeImpl::operator<(const AttributeImpl &AI) const {
if (AI.isStringAttribute()) return true;
}
+ assert(isStringAttribute());
if (AI.isEnumAttribute()) return false;
+ if (AI.isTypeAttribute()) return false;
if (AI.isIntAttribute()) return false;
if (getKindAsString() == AI.getKindAsString())
return getValueAsString() < AI.getValueAsString();
@@ -607,6 +686,10 @@ uint64_t AttributeSet::getDereferenceableOrNullBytes() const {
return SetNode ? SetNode->getDereferenceableOrNullBytes() : 0;
}
+Type *AttributeSet::getByValType() const {
+ return SetNode ? SetNode->getByValType() : nullptr;
+}
+
std::pair<unsigned, Optional<unsigned>> AttributeSet::getAllocSizeArgs() const {
return SetNode ? SetNode->getAllocSizeArgs()
: std::pair<unsigned, Optional<unsigned>>(0, 0);
@@ -637,13 +720,18 @@ LLVM_DUMP_METHOD void AttributeSet::dump() const {
//===----------------------------------------------------------------------===//
AttributeSetNode::AttributeSetNode(ArrayRef<Attribute> Attrs)
- : AvailableAttrs(0), NumAttrs(Attrs.size()) {
+ : NumAttrs(Attrs.size()) {
// There's memory after the node where we can store the entries in.
llvm::copy(Attrs, getTrailingObjects<Attribute>());
+ static_assert(Attribute::EndAttrKinds <=
+ sizeof(AvailableAttrs) * CHAR_BIT,
+ "Too many attributes");
+
for (const auto I : *this) {
if (!I.isStringAttribute()) {
- AvailableAttrs |= ((uint64_t)1) << I.getKindAsEnum();
+ Attribute::AttrKind Kind = I.getKindAsEnum();
+ AvailableAttrs[Kind / 8] |= 1ULL << (Kind % 8);
}
}
}
@@ -690,6 +778,9 @@ AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
Attribute Attr;
switch (Kind) {
+ case Attribute::ByVal:
+ Attr = Attribute::getWithByValType(C, B.getByValType());
+ break;
case Attribute::Alignment:
Attr = Attribute::getWithAlignment(C, B.getAlignment());
break;
@@ -759,6 +850,13 @@ unsigned AttributeSetNode::getStackAlignment() const {
return 0;
}
+Type *AttributeSetNode::getByValType() const {
+ for (const auto I : *this)
+ if (I.hasAttribute(Attribute::ByVal))
+ return I.getValueAsType();
+ return 0;
+}
+
uint64_t AttributeSetNode::getDereferenceableBytes() const {
for (const auto I : *this)
if (I.hasAttribute(Attribute::Dereferenceable))
@@ -805,7 +903,7 @@ static constexpr unsigned attrIdxToArrayIdx(unsigned Index) {
AttributeListImpl::AttributeListImpl(LLVMContext &C,
ArrayRef<AttributeSet> Sets)
- : AvailableFunctionAttrs(0), Context(C), NumAttrSets(Sets.size()) {
+ : Context(C), NumAttrSets(Sets.size()) {
assert(!Sets.empty() && "pointless AttributeListImpl");
// There's memory after the node where we can store the entries in.
@@ -818,8 +916,10 @@ AttributeListImpl::AttributeListImpl(LLVMContext &C,
static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U,
"function should be stored in slot 0");
for (const auto I : Sets[0]) {
- if (!I.isStringAttribute())
- AvailableFunctionAttrs |= 1ULL << I.getKindAsEnum();
+ if (!I.isStringAttribute()) {
+ Attribute::AttrKind Kind = I.getKindAsEnum();
+ AvailableFunctionAttrs[Kind / 8] |= 1ULL << (Kind % 8);
+ }
}
}
@@ -1257,6 +1357,11 @@ unsigned AttributeList::getParamAlignment(unsigned ArgNo) const {
return getAttributes(ArgNo + FirstArgIndex).getAlignment();
}
+Type *AttributeList::getParamByValType(unsigned Index) const {
+ return getAttributes(Index+FirstArgIndex).getByValType();
+}
+
+
unsigned AttributeList::getStackAlignment(unsigned Index) const {
return getAttributes(Index).getStackAlignment();
}
@@ -1335,6 +1440,7 @@ void AttrBuilder::clear() {
TargetDepAttrs.clear();
Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0;
AllocSizeArgs = 0;
+ ByValType = nullptr;
}
AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
@@ -1359,6 +1465,8 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
Alignment = Attr.getAlignment();
else if (Kind == Attribute::StackAlignment)
StackAlignment = Attr.getStackAlignment();
+ else if (Kind == Attribute::ByVal)
+ ByValType = Attr.getValueAsType();
else if (Kind == Attribute::Dereferenceable)
DerefBytes = Attr.getDereferenceableBytes();
else if (Kind == Attribute::DereferenceableOrNull)
@@ -1381,6 +1489,8 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
Alignment = 0;
else if (Val == Attribute::StackAlignment)
StackAlignment = 0;
+ else if (Val == Attribute::ByVal)
+ ByValType = nullptr;
else if (Val == Attribute::Dereferenceable)
DerefBytes = 0;
else if (Val == Attribute::DereferenceableOrNull)
@@ -1463,6 +1573,12 @@ AttrBuilder &AttrBuilder::addAllocSizeAttrFromRawRepr(uint64_t RawArgs) {
return *this;
}
+AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
+ Attrs[Attribute::ByVal] = true;
+ ByValType = Ty;
+ return *this;
+}
+
AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
// FIXME: What if both have alignments, but they don't match?!
if (!Alignment)
@@ -1480,6 +1596,9 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
if (!AllocSizeArgs)
AllocSizeArgs = B.AllocSizeArgs;
+ if (!ByValType)
+ ByValType = B.ByValType;
+
Attrs |= B.Attrs;
for (auto I : B.td_attrs())
@@ -1505,6 +1624,9 @@ AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
if (B.AllocSizeArgs)
AllocSizeArgs = 0;
+ if (B.ByValType)
+ ByValType = nullptr;
+
Attrs &= ~B.Attrs;
for (auto I : B.td_attrs())
@@ -1564,7 +1686,7 @@ bool AttrBuilder::operator==(const AttrBuilder &B) {
return false;
return Alignment == B.Alignment && StackAlignment == B.StackAlignment &&
- DerefBytes == B.DerefBytes;
+ DerefBytes == B.DerefBytes && ByValType == B.ByValType;
}
//===----------------------------------------------------------------------===//