Mercurial > hg > CbC > CbC_llvm
diff lib/IR/Attributes.cpp @ 148:63bd29f05246
merged
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Wed, 14 Aug 2019 19:46:37 +0900 |
parents | c2174574ed3a |
children |
line wrap: on
line diff
--- a/lib/IR/Attributes.cpp Sun Dec 23 19:23:36 2018 +0900 +++ b/lib/IR/Attributes.cpp Wed Aug 14 19:46:37 2019 +0900 @@ -1,14 +1,13 @@ //===- 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 // //===----------------------------------------------------------------------===// // // \file -// \brief This file implements the Attribute, AttributeImpl, AttrBuilder, +// This file implements the Attribute, AttributeImpl, AttrBuilder, // AttributeListImpl, and AttributeList classes. // //===----------------------------------------------------------------------===// @@ -24,6 +23,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" +#include "llvm/Config/llvm-config.h" #include "llvm/IR/Function.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Type.h" @@ -38,7 +38,6 @@ #include <cstddef> #include <cstdint> #include <limits> -#include <map> #include <string> #include <tuple> #include <utility> @@ -122,6 +121,27 @@ 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 @@ 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 @@ 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(); } @@ -186,19 +214,27 @@ } StringRef Attribute::getKindAsString() const { - if (!pImpl) return StringRef(); + if (!pImpl) return {}; assert(isStringAttribute() && "Invalid attribute type to get the kind as a string!"); return pImpl->getKindAsString(); } StringRef Attribute::getValueAsString() const { - if (!pImpl) return StringRef(); + if (!pImpl) return {}; assert(isStringAttribute() && "Invalid attribute type to get the value as a string!"); 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); } @@ -241,20 +277,20 @@ } std::string Attribute::getAsString(bool InAttrGrp) const { - if (!pImpl) return ""; + if (!pImpl) return {}; if (hasAttribute(Attribute::SanitizeAddress)) 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 @@ 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,10 +337,18 @@ 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)) return "norecurse"; if (hasAttribute(Attribute::NoUnwind)) return "nounwind"; + if (hasAttribute(Attribute::OptForFuzzing)) + return "optforfuzzing"; if (hasAttribute(Attribute::OptimizeNone)) return "optnone"; if (hasAttribute(Attribute::OptimizeForSize)) @@ -319,6 +365,8 @@ return "returns_twice"; if (hasAttribute(Attribute::SExt)) return "signext"; + if (hasAttribute(Attribute::SpeculativeLoadHardening)) + return "speculative_load_hardening"; if (hasAttribute(Attribute::Speculatable)) return "speculatable"; if (hasAttribute(Attribute::StackProtect)) @@ -329,6 +377,8 @@ return "sspstrong"; if (hasAttribute(Attribute::SafeStack)) return "safestack"; + if (hasAttribute(Attribute::ShadowCallStack)) + return "shadowcallstack"; if (hasAttribute(Attribute::StrictFP)) return "strictfp"; if (hasAttribute(Attribute::StructRet)) @@ -343,6 +393,21 @@ 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: // @@ -413,7 +478,7 @@ { raw_string_ostream OS(Result); OS << "=\""; - PrintEscapedString(AttrVal, OS); + printEscapedString(AttrVal, OS); OS << "\""; } return Result; @@ -442,6 +507,8 @@ void StringAttributeImpl::anchor() {} +void TypeAttributeImpl::anchor() {} + bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const { if (isStringAttribute()) return false; return getKindAsEnum() == A; @@ -453,7 +520,7 @@ } Attribute::AttrKind AttributeImpl::getKindAsEnum() const { - assert(isEnumAttribute() || isIntAttribute()); + assert(isEnumAttribute() || isIntAttribute() || isTypeAttribute()); return static_cast<const EnumAttributeImpl *>(this)->getEnumKind(); } @@ -472,6 +539,11 @@ 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. @@ -479,10 +551,23 @@ 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(); @@ -491,7 +576,9 @@ 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(); @@ -534,7 +621,7 @@ return *this; AttrBuilder B(AS); - for (Attribute I : *this) + for (const auto I : *this) B.addAttribute(I); return get(C, B); @@ -599,6 +686,10 @@ 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); @@ -629,13 +720,18 @@ //===----------------------------------------------------------------------===// 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. - std::copy(Attrs.begin(), Attrs.end(), getTrailingObjects<Attribute>()); + llvm::copy(Attrs, getTrailingObjects<Attribute>()); - for (Attribute I : *this) { + 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); } } } @@ -650,9 +746,9 @@ FoldingSetNodeID ID; SmallVector<Attribute, 8> SortedAttrs(Attrs.begin(), Attrs.end()); - std::sort(SortedAttrs.begin(), SortedAttrs.end()); + llvm::sort(SortedAttrs); - for (Attribute Attr : SortedAttrs) + for (const auto Attr : SortedAttrs) Attr.Profile(ID); void *InsertPoint; @@ -682,6 +778,9 @@ Attribute Attr; switch (Kind) { + case Attribute::ByVal: + Attr = Attribute::getWithByValType(C, B.getByValType()); + break; case Attribute::Alignment: Attr = Attribute::getWithAlignment(C, B.getAlignment()); break; @@ -715,7 +814,7 @@ } bool AttributeSetNode::hasAttribute(StringRef Kind) const { - for (Attribute I : *this) + for (const auto I : *this) if (I.hasAttribute(Kind)) return true; return false; @@ -723,43 +822,50 @@ Attribute AttributeSetNode::getAttribute(Attribute::AttrKind Kind) const { if (hasAttribute(Kind)) { - for (Attribute I : *this) + for (const auto I : *this) if (I.hasAttribute(Kind)) return I; } - return Attribute(); + return {}; } Attribute AttributeSetNode::getAttribute(StringRef Kind) const { - for (Attribute I : *this) + for (const auto I : *this) if (I.hasAttribute(Kind)) return I; - return Attribute(); + return {}; } unsigned AttributeSetNode::getAlignment() const { - for (Attribute I : *this) + for (const auto I : *this) if (I.hasAttribute(Attribute::Alignment)) return I.getAlignment(); return 0; } unsigned AttributeSetNode::getStackAlignment() const { - for (Attribute I : *this) + for (const auto I : *this) if (I.hasAttribute(Attribute::StackAlignment)) return I.getStackAlignment(); 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 (Attribute I : *this) + for (const auto I : *this) if (I.hasAttribute(Attribute::Dereferenceable)) return I.getDereferenceableBytes(); return 0; } uint64_t AttributeSetNode::getDereferenceableOrNullBytes() const { - for (Attribute I : *this) + for (const auto I : *this) if (I.hasAttribute(Attribute::DereferenceableOrNull)) return I.getDereferenceableOrNullBytes(); return 0; @@ -767,7 +873,7 @@ std::pair<unsigned, Optional<unsigned>> AttributeSetNode::getAllocSizeArgs() const { - for (Attribute I : *this) + for (const auto I : *this) if (I.hasAttribute(Attribute::AllocSize)) return I.getAllocSizeArgs(); return std::make_pair(0, 0); @@ -797,11 +903,11 @@ 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. - std::copy(Sets.begin(), Sets.end(), getTrailingObjects<AttributeSet>()); + llvm::copy(Sets, getTrailingObjects<AttributeSet>()); // Initialize AvailableFunctionAttrs summary bitset. static_assert(Attribute::EndAttrKinds <= @@ -809,9 +915,11 @@ "Too many attributes"); static_assert(attrIdxToArrayIdx(AttributeList::FunctionIndex) == 0U, "function should be stored in slot 0"); - for (Attribute I : Sets[0]) { - if (!I.isStringAttribute()) - AvailableFunctionAttrs |= 1ULL << I.getKindAsEnum(); + for (const auto I : Sets[0]) { + if (!I.isStringAttribute()) { + Attribute::AttrKind Kind = I.getKindAsEnum(); + AvailableFunctionAttrs[Kind / 8] |= 1ULL << (Kind % 8); + } } } @@ -866,17 +974,17 @@ ArrayRef<std::pair<unsigned, Attribute>> Attrs) { // If there are no attributes then return a null AttributesList pointer. if (Attrs.empty()) - return AttributeList(); + return {}; assert(std::is_sorted(Attrs.begin(), Attrs.end(), [](const std::pair<unsigned, Attribute> &LHS, const std::pair<unsigned, Attribute> &RHS) { return LHS.first < RHS.first; }) && "Misordered Attributes list!"); - assert(none_of(Attrs, - [](const std::pair<unsigned, Attribute> &Pair) { - return Pair.second.hasAttribute(Attribute::None); - }) && + assert(llvm::none_of(Attrs, + [](const std::pair<unsigned, Attribute> &Pair) { + return Pair.second.hasAttribute(Attribute::None); + }) && "Pointless attribute!"); // Create a vector if (unsigned, AttributeSetNode*) pairs from the attributes @@ -902,7 +1010,7 @@ ArrayRef<std::pair<unsigned, AttributeSet>> Attrs) { // If there are no attributes then return a null AttributesList pointer. if (Attrs.empty()) - return AttributeList(); + return {}; assert(std::is_sorted(Attrs.begin(), Attrs.end(), [](const std::pair<unsigned, AttributeSet> &LHS, @@ -910,16 +1018,20 @@ return LHS.first < RHS.first; }) && "Misordered Attributes list!"); - assert(none_of(Attrs, - [](const std::pair<unsigned, AttributeSet> &Pair) { - return !Pair.second.hasAttributes(); - }) && + assert(llvm::none_of(Attrs, + [](const std::pair<unsigned, AttributeSet> &Pair) { + return !Pair.second.hasAttributes(); + }) && "Pointless attribute!"); unsigned MaxIndex = Attrs.back().first; + // If the MaxIndex is FunctionIndex and there are other indices in front + // of it, we need to use the largest of those to get the right size. + if (MaxIndex == FunctionIndex && Attrs.size() > 1) + MaxIndex = Attrs[Attrs.size() - 2].first; SmallVector<AttributeSet, 4> AttrVec(attrIdxToArrayIdx(MaxIndex) + 1); - for (auto Pair : Attrs) + for (const auto Pair : Attrs) AttrVec[attrIdxToArrayIdx(Pair.first)] = Pair.second; return getImpl(C, AttrVec); @@ -949,7 +1061,7 @@ // If all attribute sets were empty, we can use the empty attribute list. if (NumSets == 0) - return AttributeList(); + return {}; SmallVector<AttributeSet, 8> AttrSets; AttrSets.reserve(NumSets); @@ -969,7 +1081,7 @@ AttributeList AttributeList::get(LLVMContext &C, unsigned Index, const AttrBuilder &B) { if (!B.hasAttributes()) - return AttributeList(); + return {}; Index = attrIdxToArrayIdx(Index); SmallVector<AttributeSet, 8> AttrSets(Index + 1); AttrSets[Index] = AttributeSet::get(C, B); @@ -979,7 +1091,7 @@ AttributeList AttributeList::get(LLVMContext &C, unsigned Index, ArrayRef<Attribute::AttrKind> Kinds) { SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; - for (Attribute::AttrKind K : Kinds) + for (const auto K : Kinds) Attrs.emplace_back(Index, Attribute::get(C, K)); return get(C, Attrs); } @@ -987,7 +1099,7 @@ AttributeList AttributeList::get(LLVMContext &C, unsigned Index, ArrayRef<StringRef> Kinds) { SmallVector<std::pair<unsigned, Attribute>, 8> Attrs; - for (StringRef K : Kinds) + for (const auto K : Kinds) Attrs.emplace_back(Index, Attribute::get(C, K)); return get(C, Attrs); } @@ -995,22 +1107,22 @@ AttributeList AttributeList::get(LLVMContext &C, ArrayRef<AttributeList> Attrs) { if (Attrs.empty()) - return AttributeList(); + return {}; if (Attrs.size() == 1) return Attrs[0]; unsigned MaxSize = 0; - for (AttributeList List : Attrs) + for (const auto List : Attrs) MaxSize = std::max(MaxSize, List.getNumAttrSets()); // If every list was empty, there is no point in merging the lists. if (MaxSize == 0) - return AttributeList(); + return {}; SmallVector<AttributeSet, 8> NewAttrSets(MaxSize); for (unsigned I = 0; I < MaxSize; ++I) { AttrBuilder CurBuilder; - for (AttributeList List : Attrs) + for (const auto List : Attrs) CurBuilder.merge(List.getAttributes(I - 1)); NewAttrSets[I] = AttributeSet::get(C, CurBuilder); } @@ -1120,7 +1232,7 @@ AttributeList::removeAttributes(LLVMContext &C, unsigned Index, const AttrBuilder &AttrsToRemove) const { if (!pImpl) - return AttributeList(); + return {}; Index = attrIdxToArrayIdx(Index); SmallVector<AttributeSet, 4> AttrSets(this->begin(), this->end()); @@ -1135,7 +1247,7 @@ AttributeList AttributeList::removeAttributes(LLVMContext &C, unsigned WithoutIndex) const { if (!pImpl) - return AttributeList(); + return {}; WithoutIndex = attrIdxToArrayIdx(WithoutIndex); if (WithoutIndex >= getNumAttrSets()) return *this; @@ -1245,6 +1357,11 @@ 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(); } @@ -1269,7 +1386,7 @@ AttributeSet AttributeList::getAttributes(unsigned Index) const { Index = attrIdxToArrayIdx(Index); if (!pImpl || Index >= getNumAttrSets()) - return AttributeSet(); + return {}; return pImpl->begin()[Index]; } @@ -1309,20 +1426,23 @@ // FIXME: Remove this ctor, use AttributeSet. AttrBuilder::AttrBuilder(AttributeList AL, unsigned Index) { AttributeSet AS = AL.getAttributes(Index); - for (const Attribute &A : AS) + for (const auto &A : AS) addAttribute(A); } AttrBuilder::AttrBuilder(AttributeSet AS) { - for (const Attribute &A : AS) + for (const auto &A : AS) addAttribute(A); } void AttrBuilder::clear() { Attrs.reset(); TargetDepAttrs.clear(); - Alignment = StackAlignment = DerefBytes = DerefOrNullBytes = 0; + Alignment.reset(); + StackAlignment.reset(); + DerefBytes = DerefOrNullBytes = 0; AllocSizeArgs = 0; + ByValType = nullptr; } AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) { @@ -1344,9 +1464,11 @@ Attrs[Kind] = true; if (Kind == Attribute::Alignment) - Alignment = Attr.getAlignment(); + Alignment = MaybeAlign(Attr.getAlignment()); else if (Kind == Attribute::StackAlignment) - StackAlignment = Attr.getStackAlignment(); + StackAlignment = MaybeAlign(Attr.getStackAlignment()); + else if (Kind == Attribute::ByVal) + ByValType = Attr.getValueAsType(); else if (Kind == Attribute::Dereferenceable) DerefBytes = Attr.getDereferenceableBytes(); else if (Kind == Attribute::DereferenceableOrNull) @@ -1366,9 +1488,11 @@ Attrs[Val] = false; if (Val == Attribute::Alignment) - Alignment = 0; + Alignment.reset(); else if (Val == Attribute::StackAlignment) - StackAlignment = 0; + StackAlignment.reset(); + else if (Val == Attribute::ByVal) + ByValType = nullptr; else if (Val == Attribute::Dereferenceable) DerefBytes = 0; else if (Val == Attribute::DereferenceableOrNull) @@ -1385,7 +1509,7 @@ } AttrBuilder &AttrBuilder::removeAttribute(StringRef A) { - std::map<std::string, std::string>::iterator I = TargetDepAttrs.find(A); + auto I = TargetDepAttrs.find(A); if (I != TargetDepAttrs.end()) TargetDepAttrs.erase(I); return *this; @@ -1395,23 +1519,25 @@ return unpackAllocSizeArgs(AllocSizeArgs); } -AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) { - if (Align == 0) return *this; +AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned A) { + MaybeAlign Align(A); + if (!Align) + return *this; - assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); - assert(Align <= 0x40000000 && "Alignment too large."); + assert(*Align <= 0x40000000 && "Alignment too large."); Attrs[Attribute::Alignment] = true; Alignment = Align; return *this; } -AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) { +AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned A) { + MaybeAlign Align(A); // Default alignment, allow the target to define how to align it. - if (Align == 0) return *this; + if (!Align) + return *this; - assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); - assert(Align <= 0x100 && "Alignment too large."); + assert(*Align <= 0x100 && "Alignment too large."); Attrs[Attribute::StackAlignment] = true; StackAlignment = Align; @@ -1451,6 +1577,12 @@ 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) @@ -1468,6 +1600,9 @@ if (!AllocSizeArgs) AllocSizeArgs = B.AllocSizeArgs; + if (!ByValType) + ByValType = B.ByValType; + Attrs |= B.Attrs; for (auto I : B.td_attrs()) @@ -1479,10 +1614,10 @@ AttrBuilder &AttrBuilder::remove(const AttrBuilder &B) { // FIXME: What if both have alignments, but they don't match?! if (B.Alignment) - Alignment = 0; + Alignment.reset(); if (B.StackAlignment) - StackAlignment = 0; + StackAlignment.reset(); if (B.DerefBytes) DerefBytes = 0; @@ -1493,6 +1628,9 @@ if (B.AllocSizeArgs) AllocSizeArgs = 0; + if (B.ByValType) + ByValType = nullptr; + Attrs &= ~B.Attrs; for (auto I : B.td_attrs()) @@ -1525,7 +1663,7 @@ bool AttrBuilder::hasAttributes(AttributeList AL, uint64_t Index) const { AttributeSet AS = AL.getAttributes(Index); - for (Attribute Attr : AS) { + for (const auto Attr : AS) { if (Attr.isEnumAttribute() || Attr.isIntAttribute()) { if (contains(Attr.getKindAsEnum())) return true; @@ -1552,14 +1690,14 @@ return false; return Alignment == B.Alignment && StackAlignment == B.StackAlignment && - DerefBytes == B.DerefBytes; + DerefBytes == B.DerefBytes && ByValType == B.ByValType; } //===----------------------------------------------------------------------===// // AttributeFuncs Function Defintions //===----------------------------------------------------------------------===// -/// \brief Which attributes cannot be applied to a type. +/// Which attributes cannot be applied to a type. AttrBuilder AttributeFuncs::typeIncompatible(Type *Ty) { AttrBuilder Incompatible; @@ -1591,7 +1729,7 @@ Callee.getFnAttribute(AttrClass::getKind()); } -/// \brief Compute the logical AND of the attributes of the caller and the +/// Compute the logical AND of the attributes of the caller and the /// callee. /// /// This function sets the caller's attribute to false if the callee's attribute @@ -1603,7 +1741,7 @@ AttrClass::set(Caller, AttrClass::getKind(), false); } -/// \brief Compute the logical OR of the attributes of the caller and the +/// Compute the logical OR of the attributes of the caller and the /// callee. /// /// This function sets the caller's attribute to true if the callee's attribute @@ -1615,7 +1753,7 @@ AttrClass::set(Caller, AttrClass::getKind(), true); } -/// \brief If the inlined function had a higher stack protection level than the +/// 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 upgrading the SSP attribute, clear out the old SSP Attributes first. @@ -1639,7 +1777,7 @@ Caller.addFnAttr(Attribute::StackProtect); } -/// \brief If the inlined function required stack probes, then ensure that +/// If the inlined function required stack probes, then ensure that /// the calling function has those too. static void adjustCallerStackProbes(Function &Caller, const Function &Callee) { if (!Caller.hasFnAttribute("probe-stack") && @@ -1648,7 +1786,7 @@ } } -/// \brief If the inlined function defines the size of guard region +/// If the inlined function defines the size of guard region /// on the stack, then ensure that the calling function defines a guard region /// that is no larger. static void @@ -1672,6 +1810,46 @@ } } +/// If the inlined function defines a min legal vector width, then ensure +/// the calling function has the same or larger min legal vector width. If the +/// caller has the attribute, but the callee doesn't, we need to remove the +/// attribute from the caller since we can't make any guarantees about the +/// caller's requirements. +/// This function is called after the inlining decision has been made so we have +/// to merge the attribute this way. Heuristics that would use +/// min-legal-vector-width to determine inline compatibility would need to be +/// handled as part of inline cost analysis. +static void +adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) { + if (Caller.hasFnAttribute("min-legal-vector-width")) { + if (Callee.hasFnAttribute("min-legal-vector-width")) { + uint64_t CallerVectorWidth; + Caller.getFnAttribute("min-legal-vector-width") + .getValueAsString() + .getAsInteger(0, CallerVectorWidth); + uint64_t CalleeVectorWidth; + Callee.getFnAttribute("min-legal-vector-width") + .getValueAsString() + .getAsInteger(0, CalleeVectorWidth); + if (CallerVectorWidth < CalleeVectorWidth) + Caller.addFnAttr(Callee.getFnAttribute("min-legal-vector-width")); + } else { + // If the callee doesn't have the attribute then we don't know anything + // and must drop the attribute from the caller. + Caller.removeFnAttr("min-legal-vector-width"); + } + } +} + +/// If the inlined function has "null-pointer-is-valid=true" attribute, +/// set this attribute in the caller post inlining. +static void +adjustNullPointerValidAttr(Function &Caller, const Function &Callee) { + if (Callee.nullPointerIsDefined() && !Caller.nullPointerIsDefined()) { + Caller.addFnAttr(Callee.getFnAttribute("null-pointer-is-valid")); + } +} + #define GET_ATTR_COMPAT_FUNC #include "AttributesCompatFunc.inc"