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