llvm.org GIT mirror llvm / 983ff6b
[llvm-pdbutil] Add -type-ref-stats to help find unused type info Summary: This considers module symbol streams and the global symbol stream to be roots. Most types that this considers "unreferenced" are referenced by LF_UDT_MOD_SRC_LINE id records, which VC seems to always include. Essentially, they are types that the user can only find in the debugger if they call them by name, they cannot be found by traversing a symbol. In practice, around 80% of type information in a PDB is referenced by a symbol. That seems like a reasonable number. I don't really plan to do anything with this tool. It mostly just exists for informational purposes, and to confirm that we probably don't need to implement type reference tracking in LLD. We can continue to merge all types as we do today without wasting space. Reviewers: zturner, aganea Subscribers: mgorny, hiraditya, arphaman, jdoerfert, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D59620 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@356692 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 5 months ago
11 changed file(s) with 899 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
362362 // values. One idea is to define some structures representing these types
363363 // that would allow the use of offsetof().
364364 switch (Kind) {
365 case SymbolKind::S_GPROC32:
366 case SymbolKind::S_LPROC32:
367365 case SymbolKind::S_GPROC32_ID:
368366 case SymbolKind::S_LPROC32_ID:
369367 case SymbolKind::S_LPROC32_DPC:
370368 case SymbolKind::S_LPROC32_DPC_ID:
371369 Refs.push_back({TiRefKind::IndexRef, 24, 1}); // LF_FUNC_ID
370 break;
371 case SymbolKind::S_GPROC32:
372 case SymbolKind::S_LPROC32:
373 Refs.push_back({TiRefKind::TypeRef, 24, 1}); // Type
372374 break;
373375 case SymbolKind::S_UDT:
374376 Refs.push_back({TiRefKind::TypeRef, 0, 1}); // UDT
0 RUN: llvm-pdbutil dump -types -type-ref-stats %p/Inputs/every-class.pdb \
1 RUN: | FileCheck %s
2
3 CHECK: Types (TPI Stream)
4 CHECK: ============================================================
5 CHECK: Showing 157 records
6 CHECK: 0x1000 | LF_ARGLIST [size = 16, referenced]
7 CHECK: 0x0603 (void*): `void*`
8 CHECK: 0x0023 (unsigned __int64): `unsigned __int64`
9 CHECK: 0x1001 | LF_PROCEDURE [size = 16, referenced]
10 CHECK: return type = 0x0003 (void), # args = 2, param list = 0x1000
11 CHECK: calling conv = cdecl, options = None
12 CHECK: 0x1002 | LF_ARGLIST [size = 16, referenced]
13 CHECK: 0x0603 (void*): `void*`
14 CHECK: 0x0075 (unsigned): `unsigned`
15 CHECK: 0x1003 | LF_PROCEDURE [size = 16, referenced]
16 CHECK: return type = 0x0003 (void), # args = 2, param list = 0x1002
17 CHECK: calling conv = cdecl, options = None
18 CHECK: 0x1004 | LF_POINTER [size = 12, referenced]
19 CHECK: referent = 0x0670 (char*), mode = pointer, opts = None, kind = ptr64
20 CHECK: 0x1005 | LF_ARGLIST [size = 16, referenced]
21 CHECK: 0x0074 (int): `int`
22 CHECK: 0x1004: `char**`
23 CHECK: 0x1006 | LF_PROCEDURE [size = 16, referenced]
24 CHECK: return type = 0x0074 (int), # args = 2, param list = 0x1005
25 CHECK: calling conv = cdecl, options = None
26 CHECK: 0x1007 | LF_FIELDLIST [size = 4, referenced]
27 CHECK: 0x1008 | LF_STRUCTURE [size = 124, referenced] `main::__l2::`
28 CHECK: unique name: `.?AU@?1??main@@YAHHPEAPEAD@Z@`aa6523bc`
29 CHECK: vtable: , base list: , field list: 0x1007
30 CHECK: options: has unique name | scoped, sizeof 1
31 CHECK: 0x1009 | LF_STRUCTURE [size = 88, referenced] `main::__l2::Scoped`
32 CHECK: unique name: `.?AUScoped@?1??main@@YAHHPEAPEAD@Z@`aa6523bc`
33 CHECK: vtable: , base list: , field list: 0x1007
34 CHECK: options: has unique name | scoped, sizeof 1
35 CHECK: 0x100A | LF_FIELDLIST [size = 48, unreferenced]
36 CHECK: - LF_ENUMERATE [native = 0]
37 CHECK: - LF_ENUMERATE [com = 1]
38 CHECK: - LF_ENUMERATE [managed = 2]
39 CHECK: 0x100B | LF_ENUM [size = 116, unreferenced] `__vc_attributes::event_sourceAttribute::type_e`
40 CHECK: unique name: `.?AW4type_e@event_sourceAttribute@__vc_attributes@@`
41 CHECK: field list: 0x100A, underlying type: 0x0074 (int)
42 CHECK: options: has unique name | is nested
43 CHECK: 0x100C | LF_FIELDLIST [size = 28, unreferenced]
44 CHECK: - LF_ENUMERATE [speed = 0]
45 CHECK: - LF_ENUMERATE [size = 1]
46 CHECK: 0x100D | LF_ENUM [size = 124, unreferenced] `__vc_attributes::event_sourceAttribute::optimize_e`
47 CHECK: unique name: `.?AW4optimize_e@event_sourceAttribute@__vc_attributes@@`
48 CHECK: field list: 0x100C, underlying type: 0x0074 (int)
49 CHECK: options: has unique name | is nested
50 CHECK: 0x100E | LF_STRUCTURE [size = 108, unreferenced] `__vc_attributes::event_sourceAttribute`
51 CHECK: unique name: `.?AUevent_sourceAttribute@__vc_attributes@@`
52 CHECK: vtable: , base list: , field list:
53 CHECK: options: forward ref (-> 0x1016) | has unique name, sizeof 0
54 CHECK: 0x100F | LF_POINTER [size = 12, unreferenced]
55 CHECK: referent = 0x100E, mode = pointer, opts = const, kind = ptr64
56 CHECK: 0x1010 | LF_ARGLIST [size = 12, unreferenced]
57 CHECK: 0x100B: `__vc_attributes::event_sourceAttribute::type_e`
58 CHECK: 0x1011 | LF_MFUNCTION [size = 28, unreferenced]
59 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1010
60 CHECK: class type = 0x100E, this type = 0x100F, this adjust = 0
61 CHECK: calling conv = cdecl, options = constructor
62 CHECK: 0x1012 | LF_ARGLIST [size = 8, referenced]
63 CHECK: 0x1013 | LF_MFUNCTION [size = 28, unreferenced]
64 CHECK: return type = 0x0003 (void), # args = 0, param list = 0x1012
65 CHECK: class type = 0x100E, this type = 0x100F, this adjust = 0
66 CHECK: calling conv = cdecl, options = constructor
67 CHECK: 0x1014 | LF_METHODLIST [size = 20, unreferenced]
68 CHECK: - Method [type = 0x1011, vftable offset = -1, attrs = public]
69 CHECK: - Method [type = 0x1013, vftable offset = -1, attrs = public]
70 CHECK: 0x1015 | LF_FIELDLIST [size = 128, unreferenced]
71 CHECK: - LF_NESTTYPE [name = `type_e`, parent = 0x100B]
72 CHECK: - LF_NESTTYPE [name = `optimize_e`, parent = 0x100D]
73 CHECK: - LF_METHOD [name = `event_sourceAttribute`, # overloads = 2, overload list = 0x1014]
74 CHECK: - LF_MEMBER [name = `type`, Type = 0x100B, offset = 0, attrs = public]
75 CHECK: - LF_MEMBER [name = `optimize`, Type = 0x100D, offset = 4, attrs = public]
76 CHECK: - LF_MEMBER [name = `decorate`, Type = 0x0030 (bool), offset = 8, attrs = public]
77 CHECK: 0x1016 | LF_STRUCTURE [size = 108, unreferenced] `__vc_attributes::event_sourceAttribute`
78 CHECK: unique name: `.?AUevent_sourceAttribute@__vc_attributes@@`
79 CHECK: vtable: , base list: , field list: 0x1015
80 CHECK: options: has ctor / dtor | contains nested class | has unique name, sizeof 12
81 CHECK: 0x1017 | LF_FIELDLIST [size = 68, unreferenced]
82 CHECK: - LF_ENUMERATE [eBoolean = 0]
83 CHECK: - LF_ENUMERATE [eInteger = 1]
84 CHECK: - LF_ENUMERATE [eFloat = 2]
85 CHECK: - LF_ENUMERATE [eDouble = 3]
86 CHECK: 0x1018 | LF_ENUM [size = 148, unreferenced] `__vc_attributes::helper_attributes::v1_alttypeAttribute::type_e`
87 CHECK: unique name: `.?AW4type_e@v1_alttypeAttribute@helper_attributes@__vc_attributes@@`
88 CHECK: field list: 0x1017, underlying type: 0x0074 (int)
89 CHECK: options: has unique name | is nested
90 CHECK: 0x1019 | LF_STRUCTURE [size = 140, unreferenced] `__vc_attributes::helper_attributes::v1_alttypeAttribute`
91 CHECK: unique name: `.?AUv1_alttypeAttribute@helper_attributes@__vc_attributes@@`
92 CHECK: vtable: , base list: , field list:
93 CHECK: options: forward ref (-> 0x101E) | has unique name, sizeof 0
94 CHECK: 0x101A | LF_POINTER [size = 12, unreferenced]
95 CHECK: referent = 0x1019, mode = pointer, opts = const, kind = ptr64
96 CHECK: 0x101B | LF_ARGLIST [size = 12, unreferenced]
97 CHECK: 0x1018: `__vc_attributes::helper_attributes::v1_alttypeAttribute::type_e`
98 CHECK: 0x101C | LF_MFUNCTION [size = 28, unreferenced]
99 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x101B
100 CHECK: class type = 0x1019, this type = 0x101A, this adjust = 0
101 CHECK: calling conv = cdecl, options = constructor
102 CHECK: 0x101D | LF_FIELDLIST [size = 64, unreferenced]
103 CHECK: - LF_NESTTYPE [name = `type_e`, parent = 0x1018]
104 CHECK: - LF_ONEMETHOD [name = `v1_alttypeAttribute`]
105 CHECK: type = 0x101C, vftable offset = -1, attrs = public
106 CHECK: - LF_MEMBER [name = `type`, Type = 0x1018, offset = 0, attrs = public]
107 CHECK: 0x101E | LF_STRUCTURE [size = 140, unreferenced] `__vc_attributes::helper_attributes::v1_alttypeAttribute`
108 CHECK: unique name: `.?AUv1_alttypeAttribute@helper_attributes@__vc_attributes@@`
109 CHECK: vtable: , base list: , field list: 0x101D
110 CHECK: options: has ctor / dtor | contains nested class | has unique name, sizeof 4
111 CHECK: 0x101F | LF_FIELDLIST [size = 756, unreferenced]
112 CHECK: - LF_ENUMERATE [eAnyUsage = 0]
113 CHECK: - LF_ENUMERATE [eCoClassUsage = 1]
114 CHECK: - LF_ENUMERATE [eCOMInterfaceUsage = 2]
115 CHECK: - LF_ENUMERATE [eInterfaceUsage = 6]
116 CHECK: - LF_ENUMERATE [eMemberUsage = 8]
117 CHECK: - LF_ENUMERATE [eMethodUsage = 16]
118 CHECK: - LF_ENUMERATE [eInterfaceMethodUsage = 32]
119 CHECK: - LF_ENUMERATE [eInterfaceMemberUsage = 64]
120 CHECK: - LF_ENUMERATE [eCoClassMemberUsage = 128]
121 CHECK: - LF_ENUMERATE [eCoClassMethodUsage = 256]
122 CHECK: - LF_ENUMERATE [eGlobalMethodUsage = 768]
123 CHECK: - LF_ENUMERATE [eGlobalDataUsage = 1024]
124 CHECK: - LF_ENUMERATE [eClassUsage = 2048]
125 CHECK: - LF_ENUMERATE [eInterfaceParameterUsage = 4096]
126 CHECK: - LF_ENUMERATE [eMethodParameterUsage = 12288]
127 CHECK: - LF_ENUMERATE [eIDLModuleUsage = 16384]
128 CHECK: - LF_ENUMERATE [eAnonymousUsage = 32768]
129 CHECK: - LF_ENUMERATE [eTypedefUsage = 65536]
130 CHECK: - LF_ENUMERATE [eUnionUsage = 131072]
131 CHECK: - LF_ENUMERATE [eEnumUsage = 262144]
132 CHECK: - LF_ENUMERATE [eDefineTagUsage = 524288]
133 CHECK: - LF_ENUMERATE [eStructUsage = 1048576]
134 CHECK: - LF_ENUMERATE [eLocalUsage = 2097152]
135 CHECK: - LF_ENUMERATE [ePropertyUsage = 4194304]
136 CHECK: - LF_ENUMERATE [eEventUsage = 8388608]
137 CHECK: - LF_ENUMERATE [eTemplateUsage = 16777216]
138 CHECK: - LF_ENUMERATE [eModuleUsage = 16777216]
139 CHECK: - LF_ENUMERATE [eIllegalUsage = 33554432]
140 CHECK: - LF_ENUMERATE [eAsynchronousUsage = 67108864]
141 CHECK: - LF_ENUMERATE [eAnyIDLUsage = 4161535]
142 CHECK: 0x1020 | LF_ENUM [size = 140, unreferenced] `__vc_attributes::helper_attributes::usageAttribute::usage_e`
143 CHECK: unique name: `.?AW4usage_e@usageAttribute@helper_attributes@__vc_attributes@@`
144 CHECK: field list: 0x101F, underlying type: 0x0074 (int)
145 CHECK: options: has unique name | is nested
146 CHECK: 0x1021 | LF_STRUCTURE [size = 128, unreferenced] `__vc_attributes::helper_attributes::usageAttribute`
147 CHECK: unique name: `.?AUusageAttribute@helper_attributes@__vc_attributes@@`
148 CHECK: vtable: , base list: , field list:
149 CHECK: options: forward ref (-> 0x1026) | has unique name, sizeof 0
150 CHECK: 0x1022 | LF_POINTER [size = 12, unreferenced]
151 CHECK: referent = 0x1021, mode = pointer, opts = const, kind = ptr64
152 CHECK: 0x1023 | LF_ARGLIST [size = 12, unreferenced]
153 CHECK: 0x0075 (unsigned): `unsigned`
154 CHECK: 0x1024 | LF_MFUNCTION [size = 28, unreferenced]
155 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1023
156 CHECK: class type = 0x1021, this type = 0x1022, this adjust = 0
157 CHECK: calling conv = cdecl, options = constructor
158 CHECK: 0x1025 | LF_FIELDLIST [size = 60, unreferenced]
159 CHECK: - LF_NESTTYPE [name = `usage_e`, parent = 0x1020]
160 CHECK: - LF_ONEMETHOD [name = `usageAttribute`]
161 CHECK: type = 0x1024, vftable offset = -1, attrs = public
162 CHECK: - LF_MEMBER [name = `value`, Type = 0x0075 (unsigned), offset = 0, attrs = public]
163 CHECK: 0x1026 | LF_STRUCTURE [size = 128, unreferenced] `__vc_attributes::helper_attributes::usageAttribute`
164 CHECK: unique name: `.?AUusageAttribute@helper_attributes@__vc_attributes@@`
165 CHECK: vtable: , base list: , field list: 0x1025
166 CHECK: options: has ctor / dtor | contains nested class | has unique name, sizeof 4
167 CHECK: 0x1027 | LF_FIELDLIST [size = 76, unreferenced]
168 CHECK: - LF_ENUMERATE [apartment = 1]
169 CHECK: - LF_ENUMERATE [single = 2]
170 CHECK: - LF_ENUMERATE [free = 3]
171 CHECK: - LF_ENUMERATE [neutral = 4]
172 CHECK: - LF_ENUMERATE [both = 5]
173 CHECK: 0x1028 | LF_ENUM [size = 120, unreferenced] `__vc_attributes::threadingAttribute::threading_e`
174 CHECK: unique name: `.?AW4threading_e@threadingAttribute@__vc_attributes@@`
175 CHECK: field list: 0x1027, underlying type: 0x0074 (int)
176 CHECK: options: has unique name | is nested
177 CHECK: 0x1029 | LF_STRUCTURE [size = 100, unreferenced] `__vc_attributes::threadingAttribute`
178 CHECK: unique name: `.?AUthreadingAttribute@__vc_attributes@@`
179 CHECK: vtable: , base list: , field list:
180 CHECK: options: forward ref (-> 0x1030) | has unique name, sizeof 0
181 CHECK: 0x102A | LF_POINTER [size = 12, unreferenced]
182 CHECK: referent = 0x1029, mode = pointer, opts = const, kind = ptr64
183 CHECK: 0x102B | LF_ARGLIST [size = 12, unreferenced]
184 CHECK: 0x1028: `__vc_attributes::threadingAttribute::threading_e`
185 CHECK: 0x102C | LF_MFUNCTION [size = 28, unreferenced]
186 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x102B
187 CHECK: class type = 0x1029, this type = 0x102A, this adjust = 0
188 CHECK: calling conv = cdecl, options = constructor
189 CHECK: 0x102D | LF_MFUNCTION [size = 28, unreferenced]
190 CHECK: return type = 0x0003 (void), # args = 0, param list = 0x1012
191 CHECK: class type = 0x1029, this type = 0x102A, this adjust = 0
192 CHECK: calling conv = cdecl, options = constructor
193 CHECK: 0x102E | LF_METHODLIST [size = 20, unreferenced]
194 CHECK: - Method [type = 0x102C, vftable offset = -1, attrs = public]
195 CHECK: - Method [type = 0x102D, vftable offset = -1, attrs = public]
196 CHECK: 0x102F | LF_FIELDLIST [size = 68, unreferenced]
197 CHECK: - LF_NESTTYPE [name = `threading_e`, parent = 0x1028]
198 CHECK: - LF_METHOD [name = `threadingAttribute`, # overloads = 2, overload list = 0x102E]
199 CHECK: - LF_MEMBER [name = `value`, Type = 0x1028, offset = 0, attrs = public]
200 CHECK: 0x1030 | LF_STRUCTURE [size = 100, unreferenced] `__vc_attributes::threadingAttribute`
201 CHECK: unique name: `.?AUthreadingAttribute@__vc_attributes@@`
202 CHECK: vtable: , base list: , field list: 0x102F
203 CHECK: options: has ctor / dtor | contains nested class | has unique name, sizeof 4
204 CHECK: 0x1031 | LF_FIELDLIST [size = 48, unreferenced]
205 CHECK: - LF_ENUMERATE [never = 0]
206 CHECK: - LF_ENUMERATE [allowed = 1]
207 CHECK: - LF_ENUMERATE [always = 2]
208 CHECK: 0x1032 | LF_ENUM [size = 116, unreferenced] `__vc_attributes::aggregatableAttribute::type_e`
209 CHECK: unique name: `.?AW4type_e@aggregatableAttribute@__vc_attributes@@`
210 CHECK: field list: 0x1031, underlying type: 0x0074 (int)
211 CHECK: options: has unique name | is nested
212 CHECK: 0x1033 | LF_STRUCTURE [size = 108, unreferenced] `__vc_attributes::aggregatableAttribute`
213 CHECK: unique name: `.?AUaggregatableAttribute@__vc_attributes@@`
214 CHECK: vtable: , base list: , field list:
215 CHECK: options: forward ref (-> 0x103A) | has unique name, sizeof 0
216 CHECK: 0x1034 | LF_POINTER [size = 12, unreferenced]
217 CHECK: referent = 0x1033, mode = pointer, opts = const, kind = ptr64
218 CHECK: 0x1035 | LF_ARGLIST [size = 12, unreferenced]
219 CHECK: 0x1032: `__vc_attributes::aggregatableAttribute::type_e`
220 CHECK: 0x1036 | LF_MFUNCTION [size = 28, unreferenced]
221 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1035
222 CHECK: class type = 0x1033, this type = 0x1034, this adjust = 0
223 CHECK: calling conv = cdecl, options = constructor
224 CHECK: 0x1037 | LF_MFUNCTION [size = 28, unreferenced]
225 CHECK: return type = 0x0003 (void), # args = 0, param list = 0x1012
226 CHECK: class type = 0x1033, this type = 0x1034, this adjust = 0
227 CHECK: calling conv = cdecl, options = constructor
228 CHECK: 0x1038 | LF_METHODLIST [size = 20, unreferenced]
229 CHECK: - Method [type = 0x1036, vftable offset = -1, attrs = public]
230 CHECK: - Method [type = 0x1037, vftable offset = -1, attrs = public]
231 CHECK: 0x1039 | LF_FIELDLIST [size = 68, unreferenced]
232 CHECK: - LF_NESTTYPE [name = `type_e`, parent = 0x1032]
233 CHECK: - LF_METHOD [name = `aggregatableAttribute`, # overloads = 2, overload list = 0x1038]
234 CHECK: - LF_MEMBER [name = `type`, Type = 0x1032, offset = 0, attrs = public]
235 CHECK: 0x103A | LF_STRUCTURE [size = 108, unreferenced] `__vc_attributes::aggregatableAttribute`
236 CHECK: unique name: `.?AUaggregatableAttribute@__vc_attributes@@`
237 CHECK: vtable: , base list: , field list: 0x1039
238 CHECK: options: has ctor / dtor | contains nested class | has unique name, sizeof 4
239 CHECK: 0x103B | LF_ENUM [size = 120, unreferenced] `__vc_attributes::event_receiverAttribute::type_e`
240 CHECK: unique name: `.?AW4type_e@event_receiverAttribute@__vc_attributes@@`
241 CHECK: field list: 0x100A, underlying type: 0x0074 (int)
242 CHECK: options: has unique name | is nested
243 CHECK: 0x103C | LF_STRUCTURE [size = 112, unreferenced] `__vc_attributes::event_receiverAttribute`
244 CHECK: unique name: `.?AUevent_receiverAttribute@__vc_attributes@@`
245 CHECK: vtable: , base list: , field list:
246 CHECK: options: forward ref (-> 0x1045) | has unique name, sizeof 0
247 CHECK: 0x103D | LF_POINTER [size = 12, unreferenced]
248 CHECK: referent = 0x103C, mode = pointer, opts = const, kind = ptr64
249 CHECK: 0x103E | LF_ARGLIST [size = 16, unreferenced]
250 CHECK: 0x103B: `__vc_attributes::event_receiverAttribute::type_e`
251 CHECK: 0x0030 (bool): `bool`
252 CHECK: 0x103F | LF_MFUNCTION [size = 28, unreferenced]
253 CHECK: return type = 0x0003 (void), # args = 2, param list = 0x103E
254 CHECK: class type = 0x103C, this type = 0x103D, this adjust = 0
255 CHECK: calling conv = cdecl, options = constructor
256 CHECK: 0x1040 | LF_ARGLIST [size = 12, unreferenced]
257 CHECK: 0x103B: `__vc_attributes::event_receiverAttribute::type_e`
258 CHECK: 0x1041 | LF_MFUNCTION [size = 28, unreferenced]
259 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1040
260 CHECK: class type = 0x103C, this type = 0x103D, this adjust = 0
261 CHECK: calling conv = cdecl, options = constructor
262 CHECK: 0x1042 | LF_MFUNCTION [size = 28, unreferenced]
263 CHECK: return type = 0x0003 (void), # args = 0, param list = 0x1012
264 CHECK: class type = 0x103C, this type = 0x103D, this adjust = 0
265 CHECK: calling conv = cdecl, options = constructor
266 CHECK: 0x1043 | LF_METHODLIST [size = 28, unreferenced]
267 CHECK: - Method [type = 0x103F, vftable offset = -1, attrs = public]
268 CHECK: - Method [type = 0x1041, vftable offset = -1, attrs = public]
269 CHECK: - Method [type = 0x1042, vftable offset = -1, attrs = public]
270 CHECK: 0x1044 | LF_FIELDLIST [size = 96, unreferenced]
271 CHECK: - LF_NESTTYPE [name = `type_e`, parent = 0x103B]
272 CHECK: - LF_METHOD [name = `event_receiverAttribute`, # overloads = 3, overload list = 0x1043]
273 CHECK: - LF_MEMBER [name = `type`, Type = 0x103B, offset = 0, attrs = public]
274 CHECK: - LF_MEMBER [name = `layout_dependent`, Type = 0x0030 (bool), offset = 4, attrs = public]
275 CHECK: 0x1045 | LF_STRUCTURE [size = 112, unreferenced] `__vc_attributes::event_receiverAttribute`
276 CHECK: unique name: `.?AUevent_receiverAttribute@__vc_attributes@@`
277 CHECK: vtable: , base list: , field list: 0x1044
278 CHECK: options: has ctor / dtor | contains nested class | has unique name, sizeof 8
279 CHECK: 0x1046 | LF_FIELDLIST [size = 92, unreferenced]
280 CHECK: - LF_ENUMERATE [dll = 1]
281 CHECK: - LF_ENUMERATE [exe = 2]
282 CHECK: - LF_ENUMERATE [service = 3]
283 CHECK: - LF_ENUMERATE [unspecified = 4]
284 CHECK: - LF_ENUMERATE [EXE = 2]
285 CHECK: - LF_ENUMERATE [SERVICE = 3]
286 CHECK: 0x1047 | LF_ENUM [size = 104, unreferenced] `__vc_attributes::moduleAttribute::type_e`
287 CHECK: unique name: `.?AW4type_e@moduleAttribute@__vc_attributes@@`
288 CHECK: field list: 0x1046, underlying type: 0x0074 (int)
289 CHECK: options: has unique name | is nested
290 CHECK: 0x1048 | LF_STRUCTURE [size = 96, unreferenced] `__vc_attributes::moduleAttribute`
291 CHECK: unique name: `.?AUmoduleAttribute@__vc_attributes@@`
292 CHECK: vtable: , base list: , field list:
293 CHECK: options: forward ref (-> 0x1053) | has unique name, sizeof 0
294 CHECK: 0x1049 | LF_POINTER [size = 12, unreferenced]
295 CHECK: referent = 0x1048, mode = pointer, opts = const, kind = ptr64
296 CHECK: 0x104A | LF_MODIFIER [size = 12, unreferenced]
297 CHECK: referent = 0x0070 (char), modifiers = const
298 CHECK: 0x104B | LF_POINTER [size = 12, unreferenced]
299 CHECK: referent = 0x104A, mode = pointer, opts = None, kind = ptr64
300 CHECK: 0x104C | LF_ARGLIST [size = 68, unreferenced]
301 CHECK: 0x1047: `__vc_attributes::moduleAttribute::type_e`
302 CHECK: 0x104B: `const char*`
303 CHECK: 0x104B: `const char*`
304 CHECK: 0x104B: `const char*`
305 CHECK: 0x0074 (int): `int`
306 CHECK: 0x0030 (bool): `bool`
307 CHECK: 0x104B: `const char*`
308 CHECK: 0x0074 (int): `int`
309 CHECK: 0x104B: `const char*`
310 CHECK: 0x104B: `const char*`
311 CHECK: 0x0074 (int): `int`
312 CHECK: 0x0030 (bool): `bool`
313 CHECK: 0x0030 (bool): `bool`
314 CHECK: 0x104B: `const char*`
315 CHECK: 0x104B: `const char*`
316 CHECK: 0x104D | LF_MFUNCTION [size = 28, unreferenced]
317 CHECK: return type = 0x0003 (void), # args = 15, param list = 0x104C
318 CHECK: class type = 0x1048, this type = 0x1049, this adjust = 0
319 CHECK: calling conv = cdecl, options = constructor
320 CHECK: 0x104E | LF_ARGLIST [size = 12, unreferenced]
321 CHECK: 0x1047: `__vc_attributes::moduleAttribute::type_e`
322 CHECK: 0x104F | LF_MFUNCTION [size = 28, unreferenced]
323 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x104E
324 CHECK: class type = 0x1048, this type = 0x1049, this adjust = 0
325 CHECK: calling conv = cdecl, options = constructor
326 CHECK: 0x1050 | LF_MFUNCTION [size = 28, unreferenced]
327 CHECK: return type = 0x0003 (void), # args = 0, param list = 0x1012
328 CHECK: class type = 0x1048, this type = 0x1049, this adjust = 0
329 CHECK: calling conv = cdecl, options = constructor
330 CHECK: 0x1051 | LF_METHODLIST [size = 28, unreferenced]
331 CHECK: - Method [type = 0x104D, vftable offset = -1, attrs = public]
332 CHECK: - Method [type = 0x104F, vftable offset = -1, attrs = public]
333 CHECK: - Method [type = 0x1050, vftable offset = -1, attrs = public]
334 CHECK: 0x1052 | LF_FIELDLIST [size = 356, unreferenced]
335 CHECK: - LF_NESTTYPE [name = `type_e`, parent = 0x1047]
336 CHECK: - LF_METHOD [name = `moduleAttribute`, # overloads = 3, overload list = 0x1051]
337 CHECK: - LF_MEMBER [name = `type`, Type = 0x1047, offset = 0, attrs = public]
338 CHECK: - LF_MEMBER [name = `name`, Type = 0x104B, offset = 8, attrs = public]
339 CHECK: - LF_MEMBER [name = `version`, Type = 0x104B, offset = 16, attrs = public]
340 CHECK: - LF_MEMBER [name = `uuid`, Type = 0x104B, offset = 24, attrs = public]
341 CHECK: - LF_MEMBER [name = `lcid`, Type = 0x0074 (int), offset = 32, attrs = public]
342 CHECK: - LF_MEMBER [name = `control`, Type = 0x0030 (bool), offset = 36, attrs = public]
343 CHECK: - LF_MEMBER [name = `helpstring`, Type = 0x104B, offset = 40, attrs = public]
344 CHECK: - LF_MEMBER [name = `helpstringcontext`, Type = 0x0074 (int), offset = 48, attrs = public]
345 CHECK: - LF_MEMBER [name = `helpstringdll`, Type = 0x104B, offset = 56, attrs = public]
346 CHECK: - LF_MEMBER [name = `helpfile`, Type = 0x104B, offset = 64, attrs = public]
347 CHECK: - LF_MEMBER [name = `helpcontext`, Type = 0x0074 (int), offset = 72, attrs = public]
348 CHECK: - LF_MEMBER [name = `hidden`, Type = 0x0030 (bool), offset = 76, attrs = public]
349 CHECK: - LF_MEMBER [name = `restricted`, Type = 0x0030 (bool), offset = 77, attrs = public]
350 CHECK: - LF_MEMBER [name = `custom`, Type = 0x104B, offset = 80, attrs = public]
351 CHECK: - LF_MEMBER [name = `resource_name`, Type = 0x104B, offset = 88, attrs = public]
352 CHECK: 0x1053 | LF_STRUCTURE [size = 96, unreferenced] `__vc_attributes::moduleAttribute`
353 CHECK: unique name: `.?AUmoduleAttribute@__vc_attributes@@`
354 CHECK: vtable: , base list: , field list: 0x1052
355 CHECK: options: has ctor / dtor | contains nested class | has unique name, sizeof 96
356 CHECK: 0x1054 | LF_STRUCTURE [size = 48, referenced] `Nested::F`
357 CHECK: unique name: `.?AUF@Nested@@`
358 CHECK: vtable: , base list: , field list:
359 CHECK: options: forward ref (-> 0x1057) | has unique name | is nested, sizeof 0
360 CHECK: 0x1055 | LF_FIELDLIST [size = 16, referenced]
361 CHECK: - LF_NESTTYPE [name = `F`, parent = 0x1054]
362 CHECK: 0x1056 | LF_STRUCTURE [size = 44, referenced] `Nested`
363 CHECK: unique name: `.?AUNested@@`
364 CHECK: vtable: , base list: , field list: 0x1055
365 CHECK: options: contains nested class | has unique name, sizeof 1
366 CHECK: 0x1057 | LF_STRUCTURE [size = 48, referenced] `Nested::F`
367 CHECK: unique name: `.?AUF@Nested@@`
368 CHECK: vtable: , base list: , field list: 0x1007
369 CHECK: options: has unique name | is nested, sizeof 1
370 CHECK: 0x1058 | LF_STRUCTURE [size = 52, referenced] `Constructor`
371 CHECK: unique name: `.?AUConstructor@@`
372 CHECK: vtable: , base list: , field list:
373 CHECK: options: forward ref (-> 0x105C) | has unique name, sizeof 0
374 CHECK: 0x1059 | LF_POINTER [size = 12, referenced]
375 CHECK: referent = 0x1058, mode = pointer, opts = const, kind = ptr64
376 CHECK: 0x105A | LF_MFUNCTION [size = 28, referenced]
377 CHECK: return type = 0x0003 (void), # args = 0, param list = 0x1012
378 CHECK: class type = 0x1058, this type = 0x1059, this adjust = 0
379 CHECK: calling conv = cdecl, options = constructor
380 CHECK: 0x105B | LF_FIELDLIST [size = 24, referenced]
381 CHECK: - LF_ONEMETHOD [name = `Constructor`]
382 CHECK: type = 0x105A, vftable offset = -1, attrs = public
383 CHECK: 0x105C | LF_STRUCTURE [size = 52, referenced] `Constructor`
384 CHECK: unique name: `.?AUConstructor@@`
385 CHECK: vtable: , base list: , field list: 0x105B
386 CHECK: options: has ctor / dtor | has unique name, sizeof 1
387 CHECK: 0x105D | LF_CLASS [size = 40, referenced] `Class`
388 CHECK: unique name: `.?AVClass@@`
389 CHECK: vtable: , base list: , field list: 0x1007
390 CHECK: options: has unique name, sizeof 1
391 CHECK: 0x105E | LF_UNION [size = 32, referenced] `Union`
392 CHECK: unique name: `.?ATUnion@@`
393 CHECK: field list: 0x1007
394 CHECK: options: has unique name | sealed, sizeof 1
395 CHECK: 0x105F | LF_STRUCTURE [size = 48, referenced] `Operator`
396 CHECK: unique name: `.?AUOperator@@`
397 CHECK: vtable: , base list: , field list:
398 CHECK: options: forward ref (-> 0x1064) | has unique name, sizeof 0
399 CHECK: 0x1060 | LF_POINTER [size = 12, referenced]
400 CHECK: referent = 0x105F, mode = pointer, opts = const, kind = ptr64
401 CHECK: 0x1061 | LF_ARGLIST [size = 12, referenced]
402 CHECK: 0x0074 (int): `int`
403 CHECK: 0x1062 | LF_MFUNCTION [size = 28, referenced]
404 CHECK: return type = 0x0074 (int), # args = 1, param list = 0x1061
405 CHECK: class type = 0x105F, this type = 0x1060, this adjust = 0
406 CHECK: calling conv = cdecl, options = None
407 CHECK: 0x1063 | LF_FIELDLIST [size = 24, referenced]
408 CHECK: - LF_ONEMETHOD [name = `operator+`]
409 CHECK: type = 0x1062, vftable offset = -1, attrs = public
410 CHECK: 0x1064 | LF_STRUCTURE [size = 48, referenced] `Operator`
411 CHECK: unique name: `.?AUOperator@@`
412 CHECK: vtable: , base list: , field list: 0x1063
413 CHECK: options: has unique name | overloaded operator, sizeof 1
414 CHECK: 0x1065 | LF_FIELDLIST [size = 12, referenced]
415 CHECK: - LF_ENUMERATE [A = 0]
416 CHECK: 0x1066 | LF_ENUM [size = 36, referenced] `Enum`
417 CHECK: unique name: `.?AW4Enum@@`
418 CHECK: field list: 0x1065, underlying type: 0x0074 (int)
419 CHECK: options: has unique name
420 CHECK: 0x1067 | LF_STRUCTURE [size = 40, referenced] `Cast`
421 CHECK: unique name: `.?AUCast@@`
422 CHECK: vtable: , base list: , field list:
423 CHECK: options: forward ref (-> 0x106B) | has unique name, sizeof 0
424 CHECK: 0x1068 | LF_POINTER [size = 12, referenced]
425 CHECK: referent = 0x1067, mode = pointer, opts = const, kind = ptr64
426 CHECK: 0x1069 | LF_MFUNCTION [size = 28, referenced]
427 CHECK: return type = 0x0074 (int), # args = 0, param list = 0x1012
428 CHECK: class type = 0x1067, this type = 0x1068, this adjust = 0
429 CHECK: calling conv = cdecl, options = None
430 CHECK: 0x106A | LF_FIELDLIST [size = 28, referenced]
431 CHECK: - LF_ONEMETHOD [name = `operator int`]
432 CHECK: type = 0x1069, vftable offset = -1, attrs = public
433 CHECK: 0x106B | LF_STRUCTURE [size = 40, referenced] `Cast`
434 CHECK: unique name: `.?AUCast@@`
435 CHECK: vtable: , base list: , field list: 0x106A
436 CHECK: options: conversion operator | has unique name | overloaded operator, sizeof 1
437 CHECK: 0x106C | LF_STRUCTURE [size = 44, referenced] `Nothing`
438 CHECK: unique name: `.?AUNothing@@`
439 CHECK: vtable: , base list: , field list: 0x1007
440 CHECK: options: has unique name, sizeof 1
441 CHECK: 0x106D | LF_STRUCTURE [size = 52, referenced] `Assignment`
442 CHECK: unique name: `.?AUAssignment@@`
443 CHECK: vtable: , base list: , field list:
444 CHECK: options: forward ref (-> 0x1073) | has unique name, sizeof 0
445 CHECK: 0x106E | LF_POINTER [size = 12, referenced]
446 CHECK: referent = 0x106D, mode = ref, opts = None, kind = ptr64
447 CHECK: 0x106F | LF_POINTER [size = 12, referenced]
448 CHECK: referent = 0x106D, mode = pointer, opts = const, kind = ptr64
449 CHECK: 0x1070 | LF_ARGLIST [size = 12, referenced]
450 CHECK: 0x106D: `Assignment`
451 CHECK: 0x1071 | LF_MFUNCTION [size = 28, referenced]
452 CHECK: return type = 0x106E, # args = 1, param list = 0x1070
453 CHECK: class type = 0x106D, this type = 0x106F, this adjust = 0
454 CHECK: calling conv = cdecl, options = None
455 CHECK: 0x1072 | LF_FIELDLIST [size = 24, referenced]
456 CHECK: - LF_ONEMETHOD [name = `operator=`]
457 CHECK: type = 0x1071, vftable offset = -1, attrs = public
458 CHECK: 0x1073 | LF_STRUCTURE [size = 52, referenced] `Assignment`
459 CHECK: unique name: `.?AUAssignment@@`
460 CHECK: vtable: , base list: , field list: 0x1072
461 CHECK: options: has unique name | overloaded operator | overloaded operator=, sizeof 1
462 CHECK: 0x1074 | LF_STRUCTURE [size = 44, referenced] `Nothing`
463 CHECK: unique name: `.?AUNothing@@`
464 CHECK: vtable: , base list: , field list:
465 CHECK: options: forward ref (<- 0x106C) | has unique name, sizeof 0
466 CHECK: 0x1075 | LF_MODIFIER [size = 12, referenced]
467 CHECK: referent = 0x1074, modifiers = const
468 CHECK: 0x1076 | LF_ARGLIST [size = 12, referenced]
469 CHECK: 0x1075: `const Nothing`
470 CHECK: 0x1077 | LF_PROCEDURE [size = 16, referenced]
471 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1076
472 CHECK: calling conv = cdecl, options = None
473 CHECK: 0x1078 | LF_MODIFIER [size = 12, referenced]
474 CHECK: referent = 0x1074, modifiers = volatile
475 CHECK: 0x1079 | LF_ARGLIST [size = 12, referenced]
476 CHECK: 0x1078: `volatile Nothing`
477 CHECK: 0x107A | LF_PROCEDURE [size = 16, referenced]
478 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1079
479 CHECK: calling conv = cdecl, options = None
480 CHECK: 0x107B | LF_MODIFIER [size = 12, referenced]
481 CHECK: referent = 0x1074, modifiers = const | volatile
482 CHECK: 0x107C | LF_ARGLIST [size = 12, referenced]
483 CHECK: 0x107B: `const volatile Nothing`
484 CHECK: 0x107D | LF_PROCEDURE [size = 16, referenced]
485 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x107C
486 CHECK: calling conv = cdecl, options = None
487 CHECK: 0x107E | LF_MODIFIER [size = 12, referenced]
488 CHECK: referent = 0x1074, modifiers = unaligned
489 CHECK: 0x107F | LF_ARGLIST [size = 12, referenced]
490 CHECK: 0x107E: `__unaligned Nothing`
491 CHECK: 0x1080 | LF_PROCEDURE [size = 16, referenced]
492 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x107F
493 CHECK: calling conv = cdecl, options = None
494 CHECK: 0x1081 | LF_UNION [size = 32, referenced] `Union`
495 CHECK: unique name: `.?ATUnion@@`
496 CHECK: field list:
497 CHECK: options: forward ref (<- 0x105E) | has unique name, sizeof 0
498 CHECK: 0x1082 | LF_ARGLIST [size = 12, referenced]
499 CHECK: 0x1081: `Union`
500 CHECK: 0x1083 | LF_PROCEDURE [size = 16, referenced]
501 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1082
502 CHECK: calling conv = cdecl, options = None
503 CHECK: 0x1084 | LF_STRUCTURE [size = 124, referenced] `main::__l2::`
504 CHECK: unique name: `.?AU@?1??main@@YAHHPEAPEAD@Z@`aa6523bc`
505 CHECK: vtable: , base list: , field list:
506 CHECK: options: forward ref (<- 0x1008) | has unique name | scoped, sizeof 0
507 CHECK: 0x1085 | LF_ARGLIST [size = 12, referenced]
508 CHECK: 0x1084: `main::__l2::`
509 CHECK: 0x1086 | LF_PROCEDURE [size = 16, referenced]
510 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1085
511 CHECK: calling conv = cdecl, options = None
512 CHECK: 0x1087 | LF_PROCEDURE [size = 16, referenced]
513 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1070
514 CHECK: calling conv = cdecl, options = None
515 CHECK: 0x1088 | LF_ARGLIST [size = 12, referenced]
516 CHECK: 0x1067: `Cast`
517 CHECK: 0x1089 | LF_PROCEDURE [size = 16, referenced]
518 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1088
519 CHECK: calling conv = cdecl, options = None
520 CHECK: 0x108A | LF_ARGLIST [size = 12, referenced]
521 CHECK: 0x1058: `Constructor`
522 CHECK: 0x108B | LF_PROCEDURE [size = 16, referenced]
523 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x108A
524 CHECK: calling conv = cdecl, options = None
525 CHECK: 0x108C | LF_ARGLIST [size = 12, referenced]
526 CHECK: 0x1054: `Nested::F`
527 CHECK: 0x108D | LF_PROCEDURE [size = 16, referenced]
528 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x108C
529 CHECK: calling conv = cdecl, options = None
530 CHECK: 0x108E | LF_STRUCTURE [size = 44, referenced] `Nested`
531 CHECK: unique name: `.?AUNested@@`
532 CHECK: vtable: , base list: , field list:
533 CHECK: options: forward ref (<- 0x1056) | has unique name, sizeof 0
534 CHECK: 0x108F | LF_ARGLIST [size = 12, referenced]
535 CHECK: 0x108E: `Nested`
536 CHECK: 0x1090 | LF_PROCEDURE [size = 16, referenced]
537 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x108F
538 CHECK: calling conv = cdecl, options = None
539 CHECK: 0x1091 | LF_ARGLIST [size = 12, referenced]
540 CHECK: 0x1074: `Nothing`
541 CHECK: 0x1092 | LF_PROCEDURE [size = 16, referenced]
542 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1091
543 CHECK: calling conv = cdecl, options = None
544 CHECK: 0x1093 | LF_ARGLIST [size = 12, referenced]
545 CHECK: 0x105F: `Operator`
546 CHECK: 0x1094 | LF_PROCEDURE [size = 16, referenced]
547 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1093
548 CHECK: calling conv = cdecl, options = None
549 CHECK: 0x1095 | LF_STRUCTURE [size = 88, referenced] `main::__l2::Scoped`
550 CHECK: unique name: `.?AUScoped@?1??main@@YAHHPEAPEAD@Z@`aa6523bc`
551 CHECK: vtable: , base list: , field list:
552 CHECK: options: forward ref (<- 0x1009) | has unique name | scoped, sizeof 0
553 CHECK: 0x1096 | LF_ARGLIST [size = 12, referenced]
554 CHECK: 0x1095: `main::__l2::Scoped`
555 CHECK: 0x1097 | LF_PROCEDURE [size = 16, referenced]
556 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1096
557 CHECK: calling conv = cdecl, options = None
558 CHECK: 0x1098 | LF_CLASS [size = 40, referenced] `Class`
559 CHECK: unique name: `.?AVClass@@`
560 CHECK: vtable: , base list: , field list:
561 CHECK: options: forward ref (<- 0x105D) | has unique name, sizeof 0
562 CHECK: 0x1099 | LF_ARGLIST [size = 12, referenced]
563 CHECK: 0x1098: `Class`
564 CHECK: 0x109A | LF_PROCEDURE [size = 16, referenced]
565 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x1099
566 CHECK: calling conv = cdecl, options = None
567 CHECK: 0x109B | LF_ARGLIST [size = 12, referenced]
568 CHECK: 0x1066: `Enum`
569 CHECK: 0x109C | LF_PROCEDURE [size = 16, referenced]
570 CHECK: return type = 0x0003 (void), # args = 1, param list = 0x109B
571 CHECK: calling conv = cdecl, options = None
572
573 CHECK: Type Reference Statistics
574 CHECK: ============================================================
575 CHECK: Records referenced: 84 / 157 53.50%
576 CHECK: Bytes referenced: 2,188 / 7,500 29.17%
2929 PrettyTypedefDumper.cpp
3030 PrettyVariableDumper.cpp
3131 StreamUtil.cpp
32 TypeReferenceTracker.cpp
3233 YAMLOutputStyle.cpp
3334 )
1212 #include "MinimalSymbolDumper.h"
1313 #include "MinimalTypeDumper.h"
1414 #include "StreamUtil.h"
15 #include "TypeReferenceTracker.h"
1516 #include "llvm-pdbutil.h"
1617
1718 #include "llvm/ADT/STLExtras.h"
5960 using namespace llvm::pdb;
6061
6162 DumpOutputStyle::DumpOutputStyle(InputFile &File)
62 : File(File), P(2, false, outs()) {}
63 : File(File), P(2, false, outs()) {
64 if (opts::dump::DumpTypeRefStats)
65 RefTracker.reset(new TypeReferenceTracker(File));
66 }
67
68 DumpOutputStyle::~DumpOutputStyle() {}
6369
6470 PDBFile &DumpOutputStyle::getPdb() { return File.pdb(); }
6571 object::COFFObjectFile &DumpOutputStyle::getObj() { return File.obj(); }
7581 }
7682
7783 Error DumpOutputStyle::dump() {
84 // Walk symbols & globals if we are supposed to mark types referenced.
85 if (opts::dump::DumpTypeRefStats)
86 RefTracker->mark();
87
7888 if (opts::dump::DumpSummary) {
7989 if (auto EC = dumpFileSummary())
8090 return EC;
183193 if (opts::dump::DumpSymbols) {
184194 auto EC = File.isPdb() ? dumpModuleSymsForPdb() : dumpModuleSymsForObj();
185195 if (EC)
196 return EC;
197 }
198
199 if (opts::dump::DumpTypeRefStats) {
200 if (auto EC = dumpTypeRefStats())
186201 return EC;
187202 }
188203
12261241
12271242 static void
12281243 dumpFullTypeStream(LinePrinter &Printer, LazyRandomTypeCollection &Types,
1229 uint32_t NumTypeRecords, uint32_t NumHashBuckets,
1244 TypeReferenceTracker *RefTracker, uint32_t NumTypeRecords,
1245 uint32_t NumHashBuckets,
12301246 FixedStreamArray HashValues,
12311247 TpiStream *Stream, bool Bytes, bool Extras) {
12321248
12331249 Printer.formatLine("Showing {0:N} records", NumTypeRecords);
12341250 uint32_t Width = NumDigits(TypeIndex::FirstNonSimpleIndex + NumTypeRecords);
12351251
1236 MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,
1252 MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types, RefTracker,
12371253 NumHashBuckets, HashValues, Stream);
12381254
12391255 if (auto EC = codeview::visitTypeStream(Types, V)) {
12441260
12451261 static void dumpPartialTypeStream(LinePrinter &Printer,
12461262 LazyRandomTypeCollection &Types,
1263 TypeReferenceTracker *RefTracker,
12471264 TpiStream &Stream, ArrayRef TiList,
12481265 bool Bytes, bool Extras, bool Deps) {
12491266 uint32_t Width =
12501267 NumDigits(TypeIndex::FirstNonSimpleIndex + Stream.getNumTypeRecords());
12511268
1252 MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types,
1269 MinimalTypeDumpVisitor V(Printer, Width + 2, Bytes, Extras, Types, RefTracker,
12531270 Stream.getNumHashBuckets(), Stream.getHashValues(),
12541271 &Stream);
12551272
13131330 Types.reset(Reader, 100);
13141331
13151332 if (opts::dump::DumpTypes) {
1316 dumpFullTypeStream(P, Types, 0, 0, {}, nullptr, opts::dump::DumpTypeData,
1317 false);
1333 dumpFullTypeStream(P, Types, RefTracker.get(), 0, 0, {}, nullptr,
1334 opts::dump::DumpTypeData, false);
13181335 } else if (opts::dump::DumpTypeExtras) {
13191336 auto LocalHashes = LocallyHashedType::hashTypeCollection(Types);
13201337 auto GlobalHashes = GloballyHashedType::hashTypeCollection(Types);
13831400
13841401 auto &Types = (StreamIdx == StreamTPI) ? File.types() : File.ids();
13851402
1403 // Only emit notes about referenced/unreferenced for types.
1404 TypeReferenceTracker *MaybeTracker =
1405 (StreamIdx == StreamTPI) ? RefTracker.get() : nullptr;
1406
13861407 // Enable resolving forward decls.
13871408 Stream.buildHashMap();
13881409
13891410 if (DumpTypes || !Indices.empty()) {
13901411 if (Indices.empty())
1391 dumpFullTypeStream(P, Types, Stream.getNumTypeRecords(),
1412 dumpFullTypeStream(P, Types, MaybeTracker, Stream.getNumTypeRecords(),
13921413 Stream.getNumHashBuckets(), Stream.getHashValues(),
13931414 &Stream, DumpBytes, DumpExtras);
13941415 else {
13951416 std::vector TiList(Indices.begin(), Indices.end());
1396 dumpPartialTypeStream(P, Types, Stream, TiList, DumpBytes, DumpExtras,
1397 opts::dump::DumpTypeDependents);
1417 dumpPartialTypeStream(P, Types, MaybeTracker, Stream, TiList, DumpBytes,
1418 DumpExtras, opts::dump::DumpTypeDependents);
13981419 }
13991420 }
14001421
15161537 return;
15171538 }
15181539 });
1540 return Error::success();
1541 }
1542
1543 Error DumpOutputStyle::dumpTypeRefStats() {
1544 printHeader(P, "Type Reference Statistics");
1545 AutoIndent Indent(P);
1546
1547 // Sum the byte size of all type records, and the size and count of all
1548 // referenced records.
1549 size_t TotalRecs = File.types().size();
1550 size_t RefRecs = 0;
1551 size_t TotalBytes = 0;
1552 size_t RefBytes = 0;
1553 auto &Types = File.types();
1554 for (Optional TI = Types.getFirst(); TI; TI = Types.getNext(*TI)) {
1555 CVType Type = File.types().getType(*TI);
1556 TotalBytes += Type.length();
1557 if (RefTracker->isTypeReferenced(*TI)) {
1558 ++RefRecs;
1559 RefBytes += Type.length();
1560 }
1561 }
1562
1563 P.formatLine("Records referenced: {0:N} / {1:N} {2:P}", RefRecs, TotalRecs,
1564 (double)RefRecs / TotalRecs);
1565 P.formatLine("Bytes referenced: {0:N} / {1:N} {2:P}", RefBytes, TotalBytes,
1566 (double)RefBytes / TotalBytes);
1567
15191568 return Error::success();
15201569 }
15211570
3333 namespace pdb {
3434 class GSIHashTable;
3535 class InputFile;
36 class TypeReferenceTracker;
3637
3738 struct StatCollection {
3839 struct Stat {
6162
6263 public:
6364 DumpOutputStyle(InputFile &File);
65 ~DumpOutputStyle() override;
6466
6567 Error dump() override;
6668
8890 Error dumpNewFpo(PDBFile &File);
8991 Error dumpTpiStream(uint32_t StreamIdx);
9092 Error dumpTypesFromObjectFile();
93 Error dumpTypeRefStats();
9194 Error dumpModules();
9295 Error dumpModuleFiles();
9396 Error dumpModuleSymsForPdb();
103106 void dumpSectionHeaders(StringRef Label, DbgHeaderType Type);
104107
105108 InputFile &File;
109 std::unique_ptr RefTracker;
106110 LinePrinter P;
107111 SmallVector StreamPurposes;
108112 };
99
1010 #include "FormatUtil.h"
1111 #include "LinePrinter.h"
12 #include "TypeReferenceTracker.h"
1213
1314 #include "llvm-pdbutil.h"
1415 #include "llvm/DebugInfo/CodeView/CVRecord.h"
220221 // formatLine puts the newline at the beginning, so we use formatLine here
221222 // to start a new line, and then individual visit methods use format to
222223 // append to the existing line.
223 if (!Hashes) {
224 P.formatLine("{0} | {1} [size = {2}]",
225 fmt_align(Index, AlignStyle::Right, Width),
226 formatTypeLeafKind(Record.Type), Record.length());
227 } else {
224 P.formatLine("{0} | {1} [size = {2}",
225 fmt_align(Index, AlignStyle::Right, Width),
226 formatTypeLeafKind(Record.Type), Record.length());
227 if (Hashes) {
228228 std::string H;
229229 if (Index.toArrayIndex() >= HashValues.size()) {
230230 H = "(not present)";
240240 else
241241 H = "0x" + utohexstr(Hash) + ", our hash = 0x" + utohexstr(OurHash);
242242 }
243 P.formatLine("{0} | {1} [size = {2}, hash = {3}]",
244 fmt_align(Index, AlignStyle::Right, Width),
245 formatTypeLeafKind(Record.Type), Record.length(), H);
246 }
243 P.format(", hash = {0}", H);
244 }
245 if (RefTracker) {
246 if (RefTracker->isTypeReferenced(Index))
247 P.format(", referenced");
248 else
249 P.format(", unreferenced");
250 }
251 P.format("]");
247252 P.Indent(Width + 3);
248253 return Error::success();
249254 }
255
250256 Error MinimalTypeDumpVisitor::visitTypeEnd(CVType &Record) {
251257 P.Unindent(Width + 3);
252258 if (RecordBytes) {
1919 namespace pdb {
2020 class LinePrinter;
2121 class TpiStream;
22 class TypeReferenceTracker;
2223
2324 class MinimalTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
2425 public:
2526 MinimalTypeDumpVisitor(LinePrinter &P, uint32_t Width, bool RecordBytes,
2627 bool Hashes, codeview::LazyRandomTypeCollection &Types,
28 TypeReferenceTracker *RefTracker,
2729 uint32_t NumHashBuckets,
2830 FixedStreamArray HashValues,
2931 pdb::TpiStream *Stream)
3032 : P(P), Width(Width), RecordBytes(RecordBytes), Hashes(Hashes),
31 Types(Types), NumHashBuckets(NumHashBuckets), HashValues(HashValues),
32 Stream(Stream) {}
33 Types(Types), RefTracker(RefTracker), NumHashBuckets(NumHashBuckets),
34 HashValues(HashValues), Stream(Stream) {}
3335
3436 Error visitTypeBegin(codeview::CVType &Record,
3537 codeview::TypeIndex Index) override;
5557 bool RecordBytes = false;
5658 bool Hashes = false;
5759 codeview::LazyRandomTypeCollection &Types;
60 pdb::TypeReferenceTracker *RefTracker = nullptr;
5861 uint32_t NumHashBuckets;
5962 codeview::TypeIndex CurrentTypeIndex;
6063 FixedStreamArray HashValues;
0 //===- TypeReferenceTracker.cpp ------------------------------- *- C++ --*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7
8 #include "TypeReferenceTracker.h"
9
10 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
11 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
12 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
13 #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
14 #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
15
16 using namespace llvm;
17 using namespace llvm::pdb;
18 using namespace llvm::codeview;
19
20 // LazyRandomTypeCollection doesn't appear to expose the number of records, so
21 // just iterate up front to find out.
22 static uint32_t getNumRecordsInCollection(LazyRandomTypeCollection &Types) {
23 uint32_t NumTypes = 0;
24 for (Optional TI = Types.getFirst(); TI; TI = Types.getNext(*TI))
25 ++NumTypes;
26 return NumTypes;
27 }
28
29 TypeReferenceTracker::TypeReferenceTracker(InputFile &File)
30 : File(File), Types(File.types()),
31 Ids(File.isPdb() ? &File.ids() : nullptr) {
32 NumTypeRecords = getNumRecordsInCollection(Types);
33 TypeReferenced.resize(NumTypeRecords, false);
34
35 // If this is a PDB, ids are stored separately, so make a separate bit vector.
36 if (Ids) {
37 NumIdRecords = getNumRecordsInCollection(*Ids);
38 IdReferenced.resize(NumIdRecords, false);
39 }
40
41 // Get the TpiStream pointer for forward decl resolution if this is a pdb.
42 // Build the hash map to enable resolving forward decls.
43 if (File.isPdb()) {
44 Tpi = &cantFail(File.pdb().getPDBTpiStream());
45 Tpi->buildHashMap();
46 }
47 }
48
49 void TypeReferenceTracker::mark() {
50 // Walk type roots:
51 // - globals
52 // - modi symbols
53 // - LF_UDT_MOD_SRC_LINE? VC always links these in.
54 for (SymbolGroup SG : File.symbol_groups()) {
55 if (File.isObj()) {
56 for (const auto &SS : SG.getDebugSubsections()) {
57 // FIXME: Are there other type-referencing subsections? Inlinees?
58 // Probably for IDs.
59 if (SS.kind() != DebugSubsectionKind::Symbols)
60 continue;
61
62 CVSymbolArray Symbols;
63 BinaryStreamReader Reader(SS.getRecordData());
64 cantFail(Reader.readArray(Symbols, Reader.getLength()));
65 for (const CVSymbol &S : Symbols)
66 addTypeRefsFromSymbol(S);
67 }
68 } else if (SG.hasDebugStream()) {
69 for (const CVSymbol &S : SG.getPdbModuleStream().getSymbolArray())
70 addTypeRefsFromSymbol(S);
71 }
72 }
73
74 // Walk globals and mark types referenced from globals.
75 if (File.isPdb() && File.pdb().hasPDBGlobalsStream()) {
76 SymbolStream &SymStream = cantFail(File.pdb().getPDBSymbolStream());
77 GlobalsStream &GS = cantFail(File.pdb().getPDBGlobalsStream());
78 for (uint32_t PubSymOff : GS.getGlobalsTable()) {
79 CVSymbol Sym = SymStream.readRecord(PubSymOff);
80 addTypeRefsFromSymbol(Sym);
81 }
82 }
83
84 // FIXME: Should we walk Ids?
85 }
86
87 void TypeReferenceTracker::addOneTypeRef(TiRefKind RefKind, TypeIndex RefTI) {
88 // If it's simple or already seen, no need to add to work list.
89 BitVector &TypeOrIdReferenced =
90 (Ids && RefKind == TiRefKind::IndexRef) ? IdReferenced : TypeReferenced;
91 if (RefTI.isSimple() || TypeOrIdReferenced.test(RefTI.toArrayIndex()))
92 return;
93
94 // Otherwise, mark it seen and add it to the work list.
95 TypeOrIdReferenced.set(RefTI.toArrayIndex());
96 RefWorklist.push_back({RefKind, RefTI});
97 }
98
99 void TypeReferenceTracker::addTypeRefsFromSymbol(const CVSymbol &Sym) {
100 SmallVector DepList;
101 // FIXME: Check for failure.
102 discoverTypeIndicesInSymbol(Sym, DepList);
103 addReferencedTypes(Sym.content(), DepList);
104 markReferencedTypes();
105 }
106
107 void TypeReferenceTracker::addReferencedTypes(ArrayRef RecData,
108 ArrayRef DepList) {
109 for (const auto &Ref : DepList) {
110 // FIXME: Report OOB slice instead of truncating.
111 ArrayRef ByteSlice =
112 RecData.drop_front(Ref.Offset).take_front(4 * Ref.Count);
113 ArrayRef TIs(
114 reinterpret_cast(ByteSlice.data()),
115 ByteSlice.size() / 4);
116
117 // If this is a PDB and this is an item reference, track it in the IPI
118 // bitvector. Otherwise, it's a type ref, or there is only one stream.
119 for (TypeIndex RefTI : TIs)
120 addOneTypeRef(Ref.Kind, RefTI);
121 }
122 }
123
124 void TypeReferenceTracker::markReferencedTypes() {
125 while (!RefWorklist.empty()) {
126 TiRefKind RefKind;
127 TypeIndex RefTI;
128 std::tie(RefKind, RefTI) = RefWorklist.pop_back_val();
129 Optional Rec = (Ids && RefKind == TiRefKind::IndexRef)
130 ? Ids->tryGetType(RefTI)
131 : Types.tryGetType(RefTI);
132 if (!Rec)
133 continue; // FIXME: Report a reference to a non-existant type.
134
135 SmallVector DepList;
136 // FIXME: Check for failure.
137 discoverTypeIndices(*Rec, DepList);
138 addReferencedTypes(Rec->content(), DepList);
139
140 // If this is a tag kind and this is a PDB input, mark the complete type as
141 // referenced.
142 // FIXME: This limitation makes this feature somewhat useless on object file
143 // inputs.
144 if (Tpi) {
145 switch (Rec->kind()) {
146 default:
147 break;
148 case LF_CLASS:
149 case LF_INTERFACE:
150 case LF_STRUCTURE:
151 case LF_UNION:
152 case LF_ENUM:
153 addOneTypeRef(TiRefKind::TypeRef,
154 cantFail(Tpi->findFullDeclForForwardRef(RefTI)));
155 break;
156 }
157 }
158 }
159 }
0 //===- TypeReferenceTracker.h --------------------------------- *- C++ --*-===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7
8 #ifndef LLVM_TOOLS_LLVMPDBDUMP_TYPEREFERENCETRACKER_H
9 #define LLVM_TOOLS_LLVMPDBDUMP_TYPEREFERENCETRACKER_H
10
11 #include "InputFile.h"
12
13 #include "llvm/ADT/BitVector.h"
14 #include "llvm/ADT/Optional.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/DebugInfo/CodeView/CVRecord.h"
17 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
18 #include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
19 #include "llvm/Support/Error.h"
20
21 namespace llvm {
22 namespace pdb {
23
24 class TpiStream;
25
26 /// Maintains bitvector to track whether a type was referenced by a symbol
27 /// record.
28 class TypeReferenceTracker {
29 public:
30 TypeReferenceTracker(InputFile &File);
31
32 // Do the work of marking referenced types.
33 void mark();
34
35 // Return true if a symbol record transitively references this type.
36 bool isTypeReferenced(codeview::TypeIndex TI) {
37 return TI.toArrayIndex() <= NumTypeRecords &&
38 TypeReferenced.test(TI.toArrayIndex());
39 }
40
41 private:
42 void addTypeRefsFromSymbol(const codeview::CVSymbol &Sym);
43
44 // Mark types on this list as referenced.
45 void addReferencedTypes(ArrayRef RecData,
46 ArrayRef Refs);
47
48 // Consume all types on the worklist.
49 void markReferencedTypes();
50
51 void addOneTypeRef(codeview::TiRefKind RefKind, codeview::TypeIndex RefTI);
52
53 InputFile &File;
54 codeview::LazyRandomTypeCollection &Types;
55 codeview::LazyRandomTypeCollection *Ids = nullptr;
56 TpiStream *Tpi = nullptr;
57 BitVector TypeReferenced;
58 BitVector IdReferenced;
59 SmallVector, 10>
60 RefWorklist;
61 uint32_t NumTypeRecords = 0;
62 uint32_t NumIdRecords = 0;
63 };
64
65 } // namespace pdb
66 } // namespace llvm
67
68 #endif // LLVM_TOOLS_LLVMPDBDUMP_TYPEREFERENCETRACKER_H
475475 "type-data",
476476 cl::desc("dump CodeView type record raw bytes from TPI stream"),
477477 cl::cat(TypeOptions), cl::sub(DumpSubcommand));
478 cl::opt
479 DumpTypeRefStats("type-ref-stats",
480 cl::desc("dump statistics on the number and size of types "
481 "transitively referenced by symbol records"),
482 cl::cat(TypeOptions), cl::sub(DumpSubcommand));
478483
479484 cl::opt DumpTypeExtras("type-extras",
480485 cl::desc("dump type hashes and index offsets"),
154154 extern llvm::cl::opt DumpTypeExtras;
155155 extern llvm::cl::list DumpTypeIndex;
156156 extern llvm::cl::opt DumpTypeDependents;
157 extern llvm::cl::opt DumpTypeRefStats;
157158 extern llvm::cl::opt DumpSectionHeaders;
158159
159160 extern llvm::cl::opt DumpIds;