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