aboutsummaryrefslogtreecommitdiffstats
path: root/lib/VMCore/Attributes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/VMCore/Attributes.cpp')
-rw-r--r--lib/VMCore/Attributes.cpp88
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.