LLVM API Documentation
00001 //===-- GCMetadata.cpp - Garbage collector metadata -----------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the GCFunctionInfo class and GCModuleInfo pass. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/CodeGen/GCMetadata.h" 00015 #include "llvm/CodeGen/GCStrategy.h" 00016 #include "llvm/CodeGen/MachineFrameInfo.h" 00017 #include "llvm/CodeGen/Passes.h" 00018 #include "llvm/IR/Function.h" 00019 #include "llvm/MC/MCSymbol.h" 00020 #include "llvm/Pass.h" 00021 #include "llvm/Support/Debug.h" 00022 #include "llvm/Support/ErrorHandling.h" 00023 #include "llvm/Support/raw_ostream.h" 00024 using namespace llvm; 00025 00026 namespace { 00027 00028 class Printer : public FunctionPass { 00029 static char ID; 00030 raw_ostream &OS; 00031 00032 public: 00033 explicit Printer(raw_ostream &OS) : FunctionPass(ID), OS(OS) {} 00034 00035 00036 const char *getPassName() const override; 00037 void getAnalysisUsage(AnalysisUsage &AU) const override; 00038 00039 bool runOnFunction(Function &F) override; 00040 bool doFinalization(Module &M) override; 00041 }; 00042 00043 } 00044 00045 INITIALIZE_PASS(GCModuleInfo, "collector-metadata", 00046 "Create Garbage Collector Module Metadata", false, false) 00047 00048 // ----------------------------------------------------------------------------- 00049 00050 GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S) 00051 : F(F), S(S), FrameSize(~0LL) {} 00052 00053 GCFunctionInfo::~GCFunctionInfo() {} 00054 00055 // ----------------------------------------------------------------------------- 00056 00057 char GCModuleInfo::ID = 0; 00058 00059 GCModuleInfo::GCModuleInfo() 00060 : ImmutablePass(ID) { 00061 initializeGCModuleInfoPass(*PassRegistry::getPassRegistry()); 00062 } 00063 00064 GCStrategy *GCModuleInfo::getOrCreateStrategy(const Module *M, 00065 const std::string &Name) { 00066 strategy_map_type::iterator NMI = StrategyMap.find(Name); 00067 if (NMI != StrategyMap.end()) 00068 return NMI->getValue(); 00069 00070 for (GCRegistry::iterator I = GCRegistry::begin(), 00071 E = GCRegistry::end(); I != E; ++I) { 00072 if (Name == I->getName()) { 00073 std::unique_ptr<GCStrategy> S = I->instantiate(); 00074 S->M = M; 00075 S->Name = Name; 00076 StrategyMap.GetOrCreateValue(Name).setValue(S.get()); 00077 StrategyList.push_back(std::move(S)); 00078 return StrategyList.back().get(); 00079 } 00080 } 00081 00082 dbgs() << "unsupported GC: " << Name << "\n"; 00083 llvm_unreachable(nullptr); 00084 } 00085 00086 GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) { 00087 assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!"); 00088 assert(F.hasGC()); 00089 00090 finfo_map_type::iterator I = FInfoMap.find(&F); 00091 if (I != FInfoMap.end()) 00092 return *I->second; 00093 00094 GCStrategy *S = getOrCreateStrategy(F.getParent(), F.getGC()); 00095 GCFunctionInfo *GFI = S->insertFunctionInfo(F); 00096 FInfoMap[&F] = GFI; 00097 return *GFI; 00098 } 00099 00100 void GCModuleInfo::clear() { 00101 FInfoMap.clear(); 00102 StrategyMap.clear(); 00103 StrategyList.clear(); 00104 } 00105 00106 // ----------------------------------------------------------------------------- 00107 00108 char Printer::ID = 0; 00109 00110 FunctionPass *llvm::createGCInfoPrinter(raw_ostream &OS) { 00111 return new Printer(OS); 00112 } 00113 00114 00115 const char *Printer::getPassName() const { 00116 return "Print Garbage Collector Information"; 00117 } 00118 00119 void Printer::getAnalysisUsage(AnalysisUsage &AU) const { 00120 FunctionPass::getAnalysisUsage(AU); 00121 AU.setPreservesAll(); 00122 AU.addRequired<GCModuleInfo>(); 00123 } 00124 00125 static const char *DescKind(GC::PointKind Kind) { 00126 switch (Kind) { 00127 case GC::Loop: return "loop"; 00128 case GC::Return: return "return"; 00129 case GC::PreCall: return "pre-call"; 00130 case GC::PostCall: return "post-call"; 00131 } 00132 llvm_unreachable("Invalid point kind"); 00133 } 00134 00135 bool Printer::runOnFunction(Function &F) { 00136 if (F.hasGC()) return false; 00137 00138 GCFunctionInfo *FD = &getAnalysis<GCModuleInfo>().getFunctionInfo(F); 00139 00140 OS << "GC roots for " << FD->getFunction().getName() << ":\n"; 00141 for (GCFunctionInfo::roots_iterator RI = FD->roots_begin(), 00142 RE = FD->roots_end(); RI != RE; ++RI) 00143 OS << "\t" << RI->Num << "\t" << RI->StackOffset << "[sp]\n"; 00144 00145 OS << "GC safe points for " << FD->getFunction().getName() << ":\n"; 00146 for (GCFunctionInfo::iterator PI = FD->begin(), 00147 PE = FD->end(); PI != PE; ++PI) { 00148 00149 OS << "\t" << PI->Label->getName() << ": " 00150 << DescKind(PI->Kind) << ", live = {"; 00151 00152 for (GCFunctionInfo::live_iterator RI = FD->live_begin(PI), 00153 RE = FD->live_end(PI);;) { 00154 OS << " " << RI->Num; 00155 if (++RI == RE) 00156 break; 00157 OS << ","; 00158 } 00159 00160 OS << " }\n"; 00161 } 00162 00163 return false; 00164 } 00165 00166 bool Printer::doFinalization(Module &M) { 00167 GCModuleInfo *GMI = getAnalysisIfAvailable<GCModuleInfo>(); 00168 assert(GMI && "Printer didn't require GCModuleInfo?!"); 00169 GMI->clear(); 00170 return false; 00171 }