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