1321369Sdim//===- GCMetadata.h - Garbage collector metadata ----------------*- C++ -*-===//
2193323Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193323Sed//
7193323Sed//===----------------------------------------------------------------------===//
8193323Sed//
9193323Sed// This file declares the GCFunctionInfo and GCModuleInfo classes, which are
10193323Sed// used as a communication channel from the target code generator to the target
11193323Sed// garbage collectors. This interface allows code generators and garbage
12193323Sed// collectors to be developed independently.
13193323Sed//
14193323Sed// The GCFunctionInfo class logs the data necessary to build a type accurate
15193323Sed// stack map. The code generator outputs:
16210299Sed//
17193323Sed//   - Safe points as specified by the GCStrategy's NeededSafePoints.
18193323Sed//   - Stack offsets for GC roots, as specified by calls to llvm.gcroot
19193323Sed//
20193323Sed// As a refinement, liveness analysis calculates the set of live roots at each
21193323Sed// safe point. Liveness analysis is not presently performed by the code
22193323Sed// generator, so all roots are assumed live.
23193323Sed//
24193323Sed// GCModuleInfo simply collects GCFunctionInfo instances for each Function as
25193323Sed// they are compiled. This accretion is necessary for collectors which must emit
26193323Sed// a stack map for the compilation unit as a whole. Therefore, GCFunctionInfo
27193323Sed// outlives the MachineFunction from which it is derived and must not refer to
28193323Sed// any code generator data structures.
29193323Sed//
30193323Sed//===----------------------------------------------------------------------===//
31193323Sed
32193323Sed#ifndef LLVM_CODEGEN_GCMETADATA_H
33193323Sed#define LLVM_CODEGEN_GCMETADATA_H
34193323Sed
35193323Sed#include "llvm/ADT/DenseMap.h"
36288943Sdim#include "llvm/ADT/SmallVector.h"
37193323Sed#include "llvm/ADT/StringMap.h"
38321369Sdim#include "llvm/ADT/StringRef.h"
39288943Sdim#include "llvm/CodeGen/GCStrategy.h"
40276479Sdim#include "llvm/IR/DebugLoc.h"
41249423Sdim#include "llvm/Pass.h"
42321369Sdim#include <algorithm>
43321369Sdim#include <cstddef>
44321369Sdim#include <cstdint>
45276479Sdim#include <memory>
46321369Sdim#include <vector>
47276479Sdim
48193323Sednamespace llvm {
49321369Sdim
50288943Sdimclass Constant;
51321369Sdimclass Function;
52288943Sdimclass MCSymbol;
53210299Sed
54288943Sdim/// GCPoint - Metadata for a collector-safe point in machine code.
55288943Sdim///
56288943Sdimstruct GCPoint {
57288943Sdim  MCSymbol *Label;    ///< A label.
58288943Sdim  DebugLoc Loc;
59210299Sed
60344779Sdim  GCPoint(MCSymbol *L, DebugLoc DL)
61344779Sdim      : Label(L), Loc(std::move(DL)) {}
62288943Sdim};
63210299Sed
64288943Sdim/// GCRoot - Metadata for a pointer to an object managed by the garbage
65288943Sdim/// collector.
66288943Sdimstruct GCRoot {
67288943Sdim  int Num;                  ///< Usually a frame index.
68321369Sdim  int StackOffset = -1;     ///< Offset from the stack pointer.
69288943Sdim  const Constant *Metadata; ///< Metadata straight from the call
70288943Sdim                            ///< to llvm.gcroot.
71210299Sed
72321369Sdim  GCRoot(int N, const Constant *MD) : Num(N), Metadata(MD) {}
73288943Sdim};
74210299Sed
75288943Sdim/// Garbage collection metadata for a single function.  Currently, this
76288943Sdim/// information only applies to GCStrategies which use GCRoot.
77288943Sdimclass GCFunctionInfo {
78288943Sdimpublic:
79321369Sdim  using iterator = std::vector<GCPoint>::iterator;
80321369Sdim  using roots_iterator = std::vector<GCRoot>::iterator;
81321369Sdim  using live_iterator = std::vector<GCRoot>::const_iterator;
82210299Sed
83288943Sdimprivate:
84288943Sdim  const Function &F;
85288943Sdim  GCStrategy &S;
86288943Sdim  uint64_t FrameSize;
87288943Sdim  std::vector<GCRoot> Roots;
88288943Sdim  std::vector<GCPoint> SafePoints;
89210299Sed
90288943Sdim  // FIXME: Liveness. A 2D BitVector, perhaps?
91288943Sdim  //
92288943Sdim  //   BitVector Liveness;
93288943Sdim  //
94288943Sdim  //   bool islive(int point, int root) =
95288943Sdim  //     Liveness[point * SafePoints.size() + root]
96288943Sdim  //
97288943Sdim  // The bit vector is the more compact representation where >3.2% of roots
98288943Sdim  // are live per safe point (1.5% on 64-bit hosts).
99210299Sed
100288943Sdimpublic:
101288943Sdim  GCFunctionInfo(const Function &F, GCStrategy &S);
102288943Sdim  ~GCFunctionInfo();
103210299Sed
104288943Sdim  /// getFunction - Return the function to which this metadata applies.
105288943Sdim  const Function &getFunction() const { return F; }
106210299Sed
107288943Sdim  /// getStrategy - Return the GC strategy for the function.
108288943Sdim  GCStrategy &getStrategy() { return S; }
109210299Sed
110288943Sdim  /// addStackRoot - Registers a root that lives on the stack. Num is the
111288943Sdim  ///                stack object ID for the alloca (if the code generator is
112288943Sdim  //                 using  MachineFrameInfo).
113288943Sdim  void addStackRoot(int Num, const Constant *Metadata) {
114288943Sdim    Roots.push_back(GCRoot(Num, Metadata));
115288943Sdim  }
116210299Sed
117288943Sdim  /// removeStackRoot - Removes a root.
118288943Sdim  roots_iterator removeStackRoot(roots_iterator position) {
119288943Sdim    return Roots.erase(position);
120288943Sdim  }
121210299Sed
122288943Sdim  /// addSafePoint - Notes the existence of a safe point. Num is the ID of the
123288943Sdim  /// label just prior to the safe point (if the code generator is using
124288943Sdim  /// MachineModuleInfo).
125344779Sdim  void addSafePoint(MCSymbol *Label, const DebugLoc &DL) {
126344779Sdim    SafePoints.emplace_back(Label, DL);
127288943Sdim  }
128210299Sed
129288943Sdim  /// getFrameSize/setFrameSize - Records the function's frame size.
130288943Sdim  uint64_t getFrameSize() const { return FrameSize; }
131288943Sdim  void setFrameSize(uint64_t S) { FrameSize = S; }
132243830Sdim
133288943Sdim  /// begin/end - Iterators for safe points.
134288943Sdim  iterator begin() { return SafePoints.begin(); }
135288943Sdim  iterator end() { return SafePoints.end(); }
136288943Sdim  size_t size() const { return SafePoints.size(); }
137210299Sed
138288943Sdim  /// roots_begin/roots_end - Iterators for all roots in the function.
139288943Sdim  roots_iterator roots_begin() { return Roots.begin(); }
140288943Sdim  roots_iterator roots_end() { return Roots.end(); }
141288943Sdim  size_t roots_size() const { return Roots.size(); }
142210299Sed
143288943Sdim  /// live_begin/live_end - Iterators for live roots at a given safe point.
144288943Sdim  live_iterator live_begin(const iterator &p) { return roots_begin(); }
145288943Sdim  live_iterator live_end(const iterator &p) { return roots_end(); }
146288943Sdim  size_t live_size(const iterator &p) const { return roots_size(); }
147288943Sdim};
148210299Sed
149288943Sdim/// An analysis pass which caches information about the entire Module.
150288943Sdim/// Records both the function level information used by GCRoots and a
151288943Sdim/// cache of the 'active' gc strategy objects for the current Module.
152288943Sdimclass GCModuleInfo : public ImmutablePass {
153288943Sdim  /// An owning list of all GCStrategies which have been created
154288943Sdim  SmallVector<std::unique_ptr<GCStrategy>, 1> GCStrategyList;
155288943Sdim  /// A helper map to speedup lookups into the above list
156288943Sdim  StringMap<GCStrategy*> GCStrategyMap;
157210299Sed
158288943Sdimpublic:
159288943Sdim  /// Lookup the GCStrategy object associated with the given gc name.
160288943Sdim  /// Objects are owned internally; No caller should attempt to delete the
161296417Sdim  /// returned objects.
162288943Sdim  GCStrategy *getGCStrategy(const StringRef Name);
163296417Sdim
164288943Sdim  /// List of per function info objects.  In theory, Each of these
165288943Sdim  /// may be associated with a different GC.
166321369Sdim  using FuncInfoVec = std::vector<std::unique_ptr<GCFunctionInfo>>;
167210299Sed
168288943Sdim  FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); }
169288943Sdim  FuncInfoVec::iterator funcinfo_end() { return Functions.end(); }
170210299Sed
171288943Sdimprivate:
172288943Sdim  /// Owning list of all GCFunctionInfos associated with this Module
173288943Sdim  FuncInfoVec Functions;
174210299Sed
175288943Sdim  /// Non-owning map to bypass linear search when finding the GCFunctionInfo
176288943Sdim  /// associated with a particular Function.
177321369Sdim  using finfo_map_type = DenseMap<const Function *, GCFunctionInfo *>;
178288943Sdim  finfo_map_type FInfoMap;
179210299Sed
180288943Sdimpublic:
181321369Sdim  using iterator = SmallVector<std::unique_ptr<GCStrategy>, 1>::const_iterator;
182280031Sdim
183288943Sdim  static char ID;
184280031Sdim
185288943Sdim  GCModuleInfo();
186280031Sdim
187288943Sdim  /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should
188288943Sdim  /// call it in doFinalization().
189288943Sdim  ///
190288943Sdim  void clear();
191280031Sdim
192288943Sdim  /// begin/end - Iterators for used strategies.
193288943Sdim  ///
194288943Sdim  iterator begin() const { return GCStrategyList.begin(); }
195288943Sdim  iterator end() const { return GCStrategyList.end(); }
196210299Sed
197288943Sdim  /// get - Look up function metadata.  This is currently assumed
198288943Sdim  /// have the side effect of initializing the associated GCStrategy.  That
199288943Sdim  /// will soon change.
200288943Sdim  GCFunctionInfo &getFunctionInfo(const Function &F);
201288943Sdim};
202193323Sed
203321369Sdim} // end namespace llvm
204321369Sdim
205321369Sdim#endif // LLVM_CODEGEN_GCMETADATA_H
206