xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/GCMetadata.cpp (revision a90b9d0159070121c221b966469c3e36d912bf82)
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(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(GCName))
48       Map[GCName] = getGCStrategy(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>(F);
61   assert(
62       MAMProxy.cachedResultExists<CollectorMetadataAnalysis>(*F.getParent()) &&
63       "This pass need module analysis `collector-metadata`!");
64   auto &Map =
65       MAMProxy.getCachedResult<CollectorMetadataAnalysis>(*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(*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(&F);
100   if (I != FInfoMap.end())
101     return *I->second;
102 
103   GCStrategy *S = getGCStrategy(F.getGC());
104   Functions.push_back(std::make_unique<GCFunctionInfo>(F, *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(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(std::move(S));
128   return GCStrategyList.back().get();
129 }
130