1009b1c42SEd Schouten //===-- GCMetadata.cpp - Garbage collector metadata -----------------------===//
2009b1c42SEd Schouten //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6009b1c42SEd Schouten //
7009b1c42SEd Schouten //===----------------------------------------------------------------------===//
8009b1c42SEd Schouten //
9009b1c42SEd Schouten // This file implements the GCFunctionInfo class and GCModuleInfo pass.
10009b1c42SEd Schouten //
11009b1c42SEd Schouten //===----------------------------------------------------------------------===//
12009b1c42SEd Schouten
13009b1c42SEd Schouten #include "llvm/CodeGen/GCMetadata.h"
14344a3780SDimitry Andric #include "llvm/ADT/StringExtras.h"
15009b1c42SEd Schouten #include "llvm/CodeGen/Passes.h"
164a16efa3SDimitry Andric #include "llvm/IR/Function.h"
17ac9a064cSDimitry Andric #include "llvm/IR/Module.h"
18706b4fc4SDimitry Andric #include "llvm/InitializePasses.h"
19c6910277SRoman Divacky #include "llvm/MC/MCSymbol.h"
204a16efa3SDimitry Andric #include "llvm/Pass.h"
2159850d08SRoman Divacky #include "llvm/Support/raw_ostream.h"
227ab83427SDimitry Andric #include <cassert>
237ab83427SDimitry Andric #include <memory>
247ab83427SDimitry Andric #include <string>
257ab83427SDimitry Andric
26009b1c42SEd Schouten using namespace llvm;
27009b1c42SEd Schouten
invalidate(Module & M,const PreservedAnalyses & PA,ModuleAnalysisManager::Invalidator &)28312c0ed1SDimitry Andric bool GCStrategyMap::invalidate(Module &M, const PreservedAnalyses &PA,
29312c0ed1SDimitry Andric ModuleAnalysisManager::Invalidator &) {
30312c0ed1SDimitry Andric for (const auto &F : M) {
31312c0ed1SDimitry Andric if (F.isDeclaration() || !F.hasGC())
32312c0ed1SDimitry Andric continue;
33312c0ed1SDimitry Andric if (!StrategyMap.contains(F.getGC()))
34312c0ed1SDimitry Andric return true;
35312c0ed1SDimitry Andric }
36312c0ed1SDimitry Andric return false;
37312c0ed1SDimitry Andric }
38009b1c42SEd Schouten
39312c0ed1SDimitry Andric AnalysisKey CollectorMetadataAnalysis::Key;
407ab83427SDimitry Andric
41312c0ed1SDimitry Andric CollectorMetadataAnalysis::Result
run(Module & M,ModuleAnalysisManager & MAM)42312c0ed1SDimitry Andric CollectorMetadataAnalysis::run(Module &M, ModuleAnalysisManager &MAM) {
43312c0ed1SDimitry Andric Result R;
44312c0ed1SDimitry Andric auto &Map = R.StrategyMap;
45312c0ed1SDimitry Andric for (auto &F : M) {
46312c0ed1SDimitry Andric if (F.isDeclaration() || !F.hasGC())
47312c0ed1SDimitry Andric continue;
48312c0ed1SDimitry Andric if (auto GCName = F.getGC(); !Map.contains(GCName))
49312c0ed1SDimitry Andric Map[GCName] = getGCStrategy(GCName);
50312c0ed1SDimitry Andric }
51312c0ed1SDimitry Andric return R;
52312c0ed1SDimitry Andric }
53009b1c42SEd Schouten
54312c0ed1SDimitry Andric AnalysisKey GCFunctionAnalysis::Key;
5559850d08SRoman Divacky
56312c0ed1SDimitry Andric GCFunctionAnalysis::Result
run(Function & F,FunctionAnalysisManager & FAM)57312c0ed1SDimitry Andric GCFunctionAnalysis::run(Function &F, FunctionAnalysisManager &FAM) {
58312c0ed1SDimitry Andric assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
59312c0ed1SDimitry Andric assert(F.hasGC() && "Function doesn't have GC!");
60009b1c42SEd Schouten
61312c0ed1SDimitry Andric auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
62312c0ed1SDimitry Andric assert(
63312c0ed1SDimitry Andric MAMProxy.cachedResultExists<CollectorMetadataAnalysis>(*F.getParent()) &&
64312c0ed1SDimitry Andric "This pass need module analysis `collector-metadata`!");
65312c0ed1SDimitry Andric auto &Map =
66312c0ed1SDimitry Andric MAMProxy.getCachedResult<CollectorMetadataAnalysis>(*F.getParent())
67312c0ed1SDimitry Andric ->StrategyMap;
68312c0ed1SDimitry Andric GCFunctionInfo Info(F, *Map[F.getGC()]);
69312c0ed1SDimitry Andric return Info;
70312c0ed1SDimitry Andric }
71009b1c42SEd Schouten
72d39c594dSDimitry Andric INITIALIZE_PASS(GCModuleInfo, "collector-metadata",
73cf099d11SDimitry Andric "Create Garbage Collector Module Metadata", false, false)
74009b1c42SEd Schouten
75009b1c42SEd Schouten // -----------------------------------------------------------------------------
76009b1c42SEd Schouten
GCFunctionInfo(const Function & F,GCStrategy & S)77009b1c42SEd Schouten GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S)
78009b1c42SEd Schouten : F(F), S(S), FrameSize(~0LL) {}
79009b1c42SEd Schouten
807ab83427SDimitry Andric GCFunctionInfo::~GCFunctionInfo() = default;
81009b1c42SEd Schouten
invalidate(Function & F,const PreservedAnalyses & PA,FunctionAnalysisManager::Invalidator &)82312c0ed1SDimitry Andric bool GCFunctionInfo::invalidate(Function &F, const PreservedAnalyses &PA,
83312c0ed1SDimitry Andric FunctionAnalysisManager::Invalidator &) {
84312c0ed1SDimitry Andric auto PAC = PA.getChecker<GCFunctionAnalysis>();
85312c0ed1SDimitry Andric return !PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Function>>();
86312c0ed1SDimitry Andric }
87312c0ed1SDimitry Andric
88009b1c42SEd Schouten // -----------------------------------------------------------------------------
89009b1c42SEd Schouten
90009b1c42SEd Schouten char GCModuleInfo::ID = 0;
91009b1c42SEd Schouten
GCModuleInfo()925a5ac124SDimitry Andric GCModuleInfo::GCModuleInfo() : ImmutablePass(ID) {
93cf099d11SDimitry Andric initializeGCModuleInfoPass(*PassRegistry::getPassRegistry());
94cf099d11SDimitry Andric }
95009b1c42SEd Schouten
getFunctionInfo(const Function & F)96009b1c42SEd Schouten GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) {
97009b1c42SEd Schouten assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
98009b1c42SEd Schouten assert(F.hasGC());
99009b1c42SEd Schouten
100009b1c42SEd Schouten finfo_map_type::iterator I = FInfoMap.find(&F);
101009b1c42SEd Schouten if (I != FInfoMap.end())
102009b1c42SEd Schouten return *I->second;
103009b1c42SEd Schouten
1045a5ac124SDimitry Andric GCStrategy *S = getGCStrategy(F.getGC());
1051d5ae102SDimitry Andric Functions.push_back(std::make_unique<GCFunctionInfo>(F, *S));
10667c32a98SDimitry Andric GCFunctionInfo *GFI = Functions.back().get();
107009b1c42SEd Schouten FInfoMap[&F] = GFI;
108009b1c42SEd Schouten return *GFI;
109009b1c42SEd Schouten }
110009b1c42SEd Schouten
clear()111009b1c42SEd Schouten void GCModuleInfo::clear() {
11267c32a98SDimitry Andric Functions.clear();
113009b1c42SEd Schouten FInfoMap.clear();
1145a5ac124SDimitry Andric GCStrategyList.clear();
115009b1c42SEd Schouten }
116009b1c42SEd Schouten
117009b1c42SEd Schouten // -----------------------------------------------------------------------------
118009b1c42SEd Schouten
getGCStrategy(const StringRef Name)1195a5ac124SDimitry Andric GCStrategy *GCModuleInfo::getGCStrategy(const StringRef Name) {
1205a5ac124SDimitry Andric // TODO: Arguably, just doing a linear search would be faster for small N
1215a5ac124SDimitry Andric auto NMI = GCStrategyMap.find(Name);
1225a5ac124SDimitry Andric if (NMI != GCStrategyMap.end())
1235a5ac124SDimitry Andric return NMI->getValue();
1245a5ac124SDimitry Andric
125c0981da4SDimitry Andric std::unique_ptr<GCStrategy> S = llvm::getGCStrategy(Name);
126cfca06d7SDimitry Andric S->Name = std::string(Name);
1275a5ac124SDimitry Andric GCStrategyMap[Name] = S.get();
1285a5ac124SDimitry Andric GCStrategyList.push_back(std::move(S));
1295a5ac124SDimitry Andric return GCStrategyList.back().get();
1305a5ac124SDimitry Andric }
131