xref: /aosp_15_r20/external/llvm/lib/CodeGen/GCMetadata.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- GCMetadata.cpp - Garbage collector metadata -----------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the GCFunctionInfo class and GCModuleInfo pass.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker 
14*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/GCMetadata.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/GCStrategy.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Function.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSymbol.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Pass.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
24*9880d681SAndroid Build Coastguard Worker using namespace llvm;
25*9880d681SAndroid Build Coastguard Worker 
26*9880d681SAndroid Build Coastguard Worker namespace {
27*9880d681SAndroid Build Coastguard Worker 
28*9880d681SAndroid Build Coastguard Worker class Printer : public FunctionPass {
29*9880d681SAndroid Build Coastguard Worker   static char ID;
30*9880d681SAndroid Build Coastguard Worker   raw_ostream &OS;
31*9880d681SAndroid Build Coastguard Worker 
32*9880d681SAndroid Build Coastguard Worker public:
Printer(raw_ostream & OS)33*9880d681SAndroid Build Coastguard Worker   explicit Printer(raw_ostream &OS) : FunctionPass(ID), OS(OS) {}
34*9880d681SAndroid Build Coastguard Worker 
35*9880d681SAndroid Build Coastguard Worker   const char *getPassName() const override;
36*9880d681SAndroid Build Coastguard Worker   void getAnalysisUsage(AnalysisUsage &AU) const override;
37*9880d681SAndroid Build Coastguard Worker 
38*9880d681SAndroid Build Coastguard Worker   bool runOnFunction(Function &F) override;
39*9880d681SAndroid Build Coastguard Worker   bool doFinalization(Module &M) override;
40*9880d681SAndroid Build Coastguard Worker };
41*9880d681SAndroid Build Coastguard Worker }
42*9880d681SAndroid Build Coastguard Worker 
43*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(GCModuleInfo, "collector-metadata",
44*9880d681SAndroid Build Coastguard Worker                 "Create Garbage Collector Module Metadata", false, false)
45*9880d681SAndroid Build Coastguard Worker 
46*9880d681SAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
47*9880d681SAndroid Build Coastguard Worker 
GCFunctionInfo(const Function & F,GCStrategy & S)48*9880d681SAndroid Build Coastguard Worker GCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S)
49*9880d681SAndroid Build Coastguard Worker     : F(F), S(S), FrameSize(~0LL) {}
50*9880d681SAndroid Build Coastguard Worker 
~GCFunctionInfo()51*9880d681SAndroid Build Coastguard Worker GCFunctionInfo::~GCFunctionInfo() {}
52*9880d681SAndroid Build Coastguard Worker 
53*9880d681SAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker char GCModuleInfo::ID = 0;
56*9880d681SAndroid Build Coastguard Worker 
GCModuleInfo()57*9880d681SAndroid Build Coastguard Worker GCModuleInfo::GCModuleInfo() : ImmutablePass(ID) {
58*9880d681SAndroid Build Coastguard Worker   initializeGCModuleInfoPass(*PassRegistry::getPassRegistry());
59*9880d681SAndroid Build Coastguard Worker }
60*9880d681SAndroid Build Coastguard Worker 
getFunctionInfo(const Function & F)61*9880d681SAndroid Build Coastguard Worker GCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) {
62*9880d681SAndroid Build Coastguard Worker   assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
63*9880d681SAndroid Build Coastguard Worker   assert(F.hasGC());
64*9880d681SAndroid Build Coastguard Worker 
65*9880d681SAndroid Build Coastguard Worker   finfo_map_type::iterator I = FInfoMap.find(&F);
66*9880d681SAndroid Build Coastguard Worker   if (I != FInfoMap.end())
67*9880d681SAndroid Build Coastguard Worker     return *I->second;
68*9880d681SAndroid Build Coastguard Worker 
69*9880d681SAndroid Build Coastguard Worker   GCStrategy *S = getGCStrategy(F.getGC());
70*9880d681SAndroid Build Coastguard Worker   Functions.push_back(make_unique<GCFunctionInfo>(F, *S));
71*9880d681SAndroid Build Coastguard Worker   GCFunctionInfo *GFI = Functions.back().get();
72*9880d681SAndroid Build Coastguard Worker   FInfoMap[&F] = GFI;
73*9880d681SAndroid Build Coastguard Worker   return *GFI;
74*9880d681SAndroid Build Coastguard Worker }
75*9880d681SAndroid Build Coastguard Worker 
clear()76*9880d681SAndroid Build Coastguard Worker void GCModuleInfo::clear() {
77*9880d681SAndroid Build Coastguard Worker   Functions.clear();
78*9880d681SAndroid Build Coastguard Worker   FInfoMap.clear();
79*9880d681SAndroid Build Coastguard Worker   GCStrategyList.clear();
80*9880d681SAndroid Build Coastguard Worker }
81*9880d681SAndroid Build Coastguard Worker 
82*9880d681SAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
83*9880d681SAndroid Build Coastguard Worker 
84*9880d681SAndroid Build Coastguard Worker char Printer::ID = 0;
85*9880d681SAndroid Build Coastguard Worker 
createGCInfoPrinter(raw_ostream & OS)86*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createGCInfoPrinter(raw_ostream &OS) {
87*9880d681SAndroid Build Coastguard Worker   return new Printer(OS);
88*9880d681SAndroid Build Coastguard Worker }
89*9880d681SAndroid Build Coastguard Worker 
getPassName() const90*9880d681SAndroid Build Coastguard Worker const char *Printer::getPassName() const {
91*9880d681SAndroid Build Coastguard Worker   return "Print Garbage Collector Information";
92*9880d681SAndroid Build Coastguard Worker }
93*9880d681SAndroid Build Coastguard Worker 
getAnalysisUsage(AnalysisUsage & AU) const94*9880d681SAndroid Build Coastguard Worker void Printer::getAnalysisUsage(AnalysisUsage &AU) const {
95*9880d681SAndroid Build Coastguard Worker   FunctionPass::getAnalysisUsage(AU);
96*9880d681SAndroid Build Coastguard Worker   AU.setPreservesAll();
97*9880d681SAndroid Build Coastguard Worker   AU.addRequired<GCModuleInfo>();
98*9880d681SAndroid Build Coastguard Worker }
99*9880d681SAndroid Build Coastguard Worker 
DescKind(GC::PointKind Kind)100*9880d681SAndroid Build Coastguard Worker static const char *DescKind(GC::PointKind Kind) {
101*9880d681SAndroid Build Coastguard Worker   switch (Kind) {
102*9880d681SAndroid Build Coastguard Worker   case GC::PreCall:
103*9880d681SAndroid Build Coastguard Worker     return "pre-call";
104*9880d681SAndroid Build Coastguard Worker   case GC::PostCall:
105*9880d681SAndroid Build Coastguard Worker     return "post-call";
106*9880d681SAndroid Build Coastguard Worker   }
107*9880d681SAndroid Build Coastguard Worker   llvm_unreachable("Invalid point kind");
108*9880d681SAndroid Build Coastguard Worker }
109*9880d681SAndroid Build Coastguard Worker 
runOnFunction(Function & F)110*9880d681SAndroid Build Coastguard Worker bool Printer::runOnFunction(Function &F) {
111*9880d681SAndroid Build Coastguard Worker   if (F.hasGC())
112*9880d681SAndroid Build Coastguard Worker     return false;
113*9880d681SAndroid Build Coastguard Worker 
114*9880d681SAndroid Build Coastguard Worker   GCFunctionInfo *FD = &getAnalysis<GCModuleInfo>().getFunctionInfo(F);
115*9880d681SAndroid Build Coastguard Worker 
116*9880d681SAndroid Build Coastguard Worker   OS << "GC roots for " << FD->getFunction().getName() << ":\n";
117*9880d681SAndroid Build Coastguard Worker   for (GCFunctionInfo::roots_iterator RI = FD->roots_begin(),
118*9880d681SAndroid Build Coastguard Worker                                       RE = FD->roots_end();
119*9880d681SAndroid Build Coastguard Worker        RI != RE; ++RI)
120*9880d681SAndroid Build Coastguard Worker     OS << "\t" << RI->Num << "\t" << RI->StackOffset << "[sp]\n";
121*9880d681SAndroid Build Coastguard Worker 
122*9880d681SAndroid Build Coastguard Worker   OS << "GC safe points for " << FD->getFunction().getName() << ":\n";
123*9880d681SAndroid Build Coastguard Worker   for (GCFunctionInfo::iterator PI = FD->begin(), PE = FD->end(); PI != PE;
124*9880d681SAndroid Build Coastguard Worker        ++PI) {
125*9880d681SAndroid Build Coastguard Worker 
126*9880d681SAndroid Build Coastguard Worker     OS << "\t" << PI->Label->getName() << ": " << DescKind(PI->Kind)
127*9880d681SAndroid Build Coastguard Worker        << ", live = {";
128*9880d681SAndroid Build Coastguard Worker 
129*9880d681SAndroid Build Coastguard Worker     for (GCFunctionInfo::live_iterator RI = FD->live_begin(PI),
130*9880d681SAndroid Build Coastguard Worker                                        RE = FD->live_end(PI);
131*9880d681SAndroid Build Coastguard Worker          ;) {
132*9880d681SAndroid Build Coastguard Worker       OS << " " << RI->Num;
133*9880d681SAndroid Build Coastguard Worker       if (++RI == RE)
134*9880d681SAndroid Build Coastguard Worker         break;
135*9880d681SAndroid Build Coastguard Worker       OS << ",";
136*9880d681SAndroid Build Coastguard Worker     }
137*9880d681SAndroid Build Coastguard Worker 
138*9880d681SAndroid Build Coastguard Worker     OS << " }\n";
139*9880d681SAndroid Build Coastguard Worker   }
140*9880d681SAndroid Build Coastguard Worker 
141*9880d681SAndroid Build Coastguard Worker   return false;
142*9880d681SAndroid Build Coastguard Worker }
143*9880d681SAndroid Build Coastguard Worker 
doFinalization(Module & M)144*9880d681SAndroid Build Coastguard Worker bool Printer::doFinalization(Module &M) {
145*9880d681SAndroid Build Coastguard Worker   GCModuleInfo *GMI = getAnalysisIfAvailable<GCModuleInfo>();
146*9880d681SAndroid Build Coastguard Worker   assert(GMI && "Printer didn't require GCModuleInfo?!");
147*9880d681SAndroid Build Coastguard Worker   GMI->clear();
148*9880d681SAndroid Build Coastguard Worker   return false;
149*9880d681SAndroid Build Coastguard Worker }
150*9880d681SAndroid Build Coastguard Worker 
getGCStrategy(const StringRef Name)151*9880d681SAndroid Build Coastguard Worker GCStrategy *GCModuleInfo::getGCStrategy(const StringRef Name) {
152*9880d681SAndroid Build Coastguard Worker   // TODO: Arguably, just doing a linear search would be faster for small N
153*9880d681SAndroid Build Coastguard Worker   auto NMI = GCStrategyMap.find(Name);
154*9880d681SAndroid Build Coastguard Worker   if (NMI != GCStrategyMap.end())
155*9880d681SAndroid Build Coastguard Worker     return NMI->getValue();
156*9880d681SAndroid Build Coastguard Worker 
157*9880d681SAndroid Build Coastguard Worker   for (auto& Entry : GCRegistry::entries()) {
158*9880d681SAndroid Build Coastguard Worker     if (Name == Entry.getName()) {
159*9880d681SAndroid Build Coastguard Worker       std::unique_ptr<GCStrategy> S = Entry.instantiate();
160*9880d681SAndroid Build Coastguard Worker       S->Name = Name;
161*9880d681SAndroid Build Coastguard Worker       GCStrategyMap[Name] = S.get();
162*9880d681SAndroid Build Coastguard Worker       GCStrategyList.push_back(std::move(S));
163*9880d681SAndroid Build Coastguard Worker       return GCStrategyList.back().get();
164*9880d681SAndroid Build Coastguard Worker     }
165*9880d681SAndroid Build Coastguard Worker   }
166*9880d681SAndroid Build Coastguard Worker 
167*9880d681SAndroid Build Coastguard Worker   if (GCRegistry::begin() == GCRegistry::end()) {
168*9880d681SAndroid Build Coastguard Worker     // In normal operation, the registry should not be empty.  There should
169*9880d681SAndroid Build Coastguard Worker     // be the builtin GCs if nothing else.  The most likely scenario here is
170*9880d681SAndroid Build Coastguard Worker     // that we got here without running the initializers used by the Registry
171*9880d681SAndroid Build Coastguard Worker     // itself and it's registration mechanism.
172*9880d681SAndroid Build Coastguard Worker     const std::string error = ("unsupported GC: " + Name).str() +
173*9880d681SAndroid Build Coastguard Worker       " (did you remember to link and initialize the CodeGen library?)";
174*9880d681SAndroid Build Coastguard Worker     report_fatal_error(error);
175*9880d681SAndroid Build Coastguard Worker   } else
176*9880d681SAndroid Build Coastguard Worker     report_fatal_error(std::string("unsupported GC: ") + Name);
177*9880d681SAndroid Build Coastguard Worker }
178