/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/CodeGen/GCMetadata.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- GCMetadata.h - Garbage collector metadata ----------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file declares the GCFunctionInfo and GCModuleInfo classes, which are |
10 | | // used as a communication channel from the target code generator to the target |
11 | | // garbage collectors. This interface allows code generators and garbage |
12 | | // collectors to be developed independently. |
13 | | // |
14 | | // The GCFunctionInfo class logs the data necessary to build a type accurate |
15 | | // stack map. The code generator outputs: |
16 | | // |
17 | | // - Safe points as specified by the GCStrategy's NeededSafePoints. |
18 | | // - Stack offsets for GC roots, as specified by calls to llvm.gcroot |
19 | | // |
20 | | // As a refinement, liveness analysis calculates the set of live roots at each |
21 | | // safe point. Liveness analysis is not presently performed by the code |
22 | | // generator, so all roots are assumed live. |
23 | | // |
24 | | // GCModuleInfo simply collects GCFunctionInfo instances for each Function as |
25 | | // they are compiled. This accretion is necessary for collectors which must emit |
26 | | // a stack map for the compilation unit as a whole. Therefore, GCFunctionInfo |
27 | | // outlives the MachineFunction from which it is derived and must not refer to |
28 | | // any code generator data structures. |
29 | | // |
30 | | //===----------------------------------------------------------------------===// |
31 | | |
32 | | #ifndef LLVM_CODEGEN_GCMETADATA_H |
33 | | #define LLVM_CODEGEN_GCMETADATA_H |
34 | | |
35 | | #include "llvm/ADT/DenseMap.h" |
36 | | #include "llvm/ADT/SmallVector.h" |
37 | | #include "llvm/ADT/StringMap.h" |
38 | | #include "llvm/ADT/StringRef.h" |
39 | | #include "llvm/CodeGen/GCStrategy.h" |
40 | | #include "llvm/IR/DebugLoc.h" |
41 | | #include "llvm/Pass.h" |
42 | | #include <algorithm> |
43 | | #include <cstddef> |
44 | | #include <cstdint> |
45 | | #include <memory> |
46 | | #include <vector> |
47 | | |
48 | | namespace llvm { |
49 | | |
50 | | class Constant; |
51 | | class Function; |
52 | | class MCSymbol; |
53 | | |
54 | | /// GCPoint - Metadata for a collector-safe point in machine code. |
55 | | /// |
56 | | struct GCPoint { |
57 | | MCSymbol *Label; ///< A label. |
58 | | DebugLoc Loc; |
59 | | |
60 | | GCPoint(MCSymbol *L, DebugLoc DL) |
61 | 4 | : Label(L), Loc(std::move(DL)) {} |
62 | | }; |
63 | | |
64 | | /// GCRoot - Metadata for a pointer to an object managed by the garbage |
65 | | /// collector. |
66 | | struct GCRoot { |
67 | | int Num; ///< Usually a frame index. |
68 | | int StackOffset = -1; ///< Offset from the stack pointer. |
69 | | const Constant *Metadata; ///< Metadata straight from the call |
70 | | ///< to llvm.gcroot. |
71 | | |
72 | 2 | GCRoot(int N, const Constant *MD) : Num(N), Metadata(MD) {} |
73 | | }; |
74 | | |
75 | | /// Garbage collection metadata for a single function. Currently, this |
76 | | /// information only applies to GCStrategies which use GCRoot. |
77 | | class GCFunctionInfo { |
78 | | public: |
79 | | using iterator = std::vector<GCPoint>::iterator; |
80 | | using roots_iterator = std::vector<GCRoot>::iterator; |
81 | | using live_iterator = std::vector<GCRoot>::const_iterator; |
82 | | |
83 | | private: |
84 | | const Function &F; |
85 | | GCStrategy &S; |
86 | | uint64_t FrameSize; |
87 | | std::vector<GCRoot> Roots; |
88 | | std::vector<GCPoint> SafePoints; |
89 | | |
90 | | // FIXME: Liveness. A 2D BitVector, perhaps? |
91 | | // |
92 | | // BitVector Liveness; |
93 | | // |
94 | | // bool islive(int point, int root) = |
95 | | // Liveness[point * SafePoints.size() + root] |
96 | | // |
97 | | // The bit vector is the more compact representation where >3.2% of roots |
98 | | // are live per safe point (1.5% on 64-bit hosts). |
99 | | |
100 | | public: |
101 | | GCFunctionInfo(const Function &F, GCStrategy &S); |
102 | | ~GCFunctionInfo(); |
103 | | |
104 | | /// getFunction - Return the function to which this metadata applies. |
105 | 6 | const Function &getFunction() const { return F; } |
106 | | |
107 | | /// getStrategy - Return the GC strategy for the function. |
108 | 171 | GCStrategy &getStrategy() { return S; } |
109 | | |
110 | | /// addStackRoot - Registers a root that lives on the stack. Num is the |
111 | | /// stack object ID for the alloca (if the code generator is |
112 | | // using MachineFrameInfo). |
113 | 2 | void addStackRoot(int Num, const Constant *Metadata) { |
114 | 2 | Roots.push_back(GCRoot(Num, Metadata)); |
115 | 2 | } |
116 | | |
117 | | /// removeStackRoot - Removes a root. |
118 | 0 | roots_iterator removeStackRoot(roots_iterator position) { |
119 | 0 | return Roots.erase(position); |
120 | 0 | } |
121 | | |
122 | | /// addSafePoint - Notes the existence of a safe point. Num is the ID of the |
123 | | /// label just prior to the safe point (if the code generator is using |
124 | | /// MachineModuleInfo). |
125 | 4 | void addSafePoint(MCSymbol *Label, const DebugLoc &DL) { |
126 | 4 | SafePoints.emplace_back(Label, DL); |
127 | 4 | } |
128 | | |
129 | | /// getFrameSize/setFrameSize - Records the function's frame size. |
130 | 6 | uint64_t getFrameSize() const { return FrameSize; } |
131 | 81 | void setFrameSize(uint64_t S) { FrameSize = S; } |
132 | | |
133 | | /// begin/end - Iterators for safe points. |
134 | 12 | iterator begin() { return SafePoints.begin(); } |
135 | 9 | iterator end() { return SafePoints.end(); } |
136 | 3 | size_t size() const { return SafePoints.size(); } |
137 | | |
138 | | /// roots_begin/roots_end - Iterators for all roots in the function. |
139 | 85 | roots_iterator roots_begin() { return Roots.begin(); } |
140 | 87 | roots_iterator roots_end() { return Roots.end(); } |
141 | 4 | size_t roots_size() const { return Roots.size(); } |
142 | | |
143 | | /// live_begin/live_end - Iterators for live roots at a given safe point. |
144 | 4 | live_iterator live_begin(const iterator &p) { return roots_begin(); } |
145 | 4 | live_iterator live_end(const iterator &p) { return roots_end(); } |
146 | 4 | size_t live_size(const iterator &p) const { return roots_size(); } |
147 | | }; |
148 | | |
149 | | /// An analysis pass which caches information about the entire Module. |
150 | | /// Records both the function level information used by GCRoots and a |
151 | | /// cache of the 'active' gc strategy objects for the current Module. |
152 | | class GCModuleInfo : public ImmutablePass { |
153 | | /// An owning list of all GCStrategies which have been created |
154 | | SmallVector<std::unique_ptr<GCStrategy>, 1> GCStrategyList; |
155 | | /// A helper map to speedup lookups into the above list |
156 | | StringMap<GCStrategy*> GCStrategyMap; |
157 | | |
158 | | public: |
159 | | /// Lookup the GCStrategy object associated with the given gc name. |
160 | | /// Objects are owned internally; No caller should attempt to delete the |
161 | | /// returned objects. |
162 | | GCStrategy *getGCStrategy(const StringRef Name); |
163 | | |
164 | | /// List of per function info objects. In theory, Each of these |
165 | | /// may be associated with a different GC. |
166 | | using FuncInfoVec = std::vector<std::unique_ptr<GCFunctionInfo>>; |
167 | | |
168 | 9 | FuncInfoVec::iterator funcinfo_begin() { return Functions.begin(); } |
169 | 9 | FuncInfoVec::iterator funcinfo_end() { return Functions.end(); } |
170 | | |
171 | | private: |
172 | | /// Owning list of all GCFunctionInfos associated with this Module |
173 | | FuncInfoVec Functions; |
174 | | |
175 | | /// Non-owning map to bypass linear search when finding the GCFunctionInfo |
176 | | /// associated with a particular Function. |
177 | | using finfo_map_type = DenseMap<const Function *, GCFunctionInfo *>; |
178 | | finfo_map_type FInfoMap; |
179 | | |
180 | | public: |
181 | | using iterator = SmallVector<std::unique_ptr<GCStrategy>, 1>::const_iterator; |
182 | | |
183 | | static char ID; |
184 | | |
185 | | GCModuleInfo(); |
186 | | |
187 | | /// clear - Resets the pass. Any pass, which uses GCModuleInfo, should |
188 | | /// call it in doFinalization(). |
189 | | /// |
190 | | void clear(); |
191 | | |
192 | | /// begin/end - Iterators for used strategies. |
193 | | /// |
194 | 94.3k | iterator begin() const { return GCStrategyList.begin(); } |
195 | 94.3k | iterator end() const { return GCStrategyList.end(); } |
196 | | |
197 | | /// get - Look up function metadata. This is currently assumed |
198 | | /// have the side effect of initializing the associated GCStrategy. That |
199 | | /// will soon change. |
200 | | GCFunctionInfo &getFunctionInfo(const Function &F); |
201 | | }; |
202 | | |
203 | | } // end namespace llvm |
204 | | |
205 | | #endif // LLVM_CODEGEN_GCMETADATA_H |