diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 29246f31caa..37d487f0fdd 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -146,20 +146,6 @@ public: uint64_t Raw() const; - /// \brief Which attributes cannot be applied to a type. - static Attribute typeIncompatible(Type *Ty); - - /// \brief 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. - static uint64_t encodeLLVMAttributesForBitcode(Attribute Attrs); - - /// \brief 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'. - static Attribute decodeLLVMAttributesForBitcode(LLVMContext &C, - uint64_t EncodedAttrs); - /// \brief The Attribute is converted to a string of equivalent mnemonic. This /// is, presumably, for writing out the mnemonics for the assembly writer. std::string getAsString() const; @@ -236,6 +222,7 @@ public: /// \brief Return an AttributeSet with the specified parameters in it. static AttributeSet get(LLVMContext &C, ArrayRef Attrs); + static AttributeSet get(LLVMContext &C, ArrayRef Attrs); static AttributeSet get(LLVMContext &C, unsigned Idx, Attribute::AttrKind Kind); static AttributeSet get(LLVMContext &C, unsigned Idx, AttrBuilder &B); @@ -296,6 +283,10 @@ public: /// \brief Return true if attribute exists at the given index. bool hasAttributes(unsigned Index) const; + /// \brief Returns the alignment field of an attribute as a byte alignment + /// value. + unsigned getAlignment(unsigned Index) const; + /// \brief Get the stack alignment. unsigned getStackAlignment(unsigned Index) const; @@ -342,6 +333,9 @@ public: /// \brief Return the index for the given slot. unsigned getSlotIndex(unsigned Slot) const; + /// \brief Return the attributes at the given slot. + AttributeSet getSlotAttributes(unsigned Slot) const; + /// \brief Return the AttributeWithIndex at the specified slot. This holds a /// index number plus a set of attributes. const AttributeWithIndex &getSlot(unsigned Slot) const; @@ -479,6 +473,24 @@ public: } }; +namespace AttributeFuncs { + +/// \brief Which attributes cannot be applied to a type. +Attribute typeIncompatible(Type *Ty); + +/// \brief 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 encodeLLVMAttributesForBitcode(AttributeSet Attrs, unsigned Index); + +/// \brief 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'. +Attribute decodeLLVMAttributesForBitcode(LLVMContext &C, + uint64_t EncodedAttrs); + +} // end AttributeFuncs namespace + } // end llvm namespace #endif diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index f09b93b33a5..4190161b62e 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -465,7 +465,7 @@ bool BitcodeReader::ParseAttributeBlock() { for (unsigned i = 0, e = Record.size(); i != e; i += 2) { Attribute ReconstitutedAttr = - Attribute::decodeLLVMAttributesForBitcode(Context, Record[i+1]); + AttributeFuncs::decodeLLVMAttributesForBitcode(Context, Record[i+1]); Record[i+1] = ReconstitutedAttr.Raw(); } diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index cc6b8b39fbd..b6c2bc0f750 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -173,9 +173,11 @@ static void WriteAttributeTable(const ValueEnumerator &VE, for (unsigned i = 0, e = Attrs.size(); i != e; ++i) { const AttributeSet &A = Attrs[i]; for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i) { - const AttributeWithIndex &PAWI = A.getSlot(i); - Record.push_back(A.getSlotIndex(i)); - Record.push_back(Attribute::encodeLLVMAttributesForBitcode(PAWI.Attrs)); + unsigned Index = A.getSlotIndex(i); + Record.push_back(Index); + Record.push_back(AttributeFuncs:: + encodeLLVMAttributesForBitcode(A.getSlotAttributes(i), + Index)); } Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record); diff --git a/lib/IR/AttributeImpl.h b/lib/IR/AttributeImpl.h index ebd90e29e21..d7ebec5daaa 100644 --- a/lib/IR/AttributeImpl.h +++ b/lib/IR/AttributeImpl.h @@ -104,6 +104,8 @@ public: /// \brief This class represents a set of attributes that apply to the function, /// return type, and parameters. class AttributeSetImpl : public FoldingSetNode { + friend class AttributeSet; + LLVMContext &Context; SmallVector AttrList; @@ -126,6 +128,10 @@ public: // FIXME: This needs to use AttrNodes instead. return AttrList[Slot].Index; } + AttributeSet getSlotAttributes(unsigned Slot) const { + // FIXME: This needs to use AttrNodes instead. + return AttributeSet::get(Context, AttrList[Slot]); + } void Profile(FoldingSetNodeID &ID) const { Profile(ID, AttrList); diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index 538d9fee763..f44a0fc7419 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -103,63 +103,6 @@ uint64_t Attribute::Raw() const { return pImpl ? pImpl->Raw() : 0; } -Attribute Attribute::typeIncompatible(Type *Ty) { - AttrBuilder Incompatible; - - if (!Ty->isIntegerTy()) - // Attribute that only apply to integers. - Incompatible.addAttribute(Attribute::SExt) - .addAttribute(Attribute::ZExt); - - if (!Ty->isPointerTy()) - // Attribute that only apply to pointers. - Incompatible.addAttribute(Attribute::ByVal) - .addAttribute(Attribute::Nest) - .addAttribute(Attribute::NoAlias) - .addAttribute(Attribute::NoCapture) - .addAttribute(Attribute::StructRet); - - return Attribute::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 Attribute::encodeLLVMAttributesForBitcode(Attribute 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(Attribute::Alignment)) - EncodedAttrs |= Attrs.getAlignment() << 16; - EncodedAttrs |= (Attrs.Raw() & (0xffffULL << 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'. -Attribute Attribute::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 & (0xffffULL << 32)) >> 11); - return Attribute::get(C, B); -} - std::string Attribute::getAsString() const { std::string Result; if (hasAttribute(Attribute::ZExt)) @@ -666,6 +609,18 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Idx, return get(C, AttributeWithIndex::get(Idx, Attribute::get(C, Kind))); } +AttributeSet AttributeSet::get(LLVMContext &C, ArrayRef Attrs) { + SmallVector AttrList; + for (ArrayRef::iterator I = Attrs.begin(), E = Attrs.end(); + I != E; ++I) { + AttributeSet AS = *I; + if (!AS.AttrList) continue; + AttrList.append(AS.AttrList->AttrList.begin(), AS.AttrList->AttrList.end()); + } + + return get(C, AttrList); +} + //===----------------------------------------------------------------------===// // AttributeSet Method Implementations //===----------------------------------------------------------------------===// @@ -688,6 +643,12 @@ unsigned AttributeSet::getSlotIndex(unsigned Slot) const { return AttrList->getSlotIndex(Slot); } +AttributeSet AttributeSet::getSlotAttributes(unsigned Slot) const { + assert(AttrList && Slot < AttrList->getNumAttributes() && + "Slot # out of range!"); + return AttrList->getSlotAttributes(Slot); +} + /// getSlot - Return the AttributeWithIndex at the specified slot. This /// holds a number plus a set of attributes. const AttributeWithIndex &AttributeSet::getSlot(unsigned Slot) const { @@ -859,3 +820,66 @@ void AttributeSet::dump() const { dbgs() << "]\n"; } + +//===----------------------------------------------------------------------===// +// AttributeFuncs Function Defintions +//===----------------------------------------------------------------------===// + +Attribute AttributeFuncs::typeIncompatible(Type *Ty) { + AttrBuilder Incompatible; + + if (!Ty->isIntegerTy()) + // Attribute that only apply to integers. + Incompatible.addAttribute(Attribute::SExt) + .addAttribute(Attribute::ZExt); + + if (!Ty->isPointerTy()) + // Attribute that only apply to pointers. + Incompatible.addAttribute(Attribute::ByVal) + .addAttribute(Attribute::Nest) + .addAttribute(Attribute::NoAlias) + .addAttribute(Attribute::NoCapture) + .addAttribute(Attribute::StructRet); + + return Attribute::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 AttributeFuncs::encodeLLVMAttributesForBitcode(AttributeSet Attrs, + unsigned Index) { + // 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(Index) & 0xffff; + if (Attrs.hasAttribute(Index, Attribute::Alignment)) + EncodedAttrs |= Attrs.getParamAlignment(Index) << 16; + EncodedAttrs |= (Attrs.Raw(Index) & (0xffffULL << 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'. +Attribute AttributeFuncs::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 & (0xffffULL << 32)) >> 11); + return Attribute::get(C, B); +} + diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 9a482f1452b..39f95fa772d 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -693,9 +693,9 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, uint64_t Idx, Type *Ty, "'noinline and alwaysinline' are incompatible!", V); Assert1(!AttrBuilder(Attrs, Idx). - hasAttributes(Attribute::typeIncompatible(Ty)), + hasAttributes(AttributeFuncs::typeIncompatible(Ty)), "Wrong types for attribute: " + - Attribute::typeIncompatible(Ty).getAsString(), V); + AttributeFuncs::typeIncompatible(Ty).getAsString(), V); if (PointerType *PTy = dyn_cast(Ty)) Assert1(!Attrs.hasAttribute(Idx, Attribute::ByVal) || diff --git a/lib/Target/CppBackend/CPPBackend.cpp b/lib/Target/CppBackend/CPPBackend.cpp index 2560c6e6c47..1f4bdf8d89b 100644 --- a/lib/Target/CppBackend/CPPBackend.cpp +++ b/lib/Target/CppBackend/CPPBackend.cpp @@ -474,7 +474,7 @@ void CppWriter::printAttributes(const AttributeSet &PAL, Out << "AttributeWithIndex PAWI;"; nl(Out); for (unsigned i = 0; i < PAL.getNumSlots(); ++i) { unsigned index = PAL.getSlotIndex(i); - AttrBuilder attrs(PAL.getSlot(i).Attrs); + AttrBuilder attrs(PAL.getSlotAttributes(i), index); Out << "PAWI.Index = " << index << "U;\n"; Out << " {\n AttrBuilder B;\n"; diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp index 4603146ecfa..61b37d87cca 100644 --- a/lib/Transforms/IPO/DeadArgumentElimination.cpp +++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp @@ -273,13 +273,15 @@ bool DAE::DeleteDeadVarargs(Function &Fn) { // Drop any attributes that were on the vararg arguments. AttributeSet PAL = CS.getAttributes(); if (!PAL.isEmpty() && PAL.getSlotIndex(PAL.getNumSlots() - 1) > NumArgs) { - SmallVector AttributesVec; + SmallVector AttributesVec; for (unsigned i = 0; PAL.getSlotIndex(i) <= NumArgs; ++i) - AttributesVec.push_back(PAL.getSlot(i)); + AttributesVec.push_back(PAL.getSlotAttributes(i)); if (PAL.hasAttributes(AttributeSet::FunctionIndex)) - AttributesVec.push_back(AttributeWithIndex::get(Fn.getContext(), - AttributeSet::FunctionIndex, - PAL.getFnAttributes())); + AttributesVec.push_back( + AttributeSet::get(Fn.getContext(), + AttributeWithIndex::get(Fn.getContext(), + AttributeSet::FunctionIndex, + PAL.getFnAttributes()))); PAL = AttributeSet::get(Fn.getContext(), AttributesVec); } @@ -765,10 +767,10 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { RAttrs = AttributeSet::get(NRetTy->getContext(), AttributeSet::ReturnIndex, AttrBuilder(RAttrs, AttributeSet::ReturnIndex). - removeAttributes(Attribute::typeIncompatible(NRetTy))); + removeAttributes(AttributeFuncs::typeIncompatible(NRetTy))); else assert(!AttrBuilder(RAttrs, AttributeSet::ReturnIndex). - hasAttributes(Attribute::typeIncompatible(NRetTy)) && + hasAttributes(AttributeFuncs::typeIncompatible(NRetTy)) && "Return attributes no longer compatible?"); if (RAttrs.hasAttributes(AttributeSet::ReturnIndex)) @@ -846,7 +848,7 @@ bool DAE::RemoveDeadStuffFromFunction(Function *F) { RAttrs = AttributeSet::get(NF->getContext(), AttributeSet::ReturnIndex, AttrBuilder(RAttrs, AttributeSet::ReturnIndex). - removeAttributes(Attribute::typeIncompatible(NF->getReturnType()))); + removeAttributes(AttributeFuncs::typeIncompatible(NF->getReturnType()))); if (RAttrs.hasAttributes(AttributeSet::ReturnIndex)) AttributesVec.push_back(AttributeWithIndex::get(NF->getContext(), AttributeSet::ReturnIndex, diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index 52d4e2fbba4..c753e2a85db 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -2068,11 +2068,12 @@ static void ChangeCalleesToFastCall(Function *F) { static AttributeSet StripNest(LLVMContext &C, const AttributeSet &Attrs) { for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) { - if (!Attrs.getSlot(i).Attrs.hasAttribute(Attribute::Nest)) + unsigned Index = Attrs.getSlotIndex(i); + if (!Attrs.getSlotAttributes(i).hasAttribute(Index, Attribute::Nest)) continue; // There can be only one. - return Attrs.removeAttribute(C, Attrs.getSlotIndex(i), Attribute::Nest); + return Attrs.removeAttribute(C, Index, Attribute::Nest); } return Attrs; diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 8555c2f030d..19eb965ea25 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1015,7 +1015,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { if (!CallerPAL.isEmpty() && !Caller->use_empty()) { AttrBuilder RAttrs(CallerPAL, AttributeSet::ReturnIndex); - if (RAttrs.hasAttributes(Attribute::typeIncompatible(NewRetTy))) + if (RAttrs.hasAttributes(AttributeFuncs::typeIncompatible(NewRetTy))) return false; // Attribute not compatible with transformed value. } @@ -1045,7 +1045,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { return false; // Cannot transform this parameter value. if (AttrBuilder(CallerPAL.getParamAttributes(i + 1), i + 1). - hasAttributes(Attribute::typeIncompatible(ParamTy))) + hasAttributes(AttributeFuncs::typeIncompatible(ParamTy))) return false; // Attribute not compatible with transformed value. // If the parameter is passed as a byval argument, then we have to have a @@ -1101,11 +1101,13 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { // won't be dropping them. Check that these extra arguments have attributes // that are compatible with being a vararg call argument. for (unsigned i = CallerPAL.getNumSlots(); i; --i) { - if (CallerPAL.getSlotIndex(i - 1) <= FT->getNumParams()) + unsigned Index = CallerPAL.getSlotIndex(i - 1); + if (Index <= FT->getNumParams()) break; - Attribute PAttrs = CallerPAL.getSlot(i - 1).Attrs; + // Check if it has an attribute that's incompatible with varargs. - if (PAttrs.hasAttribute(Attribute::StructRet)) + AttributeSet PAttrs = CallerPAL.getSlotAttributes(i - 1); + if (PAttrs.hasAttribute(Index, Attribute::StructRet)) return false; } @@ -1122,7 +1124,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { // If the return value is not being used, the type may not be compatible // with the existing attributes. Wipe out any problematic attributes. - RAttrs.removeAttributes(Attribute::typeIncompatible(NewRetTy)); + RAttrs.removeAttributes(AttributeFuncs::typeIncompatible(NewRetTy)); // Add the new return attributes. if (RAttrs.hasAttributes())