ForceFunctionAttrs.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. //===- ForceFunctionAttrs.cpp - Force function attrs for debugging --------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
  9. #include "llvm/ADT/StringSwitch.h"
  10. #include "llvm/IR/Function.h"
  11. #include "llvm/IR/LLVMContext.h"
  12. #include "llvm/IR/Module.h"
  13. #include "llvm/InitializePasses.h"
  14. #include "llvm/Support/CommandLine.h"
  15. #include "llvm/Support/Debug.h"
  16. #include "llvm/Support/raw_ostream.h"
  17. using namespace llvm;
  18. #define DEBUG_TYPE "forceattrs"
  19. static cl::list<std::string>
  20. ForceAttributes("force-attribute", cl::Hidden,
  21. cl::desc("Add an attribute to a function. This should be a "
  22. "pair of 'function-name:attribute-name', for "
  23. "example -force-attribute=foo:noinline. This "
  24. "option can be specified multiple times."));
  25. static cl::list<std::string> ForceRemoveAttributes(
  26. "force-remove-attribute", cl::Hidden,
  27. cl::desc("Remove an attribute from a function. This should be a "
  28. "pair of 'function-name:attribute-name', for "
  29. "example -force-remove-attribute=foo:noinline. This "
  30. "option can be specified multiple times."));
  31. static Attribute::AttrKind parseAttrKind(StringRef Kind) {
  32. return StringSwitch<Attribute::AttrKind>(Kind)
  33. .Case("alwaysinline", Attribute::AlwaysInline)
  34. .Case("builtin", Attribute::Builtin)
  35. .Case("cold", Attribute::Cold)
  36. .Case("convergent", Attribute::Convergent)
  37. .Case("inlinehint", Attribute::InlineHint)
  38. .Case("jumptable", Attribute::JumpTable)
  39. .Case("minsize", Attribute::MinSize)
  40. .Case("naked", Attribute::Naked)
  41. .Case("nobuiltin", Attribute::NoBuiltin)
  42. .Case("noduplicate", Attribute::NoDuplicate)
  43. .Case("noimplicitfloat", Attribute::NoImplicitFloat)
  44. .Case("noinline", Attribute::NoInline)
  45. .Case("nonlazybind", Attribute::NonLazyBind)
  46. .Case("noredzone", Attribute::NoRedZone)
  47. .Case("noreturn", Attribute::NoReturn)
  48. .Case("nocf_check", Attribute::NoCfCheck)
  49. .Case("norecurse", Attribute::NoRecurse)
  50. .Case("nounwind", Attribute::NoUnwind)
  51. .Case("optforfuzzing", Attribute::OptForFuzzing)
  52. .Case("optnone", Attribute::OptimizeNone)
  53. .Case("optsize", Attribute::OptimizeForSize)
  54. .Case("readnone", Attribute::ReadNone)
  55. .Case("readonly", Attribute::ReadOnly)
  56. .Case("argmemonly", Attribute::ArgMemOnly)
  57. .Case("returns_twice", Attribute::ReturnsTwice)
  58. .Case("safestack", Attribute::SafeStack)
  59. .Case("shadowcallstack", Attribute::ShadowCallStack)
  60. .Case("sanitize_address", Attribute::SanitizeAddress)
  61. .Case("sanitize_hwaddress", Attribute::SanitizeHWAddress)
  62. .Case("sanitize_memory", Attribute::SanitizeMemory)
  63. .Case("sanitize_thread", Attribute::SanitizeThread)
  64. .Case("sanitize_memtag", Attribute::SanitizeMemTag)
  65. .Case("speculative_load_hardening", Attribute::SpeculativeLoadHardening)
  66. .Case("ssp", Attribute::StackProtect)
  67. .Case("sspreq", Attribute::StackProtectReq)
  68. .Case("sspstrong", Attribute::StackProtectStrong)
  69. .Case("strictfp", Attribute::StrictFP)
  70. .Case("uwtable", Attribute::UWTable)
  71. .Default(Attribute::None);
  72. }
  73. /// If F has any forced attributes given on the command line, add them.
  74. /// If F has any forced remove attributes given on the command line, remove
  75. /// them. When both force and force-remove are given to a function, the latter
  76. /// takes precedence.
  77. static void forceAttributes(Function &F) {
  78. auto ParseFunctionAndAttr = [&](StringRef S) {
  79. auto Kind = Attribute::None;
  80. auto KV = StringRef(S).split(':');
  81. if (KV.first != F.getName())
  82. return Kind;
  83. Kind = parseAttrKind(KV.second);
  84. if (Kind == Attribute::None) {
  85. LLVM_DEBUG(dbgs() << "ForcedAttribute: " << KV.second
  86. << " unknown or not handled!\n");
  87. }
  88. return Kind;
  89. };
  90. for (auto &S : ForceAttributes) {
  91. auto Kind = ParseFunctionAndAttr(S);
  92. if (Kind == Attribute::None || F.hasFnAttribute(Kind))
  93. continue;
  94. F.addFnAttr(Kind);
  95. }
  96. for (auto &S : ForceRemoveAttributes) {
  97. auto Kind = ParseFunctionAndAttr(S);
  98. if (Kind == Attribute::None || !F.hasFnAttribute(Kind))
  99. continue;
  100. F.removeFnAttr(Kind);
  101. }
  102. }
  103. static bool hasForceAttributes() {
  104. return !ForceAttributes.empty() || !ForceRemoveAttributes.empty();
  105. }
  106. PreservedAnalyses ForceFunctionAttrsPass::run(Module &M,
  107. ModuleAnalysisManager &) {
  108. if (!hasForceAttributes())
  109. return PreservedAnalyses::all();
  110. for (Function &F : M.functions())
  111. forceAttributes(F);
  112. // Just conservatively invalidate analyses, this isn't likely to be important.
  113. return PreservedAnalyses::none();
  114. }
  115. namespace {
  116. struct ForceFunctionAttrsLegacyPass : public ModulePass {
  117. static char ID; // Pass identification, replacement for typeid
  118. ForceFunctionAttrsLegacyPass() : ModulePass(ID) {
  119. initializeForceFunctionAttrsLegacyPassPass(
  120. *PassRegistry::getPassRegistry());
  121. }
  122. bool runOnModule(Module &M) override {
  123. if (!hasForceAttributes())
  124. return false;
  125. for (Function &F : M.functions())
  126. forceAttributes(F);
  127. // Conservatively assume we changed something.
  128. return true;
  129. }
  130. };
  131. }
  132. char ForceFunctionAttrsLegacyPass::ID = 0;
  133. INITIALIZE_PASS(ForceFunctionAttrsLegacyPass, "forceattrs",
  134. "Force set function attributes", false, false)
  135. Pass *llvm::createForceFunctionAttrsLegacyPass() {
  136. return new ForceFunctionAttrsLegacyPass();
  137. }