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 
22 using namespace llvm;
23 
24 namespace {
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 
54 static RegisterPass<GCModuleInfo>
55 X("collector-metadata", "Create Garbage Collector Module Metadata");
56 
57 // -----------------------------------------------------------------------------
58 
59 GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S)
60   : F(F), S(S), FrameSize(~0LL) {}
61 
62 GCFunctionInfo::~GCFunctionInfo() {}
63 
64 // -----------------------------------------------------------------------------
65 
66 char GCModuleInfo::ID = 0;
67 
68 GCModuleInfo::GCModuleInfo()
69   : ImmutablePass(&ID) {}
70 
71 GCModuleInfo::~GCModuleInfo() {
72   clear();
73 }
74 
75 GCStrategy *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 
100 GCFunctionInfo &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 
114 void 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 
125 char Printer::ID = 0;
126 
127 FunctionPass *llvm::createGCInfoPrinter(std::ostream &OS) {
128   return new Printer(OS);
129 }
130 
131 Printer::Printer(std::ostream &OS)
132   : FunctionPass(&ID), OS(OS) {}
133 
134 const char *Printer::getPassName() const {
135   return "Print Garbage Collector Information";
136 }
137 
138 void Printer::getAnalysisUsage(AnalysisUsage &AU) const {
139   FunctionPass::getAnalysisUsage(AU);
140   AU.setPreservesAll();
141   AU.addRequired<GCModuleInfo>();
142 }
143 
144 static 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 
154 bool 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 
186 char Deleter::ID = 0;
187 
188 FunctionPass *llvm::createGCInfoDeleter() {
189   return new Deleter();
190 }
191 
192 Deleter::Deleter() : FunctionPass(&ID) {}
193 
194 const char *Deleter::getPassName() const {
195   return "Delete Garbage Collector Information";
196 }
197 
198 void Deleter::getAnalysisUsage(AnalysisUsage &AU) const {
199   AU.setPreservesAll();
200   AU.addRequired<GCModuleInfo>();
201 }
202 
203 bool Deleter::runOnFunction(Function &MF) {
204   return false;
205 }
206 
207 bool 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