GCMetadata.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  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/ADT/STLExtras.h"
  13. #include "llvm/CodeGen/GCMetadata.h"
  14. #include "llvm/CodeGen/GCStrategy.h"
  15. #include "llvm/CodeGen/Passes.h"
  16. #include "llvm/IR/Function.h"
  17. #include "llvm/MC/MCSymbol.h"
  18. #include "llvm/Pass.h"
  19. #include "llvm/Support/ErrorHandling.h"
  20. #include "llvm/Support/raw_ostream.h"
  21. #include <algorithm>
  22. #include <cassert>
  23. #include <memory>
  24. #include <string>
  25. using namespace llvm;
  26. namespace {
  27. class Printer : public FunctionPass {
  28. static char ID;
  29. raw_ostream &OS;
  30. public:
  31. explicit Printer(raw_ostream &OS) : FunctionPass(ID), OS(OS) {}
  32. StringRef getPassName() const override;
  33. void getAnalysisUsage(AnalysisUsage &AU) const override;
  34. bool runOnFunction(Function &F) override;
  35. bool doFinalization(Module &M) override;
  36. };
  37. } // end anonymous namespace
  38. INITIALIZE_PASS(GCModuleInfo, "collector-metadata",
  39. "Create Garbage Collector Module Metadata", false, false)
  40. // -----------------------------------------------------------------------------
  41. GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S)
  42. : F(F), S(S), FrameSize(~0LL) {}
  43. GCFunctionInfo::~GCFunctionInfo() = default;
  44. // -----------------------------------------------------------------------------
  45. char GCModuleInfo::ID = 0;
  46. GCModuleInfo::GCModuleInfo() : ImmutablePass(ID) {
  47. initializeGCModuleInfoPass(*PassRegistry::getPassRegistry());
  48. }
  49. GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) {
  50. assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
  51. assert(F.hasGC());
  52. finfo_map_type::iterator I = FInfoMap.find(&F);
  53. if (I != FInfoMap.end())
  54. return *I->second;
  55. GCStrategy *S = getGCStrategy(F.getGC());
  56. Functions.push_back(std::make_unique<GCFunctionInfo>(F, *S));
  57. GCFunctionInfo *GFI = Functions.back().get();
  58. FInfoMap[&F] = GFI;
  59. return *GFI;
  60. }
  61. void GCModuleInfo::clear() {
  62. Functions.clear();
  63. FInfoMap.clear();
  64. GCStrategyList.clear();
  65. }
  66. // -----------------------------------------------------------------------------
  67. char Printer::ID = 0;
  68. FunctionPass *llvm::createGCInfoPrinter(raw_ostream &OS) {
  69. return new Printer(OS);
  70. }
  71. StringRef Printer::getPassName() const {
  72. return "Print Garbage Collector Information";
  73. }
  74. void Printer::getAnalysisUsage(AnalysisUsage &AU) const {
  75. FunctionPass::getAnalysisUsage(AU);
  76. AU.setPreservesAll();
  77. AU.addRequired<GCModuleInfo>();
  78. }
  79. bool Printer::runOnFunction(Function &F) {
  80. if (F.hasGC())
  81. return false;
  82. GCFunctionInfo *FD = &getAnalysis<GCModuleInfo>().getFunctionInfo(F);
  83. OS << "GC roots for " << FD->getFunction().getName() << ":\n";
  84. for (GCFunctionInfo::roots_iterator RI = FD->roots_begin(),
  85. RE = FD->roots_end();
  86. RI != RE; ++RI)
  87. OS << "\t" << RI->Num << "\t" << RI->StackOffset << "[sp]\n";
  88. OS << "GC safe points for " << FD->getFunction().getName() << ":\n";
  89. for (GCFunctionInfo::iterator PI = FD->begin(), PE = FD->end(); PI != PE;
  90. ++PI) {
  91. OS << "\t" << PI->Label->getName() << ": " << "post-call"
  92. << ", live = {";
  93. for (GCFunctionInfo::live_iterator RI = FD->live_begin(PI),
  94. RE = FD->live_end(PI);
  95. ;) {
  96. OS << " " << RI->Num;
  97. if (++RI == RE)
  98. break;
  99. OS << ",";
  100. }
  101. OS << " }\n";
  102. }
  103. return false;
  104. }
  105. bool Printer::doFinalization(Module &M) {
  106. GCModuleInfo *GMI = getAnalysisIfAvailable<GCModuleInfo>();
  107. assert(GMI && "Printer didn't require GCModuleInfo?!");
  108. GMI->clear();
  109. return false;
  110. }
  111. GCStrategy *GCModuleInfo::getGCStrategy(const StringRef Name) {
  112. // TODO: Arguably, just doing a linear search would be faster for small N
  113. auto NMI = GCStrategyMap.find(Name);
  114. if (NMI != GCStrategyMap.end())
  115. return NMI->getValue();
  116. for (auto& Entry : GCRegistry::entries()) {
  117. if (Name == Entry.getName()) {
  118. std::unique_ptr<GCStrategy> S = Entry.instantiate();
  119. S->Name = Name;
  120. GCStrategyMap[Name] = S.get();
  121. GCStrategyList.push_back(std::move(S));
  122. return GCStrategyList.back().get();
  123. }
  124. }
  125. if (GCRegistry::begin() == GCRegistry::end()) {
  126. // In normal operation, the registry should not be empty. There should
  127. // be the builtin GCs if nothing else. The most likely scenario here is
  128. // that we got here without running the initializers used by the Registry
  129. // itself and it's registration mechanism.
  130. const std::string error = ("unsupported GC: " + Name).str() +
  131. " (did you remember to link and initialize the CodeGen library?)";
  132. report_fatal_error(error);
  133. } else
  134. report_fatal_error(std::string("unsupported GC: ") + Name);
  135. }