10b57cec5SDimitry Andric //===-- GCMetadata.cpp - Garbage collector metadata -----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the GCFunctionInfo class and GCModuleInfo pass.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/CodeGen/GCMetadata.h"
14fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h"
150b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h"
160b57cec5SDimitry Andric #include "llvm/IR/Function.h"
17480093f4SDimitry Andric #include "llvm/InitializePasses.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
190b57cec5SDimitry Andric #include "llvm/Pass.h"
200b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
210b57cec5SDimitry Andric #include <cassert>
220b57cec5SDimitry Andric #include <memory>
230b57cec5SDimitry Andric #include <string>
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
invalidate(Module & M,const PreservedAnalyses & PA,ModuleAnalysisManager::Invalidator &)27*c9157d92SDimitry Andric bool GCStrategyMap::invalidate(Module &M, const PreservedAnalyses &PA,
28*c9157d92SDimitry Andric                                ModuleAnalysisManager::Invalidator &) {
29*c9157d92SDimitry Andric   for (const auto &F : M) {
30*c9157d92SDimitry Andric     if (F.isDeclaration() || !F.hasGC())
31*c9157d92SDimitry Andric       continue;
32*c9157d92SDimitry Andric     if (!StrategyMap.contains(F.getGC()))
33*c9157d92SDimitry Andric       return true;
34*c9157d92SDimitry Andric   }
35*c9157d92SDimitry Andric   return false;
36*c9157d92SDimitry Andric }
370b57cec5SDimitry Andric 
38*c9157d92SDimitry Andric AnalysisKey CollectorMetadataAnalysis::Key;
390b57cec5SDimitry Andric 
40*c9157d92SDimitry Andric CollectorMetadataAnalysis::Result
run(Module & M,ModuleAnalysisManager & MAM)41*c9157d92SDimitry Andric CollectorMetadataAnalysis::run(Module &M, ModuleAnalysisManager &MAM) {
42*c9157d92SDimitry Andric   Result R;
43*c9157d92SDimitry Andric   auto &Map = R.StrategyMap;
44*c9157d92SDimitry Andric   for (auto &F : M) {
45*c9157d92SDimitry Andric     if (F.isDeclaration() || !F.hasGC())
46*c9157d92SDimitry Andric       continue;
47*c9157d92SDimitry Andric     if (auto GCName = F.getGC(); !Map.contains(GCName))
48*c9157d92SDimitry Andric       Map[GCName] = getGCStrategy(GCName);
49*c9157d92SDimitry Andric   }
50*c9157d92SDimitry Andric   return R;
51*c9157d92SDimitry Andric }
520b57cec5SDimitry Andric 
53*c9157d92SDimitry Andric AnalysisKey GCFunctionAnalysis::Key;
540b57cec5SDimitry Andric 
55*c9157d92SDimitry Andric GCFunctionAnalysis::Result
run(Function & F,FunctionAnalysisManager & FAM)56*c9157d92SDimitry Andric GCFunctionAnalysis::run(Function &F, FunctionAnalysisManager &FAM) {
57*c9157d92SDimitry Andric   assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
58*c9157d92SDimitry Andric   assert(F.hasGC() && "Function doesn't have GC!");
590b57cec5SDimitry Andric 
60*c9157d92SDimitry Andric   auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
61*c9157d92SDimitry Andric   assert(
62*c9157d92SDimitry Andric       MAMProxy.cachedResultExists<CollectorMetadataAnalysis>(*F.getParent()) &&
63*c9157d92SDimitry Andric       "This pass need module analysis `collector-metadata`!");
64*c9157d92SDimitry Andric   auto &Map =
65*c9157d92SDimitry Andric       MAMProxy.getCachedResult<CollectorMetadataAnalysis>(*F.getParent())
66*c9157d92SDimitry Andric           ->StrategyMap;
67*c9157d92SDimitry Andric   GCFunctionInfo Info(F, *Map[F.getGC()]);
68*c9157d92SDimitry Andric   return Info;
69*c9157d92SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric INITIALIZE_PASS(GCModuleInfo, "collector-metadata",
720b57cec5SDimitry Andric                 "Create Garbage Collector Module Metadata", false, false)
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric // -----------------------------------------------------------------------------
750b57cec5SDimitry Andric 
GCFunctionInfo(const Function & F,GCStrategy & S)760b57cec5SDimitry Andric GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S)
770b57cec5SDimitry Andric     : F(F), S(S), FrameSize(~0LL) {}
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric GCFunctionInfo::~GCFunctionInfo() = default;
800b57cec5SDimitry Andric 
invalidate(Function & F,const PreservedAnalyses & PA,FunctionAnalysisManager::Invalidator &)81*c9157d92SDimitry Andric bool GCFunctionInfo::invalidate(Function &F, const PreservedAnalyses &PA,
82*c9157d92SDimitry Andric                                 FunctionAnalysisManager::Invalidator &) {
83*c9157d92SDimitry Andric   auto PAC = PA.getChecker<GCFunctionAnalysis>();
84*c9157d92SDimitry Andric   return !PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Function>>();
85*c9157d92SDimitry Andric }
86*c9157d92SDimitry Andric 
870b57cec5SDimitry Andric // -----------------------------------------------------------------------------
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric char GCModuleInfo::ID = 0;
900b57cec5SDimitry Andric 
GCModuleInfo()910b57cec5SDimitry Andric GCModuleInfo::GCModuleInfo() : ImmutablePass(ID) {
920b57cec5SDimitry Andric   initializeGCModuleInfoPass(*PassRegistry::getPassRegistry());
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
getFunctionInfo(const Function & F)950b57cec5SDimitry Andric GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) {
960b57cec5SDimitry Andric   assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
970b57cec5SDimitry Andric   assert(F.hasGC());
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   finfo_map_type::iterator I = FInfoMap.find(&F);
1000b57cec5SDimitry Andric   if (I != FInfoMap.end())
1010b57cec5SDimitry Andric     return *I->second;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   GCStrategy *S = getGCStrategy(F.getGC());
1048bcb0991SDimitry Andric   Functions.push_back(std::make_unique<GCFunctionInfo>(F, *S));
1050b57cec5SDimitry Andric   GCFunctionInfo *GFI = Functions.back().get();
1060b57cec5SDimitry Andric   FInfoMap[&F] = GFI;
1070b57cec5SDimitry Andric   return *GFI;
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric 
clear()1100b57cec5SDimitry Andric void GCModuleInfo::clear() {
1110b57cec5SDimitry Andric   Functions.clear();
1120b57cec5SDimitry Andric   FInfoMap.clear();
1130b57cec5SDimitry Andric   GCStrategyList.clear();
1140b57cec5SDimitry Andric }
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric // -----------------------------------------------------------------------------
1170b57cec5SDimitry Andric 
getGCStrategy(const StringRef Name)1180b57cec5SDimitry Andric GCStrategy *GCModuleInfo::getGCStrategy(const StringRef Name) {
1190b57cec5SDimitry Andric   // TODO: Arguably, just doing a linear search would be faster for small N
1200b57cec5SDimitry Andric   auto NMI = GCStrategyMap.find(Name);
1210b57cec5SDimitry Andric   if (NMI != GCStrategyMap.end())
1220b57cec5SDimitry Andric     return NMI->getValue();
1230b57cec5SDimitry Andric 
124349cc55cSDimitry Andric   std::unique_ptr<GCStrategy> S = llvm::getGCStrategy(Name);
1255ffd83dbSDimitry Andric   S->Name = std::string(Name);
1260b57cec5SDimitry Andric   GCStrategyMap[Name] = S.get();
1270b57cec5SDimitry Andric   GCStrategyList.push_back(std::move(S));
1280b57cec5SDimitry Andric   return GCStrategyList.back().get();
1290b57cec5SDimitry Andric }
130