xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/GCMetadata.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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"
17*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h"
18480093f4SDimitry Andric #include "llvm/InitializePasses.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
200b57cec5SDimitry Andric #include "llvm/Pass.h"
210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
220b57cec5SDimitry Andric #include <cassert>
230b57cec5SDimitry Andric #include <memory>
240b57cec5SDimitry Andric #include <string>
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric using namespace llvm;
270b57cec5SDimitry Andric 
invalidate(Module & M,const PreservedAnalyses & PA,ModuleAnalysisManager::Invalidator &)285f757f3fSDimitry Andric bool GCStrategyMap::invalidate(Module &M, const PreservedAnalyses &PA,
295f757f3fSDimitry Andric                                ModuleAnalysisManager::Invalidator &) {
305f757f3fSDimitry Andric   for (const auto &F : M) {
315f757f3fSDimitry Andric     if (F.isDeclaration() || !F.hasGC())
325f757f3fSDimitry Andric       continue;
335f757f3fSDimitry Andric     if (!StrategyMap.contains(F.getGC()))
345f757f3fSDimitry Andric       return true;
355f757f3fSDimitry Andric   }
365f757f3fSDimitry Andric   return false;
375f757f3fSDimitry Andric }
380b57cec5SDimitry Andric 
395f757f3fSDimitry Andric AnalysisKey CollectorMetadataAnalysis::Key;
400b57cec5SDimitry Andric 
415f757f3fSDimitry Andric CollectorMetadataAnalysis::Result
run(Module & M,ModuleAnalysisManager & MAM)425f757f3fSDimitry Andric CollectorMetadataAnalysis::run(Module &M, ModuleAnalysisManager &MAM) {
435f757f3fSDimitry Andric   Result R;
445f757f3fSDimitry Andric   auto &Map = R.StrategyMap;
455f757f3fSDimitry Andric   for (auto &F : M) {
465f757f3fSDimitry Andric     if (F.isDeclaration() || !F.hasGC())
475f757f3fSDimitry Andric       continue;
485f757f3fSDimitry Andric     if (auto GCName = F.getGC(); !Map.contains(GCName))
495f757f3fSDimitry Andric       Map[GCName] = getGCStrategy(GCName);
505f757f3fSDimitry Andric   }
515f757f3fSDimitry Andric   return R;
525f757f3fSDimitry Andric }
530b57cec5SDimitry Andric 
545f757f3fSDimitry Andric AnalysisKey GCFunctionAnalysis::Key;
550b57cec5SDimitry Andric 
565f757f3fSDimitry Andric GCFunctionAnalysis::Result
run(Function & F,FunctionAnalysisManager & FAM)575f757f3fSDimitry Andric GCFunctionAnalysis::run(Function &F, FunctionAnalysisManager &FAM) {
585f757f3fSDimitry Andric   assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
595f757f3fSDimitry Andric   assert(F.hasGC() && "Function doesn't have GC!");
600b57cec5SDimitry Andric 
615f757f3fSDimitry Andric   auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
625f757f3fSDimitry Andric   assert(
635f757f3fSDimitry Andric       MAMProxy.cachedResultExists<CollectorMetadataAnalysis>(*F.getParent()) &&
645f757f3fSDimitry Andric       "This pass need module analysis `collector-metadata`!");
655f757f3fSDimitry Andric   auto &Map =
665f757f3fSDimitry Andric       MAMProxy.getCachedResult<CollectorMetadataAnalysis>(*F.getParent())
675f757f3fSDimitry Andric           ->StrategyMap;
685f757f3fSDimitry Andric   GCFunctionInfo Info(F, *Map[F.getGC()]);
695f757f3fSDimitry Andric   return Info;
705f757f3fSDimitry Andric }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric INITIALIZE_PASS(GCModuleInfo, "collector-metadata",
730b57cec5SDimitry Andric                 "Create Garbage Collector Module Metadata", false, false)
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric // -----------------------------------------------------------------------------
760b57cec5SDimitry Andric 
GCFunctionInfo(const Function & F,GCStrategy & S)770b57cec5SDimitry Andric GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S)
780b57cec5SDimitry Andric     : F(F), S(S), FrameSize(~0LL) {}
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric GCFunctionInfo::~GCFunctionInfo() = default;
810b57cec5SDimitry Andric 
invalidate(Function & F,const PreservedAnalyses & PA,FunctionAnalysisManager::Invalidator &)825f757f3fSDimitry Andric bool GCFunctionInfo::invalidate(Function &F, const PreservedAnalyses &PA,
835f757f3fSDimitry Andric                                 FunctionAnalysisManager::Invalidator &) {
845f757f3fSDimitry Andric   auto PAC = PA.getChecker<GCFunctionAnalysis>();
855f757f3fSDimitry Andric   return !PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Function>>();
865f757f3fSDimitry Andric }
875f757f3fSDimitry Andric 
880b57cec5SDimitry Andric // -----------------------------------------------------------------------------
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric char GCModuleInfo::ID = 0;
910b57cec5SDimitry Andric 
GCModuleInfo()920b57cec5SDimitry Andric GCModuleInfo::GCModuleInfo() : ImmutablePass(ID) {
930b57cec5SDimitry Andric   initializeGCModuleInfoPass(*PassRegistry::getPassRegistry());
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
getFunctionInfo(const Function & F)960b57cec5SDimitry Andric GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) {
970b57cec5SDimitry Andric   assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
980b57cec5SDimitry Andric   assert(F.hasGC());
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   finfo_map_type::iterator I = FInfoMap.find(&F);
1010b57cec5SDimitry Andric   if (I != FInfoMap.end())
1020b57cec5SDimitry Andric     return *I->second;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   GCStrategy *S = getGCStrategy(F.getGC());
1058bcb0991SDimitry Andric   Functions.push_back(std::make_unique<GCFunctionInfo>(F, *S));
1060b57cec5SDimitry Andric   GCFunctionInfo *GFI = Functions.back().get();
1070b57cec5SDimitry Andric   FInfoMap[&F] = GFI;
1080b57cec5SDimitry Andric   return *GFI;
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
clear()1110b57cec5SDimitry Andric void GCModuleInfo::clear() {
1120b57cec5SDimitry Andric   Functions.clear();
1130b57cec5SDimitry Andric   FInfoMap.clear();
1140b57cec5SDimitry Andric   GCStrategyList.clear();
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric // -----------------------------------------------------------------------------
1180b57cec5SDimitry Andric 
getGCStrategy(const StringRef Name)1190b57cec5SDimitry Andric GCStrategy *GCModuleInfo::getGCStrategy(const StringRef Name) {
1200b57cec5SDimitry Andric   // TODO: Arguably, just doing a linear search would be faster for small N
1210b57cec5SDimitry Andric   auto NMI = GCStrategyMap.find(Name);
1220b57cec5SDimitry Andric   if (NMI != GCStrategyMap.end())
1230b57cec5SDimitry Andric     return NMI->getValue();
1240b57cec5SDimitry Andric 
125349cc55cSDimitry Andric   std::unique_ptr<GCStrategy> S = llvm::getGCStrategy(Name);
1265ffd83dbSDimitry Andric   S->Name = std::string(Name);
1270b57cec5SDimitry Andric   GCStrategyMap[Name] = S.get();
1280b57cec5SDimitry Andric   GCStrategyList.push_back(std::move(S));
1290b57cec5SDimitry Andric   return GCStrategyList.back().get();
1300b57cec5SDimitry Andric }
131