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