diff options
Diffstat (limited to 'lib/VMCore/Attributes.cpp')
-rw-r--r-- | lib/VMCore/Attributes.cpp | 88 |
1 files changed, 63 insertions, 25 deletions
diff --git a/lib/VMCore/Attributes.cpp b/lib/VMCore/Attributes.cpp index e81bf3c83a..cfa276ebd6 100644 --- a/lib/VMCore/Attributes.cpp +++ b/lib/VMCore/Attributes.cpp @@ -33,14 +33,14 @@ Attributes::Attributes(AttributesImpl *A) : Attrs(A) {} Attributes::Attributes(const Attributes &A) : Attrs(A.Attrs) {} Attributes Attributes::get(LLVMContext &Context, ArrayRef<AttrVal> Vals) { - Attributes::Builder B; + AttrBuilder B; for (ArrayRef<AttrVal>::iterator I = Vals.begin(), E = Vals.end(); I != E; ++I) B.addAttribute(*I); return Attributes::get(Context, B); } -Attributes Attributes::get(LLVMContext &Context, Attributes::Builder &B) { +Attributes Attributes::get(LLVMContext &Context, AttrBuilder &B) { // If there are no attributes, return an empty Attributes class. if (B.Bits == 0) return Attributes(); @@ -96,7 +96,7 @@ uint64_t Attributes::Raw() const { } Attributes Attributes::typeIncompatible(Type *Ty) { - Attributes::Builder Incompatible; + AttrBuilder Incompatible; if (!Ty->isIntegerTy()) // Attributes that only apply to integers. @@ -114,6 +114,44 @@ Attributes Attributes::typeIncompatible(Type *Ty) { return Attributes::get(Ty->getContext(), Incompatible); } +/// encodeLLVMAttributesForBitcode - This returns an integer containing an +/// encoding of all the LLVM attributes found in the given attribute bitset. +/// Any change to this encoding is a breaking change to bitcode compatibility. +uint64_t Attributes::encodeLLVMAttributesForBitcode(Attributes Attrs) { + // FIXME: It doesn't make sense to store the alignment information as an + // expanded out value, we should store it as a log2 value. However, we can't + // just change that here without breaking bitcode compatibility. If this ever + // becomes a problem in practice, we should introduce new tag numbers in the + // bitcode file and have those tags use a more efficiently encoded alignment + // field. + + // Store the alignment in the bitcode as a 16-bit raw value instead of a 5-bit + // log2 encoded value. Shift the bits above the alignment up by 11 bits. + uint64_t EncodedAttrs = Attrs.Raw() & 0xffff; + if (Attrs.hasAttribute(Attributes::Alignment)) + EncodedAttrs |= Attrs.getAlignment() << 16; + EncodedAttrs |= (Attrs.Raw() & (0xfffULL << 21)) << 11; + return EncodedAttrs; +} + +/// decodeLLVMAttributesForBitcode - This returns an attribute bitset containing +/// the LLVM attributes that have been decoded from the given integer. This +/// function must stay in sync with 'encodeLLVMAttributesForBitcode'. +Attributes Attributes::decodeLLVMAttributesForBitcode(LLVMContext &C, + uint64_t EncodedAttrs) { + // The alignment is stored as a 16-bit raw value from bits 31--16. We shift + // the bits above 31 down by 11 bits. + unsigned Alignment = (EncodedAttrs & (0xffffULL << 16)) >> 16; + assert((!Alignment || isPowerOf2_32(Alignment)) && + "Alignment must be a power of two."); + + AttrBuilder B(EncodedAttrs & 0xffff); + if (Alignment) + B.addAlignmentAttr(Alignment); + B.addRawValue((EncodedAttrs & (0xfffULL << 32)) >> 11); + return Attributes::get(C, B); +} + std::string Attributes::getAsString() const { std::string Result; if (hasAttribute(Attributes::ZExt)) @@ -183,27 +221,27 @@ std::string Attributes::getAsString() const { } //===----------------------------------------------------------------------===// -// Attributes::Builder Implementation +// AttrBuilder Implementation //===----------------------------------------------------------------------===// -Attributes::Builder &Attributes::Builder::addAttribute(Attributes::AttrVal Val){ +AttrBuilder &AttrBuilder::addAttribute(Attributes::AttrVal Val){ Bits |= AttributesImpl::getAttrMask(Val); return *this; } -Attributes::Builder &Attributes::Builder::addRawValue(uint64_t Val) { +AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) { Bits |= Val; return *this; } -Attributes::Builder &Attributes::Builder::addAlignmentAttr(unsigned Align) { +AttrBuilder &AttrBuilder::addAlignmentAttr(unsigned Align) { if (Align == 0) return *this; assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); assert(Align <= 0x40000000 && "Alignment too large."); Bits |= (Log2_32(Align) + 1) << 16; return *this; } -Attributes::Builder &Attributes::Builder::addStackAlignmentAttr(unsigned Align){ +AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align){ // Default alignment, allow the target to define how to align it. if (Align == 0) return *this; assert(isPowerOf2_32(Align) && "Alignment must be a power of two."); @@ -212,44 +250,44 @@ Attributes::Builder &Attributes::Builder::addStackAlignmentAttr(unsigned Align){ return *this; } -Attributes::Builder &Attributes::Builder:: +AttrBuilder &AttrBuilder:: removeAttribute(Attributes::AttrVal Val) { Bits &= ~AttributesImpl::getAttrMask(Val); return *this; } -Attributes::Builder &Attributes::Builder::addAttributes(const Attributes &A) { +AttrBuilder &AttrBuilder::addAttributes(const Attributes &A) { Bits |= A.Raw(); return *this; } -Attributes::Builder &Attributes::Builder::removeAttributes(const Attributes &A){ +AttrBuilder &AttrBuilder::removeAttributes(const Attributes &A){ Bits &= ~A.Raw(); return *this; } -bool Attributes::Builder::hasAttribute(Attributes::AttrVal A) const { +bool AttrBuilder::hasAttribute(Attributes::AttrVal A) const { return Bits & AttributesImpl::getAttrMask(A); } -bool Attributes::Builder::hasAttributes() const { +bool AttrBuilder::hasAttributes() const { return Bits != 0; } -bool Attributes::Builder::hasAttributes(const Attributes &A) const { +bool AttrBuilder::hasAttributes(const Attributes &A) const { return Bits & A.Raw(); } -bool Attributes::Builder::hasAlignmentAttr() const { +bool AttrBuilder::hasAlignmentAttr() const { return Bits & AttributesImpl::getAttrMask(Attributes::Alignment); } -uint64_t Attributes::Builder::getAlignment() const { +uint64_t AttrBuilder::getAlignment() const { if (!hasAlignmentAttr()) return 0; return 1U << (((Bits & AttributesImpl::getAttrMask(Attributes::Alignment)) >> 16) - 1); } -uint64_t Attributes::Builder::getStackAlignment() const { +uint64_t AttrBuilder::getStackAlignment() const { if (!hasAlignmentAttr()) return 0; return 1U << @@ -497,9 +535,9 @@ AttrListPtr AttrListPtr::addAttr(LLVMContext &C, unsigned Idx, "Attempt to change alignment!"); #endif - Attributes::Builder NewAttrs = - Attributes::Builder(OldAttrs).addAttributes(Attrs); - if (NewAttrs == Attributes::Builder(OldAttrs)) + AttrBuilder NewAttrs = + AttrBuilder(OldAttrs).addAttributes(Attrs); + if (NewAttrs == AttrBuilder(OldAttrs)) return *this; SmallVector<AttributeWithIndex, 8> NewAttrList; @@ -515,7 +553,7 @@ AttrListPtr AttrListPtr::addAttr(LLVMContext &C, unsigned Idx, // If there are attributes already at this index, merge them in. if (i != e && OldAttrList[i].Index == Idx) { Attrs = - Attributes::get(C, Attributes::Builder(Attrs). + Attributes::get(C, AttrBuilder(Attrs). addAttributes(OldAttrList[i].Attrs)); ++i; } @@ -541,9 +579,9 @@ AttrListPtr AttrListPtr::removeAttr(LLVMContext &C, unsigned Idx, if (AttrList == 0) return AttrListPtr(); Attributes OldAttrs = getAttributes(Idx); - Attributes::Builder NewAttrs = - Attributes::Builder(OldAttrs).removeAttributes(Attrs); - if (NewAttrs == Attributes::Builder(OldAttrs)) + AttrBuilder NewAttrs = + AttrBuilder(OldAttrs).removeAttributes(Attrs); + if (NewAttrs == AttrBuilder(OldAttrs)) return *this; SmallVector<AttributeWithIndex, 8> NewAttrList; @@ -556,7 +594,7 @@ AttrListPtr AttrListPtr::removeAttr(LLVMContext &C, unsigned Idx, // If there are attributes already at this index, merge them in. assert(OldAttrList[i].Index == Idx && "Attribute isn't set?"); - Attrs = Attributes::get(C, Attributes::Builder(OldAttrList[i].Attrs). + Attrs = Attributes::get(C, AttrBuilder(OldAttrList[i].Attrs). removeAttributes(Attrs)); ++i; if (Attrs.hasAttributes()) // If any attributes left for this param, add them. |