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