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