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
invalidate(Module & M,const PreservedAnalyses & PA,ModuleAnalysisManager::Invalidator &)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 (!contains(F.getGC()))
30 return true;
31 }
32 return false;
33 }
34
35 AnalysisKey CollectorMetadataAnalysis::Key;
36
37 CollectorMetadataAnalysis::Result
run(Module & M,ModuleAnalysisManager & MAM)38 CollectorMetadataAnalysis::run(Module &M, ModuleAnalysisManager &MAM) {
39 Result StrategyMap;
40 for (auto &F : M) {
41 if (F.isDeclaration() || !F.hasGC())
42 continue;
43 StringRef GCName = F.getGC();
44 auto [It, Inserted] = StrategyMap.try_emplace(GCName);
45 if (Inserted) {
46 It->second = getGCStrategy(GCName);
47 It->second->Name = GCName;
48 }
49 }
50 return StrategyMap;
51 }
52
53 AnalysisKey GCFunctionAnalysis::Key;
54
55 GCFunctionAnalysis::Result
run(Function & F,FunctionAnalysisManager & FAM)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 GCStrategy &S = *Map.try_emplace(F.getGC()).first->second;
67 GCFunctionInfo Info(F, S);
68 return Info;
69 }
70
71 INITIALIZE_PASS(GCModuleInfo, "collector-metadata",
72 "Create Garbage Collector Module Metadata", false, true)
73
74 // -----------------------------------------------------------------------------
75
GCFunctionInfo(const Function & F,GCStrategy & S)76 GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S)
77 : F(F), S(S), FrameSize(~0LL) {}
78
79 GCFunctionInfo::~GCFunctionInfo() = default;
80
invalidate(Function & F,const PreservedAnalyses & PA,FunctionAnalysisManager::Invalidator &)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
GCModuleInfo()91 GCModuleInfo::GCModuleInfo() : ImmutablePass(ID) {
92 initializeGCModuleInfoPass(*PassRegistry::getPassRegistry());
93 }
94
getFunctionInfo(const Function & F)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
clear()110 void GCModuleInfo::clear() {
111 Functions.clear();
112 FInfoMap.clear();
113 GCStrategyList.clear();
114 }
115
116 // -----------------------------------------------------------------------------
117
getGCStrategy(const StringRef Name)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