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 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 (!StrategyMap.contains(F.getGC())) 30 return true; 31 } 32 return false; 33 } 34 35 AnalysisKey CollectorMetadataAnalysis::Key; 36 37 CollectorMetadataAnalysis::Result 38 CollectorMetadataAnalysis::run(Module &M, ModuleAnalysisManager &MAM) { 39 Result R; 40 auto &Map = R.StrategyMap; 41 for (auto &F : M) { 42 if (F.isDeclaration() || !F.hasGC()) 43 continue; 44 if (auto GCName = F.getGC(); !Map.contains(GCName)) 45 Map[GCName] = getGCStrategy(GCName); 46 } 47 return R; 48 } 49 50 AnalysisKey GCFunctionAnalysis::Key; 51 52 GCFunctionAnalysis::Result 53 GCFunctionAnalysis::run(Function &F, FunctionAnalysisManager &FAM) { 54 assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!"); 55 assert(F.hasGC() && "Function doesn't have GC!"); 56 57 auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F); 58 assert( 59 MAMProxy.cachedResultExists<CollectorMetadataAnalysis>(*F.getParent()) && 60 "This pass need module analysis `collector-metadata`!"); 61 auto &Map = 62 MAMProxy.getCachedResult<CollectorMetadataAnalysis>(*F.getParent()) 63 ->StrategyMap; 64 GCFunctionInfo Info(F, *Map[F.getGC()]); 65 return Info; 66 } 67 68 INITIALIZE_PASS(GCModuleInfo, "collector-metadata", 69 "Create Garbage Collector Module Metadata", false, true) 70 71 // ----------------------------------------------------------------------------- 72 73 GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S) 74 : F(F), S(S), FrameSize(~0LL) {} 75 76 GCFunctionInfo::~GCFunctionInfo() = default; 77 78 bool GCFunctionInfo::invalidate(Function &F, const PreservedAnalyses &PA, 79 FunctionAnalysisManager::Invalidator &) { 80 auto PAC = PA.getChecker<GCFunctionAnalysis>(); 81 return !PAC.preserved() && !PAC.preservedSet<AllAnalysesOn<Function>>(); 82 } 83 84 // ----------------------------------------------------------------------------- 85 86 char GCModuleInfo::ID = 0; 87 88 GCModuleInfo::GCModuleInfo() : ImmutablePass(ID) { 89 initializeGCModuleInfoPass(*PassRegistry::getPassRegistry()); 90 } 91 92 GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) { 93 assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!"); 94 assert(F.hasGC()); 95 96 finfo_map_type::iterator I = FInfoMap.find(&F); 97 if (I != FInfoMap.end()) 98 return *I->second; 99 100 GCStrategy *S = getGCStrategy(F.getGC()); 101 Functions.push_back(std::make_unique<GCFunctionInfo>(F, *S)); 102 GCFunctionInfo *GFI = Functions.back().get(); 103 FInfoMap[&F] = GFI; 104 return *GFI; 105 } 106 107 void GCModuleInfo::clear() { 108 Functions.clear(); 109 FInfoMap.clear(); 110 GCStrategyList.clear(); 111 } 112 113 // ----------------------------------------------------------------------------- 114 115 GCStrategy *GCModuleInfo::getGCStrategy(const StringRef Name) { 116 // TODO: Arguably, just doing a linear search would be faster for small N 117 auto NMI = GCStrategyMap.find(Name); 118 if (NMI != GCStrategyMap.end()) 119 return NMI->getValue(); 120 121 std::unique_ptr<GCStrategy> S = llvm::getGCStrategy(Name); 122 S->Name = std::string(Name); 123 GCStrategyMap[Name] = S.get(); 124 GCStrategyList.push_back(std::move(S)); 125 return GCStrategyList.back().get(); 126 } 127