1 | //===-- GCMetadata.cpp - Garbage collector metadata -----------------------===// |
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 | // This file implements the GCFunctionInfo class and GCModuleInfo pass. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/CodeGen/GCMetadata.h" |
14 | #include "llvm/ADT/StringExtras.h" |
15 | #include "llvm/CodeGen/Passes.h" |
16 | #include "llvm/IR/Function.h" |
17 | #include "llvm/IR/Module.h" |
18 | #include "llvm/InitializePasses.h" |
19 | #include "llvm/MC/MCSymbol.h" |
20 | #include "llvm/Pass.h" |
21 | #include "llvm/Support/raw_ostream.h" |
22 | #include <cassert> |
23 | #include <memory> |
24 | #include <string> |
25 | |
26 | using namespace llvm; |
27 | |
28 | bool GCStrategyMap::invalidate(Module &M, const PreservedAnalyses &PA, |
29 | ModuleAnalysisManager::Invalidator &) { |
30 | for (const auto &F : M) { |
31 | if (F.isDeclaration() || !F.hasGC()) |
32 | continue; |
33 | if (!StrategyMap.contains(Key: F.getGC())) |
34 | return true; |
35 | } |
36 | return false; |
37 | } |
38 | |
39 | AnalysisKey CollectorMetadataAnalysis::Key; |
40 | |
41 | CollectorMetadataAnalysis::Result |
42 | CollectorMetadataAnalysis::run(Module &M, ModuleAnalysisManager &MAM) { |
43 | Result R; |
44 | auto &Map = R.StrategyMap; |
45 | for (auto &F : M) { |
46 | if (F.isDeclaration() || !F.hasGC()) |
47 | continue; |
48 | if (auto GCName = F.getGC(); !Map.contains(Key: GCName)) |
49 | Map[GCName] = getGCStrategy(Name: GCName); |
50 | } |
51 | return R; |
52 | } |
53 | |
54 | AnalysisKey GCFunctionAnalysis::Key; |
55 | |
56 | GCFunctionAnalysis::Result |
57 | GCFunctionAnalysis::run(Function &F, FunctionAnalysisManager &FAM) { |
58 | assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!" ); |
59 | assert(F.hasGC() && "Function doesn't have GC!" ); |
60 | |
61 | auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(IR&: F); |
62 | assert( |
63 | MAMProxy.cachedResultExists<CollectorMetadataAnalysis>(*F.getParent()) && |
64 | "This pass need module analysis `collector-metadata`!" ); |
65 | auto &Map = |
66 | MAMProxy.getCachedResult<CollectorMetadataAnalysis>(IR&: *F.getParent()) |
67 | ->StrategyMap; |
68 | GCFunctionInfo Info(F, *Map[F.getGC()]); |
69 | return Info; |
70 | } |
71 | |
72 | INITIALIZE_PASS(GCModuleInfo, "collector-metadata" , |
73 | "Create Garbage Collector Module Metadata" , false, false) |
74 | |
75 | // ----------------------------------------------------------------------------- |
76 | |
77 | GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S) |
78 | : F(F), S(S), FrameSize(~0LL) {} |
79 | |
80 | GCFunctionInfo::~GCFunctionInfo() = default; |
81 | |
82 | bool GCFunctionInfo::invalidate(Function &F, const PreservedAnalyses &PA, |
83 | FunctionAnalysisManager::Invalidator &) { |
84 | auto PAC = PA.getChecker<GCFunctionAnalysis>(); |
85 | return !PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Function>>(); |
86 | } |
87 | |
88 | // ----------------------------------------------------------------------------- |
89 | |
90 | char GCModuleInfo::ID = 0; |
91 | |
92 | GCModuleInfo::GCModuleInfo() : ImmutablePass(ID) { |
93 | initializeGCModuleInfoPass(Registry&: *PassRegistry::getPassRegistry()); |
94 | } |
95 | |
96 | GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) { |
97 | assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!" ); |
98 | assert(F.hasGC()); |
99 | |
100 | finfo_map_type::iterator I = FInfoMap.find(Val: &F); |
101 | if (I != FInfoMap.end()) |
102 | return *I->second; |
103 | |
104 | GCStrategy *S = getGCStrategy(Name: F.getGC()); |
105 | Functions.push_back(x: std::make_unique<GCFunctionInfo>(args: F, args&: *S)); |
106 | GCFunctionInfo *GFI = Functions.back().get(); |
107 | FInfoMap[&F] = GFI; |
108 | return *GFI; |
109 | } |
110 | |
111 | void GCModuleInfo::clear() { |
112 | Functions.clear(); |
113 | FInfoMap.clear(); |
114 | GCStrategyList.clear(); |
115 | } |
116 | |
117 | // ----------------------------------------------------------------------------- |
118 | |
119 | GCStrategy *GCModuleInfo::getGCStrategy(const StringRef Name) { |
120 | // TODO: Arguably, just doing a linear search would be faster for small N |
121 | auto NMI = GCStrategyMap.find(Key: Name); |
122 | if (NMI != GCStrategyMap.end()) |
123 | return NMI->getValue(); |
124 | |
125 | std::unique_ptr<GCStrategy> S = llvm::getGCStrategy(Name); |
126 | S->Name = std::string(Name); |
127 | GCStrategyMap[Name] = S.get(); |
128 | GCStrategyList.push_back(Elt: std::move(S)); |
129 | return GCStrategyList.back().get(); |
130 | } |
131 | |