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