diff --git a/llvm/include/llvm/Attributes.h b/llvm/include/llvm/Attributes.h index c3198a555fd3..a564441deff4 100644 --- a/llvm/include/llvm/Attributes.h +++ b/llvm/include/llvm/Attributes.h @@ -199,6 +199,7 @@ public: void clear() { Bits = 0; } bool hasAttributes() const; + bool hasAttributes(const Attributes &A) const; bool hasAlignmentAttr() const; uint64_t getAlignment() const; @@ -232,6 +233,8 @@ public: void addAlignmentAttr(unsigned Align); void addStackAlignmentAttr(unsigned Align); + void removeAttributes(const Attributes &A); + void removeAddressSafetyAttr(); void removeAlwaysInlineAttr(); void removeByValAttr(); @@ -267,6 +270,11 @@ public: static Attributes get(Builder &B); static Attributes get(LLVMContext &Context, Builder &B); + /// @brief Parameter attributes that do not apply to vararg call arguments. + bool hasIncompatibleWithVarArgsAttrs() const { + return hasStructRetAttr(); + } + // Attribute query methods. // FIXME: StackAlignment & Alignment attributes have no predicate methods. bool hasAttributes() const { @@ -494,6 +502,9 @@ public: /// least one parameter or for the return value. bool hasAttrSomewhere(Attributes Attr) const; + unsigned getNumAttrs() const; + Attributes &getAttributesAtIndex(unsigned i) const; + /// operator==/!= - Provide equality predicates. bool operator==(const AttrListPtr &RHS) const { return AttrList == RHS.AttrList; } @@ -537,7 +548,6 @@ private: /// getAttributes - The attributes for the specified index are /// returned. Attributes for the result are denoted with Idx = 0. Attributes getAttributes(unsigned Idx) const; - }; } // End llvm namespace diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 048afae9f102..a0002ee4bca5 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -2779,7 +2779,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) { AttrListPtr PAL = AttrListPtr::get(Attrs); - if (PAL.paramHasAttr(1, Attribute::StructRet) && !RetType->isVoidTy()) + if (PAL.getParamAttributes(1).hasStructRetAttr() && !RetType->isVoidTy()) return Error(RetTypeLoc, "functions with 'sret' argument must return void"); FunctionType *FT = diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index d2f9fc921bd9..f4802606d337 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1036,8 +1036,8 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { return false; // Cannot transform this return value. if (!CallerPAL.isEmpty() && !Caller->use_empty()) { - Attributes RAttrs = CallerPAL.getRetAttributes(); - if (RAttrs & Attributes::typeIncompatible(NewRetTy)) + Attributes::Builder RAttrs = CallerPAL.getRetAttributes(); + if (RAttrs.hasAttributes(Attributes::typeIncompatible(NewRetTy))) return false; // Attribute not compatible with transformed value. } @@ -1072,7 +1072,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { // If the parameter is passed as a byval argument, then we have to have a // sized type and the sized type has to have the same size as the old type. - if (ParamTy != ActTy && (Attrs & Attribute::ByVal)) { + if (ParamTy != ActTy && Attrs.hasByValAttr()) { PointerType *ParamPTy = dyn_cast(ParamTy); if (ParamPTy == 0 || !ParamPTy->getElementType()->isSized() || TD == 0) return false; @@ -1124,7 +1124,7 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { if (CallerPAL.getSlot(i - 1).Index <= FT->getNumParams()) break; Attributes PAttrs = CallerPAL.getSlot(i - 1).Attrs; - if (PAttrs & Attribute::VarArgsIncompatible) + if (PAttrs.hasIncompatibleWithVarArgsAttrs()) return false; } @@ -1137,15 +1137,15 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { attrVec.reserve(NumCommonArgs); // Get any return attributes. - Attributes RAttrs = CallerPAL.getRetAttributes(); + Attributes::Builder RAttrs = CallerPAL.getRetAttributes(); // If the return value is not being used, the type may not be compatible // with the existing attributes. Wipe out any problematic attributes. - RAttrs &= ~Attributes::typeIncompatible(NewRetTy); + RAttrs.removeAttributes(Attributes::typeIncompatible(NewRetTy)); // Add the new return attributes. - if (RAttrs) - attrVec.push_back(AttributeWithIndex::get(0, RAttrs)); + if (RAttrs.hasAttributes()) + attrVec.push_back(AttributeWithIndex::get(0, Attributes::get(RAttrs))); AI = CS.arg_begin(); for (unsigned i = 0; i != NumCommonArgs; ++i, ++AI) { @@ -1263,8 +1263,9 @@ InstCombiner::transformCallThroughTrampoline(CallSite CS, // If the call already has the 'nest' attribute somewhere then give up - // otherwise 'nest' would occur twice after splicing in the chain. - if (Attrs.hasAttrSomewhere(Attribute::Nest)) - return 0; + for (unsigned I = 0, E = Attrs.getNumAttrs(); I != E; ++I) + if (Attrs.getAttributesAtIndex(I).hasNestAttr()) + return 0; assert(Tramp && "transformCallThroughTrampoline called with incorrect CallSite."); @@ -1277,12 +1278,12 @@ InstCombiner::transformCallThroughTrampoline(CallSite CS, if (!NestAttrs.isEmpty()) { unsigned NestIdx = 1; Type *NestTy = 0; - Attributes NestAttr = Attribute::None; + Attributes NestAttr; // Look for a parameter marked with the 'nest' attribute. for (FunctionType::param_iterator I = NestFTy->param_begin(), E = NestFTy->param_end(); I != E; ++NestIdx, ++I) - if (NestAttrs.paramHasAttr(NestIdx, Attribute::Nest)) { + if (NestAttrs.getParamAttributes(NestIdx).hasNestAttr()) { // Record the parameter type and any other attributes. NestTy = *I; NestAttr = NestAttrs.getParamAttributes(NestIdx); diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp index bcee0c5f04ee..4c71fe3f4a92 100644 --- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -682,7 +682,9 @@ void GCOVProfiler::insertCounterWriteout( "__llvm_gcov_init", M); F->setUnnamedAddr(true); F->setLinkage(GlobalValue::InternalLinkage); - F->addFnAttr(Attribute::NoInline); + Attributes::Builder B; + B.addNoInlineAttr(); + F->addFnAttr(Attributes::get(B)); BB = BasicBlock::Create(*Ctx, "entry", F); Builder.SetInsertPoint(BB); @@ -701,7 +703,9 @@ void GCOVProfiler::insertIndirectCounterIncrement() { cast(GCOVProfiler::getIncrementIndirectCounterFunc()); Fn->setUnnamedAddr(true); Fn->setLinkage(GlobalValue::InternalLinkage); - Fn->addFnAttr(Attribute::NoInline); + Attributes::Builder B; + B.addNoInlineAttr(); + Fn->addFnAttr(Attributes::get(B)); Type *Int32Ty = Type::getInt32Ty(*Ctx); Type *Int64Ty = Type::getInt64Ty(*Ctx); diff --git a/llvm/lib/VMCore/Attributes.cpp b/llvm/lib/VMCore/Attributes.cpp index 6905e4df39c4..6f5eefae0d22 100644 --- a/llvm/lib/VMCore/Attributes.cpp +++ b/llvm/lib/VMCore/Attributes.cpp @@ -377,6 +377,10 @@ void Attributes::Builder::addStackAlignmentAttr(unsigned Align) { Bits |= (Log2_32(Align) + 1) << 26; } +void Attributes::Builder::removeAttributes(const Attributes &A) { + Bits &= ~A.Raw(); +} + void Attributes::Builder::removeAddressSafetyAttr() { Bits &= ~Attribute::AddressSafety_i; } @@ -463,6 +467,9 @@ void Attributes::Builder::removeStackAlignmentAttr() { bool Attributes::Builder::hasAttributes() const { return Bits != 0; } +bool Attributes::Builder::hasAttributes(const Attributes &A) const { + return Bits & A.Raw(); +} bool Attributes::Builder::hasAlignmentAttr() const { return Bits & Attribute::Alignment_i; } @@ -662,6 +669,15 @@ bool AttrListPtr::hasAttrSomewhere(Attributes Attr) const { return false; } +unsigned AttrListPtr::getNumAttrs() const { + return AttrList ? AttrList->Attrs.size() : 0; +} + +Attributes &AttrListPtr::getAttributesAtIndex(unsigned i) const { + assert(AttrList && "Trying to get an attribute from an empty list!"); + assert(i < AttrList->Attrs.size() && "Index out of range!"); + return AttrList->Attrs[i].Attrs; +} AttrListPtr AttrListPtr::addAttr(unsigned Idx, Attributes Attrs) const { Attributes OldAttrs = getAttributes(Idx);