GCMetadata.cpp 4.3 KB

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