| #ifdef GET_ATTR_ENUM | |
| #undef GET_ATTR_ENUM | |
| Alignment, | |
| AllocSize, | |
| AlwaysInline, | |
| ArgMemOnly, | |
| Builtin, | |
| ByVal, | |
| Cold, | |
| Convergent, | |
| Dereferenceable, | |
| DereferenceableOrNull, | |
| InAlloca, | |
| InReg, | |
| InaccessibleMemOnly, | |
| InaccessibleMemOrArgMemOnly, | |
| InlineHint, | |
| JumpTable, | |
| MinSize, | |
| Naked, | |
| Nest, | |
| NoAlias, | |
| NoBuiltin, | |
| NoCapture, | |
| NoDuplicate, | |
| NoImplicitFloat, | |
| NoInline, | |
| NoRecurse, | |
| NoRedZone, | |
| NoReturn, | |
| NoUnwind, | |
| NonLazyBind, | |
| NonNull, | |
| OptimizeForSize, | |
| OptimizeNone, | |
| ReadNone, | |
| ReadOnly, | |
| Returned, | |
| ReturnsTwice, | |
| SExt, | |
| SafeStack, | |
| SanitizeAddress, | |
| SanitizeMemory, | |
| SanitizeThread, | |
| StackAlignment, | |
| StackProtect, | |
| StackProtectReq, | |
| StackProtectStrong, | |
| StructRet, | |
| SwiftError, | |
| SwiftSelf, | |
| UWTable, | |
| WriteOnly, | |
| ZExt, | |
| #endif | |
| #ifdef GET_ATTR_KIND_FROM_NAME | |
| #undef GET_ATTR_KIND_FROM_NAME | |
| static Attribute::AttrKind getAttrKindFromName(StringRef AttrName) { | |
| return StringSwitch<Attribute::AttrKind>(AttrName) | |
| .Case("align", Attribute::Alignment) | |
| .Case("allocsize", Attribute::AllocSize) | |
| .Case("alwaysinline", Attribute::AlwaysInline) | |
| .Case("argmemonly", Attribute::ArgMemOnly) | |
| .Case("builtin", Attribute::Builtin) | |
| .Case("byval", Attribute::ByVal) | |
| .Case("cold", Attribute::Cold) | |
| .Case("convergent", Attribute::Convergent) | |
| .Case("dereferenceable", Attribute::Dereferenceable) | |
| .Case("dereferenceable_or_null", Attribute::DereferenceableOrNull) | |
| .Case("inalloca", Attribute::InAlloca) | |
| .Case("inreg", Attribute::InReg) | |
| .Case("inaccessiblememonly", Attribute::InaccessibleMemOnly) | |
| .Case("inaccessiblemem_or_argmemonly", Attribute::InaccessibleMemOrArgMemOnly) | |
| .Case("inlinehint", Attribute::InlineHint) | |
| .Case("jumptable", Attribute::JumpTable) | |
| .Case("minsize", Attribute::MinSize) | |
| .Case("naked", Attribute::Naked) | |
| .Case("nest", Attribute::Nest) | |
| .Case("noalias", Attribute::NoAlias) | |
| .Case("nobuiltin", Attribute::NoBuiltin) | |
| .Case("nocapture", Attribute::NoCapture) | |
| .Case("noduplicate", Attribute::NoDuplicate) | |
| .Case("noimplicitfloat", Attribute::NoImplicitFloat) | |
| .Case("noinline", Attribute::NoInline) | |
| .Case("norecurse", Attribute::NoRecurse) | |
| .Case("noredzone", Attribute::NoRedZone) | |
| .Case("noreturn", Attribute::NoReturn) | |
| .Case("nounwind", Attribute::NoUnwind) | |
| .Case("nonlazybind", Attribute::NonLazyBind) | |
| .Case("nonnull", Attribute::NonNull) | |
| .Case("optsize", Attribute::OptimizeForSize) | |
| .Case("optnone", Attribute::OptimizeNone) | |
| .Case("readnone", Attribute::ReadNone) | |
| .Case("readonly", Attribute::ReadOnly) | |
| .Case("returned", Attribute::Returned) | |
| .Case("returns_twice", Attribute::ReturnsTwice) | |
| .Case("signext", Attribute::SExt) | |
| .Case("safestack", Attribute::SafeStack) | |
| .Case("sanitize_address", Attribute::SanitizeAddress) | |
| .Case("sanitize_memory", Attribute::SanitizeMemory) | |
| .Case("sanitize_thread", Attribute::SanitizeThread) | |
| .Case("alignstack", Attribute::StackAlignment) | |
| .Case("ssp", Attribute::StackProtect) | |
| .Case("sspreq", Attribute::StackProtectReq) | |
| .Case("sspstrong", Attribute::StackProtectStrong) | |
| .Case("sret", Attribute::StructRet) | |
| .Case("swifterror", Attribute::SwiftError) | |
| .Case("swiftself", Attribute::SwiftSelf) | |
| .Case("uwtable", Attribute::UWTable) | |
| .Case("writeonly", Attribute::WriteOnly) | |
| .Case("zeroext", Attribute::ZExt) | |
| .Default(Attribute::None); | |
| } | |
| #endif | |
| #ifdef GET_ATTR_COMPAT_FUNC | |
| #undef GET_ATTR_COMPAT_FUNC | |
| struct EnumAttr { | |
| static bool isSet(const Function &Fn, | |
| Attribute::AttrKind Kind) { | |
| return Fn.hasFnAttribute(Kind); | |
| } | |
| static void set(Function &Fn, | |
| Attribute::AttrKind Kind, bool Val) { | |
| if (Val) | |
| Fn.addFnAttr(Kind); | |
| else | |
| Fn.removeFnAttr(Kind); | |
| } | |
| }; | |
| struct StrBoolAttr { | |
| static bool isSet(const Function &Fn, | |
| StringRef Kind) { | |
| auto A = Fn.getFnAttribute(Kind); | |
| return A.getValueAsString().equals("true"); | |
| } | |
| static void set(Function &Fn, | |
| StringRef Kind, bool Val) { | |
| Fn.addFnAttr(Kind, Val ? "true" : "false"); | |
| } | |
| }; | |
| // EnumAttr classes | |
| struct AlignmentAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::Alignment; | |
| } | |
| }; | |
| struct AllocSizeAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::AllocSize; | |
| } | |
| }; | |
| struct AlwaysInlineAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::AlwaysInline; | |
| } | |
| }; | |
| struct ArgMemOnlyAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::ArgMemOnly; | |
| } | |
| }; | |
| struct BuiltinAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::Builtin; | |
| } | |
| }; | |
| struct ByValAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::ByVal; | |
| } | |
| }; | |
| struct ColdAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::Cold; | |
| } | |
| }; | |
| struct ConvergentAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::Convergent; | |
| } | |
| }; | |
| struct DereferenceableAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::Dereferenceable; | |
| } | |
| }; | |
| struct DereferenceableOrNullAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::DereferenceableOrNull; | |
| } | |
| }; | |
| struct InAllocaAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::InAlloca; | |
| } | |
| }; | |
| struct InRegAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::InReg; | |
| } | |
| }; | |
| struct InaccessibleMemOnlyAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::InaccessibleMemOnly; | |
| } | |
| }; | |
| struct InaccessibleMemOrArgMemOnlyAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::InaccessibleMemOrArgMemOnly; | |
| } | |
| }; | |
| struct InlineHintAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::InlineHint; | |
| } | |
| }; | |
| struct JumpTableAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::JumpTable; | |
| } | |
| }; | |
| struct MinSizeAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::MinSize; | |
| } | |
| }; | |
| struct NakedAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::Naked; | |
| } | |
| }; | |
| struct NestAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::Nest; | |
| } | |
| }; | |
| struct NoAliasAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::NoAlias; | |
| } | |
| }; | |
| struct NoBuiltinAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::NoBuiltin; | |
| } | |
| }; | |
| struct NoCaptureAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::NoCapture; | |
| } | |
| }; | |
| struct NoDuplicateAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::NoDuplicate; | |
| } | |
| }; | |
| struct NoImplicitFloatAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::NoImplicitFloat; | |
| } | |
| }; | |
| struct NoInlineAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::NoInline; | |
| } | |
| }; | |
| struct NoRecurseAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::NoRecurse; | |
| } | |
| }; | |
| struct NoRedZoneAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::NoRedZone; | |
| } | |
| }; | |
| struct NoReturnAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::NoReturn; | |
| } | |
| }; | |
| struct NoUnwindAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::NoUnwind; | |
| } | |
| }; | |
| struct NonLazyBindAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::NonLazyBind; | |
| } | |
| }; | |
| struct NonNullAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::NonNull; | |
| } | |
| }; | |
| struct OptimizeForSizeAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::OptimizeForSize; | |
| } | |
| }; | |
| struct OptimizeNoneAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::OptimizeNone; | |
| } | |
| }; | |
| struct ReadNoneAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::ReadNone; | |
| } | |
| }; | |
| struct ReadOnlyAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::ReadOnly; | |
| } | |
| }; | |
| struct ReturnedAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::Returned; | |
| } | |
| }; | |
| struct ReturnsTwiceAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::ReturnsTwice; | |
| } | |
| }; | |
| struct SExtAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::SExt; | |
| } | |
| }; | |
| struct SafeStackAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::SafeStack; | |
| } | |
| }; | |
| struct SanitizeAddressAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::SanitizeAddress; | |
| } | |
| }; | |
| struct SanitizeMemoryAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::SanitizeMemory; | |
| } | |
| }; | |
| struct SanitizeThreadAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::SanitizeThread; | |
| } | |
| }; | |
| struct StackAlignmentAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::StackAlignment; | |
| } | |
| }; | |
| struct StackProtectAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::StackProtect; | |
| } | |
| }; | |
| struct StackProtectReqAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::StackProtectReq; | |
| } | |
| }; | |
| struct StackProtectStrongAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::StackProtectStrong; | |
| } | |
| }; | |
| struct StructRetAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::StructRet; | |
| } | |
| }; | |
| struct SwiftErrorAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::SwiftError; | |
| } | |
| }; | |
| struct SwiftSelfAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::SwiftSelf; | |
| } | |
| }; | |
| struct UWTableAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::UWTable; | |
| } | |
| }; | |
| struct WriteOnlyAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::WriteOnly; | |
| } | |
| }; | |
| struct ZExtAttr : EnumAttr { | |
| static enum Attribute::AttrKind getKind() { | |
| return llvm::Attribute::ZExt; | |
| } | |
| }; | |
| // StrBoolAttr classes | |
| struct LessPreciseFPMADAttr : StrBoolAttr { | |
| static const char *getKind() { | |
| return "less-precise-fpmad"; | |
| } | |
| }; | |
| struct NoInfsFPMathAttr : StrBoolAttr { | |
| static const char *getKind() { | |
| return "no-infs-fp-math"; | |
| } | |
| }; | |
| struct NoJumpTablesAttr : StrBoolAttr { | |
| static const char *getKind() { | |
| return "no-jump-tables"; | |
| } | |
| }; | |
| struct NoNansFPMathAttr : StrBoolAttr { | |
| static const char *getKind() { | |
| return "no-nans-fp-math"; | |
| } | |
| }; | |
| struct UnsafeFPMathAttr : StrBoolAttr { | |
| static const char *getKind() { | |
| return "unsafe-fp-math"; | |
| } | |
| }; | |
| static inline bool hasCompatibleFnAttrs(const Function &Caller, | |
| const Function &Callee) { | |
| bool Ret = true; | |
| Ret &= isEqual<SanitizeAddressAttr>(Caller, Callee); | |
| Ret &= isEqual<SanitizeThreadAttr>(Caller, Callee); | |
| Ret &= isEqual<SanitizeMemoryAttr>(Caller, Callee); | |
| Ret &= isEqual<SafeStackAttr>(Caller, Callee); | |
| return Ret; | |
| } | |
| static inline void mergeFnAttrs(Function &Caller, | |
| const Function &Callee) { | |
| adjustCallerSSPLevel(Caller, Callee); | |
| setAND<LessPreciseFPMADAttr>(Caller, Callee); | |
| setAND<NoInfsFPMathAttr>(Caller, Callee); | |
| setAND<NoNansFPMathAttr>(Caller, Callee); | |
| setAND<UnsafeFPMathAttr>(Caller, Callee); | |
| setOR<NoImplicitFloatAttr>(Caller, Callee); | |
| setOR<NoJumpTablesAttr>(Caller, Callee); | |
| } | |
| #endif |