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