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