LCOV - code coverage report
Current view: top level - lib/CodeGen - GCMetadata.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 23 60 38.3 %
Date: 2018-10-20 13:21:21 Functions: 6 12 50.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13