xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp (revision c989957f28ef5b03f594265612e3437c1e826ed4)
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  
9  #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
10  #include "llvm/IR/Function.h"
11  #include "llvm/IR/Module.h"
12  #include "llvm/InitializePasses.h"
13  #include "llvm/Pass.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  
19  #define DEBUG_TYPE "forceattrs"
20  
21  static cl::list<std::string>
22      ForceAttributes("force-attribute", cl::Hidden,
23                      cl::desc("Add an attribute to a function. This should be a "
24                               "pair of 'function-name:attribute-name', for "
25                               "example -force-attribute=foo:noinline. This "
26                               "option can be specified multiple times."));
27  
28  static cl::list<std::string> ForceRemoveAttributes(
29      "force-remove-attribute", cl::Hidden,
30      cl::desc("Remove an attribute from a function. This should be a "
31               "pair of 'function-name:attribute-name', for "
32               "example -force-remove-attribute=foo:noinline. This "
33               "option can be specified multiple times."));
34  
35  /// If F has any forced attributes given on the command line, add them.
36  /// If F has any forced remove attributes given on the command line, remove
37  /// them. When both force and force-remove are given to a function, the latter
38  /// takes precedence.
39  static void forceAttributes(Function &F) {
40    auto ParseFunctionAndAttr = [&](StringRef S) {
41      auto Kind = Attribute::None;
42      auto KV = StringRef(S).split(':');
43      if (KV.first != F.getName())
44        return Kind;
45      Kind = Attribute::getAttrKindFromName(KV.second);
46      if (Kind == Attribute::None || !Attribute::canUseAsFnAttr(Kind)) {
47        LLVM_DEBUG(dbgs() << "ForcedAttribute: " << KV.second
48                          << " unknown or not a function attribute!\n");
49      }
50      return Kind;
51    };
52  
53    for (const auto &S : ForceAttributes) {
54      auto Kind = ParseFunctionAndAttr(S);
55      if (Kind == Attribute::None || F.hasFnAttribute(Kind))
56        continue;
57      F.addFnAttr(Kind);
58    }
59  
60    for (const auto &S : ForceRemoveAttributes) {
61      auto Kind = ParseFunctionAndAttr(S);
62      if (Kind == Attribute::None || !F.hasFnAttribute(Kind))
63        continue;
64      F.removeFnAttr(Kind);
65    }
66  }
67  
68  static bool hasForceAttributes() {
69    return !ForceAttributes.empty() || !ForceRemoveAttributes.empty();
70  }
71  
72  PreservedAnalyses ForceFunctionAttrsPass::run(Module &M,
73                                                ModuleAnalysisManager &) {
74    if (!hasForceAttributes())
75      return PreservedAnalyses::all();
76  
77    for (Function &F : M.functions())
78      forceAttributes(F);
79  
80    // Just conservatively invalidate analyses, this isn't likely to be important.
81    return PreservedAnalyses::none();
82  }
83  
84  namespace {
85  struct ForceFunctionAttrsLegacyPass : public ModulePass {
86    static char ID; // Pass identification, replacement for typeid
87    ForceFunctionAttrsLegacyPass() : ModulePass(ID) {
88      initializeForceFunctionAttrsLegacyPassPass(
89          *PassRegistry::getPassRegistry());
90    }
91  
92    bool runOnModule(Module &M) override {
93      if (!hasForceAttributes())
94        return false;
95  
96      for (Function &F : M.functions())
97        forceAttributes(F);
98  
99      // Conservatively assume we changed something.
100      return true;
101    }
102  };
103  }
104  
105  char ForceFunctionAttrsLegacyPass::ID = 0;
106  INITIALIZE_PASS(ForceFunctionAttrsLegacyPass, "forceattrs",
107                  "Force set function attributes", false, false)
108  
109  Pass *llvm::createForceFunctionAttrsLegacyPass() {
110    return new ForceFunctionAttrsLegacyPass();
111  }
112