aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/Attributes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR/Attributes.cpp')
-rw-r--r--llvm/lib/IR/Attributes.cpp346
1 files changed, 137 insertions, 209 deletions
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index c899afae6cce..c92bacaee36d 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -607,14 +607,14 @@ AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef<Attribute> Attrs) {
AttributeSet AttributeSet::addAttribute(LLVMContext &C,
Attribute::AttrKind Kind) const {
if (hasAttribute(Kind)) return *this;
- AttrBuilder B;
+ AttrBuilder B(C);
B.addAttribute(Kind);
return addAttributes(C, AttributeSet::get(C, B));
}
AttributeSet AttributeSet::addAttribute(LLVMContext &C, StringRef Kind,
StringRef Value) const {
- AttrBuilder B;
+ AttrBuilder B(C);
B.addAttribute(Kind, Value);
return addAttributes(C, AttributeSet::get(C, B));
}
@@ -627,17 +627,15 @@ AttributeSet AttributeSet::addAttributes(LLVMContext &C,
if (!AS.hasAttributes())
return *this;
- AttrBuilder B(AS);
- for (const auto &I : *this)
- B.addAttribute(I);
-
- return get(C, B);
+ AttrBuilder B(C, *this);
+ B.merge(AttrBuilder(C, AS));
+ return get(C, B);
}
AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
Attribute::AttrKind Kind) const {
if (!hasAttribute(Kind)) return *this;
- AttrBuilder B(*this);
+ AttrBuilder B(C, *this);
B.removeAttribute(Kind);
return get(C, B);
}
@@ -645,14 +643,14 @@ AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
AttributeSet AttributeSet::removeAttribute(LLVMContext &C,
StringRef Kind) const {
if (!hasAttribute(Kind)) return *this;
- AttrBuilder B(*this);
+ AttrBuilder B(C, *this);
B.removeAttribute(Kind);
return get(C, B);
}
AttributeSet AttributeSet::removeAttributes(LLVMContext &C,
- const AttrBuilder &Attrs) const {
- AttrBuilder B(*this);
+ const AttributeMask &Attrs) const {
+ AttrBuilder B(C, *this);
// If there is nothing to remove, directly return the original set.
if (!B.overlaps(Attrs))
return *this;
@@ -817,28 +815,7 @@ AttributeSetNode *AttributeSetNode::getSorted(LLVMContext &C,
}
AttributeSetNode *AttributeSetNode::get(LLVMContext &C, const AttrBuilder &B) {
- // Add target-independent attributes.
- SmallVector<Attribute, 8> Attrs;
- for (Attribute::AttrKind Kind = Attribute::None;
- Kind != Attribute::EndAttrKinds; Kind = Attribute::AttrKind(Kind + 1)) {
- if (!B.contains(Kind))
- continue;
-
- Attribute Attr;
- if (Attribute::isTypeAttrKind(Kind))
- Attr = Attribute::get(C, Kind, B.getTypeAttr(Kind));
- else if (Attribute::isIntAttrKind(Kind))
- Attr = Attribute::get(C, Kind, B.getRawIntAttr(Kind));
- else
- Attr = Attribute::get(C, Kind);
- Attrs.push_back(Attr);
- }
-
- // Add target-dependent (string) attributes.
- for (const auto &TDA : B.td_attrs())
- Attrs.emplace_back(Attribute::get(C, TDA.first, TDA.second));
-
- return getSorted(C, Attrs);
+ return getSorted(C, B.attrs());
}
bool AttributeSetNode::hasAttribute(StringRef Kind) const {
@@ -1194,9 +1171,9 @@ AttributeList AttributeList::get(LLVMContext &C,
SmallVector<AttributeSet, 8> NewAttrSets(MaxSize);
for (unsigned I = 0; I < MaxSize; ++I) {
- AttrBuilder CurBuilder;
+ AttrBuilder CurBuilder(C);
for (const auto &List : Attrs)
- CurBuilder.merge(List.getAttributes(I - 1));
+ CurBuilder.merge(AttrBuilder(C, List.getAttributes(I - 1)));
NewAttrSets[I] = AttributeSet::get(C, CurBuilder);
}
@@ -1218,14 +1195,14 @@ AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
StringRef Kind,
StringRef Value) const {
- AttrBuilder B;
+ AttrBuilder B(C);
B.addAttribute(Kind, Value);
return addAttributesAtIndex(C, Index, B);
}
AttributeList AttributeList::addAttributeAtIndex(LLVMContext &C, unsigned Index,
Attribute A) const {
- AttrBuilder B;
+ AttrBuilder B(C);
B.addAttribute(A);
return addAttributesAtIndex(C, Index, B);
}
@@ -1250,16 +1227,7 @@ AttributeList AttributeList::addAttributesAtIndex(LLVMContext &C,
if (!pImpl)
return AttributeList::get(C, {{Index, AttributeSet::get(C, B)}});
-#ifndef NDEBUG
- // FIXME it is not obvious how this should work for alignment. For now, say
- // we can't change a known alignment.
- const MaybeAlign OldAlign = getAttributes(Index).getAlignment();
- const MaybeAlign NewAlign = B.getAlignment();
- assert((!OldAlign || !NewAlign || OldAlign == NewAlign) &&
- "Attempt to change alignment!");
-#endif
-
- AttrBuilder Merged(getAttributes(Index));
+ AttrBuilder Merged(C, getAttributes(Index));
Merged.merge(B);
return setAttributesAtIndex(C, Index, AttributeSet::get(C, Merged));
}
@@ -1276,7 +1244,7 @@ AttributeList AttributeList::addParamAttribute(LLVMContext &C,
for (unsigned ArgNo : ArgNos) {
unsigned Index = attrIdxToArrayIdx(ArgNo + FirstArgIndex);
- AttrBuilder B(AttrSets[Index]);
+ AttrBuilder B(C, AttrSets[Index]);
B.addAttribute(A);
AttrSets[Index] = AttributeSet::get(C, B);
}
@@ -1314,9 +1282,8 @@ AttributeList AttributeList::removeAttributeAtIndex(LLVMContext &C,
return getImpl(C, AttrSets);
}
-AttributeList
-AttributeList::removeAttributesAtIndex(LLVMContext &C, unsigned Index,
- const AttrBuilder &AttrsToRemove) const {
+AttributeList AttributeList::removeAttributesAtIndex(
+ LLVMContext &C, unsigned Index, const AttributeMask &AttrsToRemove) const {
AttributeSet Attrs = getAttributes(Index);
AttributeSet NewAttrs = Attrs.removeAttributes(C, AttrsToRemove);
// If nothing was removed, return the original list.
@@ -1340,7 +1307,7 @@ AttributeList::removeAttributesAtIndex(LLVMContext &C,
AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
uint64_t Bytes) const {
- AttrBuilder B;
+ AttrBuilder B(C);
B.addDereferenceableAttr(Bytes);
return addRetAttributes(C, B);
}
@@ -1348,7 +1315,7 @@ AttributeList AttributeList::addDereferenceableRetAttr(LLVMContext &C,
AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
unsigned Index,
uint64_t Bytes) const {
- AttrBuilder B;
+ AttrBuilder B(C);
B.addDereferenceableAttr(Bytes);
return addParamAttributes(C, Index, B);
}
@@ -1356,7 +1323,7 @@ AttributeList AttributeList::addDereferenceableParamAttr(LLVMContext &C,
AttributeList
AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
uint64_t Bytes) const {
- AttrBuilder B;
+ AttrBuilder B(C);
B.addDereferenceableOrNullAttr(Bytes);
return addParamAttributes(C, Index, B);
}
@@ -1365,7 +1332,7 @@ AttributeList
AttributeList::addAllocSizeParamAttr(LLVMContext &C, unsigned Index,
unsigned ElemSizeArg,
const Optional<unsigned> &NumElemsArg) {
- AttrBuilder B;
+ AttrBuilder B(C);
B.addAllocSizeAttr(ElemSizeArg, NumElemsArg);
return addParamAttributes(C, Index, B);
}
@@ -1549,97 +1516,93 @@ LLVM_DUMP_METHOD void AttributeList::dump() const { print(dbgs()); }
// AttrBuilder Method Implementations
//===----------------------------------------------------------------------===//
-// FIXME: Remove this ctor, use AttributeSet.
-AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) {
- AttributeSet AS = AL.getAttributes(Index);
- for (const auto &A : AS)
- addAttribute(A);
-}
-
-AttrBuilder::AttrBuilder(AttributeSet AS) {
- for (const auto &A : AS)
- addAttribute(A);
+AttrBuilder::AttrBuilder(LLVMContext &Ctx, AttributeSet AS) : Ctx(Ctx) {
+ append_range(Attrs, AS);
+ assert(is_sorted(Attrs) && "AttributeSet should be sorted");
}
-void AttrBuilder::clear() {
- Attrs.reset();
- TargetDepAttrs.clear();
- IntAttrs = {};
- TypeAttrs = {};
-}
+void AttrBuilder::clear() { Attrs.clear(); }
-Optional<unsigned>
-AttrBuilder::kindToIntIndex(Attribute::AttrKind Kind) const {
- if (Attribute::isIntAttrKind(Kind))
- return Kind - Attribute::FirstIntAttr;
- return None;
-}
+/// Attribute comparator that only compares attribute keys. Enum attributes are
+/// sorted before string attributes.
+struct AttributeComparator {
+ bool operator()(Attribute A0, Attribute A1) const {
+ bool A0IsString = A0.isStringAttribute();
+ bool A1IsString = A1.isStringAttribute();
+ if (A0IsString) {
+ if (A1IsString)
+ return A0.getKindAsString() < A1.getKindAsString();
+ else
+ return false;
+ }
+ if (A1IsString)
+ return true;
+ return A0.getKindAsEnum() < A1.getKindAsEnum();
+ }
+ bool operator()(Attribute A0, Attribute::AttrKind Kind) const {
+ if (A0.isStringAttribute())
+ return false;
+ return A0.getKindAsEnum() < Kind;
+ }
+ bool operator()(Attribute A0, StringRef Kind) const {
+ if (A0.isStringAttribute())
+ return A0.getKindAsString() < Kind;
+ return true;
+ }
+};
-Optional<unsigned>
-AttrBuilder::kindToTypeIndex(Attribute::AttrKind Kind) const {
- if (Attribute::isTypeAttrKind(Kind))
- return Kind - Attribute::FirstTypeAttr;
- return None;
+template <typename K>
+static void addAttributeImpl(SmallVectorImpl<Attribute> &Attrs, K Kind,
+ Attribute Attr) {
+ auto It = lower_bound(Attrs, Kind, AttributeComparator());
+ if (It != Attrs.end() && It->hasAttribute(Kind))
+ std::swap(*It, Attr);
+ else
+ Attrs.insert(It, Attr);
}
AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
- if (Attr.isStringAttribute()) {
- addAttribute(Attr.getKindAsString(), Attr.getValueAsString());
- return *this;
- }
-
- Attribute::AttrKind Kind = Attr.getKindAsEnum();
- Attrs[Kind] = true;
-
- if (Optional<unsigned> TypeIndex = kindToTypeIndex(Kind))
- TypeAttrs[*TypeIndex] = Attr.getValueAsType();
- else if (Optional<unsigned> IntIndex = kindToIntIndex(Kind))
- IntAttrs[*IntIndex] = Attr.getValueAsInt();
+ if (Attr.isStringAttribute())
+ addAttributeImpl(Attrs, Attr.getKindAsString(), Attr);
+ else
+ addAttributeImpl(Attrs, Attr.getKindAsEnum(), Attr);
+ return *this;
+}
+AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Kind) {
+ addAttributeImpl(Attrs, Kind, Attribute::get(Ctx, Kind));
return *this;
}
AttrBuilder &AttrBuilder::addAttribute(StringRef A, StringRef V) {
- TargetDepAttrs[A] = V;
+ addAttributeImpl(Attrs, A, Attribute::get(Ctx, A, V));
return *this;
}
AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
- Attrs[Val] = false;
-
- if (Optional<unsigned> TypeIndex = kindToTypeIndex(Val))
- TypeAttrs[*TypeIndex] = nullptr;
- else if (Optional<unsigned> IntIndex = kindToIntIndex(Val))
- IntAttrs[*IntIndex] = 0;
-
- return *this;
-}
-
-AttrBuilder &AttrBuilder::removeAttributes(AttributeList A, uint64_t Index) {
- remove(A.getAttributes(Index));
+ auto It = lower_bound(Attrs, Val, AttributeComparator());
+ if (It != Attrs.end() && It->hasAttribute(Val))
+ Attrs.erase(It);
return *this;
}
AttrBuilder &AttrBuilder::removeAttribute(StringRef A) {
- TargetDepAttrs.erase(A);
+ auto It = lower_bound(Attrs, A, AttributeComparator());
+ if (It != Attrs.end() && It->hasAttribute(A))
+ Attrs.erase(It);
return *this;
}
uint64_t AttrBuilder::getRawIntAttr(Attribute::AttrKind Kind) const {
- Optional<unsigned> IntIndex = kindToIntIndex(Kind);
- assert(IntIndex && "Not an int attribute");
- return IntAttrs[*IntIndex];
+ assert(Attribute::isIntAttrKind(Kind) && "Not an int attribute");
+ Attribute A = getAttribute(Kind);
+ return A.isValid() ? A.getValueAsInt() : 0;
}
AttrBuilder &AttrBuilder::addRawIntAttr(Attribute::AttrKind Kind,
uint64_t Value) {
- Optional<unsigned> IntIndex = kindToIntIndex(Kind);
- assert(IntIndex && "Not an int attribute");
- assert(Value && "Value cannot be zero");
- Attrs[Kind] = true;
- IntAttrs[*IntIndex] = Value;
- return *this;
+ return addAttribute(Attribute::get(Ctx, Kind, Value));
}
std::pair<unsigned, Optional<unsigned>> AttrBuilder::getAllocSizeArgs() const {
@@ -1709,17 +1672,13 @@ AttrBuilder &AttrBuilder::addVScaleRangeAttrFromRawRepr(uint64_t RawArgs) {
}
Type *AttrBuilder::getTypeAttr(Attribute::AttrKind Kind) const {
- Optional<unsigned> TypeIndex = kindToTypeIndex(Kind);
- assert(TypeIndex && "Not a type attribute");
- return TypeAttrs[*TypeIndex];
+ assert(Attribute::isTypeAttrKind(Kind) && "Not a type attribute");
+ Attribute A = getAttribute(Kind);
+ return A.isValid() ? A.getValueAsType() : nullptr;
}
AttrBuilder &AttrBuilder::addTypeAttr(Attribute::AttrKind Kind, Type *Ty) {
- Optional<unsigned> TypeIndex = kindToTypeIndex(Kind);
- assert(TypeIndex && "Not a type attribute");
- Attrs[Kind] = true;
- TypeAttrs[*TypeIndex] = Ty;
- return *this;
+ return addAttribute(Attribute::get(Ctx, Kind, Ty));
}
AttrBuilder &AttrBuilder::addByValAttr(Type *Ty) {
@@ -1743,76 +1702,43 @@ AttrBuilder &AttrBuilder::addInAllocaAttr(Type *Ty) {
}
AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
- // FIXME: What if both have an int/type attribute, but they don't match?!
- for (unsigned Index = 0; Index < Attribute::NumIntAttrKinds; ++Index)
- if (!IntAttrs[Index])
- IntAttrs[Index] = B.IntAttrs[Index];
-
- for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index)
- if (!TypeAttrs[Index])
- TypeAttrs[Index] = B.TypeAttrs[Index];
-
- Attrs |= B.Attrs;
-
- for (const auto &I : B.td_attrs())
- TargetDepAttrs[I.first] = I.second;
+ // TODO: Could make this O(n) as we're merging two sorted lists.
+ for (const auto &I : B.attrs())
+ addAttribute(I);
return *this;
}
-AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) {
- // FIXME: What if both have an int/type attribute, but they don't match?!
- for (unsigned Index = 0; Index < Attribute::NumIntAttrKinds; ++Index)
- if (B.IntAttrs[Index])
- IntAttrs[Index] = 0;
-
- for (unsigned Index = 0; Index < Attribute::NumTypeAttrKinds; ++Index)
- if (B.TypeAttrs[Index])
- TypeAttrs[Index] = nullptr;
-
- Attrs &= ~B.Attrs;
-
- for (const auto &I : B.td_attrs())
- TargetDepAttrs.erase(I.first);
-
+AttrBuilder &AttrBuilder::remove(const AttributeMask &AM) {
+ erase_if(Attrs, [&](Attribute A) { return AM.contains(A); });
return *this;
}
-bool AttrBuilder::overlaps(const AttrBuilder &B) const {
- // First check if any of the target independent attributes overlap.
- if ((Attrs & B.Attrs).any())
- return true;
-
- // Then check if any target dependent ones do.
- for (const auto &I : td_attrs())
- if (B.contains(I.first))
- return true;
-
- return false;
+bool AttrBuilder::overlaps(const AttributeMask &AM) const {
+ return any_of(Attrs, [&](Attribute A) { return AM.contains(A); });
}
-bool AttrBuilder::contains(StringRef A) const {
- return TargetDepAttrs.find(A) != TargetDepAttrs.end();
+Attribute AttrBuilder::getAttribute(Attribute::AttrKind A) const {
+ assert((unsigned)A < Attribute::EndAttrKinds && "Attribute out of range!");
+ auto It = lower_bound(Attrs, A, AttributeComparator());
+ if (It != Attrs.end() && It->hasAttribute(A))
+ return *It;
+ return {};
}
-bool AttrBuilder::hasAttributes() const {
- return !Attrs.none() || !TargetDepAttrs.empty();
+Attribute AttrBuilder::getAttribute(StringRef A) const {
+ auto It = lower_bound(Attrs, A, AttributeComparator());
+ if (It != Attrs.end() && It->hasAttribute(A))
+ return *It;
+ return {};
}
-bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const {
- AttributeSet AS = AL.getAttributes(Index);
-
- for (const auto &Attr : AS) {
- if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
- if (contains(Attr.getKindAsEnum()))
- return true;
- } else {
- assert(Attr.isStringAttribute() && "Invalid attribute kind!");
- return contains(Attr.getKindAsString());
- }
- }
+bool AttrBuilder::contains(Attribute::AttrKind A) const {
+ return getAttribute(A).isValid();
+}
- return false;
+bool AttrBuilder::contains(StringRef A) const {
+ return getAttribute(A).isValid();
}
bool AttrBuilder::hasAlignmentAttr() const {
@@ -1820,14 +1746,7 @@ bool AttrBuilder::hasAlignmentAttr() const {
}
bool AttrBuilder::operator==(const AttrBuilder &B) const {
- if (Attrs != B.Attrs)
- return false;
-
- for (const auto &TDA : TargetDepAttrs)
- if (B.TargetDepAttrs.find(TDA.first) == B.TargetDepAttrs.end())
- return false;
-
- return IntAttrs == B.IntAttrs && TypeAttrs == B.TypeAttrs;
+ return Attrs == B.Attrs;
}
//===----------------------------------------------------------------------===//
@@ -1835,16 +1754,16 @@ bool AttrBuilder::operator==(const AttrBuilder &B) const {
//===----------------------------------------------------------------------===//
/// Which attributes cannot be applied to a type.
-AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
- AttrBuilder Incompatible;
+AttributeMask AttributeFuncs::typeIncompatible(Type *Ty) {
+ AttributeMask Incompatible;
if (!Ty->isIntegerTy())
- // Attribute that only apply to integers.
+ // Attributes that only apply to integers.
Incompatible.addAttribute(Attribute::SExt)
.addAttribute(Attribute::ZExt);
if (!Ty->isPointerTy())
- // Attribute that only apply to pointers.
+ // Attributes that only apply to pointers.
Incompatible.addAttribute(Attribute::Nest)
.addAttribute(Attribute::NoAlias)
.addAttribute(Attribute::NoCapture)
@@ -1852,15 +1771,18 @@ AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
.addAttribute(Attribute::ReadNone)
.addAttribute(Attribute::ReadOnly)
.addAttribute(Attribute::SwiftError)
- .addAlignmentAttr(1) // the int here is ignored
- .addDereferenceableAttr(1) // the int here is ignored
- .addDereferenceableOrNullAttr(1) // the int here is ignored
- .addPreallocatedAttr(Ty)
- .addInAllocaAttr(Ty)
- .addByValAttr(Ty)
- .addStructRetAttr(Ty)
- .addByRefAttr(Ty)
- .addTypeAttr(Attribute::ElementType, Ty);
+ .addAttribute(Attribute::Dereferenceable)
+ .addAttribute(Attribute::DereferenceableOrNull)
+ .addAttribute(Attribute::Preallocated)
+ .addAttribute(Attribute::InAlloca)
+ .addAttribute(Attribute::ByVal)
+ .addAttribute(Attribute::StructRet)
+ .addAttribute(Attribute::ByRef)
+ .addAttribute(Attribute::ElementType);
+
+ if (!Ty->isPtrOrPtrVectorTy())
+ // Attributes that only apply to pointers or vectors of pointers.
+ Incompatible.addAttribute(Attribute::Alignment);
// Some attributes can apply to all "values" but there are no `void` values.
if (Ty->isVoidTy())
@@ -1869,12 +1791,12 @@ AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) {
return Incompatible;
}
-AttrBuilder AttributeFuncs::getUBImplyingAttributes() {
- AttrBuilder B;
- B.addAttribute(Attribute::NoUndef);
- B.addDereferenceableAttr(1);
- B.addDereferenceableOrNullAttr(1);
- return B;
+AttributeMask AttributeFuncs::getUBImplyingAttributes() {
+ AttributeMask AM;
+ AM.addAttribute(Attribute::NoUndef);
+ AM.addAttribute(Attribute::Dereferenceable);
+ AM.addAttribute(Attribute::DereferenceableOrNull);
+ return AM;
}
template<typename AttrClass>
@@ -1910,10 +1832,16 @@ static void setOR(Function &Caller, const Function &Callee) {
/// If the inlined function had a higher stack protection level than the
/// calling function, then bump up the caller's stack protection level.
static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
+ // If the calling function has *no* stack protection level (e.g. it was built
+ // with Clang's -fno-stack-protector or no_stack_protector attribute), don't
+ // change it as that could change the program's semantics.
+ if (!Caller.hasStackProtectorFnAttr())
+ return;
+
// If upgrading the SSP attribute, clear out the old SSP Attributes first.
// Having multiple SSP attributes doesn't actually hurt, but it adds useless
// clutter to the IR.
- AttrBuilder OldSSPAttr;
+ AttributeMask OldSSPAttr;
OldSSPAttr.addAttribute(Attribute::StackProtect)
.addAttribute(Attribute::StackProtectStrong)
.addAttribute(Attribute::StackProtectReq);