GCMetadata.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. #include "llvm/CodeGen/GCMetadata.h"
  13. #include "llvm/ADT/StringExtras.h"
  14. #include "llvm/CodeGen/Passes.h"
  15. #include "llvm/IR/Function.h"
  16. #include "llvm/InitializePasses.h"
  17. #include "llvm/MC/MCSymbol.h"
  18. #include "llvm/Pass.h"
  19. #include "llvm/Support/raw_ostream.h"
  20. #include <cassert>
  21. #include <memory>
  22. #include <string>
  23. using namespace llvm;
  24. namespace {
  25. class Printer : public FunctionPass {
  26. static char ID;
  27. raw_ostream &OS;
  28. public:
  29. explicit Printer(raw_ostream &OS) : FunctionPass(ID), OS(OS) {}
  30. StringRef getPassName() const override;
  31. void getAnalysisUsage(AnalysisUsage &AU) const override;
  32. bool runOnFunction(Function &F) override;
  33. bool doFinalization(Module &M) override;
  34. };
  35. } // end anonymous namespace
  36. INITIALIZE_PASS(GCModuleInfo, "collector-metadata",
  37. "Create Garbage Collector Module Metadata", false, false)
  38. // -----------------------------------------------------------------------------
  39. GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S)
  40. : F(F), S(S), FrameSize(~0LL) {}
  41. GCFunctionInfo::~GCFunctionInfo() = default;
  42. // -----------------------------------------------------------------------------
  43. char GCModuleInfo::ID = 0;
  44. GCModuleInfo::GCModuleInfo() : ImmutablePass(ID) {
  45. initializeGCModuleInfoPass(*PassRegistry::getPassRegistry());
  46. }
  47. GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) {
  48. assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
  49. assert(F.hasGC());
  50. finfo_map_type::iterator I = FInfoMap.find(&F);
  51. if (I != FInfoMap.end())
  52. return *I->second;
  53. GCStrategy *S = getGCStrategy(F.getGC());
  54. Functions.push_back(std::make_unique<GCFunctionInfo>(F, *S));
  55. GCFunctionInfo *GFI = Functions.back().get();
  56. FInfoMap[&F] = GFI;
  57. return *GFI;
  58. }
  59. void GCModuleInfo::clear() {
  60. Functions.clear();
  61. FInfoMap.clear();
  62. GCStrategyList.clear();
  63. }
  64. // -----------------------------------------------------------------------------
  65. char Printer::ID = 0;
  66. FunctionPass *llvm::createGCInfoPrinter(raw_ostream &OS) {
  67. return new Printer(OS);
  68. }
  69. StringRef Printer::getPassName() const {
  70. return "Print Garbage Collector Information";
  71. }
  72. void Printer::getAnalysisUsage(AnalysisUsage &AU) const {
  73. FunctionPass::getAnalysisUsage(AU);
  74. AU.setPreservesAll();
  75. AU.addRequired<GCModuleInfo>();
  76. }
  77. bool Printer::runOnFunction(Function &F) {
  78. if (F.hasGC())
  79. return false;
  80. GCFunctionInfo *FD = &getAnalysis<GCModuleInfo>().getFunctionInfo(F);
  81. OS << "GC roots for " << FD->getFunction().getName() << ":\n";
  82. for (GCFunctionInfo::roots_iterator RI = FD->roots_begin(),
  83. RE = FD->roots_end();
  84. RI != RE; ++RI)
  85. OS << "\t" << RI->Num << "\t" << RI->StackOffset << "[sp]\n";
  86. OS << "GC safe points for " << FD->getFunction().getName() << ":\n";
  87. for (GCFunctionInfo::iterator PI = FD->begin(), PE = FD->end(); PI != PE;
  88. ++PI) {
  89. OS << "\t" << PI->Label->getName() << ": " << "post-call"
  90. << ", live = {";
  91. ListSeparator LS(",");
  92. for (const GCRoot &R : make_range(FD->live_begin(PI), FD->live_end(PI)))
  93. OS << LS << " " << R.Num;
  94. OS << " }\n";
  95. }
  96. return false;
  97. }
  98. bool Printer::doFinalization(Module &M) {
  99. GCModuleInfo *GMI = getAnalysisIfAvailable<GCModuleInfo>();
  100. assert(GMI && "Printer didn't require GCModuleInfo?!");
  101. GMI->clear();
  102. return false;
  103. }
  104. GCStrategy *GCModuleInfo::getGCStrategy(const StringRef Name) {
  105. // TODO: Arguably, just doing a linear search would be faster for small N
  106. auto NMI = GCStrategyMap.find(Name);
  107. if (NMI != GCStrategyMap.end())
  108. return NMI->getValue();
  109. std::unique_ptr<GCStrategy> S = llvm::getGCStrategy(Name);
  110. S->Name = std::string(Name);
  111. GCStrategyMap[Name] = S.get();
  112. GCStrategyList.push_back(std::move(S));
  113. return GCStrategyList.back().get();
  114. }