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