2
0

GCMetadata.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. //===-- GCMetadata.cpp - Garbage collector metadata -----------------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file implements the GCFunctionInfo class and GCModuleInfo pass.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/CodeGen/GCMetadata.h"
  14. #include "llvm/CodeGen/GCStrategy.h"
  15. #include "llvm/CodeGen/MachineFrameInfo.h"
  16. #include "llvm/CodeGen/Passes.h"
  17. #include "llvm/IR/Function.h"
  18. #include "llvm/MC/MCSymbol.h"
  19. #include "llvm/Pass.h"
  20. #include "llvm/Support/Debug.h"
  21. #include "llvm/Support/ErrorHandling.h"
  22. #include "llvm/Support/raw_ostream.h"
  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. const char *getPassName() const override;
  31. void getAnalysisUsage(AnalysisUsage &AU) const override;
  32. bool runOnFunction(Function &F) override;
  33. bool doFinalization(Module &M) override;
  34. };
  35. }
  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() {}
  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(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. const char *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. static const char *DescKind(GC::PointKind Kind) {
  78. switch (Kind) {
  79. case GC::PreCall:
  80. return "pre-call";
  81. case GC::PostCall:
  82. return "post-call";
  83. }
  84. llvm_unreachable("Invalid point kind");
  85. }
  86. bool Printer::runOnFunction(Function &F) {
  87. if (F.hasGC())
  88. return false;
  89. GCFunctionInfo *FD = &getAnalysis<GCModuleInfo>().getFunctionInfo(F);
  90. OS << "GC roots for " << FD->getFunction().getName() << ":\n";
  91. for (GCFunctionInfo::roots_iterator RI = FD->roots_begin(),
  92. RE = FD->roots_end();
  93. RI != RE; ++RI)
  94. OS << "\t" << RI->Num << "\t" << RI->StackOffset << "[sp]\n";
  95. OS << "GC safe points for " << FD->getFunction().getName() << ":\n";
  96. for (GCFunctionInfo::iterator PI = FD->begin(), PE = FD->end(); PI != PE;
  97. ++PI) {
  98. OS << "\t" << PI->Label->getName() << ": " << DescKind(PI->Kind)
  99. << ", live = {";
  100. for (GCFunctionInfo::live_iterator RI = FD->live_begin(PI),
  101. RE = FD->live_end(PI);
  102. ;) {
  103. OS << " " << RI->Num;
  104. if (++RI == RE)
  105. break;
  106. OS << ",";
  107. }
  108. OS << " }\n";
  109. }
  110. return false;
  111. }
  112. bool Printer::doFinalization(Module &M) {
  113. GCModuleInfo *GMI = getAnalysisIfAvailable<GCModuleInfo>();
  114. assert(GMI && "Printer didn't require GCModuleInfo?!");
  115. GMI->clear();
  116. return false;
  117. }
  118. GCStrategy *GCModuleInfo::getGCStrategy(const StringRef Name) {
  119. // TODO: Arguably, just doing a linear search would be faster for small N
  120. auto NMI = GCStrategyMap.find(Name);
  121. if (NMI != GCStrategyMap.end())
  122. return NMI->getValue();
  123. for (auto& Entry : GCRegistry::entries()) {
  124. if (Name == Entry.getName()) {
  125. std::unique_ptr<GCStrategy> S = Entry.instantiate();
  126. S->Name = Name;
  127. GCStrategyMap[Name] = S.get();
  128. GCStrategyList.push_back(std::move(S));
  129. return GCStrategyList.back().get();
  130. }
  131. }
  132. if (GCRegistry::begin() == GCRegistry::end()) {
  133. // In normal operation, the registry should not be empty. There should
  134. // be the builtin GCs if nothing else. The most likely scenario here is
  135. // that we got here without running the initializers used by the Registry
  136. // itself and it's registration mechanism.
  137. const std::string error = ("unsupported GC: " + Name).str() +
  138. " (did you remember to link and initialize the CodeGen library?)";
  139. report_fatal_error(error);
  140. } else
  141. report_fatal_error(std::string("unsupported GC: ") + Name);
  142. }