//
//===----------------------------------------------------------------------===//
+/// Attribute property base class.
+class AttrProperty;
+
+/// Can be used as function attribute.
+def FnAttr : AttrProperty;
+
+/// Can be used as parameter attribute.
+def ParamAttr : AttrProperty;
+
+/// Can be used as return attribute.
+def RetAttr : AttrProperty;
+
/// Attribute base class.
-class Attr<string S> {
+class Attr<string S, list<AttrProperty> P> {
// String representation of this attribute in the IR.
string AttrString = S;
+ list<AttrProperty> Properties = P;
}
/// Enum attribute.
-class EnumAttr<string S> : Attr<S>;
+class EnumAttr<string S, list<AttrProperty> P> : Attr<S, P>;
/// Int attribute.
-class IntAttr<string S> : Attr<S>;
-
-/// StringBool attribute.
-class StrBoolAttr<string S> : Attr<S>;
+class IntAttr<string S, list<AttrProperty> P> : Attr<S, P>;
/// Type attribute.
-class TypeAttr<string S> : Attr<S>;
+class TypeAttr<string S, list<AttrProperty> P> : Attr<S, P>;
+
+/// StringBool attribute.
+class StrBoolAttr<string S> : Attr<S, []>;
/// Target-independent enum attributes.
/// Alignment of parameter (5 bits) stored as log2 of alignment with +1 bias.
/// 0 means unaligned (different from align(1)).
-def Alignment : IntAttr<"align">;
+def Alignment : IntAttr<"align", [ParamAttr, RetAttr]>;
/// The result of the function is guaranteed to point to a number of bytes that
/// we can determine if we know the value of the function's arguments.
-def AllocSize : IntAttr<"allocsize">;
+def AllocSize : IntAttr<"allocsize", [FnAttr]>;
/// inline=always.
-def AlwaysInline : EnumAttr<"alwaysinline">;
+def AlwaysInline : EnumAttr<"alwaysinline", [FnAttr]>;
/// Function can access memory only using pointers based on its arguments.
-def ArgMemOnly : EnumAttr<"argmemonly">;
+def ArgMemOnly : EnumAttr<"argmemonly", [FnAttr]>;
/// Callee is recognized as a builtin, despite nobuiltin attribute on its
/// declaration.
-def Builtin : EnumAttr<"builtin">;
+def Builtin : EnumAttr<"builtin", [FnAttr]>;
/// Pass structure by value.
-def ByVal : TypeAttr<"byval">;
+def ByVal : TypeAttr<"byval", [ParamAttr]>;
/// Mark in-memory ABI type.
-def ByRef : TypeAttr<"byref">;
+def ByRef : TypeAttr<"byref", [ParamAttr]>;
/// Parameter or return value may not contain uninitialized or poison bits.
-def NoUndef : EnumAttr<"noundef">;
+def NoUndef : EnumAttr<"noundef", [ParamAttr, RetAttr]>;
/// Marks function as being in a cold path.
-def Cold : EnumAttr<"cold">;
+def Cold : EnumAttr<"cold", [FnAttr]>;
/// Can only be moved to control-equivalent blocks.
-def Convergent : EnumAttr<"convergent">;
+def Convergent : EnumAttr<"convergent", [FnAttr]>;
/// Marks function as being in a hot path and frequently called.
-def Hot: EnumAttr<"hot">;
+def Hot: EnumAttr<"hot", [FnAttr]>;
/// Pointer is known to be dereferenceable.
-def Dereferenceable : IntAttr<"dereferenceable">;
+def Dereferenceable : IntAttr<"dereferenceable", [ParamAttr, RetAttr]>;
/// Pointer is either null or dereferenceable.
-def DereferenceableOrNull : IntAttr<"dereferenceable_or_null">;
+def DereferenceableOrNull : IntAttr<"dereferenceable_or_null",
+ [ParamAttr, RetAttr]>;
/// Function may only access memory that is inaccessible from IR.
-def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly">;
+def InaccessibleMemOnly : EnumAttr<"inaccessiblememonly", [FnAttr]>;
/// Function may only access memory that is either inaccessible from the IR,
/// or pointed to by its pointer arguments.
-def InaccessibleMemOrArgMemOnly : EnumAttr<"inaccessiblemem_or_argmemonly">;
+def InaccessibleMemOrArgMemOnly : EnumAttr<"inaccessiblemem_or_argmemonly",
+ [FnAttr]>;
/// Pass structure in an alloca.
-def InAlloca : TypeAttr<"inalloca">;
+def InAlloca : TypeAttr<"inalloca", [ParamAttr]>;
/// Source said inlining was desirable.
-def InlineHint : EnumAttr<"inlinehint">;
+def InlineHint : EnumAttr<"inlinehint", [FnAttr]>;
/// Force argument to be passed in register.
-def InReg : EnumAttr<"inreg">;
+def InReg : EnumAttr<"inreg", [ParamAttr, RetAttr]>;
/// Build jump-instruction tables and replace refs.
-def JumpTable : EnumAttr<"jumptable">;
+def JumpTable : EnumAttr<"jumptable", [FnAttr]>;
/// Function must be optimized for size first.
-def MinSize : EnumAttr<"minsize">;
+def MinSize : EnumAttr<"minsize", [FnAttr]>;
/// Naked function.
-def Naked : EnumAttr<"naked">;
+def Naked : EnumAttr<"naked", [FnAttr]>;
/// Nested function static chain.
-def Nest : EnumAttr<"nest">;
+def Nest : EnumAttr<"nest", [ParamAttr]>;
/// Considered to not alias after call.
-def NoAlias : EnumAttr<"noalias">;
+def NoAlias : EnumAttr<"noalias", [ParamAttr, RetAttr]>;
/// Callee isn't recognized as a builtin.
-def NoBuiltin : EnumAttr<"nobuiltin">;
+def NoBuiltin : EnumAttr<"nobuiltin", [FnAttr]>;
/// Function cannot enter into caller's translation unit.
-def NoCallback : EnumAttr<"nocallback">;
+def NoCallback : EnumAttr<"nocallback", [FnAttr]>;
/// Function creates no aliases of pointer.
-def NoCapture : EnumAttr<"nocapture">;
+def NoCapture : EnumAttr<"nocapture", [ParamAttr]>;
/// Call cannot be duplicated.
-def NoDuplicate : EnumAttr<"noduplicate">;
+def NoDuplicate : EnumAttr<"noduplicate", [FnAttr]>;
/// Function does not deallocate memory.
-def NoFree : EnumAttr<"nofree">;
+def NoFree : EnumAttr<"nofree", [FnAttr, ParamAttr]>;
/// Disable implicit floating point insts.
-def NoImplicitFloat : EnumAttr<"noimplicitfloat">;
+def NoImplicitFloat : EnumAttr<"noimplicitfloat", [FnAttr]>;
/// inline=never.
-def NoInline : EnumAttr<"noinline">;
+def NoInline : EnumAttr<"noinline", [FnAttr]>;
/// Function is called early and/or often, so lazy binding isn't worthwhile.
-def NonLazyBind : EnumAttr<"nonlazybind">;
+def NonLazyBind : EnumAttr<"nonlazybind", [FnAttr]>;
/// Disable merging for specified functions or call sites.
-def NoMerge : EnumAttr<"nomerge">;
+def NoMerge : EnumAttr<"nomerge", [FnAttr]>;
/// Pointer is known to be not null.
-def NonNull : EnumAttr<"nonnull">;
+def NonNull : EnumAttr<"nonnull", [ParamAttr, RetAttr]>;
/// The function does not recurse.
-def NoRecurse : EnumAttr<"norecurse">;
+def NoRecurse : EnumAttr<"norecurse", [FnAttr]>;
/// Disable redzone.
-def NoRedZone : EnumAttr<"noredzone">;
+def NoRedZone : EnumAttr<"noredzone", [FnAttr]>;
/// Mark the function as not returning.
-def NoReturn : EnumAttr<"noreturn">;
+def NoReturn : EnumAttr<"noreturn", [FnAttr]>;
/// Function does not synchronize.
-def NoSync : EnumAttr<"nosync">;
+def NoSync : EnumAttr<"nosync", [FnAttr]>;
/// Disable Indirect Branch Tracking.
-def NoCfCheck : EnumAttr<"nocf_check">;
+def NoCfCheck : EnumAttr<"nocf_check", [FnAttr]>;
/// Function should not be instrumented.
-def NoProfile : EnumAttr<"noprofile">;
+def NoProfile : EnumAttr<"noprofile", [FnAttr]>;
/// Function doesn't unwind stack.
-def NoUnwind : EnumAttr<"nounwind">;
+def NoUnwind : EnumAttr<"nounwind", [FnAttr]>;
/// No SanitizeCoverage instrumentation.
-def NoSanitizeCoverage : EnumAttr<"nosanitize_coverage">;
+def NoSanitizeCoverage : EnumAttr<"nosanitize_coverage", [FnAttr]>;
/// Null pointer in address space zero is valid.
-def NullPointerIsValid : EnumAttr<"null_pointer_is_valid">;
+def NullPointerIsValid : EnumAttr<"null_pointer_is_valid", [FnAttr]>;
/// Select optimizations for best fuzzing signal.
-def OptForFuzzing : EnumAttr<"optforfuzzing">;
+def OptForFuzzing : EnumAttr<"optforfuzzing", [FnAttr]>;
/// opt_size.
-def OptimizeForSize : EnumAttr<"optsize">;
+def OptimizeForSize : EnumAttr<"optsize", [FnAttr]>;
/// Function must not be optimized.
-def OptimizeNone : EnumAttr<"optnone">;
+def OptimizeNone : EnumAttr<"optnone", [FnAttr]>;
/// Similar to byval but without a copy.
-def Preallocated : TypeAttr<"preallocated">;
+def Preallocated : TypeAttr<"preallocated", [FnAttr, ParamAttr]>;
/// Function does not access memory.
-def ReadNone : EnumAttr<"readnone">;
+def ReadNone : EnumAttr<"readnone", [FnAttr, ParamAttr]>;
/// Function only reads from memory.
-def ReadOnly : EnumAttr<"readonly">;
+def ReadOnly : EnumAttr<"readonly", [FnAttr, ParamAttr]>;
/// Return value is always equal to this argument.
-def Returned : EnumAttr<"returned">;
+def Returned : EnumAttr<"returned", [ParamAttr]>;
/// Parameter is required to be a trivial constant.
-def ImmArg : EnumAttr<"immarg">;
+def ImmArg : EnumAttr<"immarg", [ParamAttr]>;
/// Function can return twice.
-def ReturnsTwice : EnumAttr<"returns_twice">;
+def ReturnsTwice : EnumAttr<"returns_twice", [FnAttr]>;
/// Safe Stack protection.
-def SafeStack : EnumAttr<"safestack">;
+def SafeStack : EnumAttr<"safestack", [FnAttr]>;
/// Shadow Call Stack protection.
-def ShadowCallStack : EnumAttr<"shadowcallstack">;
+def ShadowCallStack : EnumAttr<"shadowcallstack", [FnAttr]>;
/// Sign extended before/after call.
-def SExt : EnumAttr<"signext">;
+def SExt : EnumAttr<"signext", [ParamAttr, RetAttr]>;
/// Alignment of stack for function (3 bits) stored as log2 of alignment with
/// +1 bias 0 means unaligned (different from alignstack=(1)).
-def StackAlignment : IntAttr<"alignstack">;
+def StackAlignment : IntAttr<"alignstack", [FnAttr, ParamAttr]>;
/// Function can be speculated.
-def Speculatable : EnumAttr<"speculatable">;
+def Speculatable : EnumAttr<"speculatable", [FnAttr]>;
/// Stack protection.
-def StackProtect : EnumAttr<"ssp">;
+def StackProtect : EnumAttr<"ssp", [FnAttr]>;
/// Stack protection required.
-def StackProtectReq : EnumAttr<"sspreq">;
+def StackProtectReq : EnumAttr<"sspreq", [FnAttr]>;
/// Strong Stack protection.
-def StackProtectStrong : EnumAttr<"sspstrong">;
+def StackProtectStrong : EnumAttr<"sspstrong", [FnAttr]>;
/// Function was called in a scope requiring strict floating point semantics.
-def StrictFP : EnumAttr<"strictfp">;
+def StrictFP : EnumAttr<"strictfp", [FnAttr]>;
/// Hidden pointer to structure to return.
-def StructRet : TypeAttr<"sret">;
+def StructRet : TypeAttr<"sret", [ParamAttr]>;
/// AddressSanitizer is on.
-def SanitizeAddress : EnumAttr<"sanitize_address">;
+def SanitizeAddress : EnumAttr<"sanitize_address", [FnAttr]>;
/// ThreadSanitizer is on.
-def SanitizeThread : EnumAttr<"sanitize_thread">;
+def SanitizeThread : EnumAttr<"sanitize_thread", [FnAttr]>;
/// MemorySanitizer is on.
-def SanitizeMemory : EnumAttr<"sanitize_memory">;
+def SanitizeMemory : EnumAttr<"sanitize_memory", [FnAttr]>;
/// HWAddressSanitizer is on.
-def SanitizeHWAddress : EnumAttr<"sanitize_hwaddress">;
+def SanitizeHWAddress : EnumAttr<"sanitize_hwaddress", [FnAttr]>;
/// MemTagSanitizer is on.
-def SanitizeMemTag : EnumAttr<"sanitize_memtag">;
+def SanitizeMemTag : EnumAttr<"sanitize_memtag", [FnAttr]>;
/// Speculative Load Hardening is enabled.
///
/// inlining) and a conservative merge strategy where inlining an attributed
/// body will add the attribute to the caller. This ensures that code carrying
/// this attribute will always be lowered with hardening enabled.
-def SpeculativeLoadHardening : EnumAttr<"speculative_load_hardening">;
+def SpeculativeLoadHardening : EnumAttr<"speculative_load_hardening",
+ [FnAttr]>;
/// Argument is swift error.
-def SwiftError : EnumAttr<"swifterror">;
+def SwiftError : EnumAttr<"swifterror", [ParamAttr]>;
/// Argument is swift self/context.
-def SwiftSelf : EnumAttr<"swiftself">;
+def SwiftSelf : EnumAttr<"swiftself", [ParamAttr]>;
/// Argument is swift async context.
-def SwiftAsync : EnumAttr<"swiftasync">;
+def SwiftAsync : EnumAttr<"swiftasync", [ParamAttr]>;
/// Function must be in a unwind table.
-def UWTable : EnumAttr<"uwtable">;
+def UWTable : EnumAttr<"uwtable", [FnAttr]>;
/// Minimum/Maximum vscale value for function.
-def VScaleRange : IntAttr<"vscale_range">;
+def VScaleRange : IntAttr<"vscale_range", [FnAttr]>;
/// Function always comes back to callsite.
-def WillReturn : EnumAttr<"willreturn">;
+def WillReturn : EnumAttr<"willreturn", [FnAttr]>;
/// Function only writes to memory.
-def WriteOnly : EnumAttr<"writeonly">;
+def WriteOnly : EnumAttr<"writeonly", [FnAttr, ParamAttr]>;
/// Zero extended before/after call.
-def ZExt : EnumAttr<"zeroext">;
+def ZExt : EnumAttr<"zeroext", [ParamAttr, RetAttr]>;
/// Function is required to make Forward Progress.
-def MustProgress : EnumAttr<"mustprogress">;
+def MustProgress : EnumAttr<"mustprogress", [FnAttr]>;
/// Target-independent string attributes.
def LessPreciseFPMAD : StrBoolAttr<"less-precise-fpmad">;
void verifyTailCCMustTailAttrs(AttrBuilder Attrs, StringRef Context);
void verifyMustTailCall(CallInst &CI);
bool verifyAttributeCount(AttributeList Attrs, unsigned Params);
- void verifyAttributeTypes(AttributeSet Attrs, bool IsFunction,
- const Value *V);
+ void verifyAttributeTypes(AttributeSet Attrs, const Value *V);
void verifyParameterAttrs(AttributeSet Attrs, Type *Ty, const Value *V);
void checkUnsignedBaseTenFuncAttr(AttributeList Attrs, StringRef Attr,
const Value *V);
"expected an integer constant", Node->getOperand(2));
}
-/// Return true if this attribute kind only applies to functions.
-static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {
- switch (Kind) {
- case Attribute::NoMerge:
- case Attribute::NoReturn:
- case Attribute::NoSync:
- case Attribute::WillReturn:
- case Attribute::NoCallback:
- case Attribute::NoCfCheck:
- case Attribute::NoUnwind:
- case Attribute::NoInline:
- case Attribute::NoSanitizeCoverage:
- case Attribute::AlwaysInline:
- case Attribute::OptimizeForSize:
- case Attribute::StackProtect:
- case Attribute::StackProtectReq:
- case Attribute::StackProtectStrong:
- case Attribute::SafeStack:
- case Attribute::ShadowCallStack:
- case Attribute::NoRedZone:
- case Attribute::NoImplicitFloat:
- case Attribute::Naked:
- case Attribute::InlineHint:
- case Attribute::UWTable:
- case Attribute::VScaleRange:
- case Attribute::NonLazyBind:
- case Attribute::ReturnsTwice:
- case Attribute::SanitizeAddress:
- case Attribute::SanitizeHWAddress:
- case Attribute::SanitizeMemTag:
- case Attribute::SanitizeThread:
- case Attribute::SanitizeMemory:
- case Attribute::MinSize:
- case Attribute::NoDuplicate:
- case Attribute::Builtin:
- case Attribute::NoBuiltin:
- case Attribute::Cold:
- case Attribute::Hot:
- case Attribute::OptForFuzzing:
- case Attribute::OptimizeNone:
- case Attribute::JumpTable:
- case Attribute::Convergent:
- case Attribute::ArgMemOnly:
- case Attribute::NoRecurse:
- case Attribute::InaccessibleMemOnly:
- case Attribute::InaccessibleMemOrArgMemOnly:
- case Attribute::AllocSize:
- case Attribute::SpeculativeLoadHardening:
- case Attribute::Speculatable:
- case Attribute::StrictFP:
- case Attribute::NullPointerIsValid:
- case Attribute::MustProgress:
- case Attribute::NoProfile:
- return true;
- default:
- break;
- }
- return false;
-}
-
-/// Return true if this is a function attribute that can also appear on
-/// arguments.
-static bool isFuncOrArgAttr(Attribute::AttrKind Kind) {
- return Kind == Attribute::ReadOnly || Kind == Attribute::WriteOnly ||
- Kind == Attribute::ReadNone || Kind == Attribute::NoFree ||
- Kind == Attribute::Preallocated || Kind == Attribute::StackAlignment;
-}
-
-void Verifier::verifyAttributeTypes(AttributeSet Attrs, bool IsFunction,
- const Value *V) {
+void Verifier::verifyAttributeTypes(AttributeSet Attrs, const Value *V) {
for (Attribute A : Attrs) {
if (A.isStringAttribute()) {
V);
return;
}
-
- if (isFuncOnlyAttr(A.getKindAsEnum())) {
- if (!IsFunction) {
- CheckFailed("Attribute '" + A.getAsString() +
- "' only applies to functions!",
- V);
- return;
- }
- } else if (IsFunction && !isFuncOrArgAttr(A.getKindAsEnum())) {
- CheckFailed("Attribute '" + A.getAsString() +
- "' does not apply to functions!",
- V);
- return;
- }
}
}
if (!Attrs.hasAttributes())
return;
- verifyAttributeTypes(Attrs, /*IsFunction=*/false, V);
+ verifyAttributeTypes(Attrs, V);
+
+ for (Attribute Attr : Attrs)
+ Assert(Attr.isStringAttribute() ||
+ Attribute::canUseAsParamAttr(Attr.getKindAsEnum()),
+ "Attribute '" + Attr.getAsString() +
+ "' does not apply to parameters",
+ V);
if (Attrs.hasAttribute(Attribute::ImmArg)) {
Assert(Attrs.getNumAttributes() == 1,
// Verify return value attributes.
AttributeSet RetAttrs = Attrs.getRetAttributes();
- Assert((!RetAttrs.hasAttribute(Attribute::ByVal) &&
- !RetAttrs.hasAttribute(Attribute::Nest) &&
- !RetAttrs.hasAttribute(Attribute::StructRet) &&
- !RetAttrs.hasAttribute(Attribute::NoCapture) &&
- !RetAttrs.hasAttribute(Attribute::NoFree) &&
- !RetAttrs.hasAttribute(Attribute::Returned) &&
- !RetAttrs.hasAttribute(Attribute::InAlloca) &&
- !RetAttrs.hasAttribute(Attribute::Preallocated) &&
- !RetAttrs.hasAttribute(Attribute::ByRef) &&
- !RetAttrs.hasAttribute(Attribute::SwiftSelf) &&
- !RetAttrs.hasAttribute(Attribute::SwiftAsync) &&
- !RetAttrs.hasAttribute(Attribute::SwiftError)),
- "Attributes 'byval', 'inalloca', 'preallocated', 'byref', "
- "'nest', 'sret', 'nocapture', 'nofree', "
- "'returned', 'swiftself', 'swiftasync', and 'swifterror'"
- " do not apply to return values!",
- V);
- Assert((!RetAttrs.hasAttribute(Attribute::ReadOnly) &&
- !RetAttrs.hasAttribute(Attribute::WriteOnly) &&
- !RetAttrs.hasAttribute(Attribute::ReadNone)),
- "Attribute '" + RetAttrs.getAsString() +
- "' does not apply to function returns",
- V);
+ for (Attribute RetAttr : RetAttrs)
+ Assert(RetAttr.isStringAttribute() ||
+ Attribute::canUseAsRetAttr(RetAttr.getKindAsEnum()),
+ "Attribute '" + RetAttr.getAsString() +
+ "' does not apply to function return values",
+ V);
+
verifyParameterAttrs(RetAttrs, FT->getReturnType(), V);
// Verify parameter attributes.
if (!Attrs.hasAttributes(AttributeList::FunctionIndex))
return;
- verifyAttributeTypes(Attrs.getFnAttributes(), /*IsFunction=*/true, V);
+ verifyAttributeTypes(Attrs.getFnAttributes(), V);
+ for (Attribute FnAttr : Attrs.getFnAttributes())
+ Assert(FnAttr.isStringAttribute() ||
+ Attribute::canUseAsFnAttr(FnAttr.getKindAsEnum()),
+ "Attribute '" + FnAttr.getAsString() +
+ "' does not apply to functions!",
+ V);
Assert(!(Attrs.hasFnAttribute(Attribute::ReadNone) &&
Attrs.hasFnAttribute(Attribute::ReadOnly)),
Assert(ArgCount == 2, "this attribute should have 2 arguments");
Assert(isa<ConstantInt>(Call.getOperand(Elem.Begin + 1)),
"the second argument should be a constant integral value");
- } else if (isFuncOnlyAttr(Kind)) {
- Assert((ArgCount) == 0, "this attribute has no argument");
- } else if (!isFuncOrArgAttr(Kind)) {
+ } else if (Attribute::canUseAsParamAttr(Kind)) {
Assert((ArgCount) == 1, "this attribute should have one argument");
+ } else if (Attribute::canUseAsFnAttr(Kind)) {
+ Assert((ArgCount) == 0, "this attribute has no argument");
}
}
break;
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
-#include "llvm/ADT/StringSwitch.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
"example -force-remove-attribute=foo:noinline. This "
"option can be specified multiple times."));
-static Attribute::AttrKind parseAttrKind(StringRef Kind) {
- return StringSwitch<Attribute::AttrKind>(Kind)
- .Case("alwaysinline", Attribute::AlwaysInline)
- .Case("builtin", Attribute::Builtin)
- .Case("cold", Attribute::Cold)
- .Case("convergent", Attribute::Convergent)
- .Case("inlinehint", Attribute::InlineHint)
- .Case("jumptable", Attribute::JumpTable)
- .Case("minsize", Attribute::MinSize)
- .Case("naked", Attribute::Naked)
- .Case("nobuiltin", Attribute::NoBuiltin)
- .Case("noduplicate", Attribute::NoDuplicate)
- .Case("noimplicitfloat", Attribute::NoImplicitFloat)
- .Case("noinline", Attribute::NoInline)
- .Case("nonlazybind", Attribute::NonLazyBind)
- .Case("noredzone", Attribute::NoRedZone)
- .Case("noreturn", Attribute::NoReturn)
- .Case("nocf_check", Attribute::NoCfCheck)
- .Case("norecurse", Attribute::NoRecurse)
- .Case("nounwind", Attribute::NoUnwind)
- .Case("nosanitize_coverage", Attribute::NoSanitizeCoverage)
- .Case("optforfuzzing", Attribute::OptForFuzzing)
- .Case("optnone", Attribute::OptimizeNone)
- .Case("optsize", Attribute::OptimizeForSize)
- .Case("readnone", Attribute::ReadNone)
- .Case("readonly", Attribute::ReadOnly)
- .Case("argmemonly", Attribute::ArgMemOnly)
- .Case("returns_twice", Attribute::ReturnsTwice)
- .Case("safestack", Attribute::SafeStack)
- .Case("shadowcallstack", Attribute::ShadowCallStack)
- .Case("sanitize_address", Attribute::SanitizeAddress)
- .Case("sanitize_hwaddress", Attribute::SanitizeHWAddress)
- .Case("sanitize_memory", Attribute::SanitizeMemory)
- .Case("sanitize_thread", Attribute::SanitizeThread)
- .Case("sanitize_memtag", Attribute::SanitizeMemTag)
- .Case("speculative_load_hardening", Attribute::SpeculativeLoadHardening)
- .Case("ssp", Attribute::StackProtect)
- .Case("sspreq", Attribute::StackProtectReq)
- .Case("sspstrong", Attribute::StackProtectStrong)
- .Case("strictfp", Attribute::StrictFP)
- .Case("uwtable", Attribute::UWTable)
- .Case("vscale_range", Attribute::VScaleRange)
- .Default(Attribute::None);
-}
-
/// If F has any forced attributes given on the command line, add them.
/// If F has any forced remove attributes given on the command line, remove
/// them. When both force and force-remove are given to a function, the latter
auto KV = StringRef(S).split(':');
if (KV.first != F.getName())
return Kind;
- Kind = parseAttrKind(KV.second);
- if (Kind == Attribute::None) {
+ Kind = Attribute::getAttrKindFromName(KV.second);
+ if (Kind == Attribute::None || !Attribute::canUseAsFnAttr(Kind)) {
LLVM_DEBUG(dbgs() << "ForcedAttribute: " << KV.second
- << " unknown or not handled!\n");
+ << " unknown or not a function attribute!\n");
}
return Kind;
};