| #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 StringRef getKind() { |
| return "less-precise-fpmad"; |
| } |
| }; |
| struct NoInfsFPMathAttr : StrBoolAttr { |
| static StringRef getKind() { |
| return "no-infs-fp-math"; |
| } |
| }; |
| struct NoJumpTablesAttr : StrBoolAttr { |
| static StringRef getKind() { |
| return "no-jump-tables"; |
| } |
| }; |
| struct NoNansFPMathAttr : StrBoolAttr { |
| static StringRef getKind() { |
| return "no-nans-fp-math"; |
| } |
| }; |
| struct UnsafeFPMathAttr : StrBoolAttr { |
| static StringRef 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 |