GCMetadata.cpp revision c74a197153dae0577209a2e12b9bc984f9f4df45
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/Pass.h"
18#include "llvm/CodeGen/Passes.h"
19#include "llvm/Function.h"
20#include "llvm/Support/Compiler.h"
21
22using namespace llvm;
23
24namespace {
25
26  class VISIBILITY_HIDDEN Printer : public FunctionPass {
27    static char ID;
28    std::ostream &OS;
29
30  public:
31    explicit Printer(std::ostream &OS = *cerr);
32
33    const char *getPassName() const;
34    void getAnalysisUsage(AnalysisUsage &AU) const;
35
36    bool runOnFunction(Function &F);
37  };
38
39  class VISIBILITY_HIDDEN Deleter : public FunctionPass {
40    static char ID;
41
42  public:
43    Deleter();
44
45    const char *getPassName() const;
46    void getAnalysisUsage(AnalysisUsage &AU) const;
47
48    bool runOnFunction(Function &F);
49    bool doFinalization(Module &M);
50  };
51
52}
53
54static RegisterPass<GCModuleInfo>
55X("collector-metadata", "Create Garbage Collector Module Metadata");
56
57// -----------------------------------------------------------------------------
58
59GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S)
60  : F(F), S(S), FrameSize(~0LL) {}
61
62GCFunctionInfo::~GCFunctionInfo() {}
63
64// -----------------------------------------------------------------------------
65
66char GCModuleInfo::ID = 0;
67
68GCModuleInfo::GCModuleInfo()
69  : ImmutablePass(&ID) {}
70
71GCModuleInfo::~GCModuleInfo() {
72  clear();
73}
74
75GCStrategy *GCModuleInfo::getOrCreateStrategy(const Module *M,
76                                              const std::string &Name) {
77  const char *Start = Name.c_str();
78
79  strategy_map_type::iterator NMI =
80    StrategyMap.find(Start, Start + Name.size());
81  if (NMI != StrategyMap.end())
82    return NMI->getValue();
83
84  for (GCRegistry::iterator I = GCRegistry::begin(),
85                            E = GCRegistry::end(); I != E; ++I) {
86    if (strcmp(Start, I->getName()) == 0) {
87      GCStrategy *S = I->instantiate();
88      S->M = M;
89      S->Name = Name;
90      StrategyMap.GetOrCreateValue(Start, Start + Name.size()).setValue(S);
91      StrategyList.push_back(S);
92      return S;
93    }
94  }
95
96  cerr << "unsupported GC: " << Name << "\n";
97  abort();
98}
99
100GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) {
101  assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
102  assert(F.hasGC());
103
104  finfo_map_type::iterator I = FInfoMap.find(&F);
105  if (I != FInfoMap.end())
106    return *I->second;
107
108  GCStrategy *S = getOrCreateStrategy(F.getParent(), F.getGC());
109  GCFunctionInfo *GFI = S->insertFunctionInfo(F);
110  FInfoMap[&F] = GFI;
111  return *GFI;
112}
113
114void GCModuleInfo::clear() {
115  FInfoMap.clear();
116  StrategyMap.clear();
117
118  for (iterator I = begin(), E = end(); I != E; ++I)
119    delete *I;
120  StrategyList.clear();
121}
122
123// -----------------------------------------------------------------------------
124
125char Printer::ID = 0;
126
127FunctionPass *llvm::createGCInfoPrinter(std::ostream &OS) {
128  return new Printer(OS);
129}
130
131Printer::Printer(std::ostream &OS)
132  : FunctionPass(&ID), OS(OS) {}
133
134const char *Printer::getPassName() const {
135  return "Print Garbage Collector Information";
136}
137
138void Printer::getAnalysisUsage(AnalysisUsage &AU) const {
139  FunctionPass::getAnalysisUsage(AU);
140  AU.setPreservesAll();
141  AU.addRequired<GCModuleInfo>();
142}
143
144static const char *DescKind(GC::PointKind Kind) {
145  switch (Kind) {
146    default: assert(0 && "Unknown GC point kind");
147    case GC::Loop:     return "loop";
148    case GC::Return:   return "return";
149    case GC::PreCall:  return "pre-call";
150    case GC::PostCall: return "post-call";
151  }
152}
153
154bool Printer::runOnFunction(Function &F) {
155  if (!F.hasGC()) {
156    GCFunctionInfo *FD = &getAnalysis<GCModuleInfo>().getFunctionInfo(F);
157
158    OS << "GC roots for " << FD->getFunction().getNameStart() << ":\n";
159    for (GCFunctionInfo::roots_iterator RI = FD->roots_begin(),
160                                        RE = FD->roots_end(); RI != RE; ++RI)
161      OS << "\t" << RI->Num << "\t" << RI->StackOffset << "[sp]\n";
162
163    OS << "GC safe points for " << FD->getFunction().getNameStart() << ":\n";
164    for (GCFunctionInfo::iterator PI = FD->begin(),
165                                  PE = FD->end(); PI != PE; ++PI) {
166
167      OS << "\tlabel " << PI->Num << ": " << DescKind(PI->Kind) << ", live = {";
168
169      for (GCFunctionInfo::live_iterator RI = FD->live_begin(PI),
170                                         RE = FD->live_end(PI);;) {
171        OS << " " << RI->Num;
172        if (++RI == RE)
173          break;
174        OS << ",";
175      }
176
177      OS << " }\n";
178    }
179  }
180
181  return false;
182}
183
184// -----------------------------------------------------------------------------
185
186char Deleter::ID = 0;
187
188FunctionPass *llvm::createGCInfoDeleter() {
189  return new Deleter();
190}
191
192Deleter::Deleter() : FunctionPass(&ID) {}
193
194const char *Deleter::getPassName() const {
195  return "Delete Garbage Collector Information";
196}
197
198void Deleter::getAnalysisUsage(AnalysisUsage &AU) const {
199  AU.setPreservesAll();
200  AU.addRequired<GCModuleInfo>();
201}
202
203bool Deleter::runOnFunction(Function &MF) {
204  return false;
205}
206
207bool Deleter::doFinalization(Module &M) {
208  GCModuleInfo *GMI = getAnalysisIfAvailable<GCModuleInfo>();
209  assert(GMI && "Deleter didn't require GCModuleInfo?!");
210  GMI->clear();
211  return false;
212}
213