xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/GCMetadata.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
invalidate(Module & M,const PreservedAnalyses & PA,ModuleAnalysisManager::Invalidator &)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(F.getGC()))
34       return true;
35   }
36   return false;
37 }
38 
39 AnalysisKey CollectorMetadataAnalysis::Key;
40 
41 CollectorMetadataAnalysis::Result
run(Module & M,ModuleAnalysisManager & MAM)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(GCName))
49       Map[GCName] = getGCStrategy(GCName);
50   }
51   return R;
52 }
53 
54 AnalysisKey GCFunctionAnalysis::Key;
55 
56 GCFunctionAnalysis::Result
run(Function & F,FunctionAnalysisManager & FAM)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>(F);
62   assert(
63       MAMProxy.cachedResultExists<CollectorMetadataAnalysis>(*F.getParent()) &&
64       "This pass need module analysis `collector-metadata`!");
65   auto &Map =
66       MAMProxy.getCachedResult<CollectorMetadataAnalysis>(*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 
GCFunctionInfo(const Function & F,GCStrategy & S)77 GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S)
78     : F(F), S(S), FrameSize(~0LL) {}
79 
80 GCFunctionInfo::~GCFunctionInfo() = default;
81 
invalidate(Function & F,const PreservedAnalyses & PA,FunctionAnalysisManager::Invalidator &)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 
GCModuleInfo()92 GCModuleInfo::GCModuleInfo() : ImmutablePass(ID) {
93   initializeGCModuleInfoPass(*PassRegistry::getPassRegistry());
94 }
95 
getFunctionInfo(const Function & F)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(&F);
101   if (I != FInfoMap.end())
102     return *I->second;
103 
104   GCStrategy *S = getGCStrategy(F.getGC());
105   Functions.push_back(std::make_unique<GCFunctionInfo>(F, *S));
106   GCFunctionInfo *GFI = Functions.back().get();
107   FInfoMap[&F] = GFI;
108   return *GFI;
109 }
110 
clear()111 void GCModuleInfo::clear() {
112   Functions.clear();
113   FInfoMap.clear();
114   GCStrategyList.clear();
115 }
116 
117 // -----------------------------------------------------------------------------
118 
getGCStrategy(const StringRef Name)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(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(std::move(S));
129   return GCStrategyList.back().get();
130 }
131