15eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen//===-- GCMetadata.cpp - Garbage collector metadata -----------------------===//
2fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen//
3fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen//                     The LLVM Compiler Infrastructure
4fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen//
8fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen//===----------------------------------------------------------------------===//
9fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen//
105eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen// This file implements the GCFunctionInfo class and GCModuleInfo pass.
11fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen//
12fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen//===----------------------------------------------------------------------===//
13fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
145a29c9eed157af51a8d338b5a225b146881819e8Gordon Henriksen#include "llvm/CodeGen/GCMetadata.h"
155a29c9eed157af51a8d338b5a225b146881819e8Gordon Henriksen#include "llvm/CodeGen/GCStrategy.h"
16fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen#include "llvm/CodeGen/MachineFrameInfo.h"
17ad93c4f936d220570535711262e0fff8857f798aGordon Henriksen#include "llvm/CodeGen/Passes.h"
180b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth#include "llvm/IR/Function.h"
19aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner#include "llvm/MC/MCSymbol.h"
20d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Pass.h"
21aba28d1273f7332a6a8c335e99dd5a68af748d4fDavid Greene#include "llvm/Support/Debug.h"
227d696d80409aad20bb5da0fc4eccab941dd371d4Torok Edwin#include "llvm/Support/ErrorHandling.h"
23cf143a4d917699f8f4202f331fa9e184070471fbChris Lattner#include "llvm/Support/raw_ostream.h"
24fc3282221f90c626d80292327213e2badc3de86bGordon Henriksenusing namespace llvm;
25fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
26fc3282221f90c626d80292327213e2badc3de86bGordon Henriksennamespace {
27fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
286726b6d75a8b679068a58cb954ba97cf9d1690baNick Lewycky  class Printer : public FunctionPass {
29fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen    static char ID;
30cf143a4d917699f8f4202f331fa9e184070471fbChris Lattner    raw_ostream &OS;
31fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
32fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen  public:
3390c579de5a383cee278acc3f7e7b9d0a656e6a35Owen Anderson    explicit Printer(raw_ostream &OS) : FunctionPass(ID), OS(OS) {}
34cf143a4d917699f8f4202f331fa9e184070471fbChris Lattner
3536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
3636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const char *getPassName() const override;
3736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    void getAnalysisUsage(AnalysisUsage &AU) const override;
3836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
3936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool runOnFunction(Function &F) override;
4036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool doFinalization(Module &M) override;
41fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen  };
42063337309e71683fc57c049c10d03d4f8a2ce356Benjamin Kramer
43fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen}
44fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
45d13db2c59cc94162d6cf0a04187d408bfef6d4a7Owen AndersonINITIALIZE_PASS(GCModuleInfo, "collector-metadata",
46ce665bd2e2b581ab0858d1afe359192bac96b868Owen Anderson                "Create Garbage Collector Module Metadata", false, false)
47844731a7f1909f55935e3514c9e713a62d67662eDan Gohman
48fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen// -----------------------------------------------------------------------------
49fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
505eca075b74d62c621b160aa216b4cd50829a2cc7Gordon HenriksenGCFunctionInfo::GCFunctionInfo(const Function &F, GCStrategy &S)
515eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  : F(F), S(S), FrameSize(~0LL) {}
52fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
535eca075b74d62c621b160aa216b4cd50829a2cc7Gordon HenriksenGCFunctionInfo::~GCFunctionInfo() {}
54fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
55fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen// -----------------------------------------------------------------------------
56fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
575eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksenchar GCModuleInfo::ID = 0;
58fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
595eca075b74d62c621b160aa216b4cd50829a2cc7Gordon HenriksenGCModuleInfo::GCModuleInfo()
60081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson    : ImmutablePass(ID) {
61081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson  initializeGCModuleInfoPass(*PassRegistry::getPassRegistry());
62081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson}
63fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
645eca075b74d62c621b160aa216b4cd50829a2cc7Gordon HenriksenGCStrategy *GCModuleInfo::getOrCreateStrategy(const Module *M,
655eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen                                              const std::string &Name) {
666316fbcb04af00fe76b6526fab09f51484014b3eDaniel Dunbar  strategy_map_type::iterator NMI = StrategyMap.find(Name);
675eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  if (NMI != StrategyMap.end())
68ad93c4f936d220570535711262e0fff8857f798aGordon Henriksen    return NMI->getValue();
69ad93c4f936d220570535711262e0fff8857f798aGordon Henriksen
705eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  for (GCRegistry::iterator I = GCRegistry::begin(),
715eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen                            E = GCRegistry::end(); I != E; ++I) {
726316fbcb04af00fe76b6526fab09f51484014b3eDaniel Dunbar    if (Name == I->getName()) {
73dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      std::unique_ptr<GCStrategy> S = I->instantiate();
745eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen      S->M = M;
755eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen      S->Name = Name;
76dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      StrategyMap.GetOrCreateValue(Name).setValue(S.get());
77dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      StrategyList.push_back(std::move(S));
78dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      return StrategyList.back().get();
79ad93c4f936d220570535711262e0fff8857f798aGordon Henriksen    }
80ad93c4f936d220570535711262e0fff8857f798aGordon Henriksen  }
817d696d80409aad20bb5da0fc4eccab941dd371d4Torok Edwin
82aba28d1273f7332a6a8c335e99dd5a68af748d4fDavid Greene  dbgs() << "unsupported GC: " << Name << "\n";
83dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  llvm_unreachable(nullptr);
84fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen}
85fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
865eca075b74d62c621b160aa216b4cd50829a2cc7Gordon HenriksenGCFunctionInfo &GCModuleInfo::getFunctionInfo(const Function &F) {
87418b6e875f844261064c5dd43e76cb401117ac74Gordon Henriksen  assert(!F.isDeclaration() && "Can only get GCFunctionInfo for a definition!");
885eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  assert(F.hasGC());
89418b6e875f844261064c5dd43e76cb401117ac74Gordon Henriksen
905eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  finfo_map_type::iterator I = FInfoMap.find(&F);
915eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  if (I != FInfoMap.end())
92ad93c4f936d220570535711262e0fff8857f798aGordon Henriksen    return *I->second;
935eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen
945eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  GCStrategy *S = getOrCreateStrategy(F.getParent(), F.getGC());
955eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  GCFunctionInfo *GFI = S->insertFunctionInfo(F);
965eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  FInfoMap[&F] = GFI;
975eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  return *GFI;
98fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen}
99fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
1005eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksenvoid GCModuleInfo::clear() {
1015eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  FInfoMap.clear();
1025eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  StrategyMap.clear();
1035eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  StrategyList.clear();
104fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen}
105fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
106fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen// -----------------------------------------------------------------------------
107fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
108fc3282221f90c626d80292327213e2badc3de86bGordon Henriksenchar Printer::ID = 0;
109fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
110cf143a4d917699f8f4202f331fa9e184070471fbChris LattnerFunctionPass *llvm::createGCInfoPrinter(raw_ostream &OS) {
111fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen  return new Printer(OS);
112fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen}
113fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
114fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
115fc3282221f90c626d80292327213e2badc3de86bGordon Henriksenconst char *Printer::getPassName() const {
116fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen  return "Print Garbage Collector Information";
117fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen}
118fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
119fc3282221f90c626d80292327213e2badc3de86bGordon Henriksenvoid Printer::getAnalysisUsage(AnalysisUsage &AU) const {
120ad93c4f936d220570535711262e0fff8857f798aGordon Henriksen  FunctionPass::getAnalysisUsage(AU);
121fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen  AU.setPreservesAll();
1225eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  AU.addRequired<GCModuleInfo>();
123fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen}
124fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
125fc3282221f90c626d80292327213e2badc3de86bGordon Henriksenstatic const char *DescKind(GC::PointKind Kind) {
126fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen  switch (Kind) {
127fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen    case GC::Loop:     return "loop";
128fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen    case GC::Return:   return "return";
129fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen    case GC::PreCall:  return "pre-call";
130fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen    case GC::PostCall: return "post-call";
131fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen  }
132732f05c41f177a0bc4d47e93a5d02120f146cb4cChandler Carruth  llvm_unreachable("Invalid point kind");
133fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen}
134fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
135ad93c4f936d220570535711262e0fff8857f798aGordon Henriksenbool Printer::runOnFunction(Function &F) {
136aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner  if (F.hasGC()) return false;
137aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner
138aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner  GCFunctionInfo *FD = &getAnalysis<GCModuleInfo>().getFunctionInfo(F);
139aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner
140a7b0cb759433c715065440ee2a963a04db7f2b0bBenjamin Kramer  OS << "GC roots for " << FD->getFunction().getName() << ":\n";
141aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner  for (GCFunctionInfo::roots_iterator RI = FD->roots_begin(),
142aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner                                      RE = FD->roots_end(); RI != RE; ++RI)
143aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner    OS << "\t" << RI->Num << "\t" << RI->StackOffset << "[sp]\n";
144aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner
145a7b0cb759433c715065440ee2a963a04db7f2b0bBenjamin Kramer  OS << "GC safe points for " << FD->getFunction().getName() << ":\n";
146aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner  for (GCFunctionInfo::iterator PI = FD->begin(),
147aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner                                PE = FD->end(); PI != PE; ++PI) {
148fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
149aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner    OS << "\t" << PI->Label->getName() << ": "
150aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner       << DescKind(PI->Kind) << ", live = {";
151fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
152aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner    for (GCFunctionInfo::live_iterator RI = FD->live_begin(PI),
153aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner                                       RE = FD->live_end(PI);;) {
154aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner      OS << " " << RI->Num;
155aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner      if (++RI == RE)
156aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner        break;
157aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner      OS << ",";
158fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen    }
159aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner
160aba9bcb9b60edbad3646b2f3088c120d06549cc7Chris Lattner    OS << " }\n";
161fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen  }
162fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
163fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen  return false;
164fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen}
165fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen
166063337309e71683fc57c049c10d03d4f8a2ce356Benjamin Kramerbool Printer::doFinalization(Module &M) {
1671465d61bdd36cfd6021036a527895f0dd358e97dDuncan Sands  GCModuleInfo *GMI = getAnalysisIfAvailable<GCModuleInfo>();
168063337309e71683fc57c049c10d03d4f8a2ce356Benjamin Kramer  assert(GMI && "Printer didn't require GCModuleInfo?!");
1695eca075b74d62c621b160aa216b4cd50829a2cc7Gordon Henriksen  GMI->clear();
170fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen  return false;
171fc3282221f90c626d80292327213e2badc3de86bGordon Henriksen}
172