1 | //===-- BitcodeReader.cpp - ClangDoc Bitcode Reader ------------*- 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 | #include "BitcodeReader.h" |
10 | #include "llvm/ADT/IndexedMap.h" |
11 | #include "llvm/Support/Error.h" |
12 | #include "llvm/Support/TimeProfiler.h" |
13 | #include "llvm/Support/raw_ostream.h" |
14 | #include <optional> |
15 | |
16 | namespace clang { |
17 | namespace doc { |
18 | |
19 | using Record = llvm::SmallVector<uint64_t, 1024>; |
20 | |
21 | // This implements decode for SmallString. |
22 | static llvm::Error decodeRecord(const Record &R, |
23 | llvm::SmallVectorImpl<char> &Field, |
24 | llvm::StringRef Blob) { |
25 | Field.assign(in_start: Blob.begin(), in_end: Blob.end()); |
26 | return llvm::Error::success(); |
27 | } |
28 | |
29 | static llvm::Error decodeRecord(const Record &R, SymbolID &Field, |
30 | llvm::StringRef Blob) { |
31 | if (R[0] != BitCodeConstants::USRHashSize) |
32 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
33 | S: "incorrect USR size"); |
34 | |
35 | // First position in the record is the length of the following array, so we |
36 | // copy the following elements to the field. |
37 | for (int I = 0, E = R[0]; I < E; ++I) |
38 | Field[I] = R[I + 1]; |
39 | return llvm::Error::success(); |
40 | } |
41 | |
42 | static llvm::Error decodeRecord(const Record &R, bool &Field, |
43 | llvm::StringRef Blob) { |
44 | Field = R[0] != 0; |
45 | return llvm::Error::success(); |
46 | } |
47 | |
48 | static llvm::Error decodeRecord(const Record &R, AccessSpecifier &Field, |
49 | llvm::StringRef Blob) { |
50 | switch (R[0]) { |
51 | case AS_public: |
52 | case AS_private: |
53 | case AS_protected: |
54 | case AS_none: |
55 | Field = (AccessSpecifier)R[0]; |
56 | return llvm::Error::success(); |
57 | default: |
58 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
59 | S: "invalid value for AccessSpecifier"); |
60 | } |
61 | } |
62 | |
63 | static llvm::Error decodeRecord(const Record &R, TagTypeKind &Field, |
64 | llvm::StringRef Blob) { |
65 | switch (static_cast<TagTypeKind>(R[0])) { |
66 | case TagTypeKind::Struct: |
67 | case TagTypeKind::Interface: |
68 | case TagTypeKind::Union: |
69 | case TagTypeKind::Class: |
70 | case TagTypeKind::Enum: |
71 | Field = static_cast<TagTypeKind>(R[0]); |
72 | return llvm::Error::success(); |
73 | } |
74 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
75 | S: "invalid value for TagTypeKind"); |
76 | } |
77 | |
78 | static llvm::Error decodeRecord(const Record &R, std::optional<Location> &Field, |
79 | llvm::StringRef Blob) { |
80 | if (R[0] > INT_MAX) |
81 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
82 | S: "integer too large to parse"); |
83 | Field.emplace(args: static_cast<int>(R[0]), args: static_cast<int>(R[1]), args&: Blob, |
84 | args: static_cast<bool>(R[2])); |
85 | return llvm::Error::success(); |
86 | } |
87 | |
88 | static llvm::Error decodeRecord(const Record &R, InfoType &Field, |
89 | llvm::StringRef Blob) { |
90 | switch (auto IT = static_cast<InfoType>(R[0])) { |
91 | case InfoType::IT_namespace: |
92 | case InfoType::IT_record: |
93 | case InfoType::IT_function: |
94 | case InfoType::IT_default: |
95 | case InfoType::IT_enum: |
96 | case InfoType::IT_typedef: |
97 | Field = IT; |
98 | return llvm::Error::success(); |
99 | } |
100 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
101 | S: "invalid value for InfoType"); |
102 | } |
103 | |
104 | static llvm::Error decodeRecord(const Record &R, FieldId &Field, |
105 | llvm::StringRef Blob) { |
106 | switch (auto F = static_cast<FieldId>(R[0])) { |
107 | case FieldId::F_namespace: |
108 | case FieldId::F_parent: |
109 | case FieldId::F_vparent: |
110 | case FieldId::F_type: |
111 | case FieldId::F_child_namespace: |
112 | case FieldId::F_child_record: |
113 | case FieldId::F_default: |
114 | Field = F; |
115 | return llvm::Error::success(); |
116 | } |
117 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
118 | S: "invalid value for FieldId"); |
119 | } |
120 | |
121 | static llvm::Error |
122 | decodeRecord(const Record &R, |
123 | llvm::SmallVectorImpl<llvm::SmallString<16>> &Field, |
124 | llvm::StringRef Blob) { |
125 | Field.push_back(Elt: Blob); |
126 | return llvm::Error::success(); |
127 | } |
128 | |
129 | static llvm::Error decodeRecord(const Record &R, |
130 | llvm::SmallVectorImpl<Location> &Field, |
131 | llvm::StringRef Blob) { |
132 | if (R[0] > INT_MAX) |
133 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
134 | S: "integer too large to parse"); |
135 | Field.emplace_back(Args: static_cast<int>(R[0]), Args: static_cast<int>(R[1]), Args&: Blob, |
136 | Args: static_cast<bool>(R[2])); |
137 | return llvm::Error::success(); |
138 | } |
139 | |
140 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
141 | llvm::StringRef Blob, const unsigned VersionNo) { |
142 | if (ID == VERSION && R[0] == VersionNo) |
143 | return llvm::Error::success(); |
144 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
145 | S: "mismatched bitcode version number"); |
146 | } |
147 | |
148 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
149 | llvm::StringRef Blob, NamespaceInfo *I) { |
150 | switch (ID) { |
151 | case NAMESPACE_USR: |
152 | return decodeRecord(R, Field&: I->USR, Blob); |
153 | case NAMESPACE_NAME: |
154 | return decodeRecord(R, Field&: I->Name, Blob); |
155 | case NAMESPACE_PATH: |
156 | return decodeRecord(R, Field&: I->Path, Blob); |
157 | default: |
158 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
159 | S: "invalid field for NamespaceInfo"); |
160 | } |
161 | } |
162 | |
163 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
164 | llvm::StringRef Blob, RecordInfo *I) { |
165 | switch (ID) { |
166 | case RECORD_USR: |
167 | return decodeRecord(R, Field&: I->USR, Blob); |
168 | case RECORD_NAME: |
169 | return decodeRecord(R, Field&: I->Name, Blob); |
170 | case RECORD_PATH: |
171 | return decodeRecord(R, Field&: I->Path, Blob); |
172 | case RECORD_DEFLOCATION: |
173 | return decodeRecord(R, Field&: I->DefLoc, Blob); |
174 | case RECORD_LOCATION: |
175 | return decodeRecord(R, Field&: I->Loc, Blob); |
176 | case RECORD_TAG_TYPE: |
177 | return decodeRecord(R, Field&: I->TagType, Blob); |
178 | case RECORD_IS_TYPE_DEF: |
179 | return decodeRecord(R, Field&: I->IsTypeDef, Blob); |
180 | default: |
181 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
182 | S: "invalid field for RecordInfo"); |
183 | } |
184 | } |
185 | |
186 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
187 | llvm::StringRef Blob, BaseRecordInfo *I) { |
188 | switch (ID) { |
189 | case BASE_RECORD_USR: |
190 | return decodeRecord(R, Field&: I->USR, Blob); |
191 | case BASE_RECORD_NAME: |
192 | return decodeRecord(R, Field&: I->Name, Blob); |
193 | case BASE_RECORD_PATH: |
194 | return decodeRecord(R, Field&: I->Path, Blob); |
195 | case BASE_RECORD_TAG_TYPE: |
196 | return decodeRecord(R, Field&: I->TagType, Blob); |
197 | case BASE_RECORD_IS_VIRTUAL: |
198 | return decodeRecord(R, Field&: I->IsVirtual, Blob); |
199 | case BASE_RECORD_ACCESS: |
200 | return decodeRecord(R, Field&: I->Access, Blob); |
201 | case BASE_RECORD_IS_PARENT: |
202 | return decodeRecord(R, Field&: I->IsParent, Blob); |
203 | default: |
204 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
205 | S: "invalid field for BaseRecordInfo"); |
206 | } |
207 | } |
208 | |
209 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
210 | llvm::StringRef Blob, EnumInfo *I) { |
211 | switch (ID) { |
212 | case ENUM_USR: |
213 | return decodeRecord(R, Field&: I->USR, Blob); |
214 | case ENUM_NAME: |
215 | return decodeRecord(R, Field&: I->Name, Blob); |
216 | case ENUM_DEFLOCATION: |
217 | return decodeRecord(R, Field&: I->DefLoc, Blob); |
218 | case ENUM_LOCATION: |
219 | return decodeRecord(R, Field&: I->Loc, Blob); |
220 | case ENUM_SCOPED: |
221 | return decodeRecord(R, Field&: I->Scoped, Blob); |
222 | default: |
223 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
224 | S: "invalid field for EnumInfo"); |
225 | } |
226 | } |
227 | |
228 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
229 | llvm::StringRef Blob, TypedefInfo *I) { |
230 | switch (ID) { |
231 | case TYPEDEF_USR: |
232 | return decodeRecord(R, Field&: I->USR, Blob); |
233 | case TYPEDEF_NAME: |
234 | return decodeRecord(R, Field&: I->Name, Blob); |
235 | case TYPEDEF_DEFLOCATION: |
236 | return decodeRecord(R, Field&: I->DefLoc, Blob); |
237 | case TYPEDEF_IS_USING: |
238 | return decodeRecord(R, Field&: I->IsUsing, Blob); |
239 | default: |
240 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
241 | S: "invalid field for TypedefInfo"); |
242 | } |
243 | } |
244 | |
245 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
246 | llvm::StringRef Blob, EnumValueInfo *I) { |
247 | switch (ID) { |
248 | case ENUM_VALUE_NAME: |
249 | return decodeRecord(R, Field&: I->Name, Blob); |
250 | case ENUM_VALUE_VALUE: |
251 | return decodeRecord(R, Field&: I->Value, Blob); |
252 | case ENUM_VALUE_EXPR: |
253 | return decodeRecord(R, Field&: I->ValueExpr, Blob); |
254 | default: |
255 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
256 | S: "invalid field for EnumValueInfo"); |
257 | } |
258 | } |
259 | |
260 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
261 | llvm::StringRef Blob, FunctionInfo *I) { |
262 | switch (ID) { |
263 | case FUNCTION_USR: |
264 | return decodeRecord(R, Field&: I->USR, Blob); |
265 | case FUNCTION_NAME: |
266 | return decodeRecord(R, Field&: I->Name, Blob); |
267 | case FUNCTION_DEFLOCATION: |
268 | return decodeRecord(R, Field&: I->DefLoc, Blob); |
269 | case FUNCTION_LOCATION: |
270 | return decodeRecord(R, Field&: I->Loc, Blob); |
271 | case FUNCTION_ACCESS: |
272 | return decodeRecord(R, Field&: I->Access, Blob); |
273 | case FUNCTION_IS_METHOD: |
274 | return decodeRecord(R, Field&: I->IsMethod, Blob); |
275 | case FUNCTION_IS_STATIC: |
276 | return decodeRecord(R, Field&: I->IsStatic, Blob); |
277 | default: |
278 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
279 | S: "invalid field for FunctionInfo"); |
280 | } |
281 | } |
282 | |
283 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
284 | llvm::StringRef Blob, TypeInfo *I) { |
285 | return llvm::Error::success(); |
286 | } |
287 | |
288 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
289 | llvm::StringRef Blob, FieldTypeInfo *I) { |
290 | switch (ID) { |
291 | case FIELD_TYPE_NAME: |
292 | return decodeRecord(R, Field&: I->Name, Blob); |
293 | case FIELD_DEFAULT_VALUE: |
294 | return decodeRecord(R, Field&: I->DefaultValue, Blob); |
295 | default: |
296 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
297 | S: "invalid field for TypeInfo"); |
298 | } |
299 | } |
300 | |
301 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
302 | llvm::StringRef Blob, MemberTypeInfo *I) { |
303 | switch (ID) { |
304 | case MEMBER_TYPE_NAME: |
305 | return decodeRecord(R, Field&: I->Name, Blob); |
306 | case MEMBER_TYPE_ACCESS: |
307 | return decodeRecord(R, Field&: I->Access, Blob); |
308 | case MEMBER_TYPE_IS_STATIC: |
309 | return decodeRecord(R, Field&: I->IsStatic, Blob); |
310 | default: |
311 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
312 | S: "invalid field for MemberTypeInfo"); |
313 | } |
314 | } |
315 | |
316 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
317 | llvm::StringRef Blob, CommentInfo *I) { |
318 | llvm::SmallString<16> KindStr; |
319 | switch (ID) { |
320 | case COMMENT_KIND: |
321 | if (llvm::Error Err = decodeRecord(R, Field&: KindStr, Blob)) |
322 | return Err; |
323 | I->Kind = stringToCommentKind(KindStr); |
324 | return llvm::Error::success(); |
325 | case COMMENT_TEXT: |
326 | return decodeRecord(R, Field&: I->Text, Blob); |
327 | case COMMENT_NAME: |
328 | return decodeRecord(R, Field&: I->Name, Blob); |
329 | case COMMENT_DIRECTION: |
330 | return decodeRecord(R, Field&: I->Direction, Blob); |
331 | case COMMENT_PARAMNAME: |
332 | return decodeRecord(R, Field&: I->ParamName, Blob); |
333 | case COMMENT_CLOSENAME: |
334 | return decodeRecord(R, Field&: I->CloseName, Blob); |
335 | case COMMENT_ATTRKEY: |
336 | return decodeRecord(R, Field&: I->AttrKeys, Blob); |
337 | case COMMENT_ATTRVAL: |
338 | return decodeRecord(R, Field&: I->AttrValues, Blob); |
339 | case COMMENT_ARG: |
340 | return decodeRecord(R, Field&: I->Args, Blob); |
341 | case COMMENT_SELFCLOSING: |
342 | return decodeRecord(R, Field&: I->SelfClosing, Blob); |
343 | case COMMENT_EXPLICIT: |
344 | return decodeRecord(R, Field&: I->Explicit, Blob); |
345 | default: |
346 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
347 | S: "invalid field for CommentInfo"); |
348 | } |
349 | } |
350 | |
351 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
352 | llvm::StringRef Blob, Reference *I, FieldId &F) { |
353 | switch (ID) { |
354 | case REFERENCE_USR: |
355 | return decodeRecord(R, Field&: I->USR, Blob); |
356 | case REFERENCE_NAME: |
357 | return decodeRecord(R, Field&: I->Name, Blob); |
358 | case REFERENCE_QUAL_NAME: |
359 | return decodeRecord(R, Field&: I->QualName, Blob); |
360 | case REFERENCE_TYPE: |
361 | return decodeRecord(R, Field&: I->RefType, Blob); |
362 | case REFERENCE_PATH: |
363 | return decodeRecord(R, Field&: I->Path, Blob); |
364 | case REFERENCE_FIELD: |
365 | return decodeRecord(R, Field&: F, Blob); |
366 | default: |
367 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
368 | S: "invalid field for Reference"); |
369 | } |
370 | } |
371 | |
372 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
373 | llvm::StringRef Blob, TemplateInfo *I) { |
374 | // Currently there are no child records of TemplateInfo (only child blocks). |
375 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
376 | S: "invalid field for TemplateParamInfo"); |
377 | } |
378 | |
379 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
380 | llvm::StringRef Blob, |
381 | TemplateSpecializationInfo *I) { |
382 | if (ID == TEMPLATE_SPECIALIZATION_OF) |
383 | return decodeRecord(R, Field&: I->SpecializationOf, Blob); |
384 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
385 | S: "invalid field for TemplateParamInfo"); |
386 | } |
387 | |
388 | static llvm::Error parseRecord(const Record &R, unsigned ID, |
389 | llvm::StringRef Blob, TemplateParamInfo *I) { |
390 | if (ID == TEMPLATE_PARAM_CONTENTS) |
391 | return decodeRecord(R, Field&: I->Contents, Blob); |
392 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
393 | S: "invalid field for TemplateParamInfo"); |
394 | } |
395 | |
396 | template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) { |
397 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
398 | S: "invalid type cannot contain CommentInfo"); |
399 | } |
400 | |
401 | template <> llvm::Expected<CommentInfo *> getCommentInfo(FunctionInfo *I) { |
402 | return &I->Description.emplace_back(); |
403 | } |
404 | |
405 | template <> llvm::Expected<CommentInfo *> getCommentInfo(NamespaceInfo *I) { |
406 | return &I->Description.emplace_back(); |
407 | } |
408 | |
409 | template <> llvm::Expected<CommentInfo *> getCommentInfo(RecordInfo *I) { |
410 | return &I->Description.emplace_back(); |
411 | } |
412 | |
413 | template <> llvm::Expected<CommentInfo *> getCommentInfo(MemberTypeInfo *I) { |
414 | return &I->Description.emplace_back(); |
415 | } |
416 | |
417 | template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) { |
418 | return &I->Description.emplace_back(); |
419 | } |
420 | |
421 | template <> llvm::Expected<CommentInfo *> getCommentInfo(TypedefInfo *I) { |
422 | return &I->Description.emplace_back(); |
423 | } |
424 | |
425 | template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumValueInfo *I) { |
426 | return &I->Description.emplace_back(); |
427 | } |
428 | |
429 | template <> llvm::Expected<CommentInfo *> getCommentInfo(CommentInfo *I) { |
430 | I->Children.emplace_back(args: std::make_unique<CommentInfo>()); |
431 | return I->Children.back().get(); |
432 | } |
433 | |
434 | // When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on |
435 | // the parent block to set it. The template specializations define what to do |
436 | // for each supported parent block. |
437 | template <typename T, typename TTypeInfo> |
438 | static llvm::Error addTypeInfo(T I, TTypeInfo &&TI) { |
439 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
440 | S: "invalid type cannot contain TypeInfo"); |
441 | } |
442 | |
443 | template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) { |
444 | I->Members.emplace_back(Args: std::move(T)); |
445 | return llvm::Error::success(); |
446 | } |
447 | |
448 | template <> llvm::Error addTypeInfo(BaseRecordInfo *I, MemberTypeInfo &&T) { |
449 | I->Members.emplace_back(Args: std::move(T)); |
450 | return llvm::Error::success(); |
451 | } |
452 | |
453 | template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) { |
454 | I->ReturnType = std::move(T); |
455 | return llvm::Error::success(); |
456 | } |
457 | |
458 | template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) { |
459 | I->Params.emplace_back(Args: std::move(T)); |
460 | return llvm::Error::success(); |
461 | } |
462 | |
463 | template <> llvm::Error addTypeInfo(EnumInfo *I, TypeInfo &&T) { |
464 | I->BaseType = std::move(T); |
465 | return llvm::Error::success(); |
466 | } |
467 | |
468 | template <> llvm::Error addTypeInfo(TypedefInfo *I, TypeInfo &&T) { |
469 | I->Underlying = std::move(T); |
470 | return llvm::Error::success(); |
471 | } |
472 | |
473 | template <typename T> |
474 | static llvm::Error addReference(T I, Reference &&R, FieldId F) { |
475 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
476 | S: "invalid type cannot contain Reference"); |
477 | } |
478 | |
479 | template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F) { |
480 | switch (F) { |
481 | case FieldId::F_type: |
482 | I->Type = std::move(R); |
483 | return llvm::Error::success(); |
484 | default: |
485 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
486 | S: "invalid type cannot contain Reference"); |
487 | } |
488 | } |
489 | |
490 | template <> |
491 | llvm::Error addReference(FieldTypeInfo *I, Reference &&R, FieldId F) { |
492 | switch (F) { |
493 | case FieldId::F_type: |
494 | I->Type = std::move(R); |
495 | return llvm::Error::success(); |
496 | default: |
497 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
498 | S: "invalid type cannot contain Reference"); |
499 | } |
500 | } |
501 | |
502 | template <> |
503 | llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F) { |
504 | switch (F) { |
505 | case FieldId::F_type: |
506 | I->Type = std::move(R); |
507 | return llvm::Error::success(); |
508 | default: |
509 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
510 | S: "invalid type cannot contain Reference"); |
511 | } |
512 | } |
513 | |
514 | template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) { |
515 | switch (F) { |
516 | case FieldId::F_namespace: |
517 | I->Namespace.emplace_back(Args: std::move(R)); |
518 | return llvm::Error::success(); |
519 | default: |
520 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
521 | S: "invalid type cannot contain Reference"); |
522 | } |
523 | } |
524 | |
525 | template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) { |
526 | switch (F) { |
527 | case FieldId::F_namespace: |
528 | I->Namespace.emplace_back(Args: std::move(R)); |
529 | return llvm::Error::success(); |
530 | default: |
531 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
532 | S: "invalid type cannot contain Reference"); |
533 | } |
534 | } |
535 | |
536 | template <> |
537 | llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) { |
538 | switch (F) { |
539 | case FieldId::F_namespace: |
540 | I->Namespace.emplace_back(Args: std::move(R)); |
541 | return llvm::Error::success(); |
542 | case FieldId::F_child_namespace: |
543 | I->Children.Namespaces.emplace_back(args: std::move(R)); |
544 | return llvm::Error::success(); |
545 | case FieldId::F_child_record: |
546 | I->Children.Records.emplace_back(args: std::move(R)); |
547 | return llvm::Error::success(); |
548 | default: |
549 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
550 | S: "invalid type cannot contain Reference"); |
551 | } |
552 | } |
553 | |
554 | template <> |
555 | llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) { |
556 | switch (F) { |
557 | case FieldId::F_namespace: |
558 | I->Namespace.emplace_back(Args: std::move(R)); |
559 | return llvm::Error::success(); |
560 | case FieldId::F_parent: |
561 | I->Parent = std::move(R); |
562 | return llvm::Error::success(); |
563 | default: |
564 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
565 | S: "invalid type cannot contain Reference"); |
566 | } |
567 | } |
568 | |
569 | template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) { |
570 | switch (F) { |
571 | case FieldId::F_namespace: |
572 | I->Namespace.emplace_back(Args: std::move(R)); |
573 | return llvm::Error::success(); |
574 | case FieldId::F_parent: |
575 | I->Parents.emplace_back(Args: std::move(R)); |
576 | return llvm::Error::success(); |
577 | case FieldId::F_vparent: |
578 | I->VirtualParents.emplace_back(Args: std::move(R)); |
579 | return llvm::Error::success(); |
580 | case FieldId::F_child_record: |
581 | I->Children.Records.emplace_back(args: std::move(R)); |
582 | return llvm::Error::success(); |
583 | default: |
584 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
585 | S: "invalid type cannot contain Reference"); |
586 | } |
587 | } |
588 | |
589 | template <typename T, typename ChildInfoType> |
590 | static void addChild(T I, ChildInfoType &&R) { |
591 | llvm::errs() << "invalid child type for info"; |
592 | exit(status: 1); |
593 | } |
594 | |
595 | // Namespace children: |
596 | template <> void addChild(NamespaceInfo *I, FunctionInfo &&R) { |
597 | I->Children.Functions.emplace_back(args: std::move(R)); |
598 | } |
599 | template <> void addChild(NamespaceInfo *I, EnumInfo &&R) { |
600 | I->Children.Enums.emplace_back(args: std::move(R)); |
601 | } |
602 | template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) { |
603 | I->Children.Typedefs.emplace_back(args: std::move(R)); |
604 | } |
605 | |
606 | // Record children: |
607 | template <> void addChild(RecordInfo *I, FunctionInfo &&R) { |
608 | I->Children.Functions.emplace_back(args: std::move(R)); |
609 | } |
610 | template <> void addChild(RecordInfo *I, EnumInfo &&R) { |
611 | I->Children.Enums.emplace_back(args: std::move(R)); |
612 | } |
613 | template <> void addChild(RecordInfo *I, TypedefInfo &&R) { |
614 | I->Children.Typedefs.emplace_back(args: std::move(R)); |
615 | } |
616 | |
617 | // Other types of children: |
618 | template <> void addChild(EnumInfo *I, EnumValueInfo &&R) { |
619 | I->Members.emplace_back(Args: std::move(R)); |
620 | } |
621 | template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) { |
622 | I->Bases.emplace_back(args: std::move(R)); |
623 | } |
624 | template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) { |
625 | I->Children.Functions.emplace_back(args: std::move(R)); |
626 | } |
627 | |
628 | // TemplateParam children. These go into either a TemplateInfo (for template |
629 | // parameters) or TemplateSpecializationInfo (for the specialization's |
630 | // parameters). |
631 | template <typename T> static void addTemplateParam(T I, TemplateParamInfo &&P) { |
632 | llvm::errs() << "invalid container for template parameter"; |
633 | exit(status: 1); |
634 | } |
635 | template <> void addTemplateParam(TemplateInfo *I, TemplateParamInfo &&P) { |
636 | I->Params.emplace_back(args: std::move(P)); |
637 | } |
638 | template <> |
639 | void addTemplateParam(TemplateSpecializationInfo *I, TemplateParamInfo &&P) { |
640 | I->Params.emplace_back(args: std::move(P)); |
641 | } |
642 | |
643 | // Template info. These apply to either records or functions. |
644 | template <typename T> static void addTemplate(T I, TemplateInfo &&P) { |
645 | llvm::errs() << "invalid container for template info"; |
646 | exit(status: 1); |
647 | } |
648 | template <> void addTemplate(RecordInfo *I, TemplateInfo &&P) { |
649 | I->Template.emplace(args: std::move(P)); |
650 | } |
651 | template <> void addTemplate(FunctionInfo *I, TemplateInfo &&P) { |
652 | I->Template.emplace(args: std::move(P)); |
653 | } |
654 | |
655 | // Template specializations go only into template records. |
656 | template <typename T> |
657 | static void addTemplateSpecialization(T I, TemplateSpecializationInfo &&TSI) { |
658 | llvm::errs() << "invalid container for template specialization info"; |
659 | exit(status: 1); |
660 | } |
661 | template <> |
662 | void addTemplateSpecialization(TemplateInfo *I, |
663 | TemplateSpecializationInfo &&TSI) { |
664 | I->Specialization.emplace(args: std::move(TSI)); |
665 | } |
666 | |
667 | // Read records from bitcode into a given info. |
668 | template <typename T> |
669 | llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, T I) { |
670 | Record R; |
671 | llvm::StringRef Blob; |
672 | llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(AbbrevID: ID, Vals&: R, Blob: &Blob); |
673 | if (!MaybeRecID) |
674 | return MaybeRecID.takeError(); |
675 | return parseRecord(R, MaybeRecID.get(), Blob, I); |
676 | } |
677 | |
678 | template <> |
679 | llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) { |
680 | llvm::TimeTraceScope("Reducing infos", "readRecord"); |
681 | Record R; |
682 | llvm::StringRef Blob; |
683 | llvm::Expected<unsigned> MaybeRecID = Stream.readRecord(AbbrevID: ID, Vals&: R, Blob: &Blob); |
684 | if (!MaybeRecID) |
685 | return MaybeRecID.takeError(); |
686 | return parseRecord(R, ID: MaybeRecID.get(), Blob, I, F&: CurrentReferenceField); |
687 | } |
688 | |
689 | // Read a block of records into a single info. |
690 | template <typename T> |
691 | llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) { |
692 | llvm::TimeTraceScope("Reducing infos", "readBlock"); |
693 | if (llvm::Error Err = Stream.EnterSubBlock(BlockID: ID)) |
694 | return Err; |
695 | |
696 | while (true) { |
697 | unsigned BlockOrCode = 0; |
698 | Cursor Res = skipUntilRecordOrBlock(BlockOrRecordID&: BlockOrCode); |
699 | |
700 | switch (Res) { |
701 | case Cursor::BadBlock: |
702 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
703 | S: "bad block found"); |
704 | case Cursor::BlockEnd: |
705 | return llvm::Error::success(); |
706 | case Cursor::BlockBegin: |
707 | if (llvm::Error Err = readSubBlock(BlockOrCode, I)) { |
708 | if (llvm::Error Skipped = Stream.SkipBlock()) |
709 | return joinErrors(E1: std::move(Err), E2: std::move(Skipped)); |
710 | return Err; |
711 | } |
712 | continue; |
713 | case Cursor::Record: |
714 | break; |
715 | } |
716 | if (auto Err = readRecord(BlockOrCode, I)) |
717 | return Err; |
718 | } |
719 | } |
720 | |
721 | template <typename T> |
722 | llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) { |
723 | llvm::TimeTraceScope("Reducing infos", "readSubBlock"); |
724 | switch (ID) { |
725 | // Blocks can only have certain types of sub blocks. |
726 | case BI_COMMENT_BLOCK_ID: { |
727 | auto Comment = getCommentInfo(I); |
728 | if (!Comment) |
729 | return Comment.takeError(); |
730 | if (auto Err = readBlock(ID, Comment.get())) |
731 | return Err; |
732 | return llvm::Error::success(); |
733 | } |
734 | case BI_TYPE_BLOCK_ID: { |
735 | TypeInfo TI; |
736 | if (auto Err = readBlock(ID, I: &TI)) |
737 | return Err; |
738 | if (auto Err = addTypeInfo(I, std::move(TI))) |
739 | return Err; |
740 | return llvm::Error::success(); |
741 | } |
742 | case BI_FIELD_TYPE_BLOCK_ID: { |
743 | FieldTypeInfo TI; |
744 | if (auto Err = readBlock(ID, I: &TI)) |
745 | return Err; |
746 | if (auto Err = addTypeInfo(I, std::move(TI))) |
747 | return Err; |
748 | return llvm::Error::success(); |
749 | } |
750 | case BI_MEMBER_TYPE_BLOCK_ID: { |
751 | MemberTypeInfo TI; |
752 | if (auto Err = readBlock(ID, I: &TI)) |
753 | return Err; |
754 | if (auto Err = addTypeInfo(I, std::move(TI))) |
755 | return Err; |
756 | return llvm::Error::success(); |
757 | } |
758 | case BI_REFERENCE_BLOCK_ID: { |
759 | Reference R; |
760 | if (auto Err = readBlock(ID, I: &R)) |
761 | return Err; |
762 | if (auto Err = addReference(I, std::move(R), CurrentReferenceField)) |
763 | return Err; |
764 | return llvm::Error::success(); |
765 | } |
766 | case BI_FUNCTION_BLOCK_ID: { |
767 | FunctionInfo F; |
768 | if (auto Err = readBlock(ID, I: &F)) |
769 | return Err; |
770 | addChild(I, std::move(F)); |
771 | return llvm::Error::success(); |
772 | } |
773 | case BI_BASE_RECORD_BLOCK_ID: { |
774 | BaseRecordInfo BR; |
775 | if (auto Err = readBlock(ID, I: &BR)) |
776 | return Err; |
777 | addChild(I, std::move(BR)); |
778 | return llvm::Error::success(); |
779 | } |
780 | case BI_ENUM_BLOCK_ID: { |
781 | EnumInfo E; |
782 | if (auto Err = readBlock(ID, I: &E)) |
783 | return Err; |
784 | addChild(I, std::move(E)); |
785 | return llvm::Error::success(); |
786 | } |
787 | case BI_ENUM_VALUE_BLOCK_ID: { |
788 | EnumValueInfo EV; |
789 | if (auto Err = readBlock(ID, I: &EV)) |
790 | return Err; |
791 | addChild(I, std::move(EV)); |
792 | return llvm::Error::success(); |
793 | } |
794 | case BI_TEMPLATE_BLOCK_ID: { |
795 | TemplateInfo TI; |
796 | if (auto Err = readBlock(ID, I: &TI)) |
797 | return Err; |
798 | addTemplate(I, std::move(TI)); |
799 | return llvm::Error::success(); |
800 | } |
801 | case BI_TEMPLATE_SPECIALIZATION_BLOCK_ID: { |
802 | TemplateSpecializationInfo TSI; |
803 | if (auto Err = readBlock(ID, I: &TSI)) |
804 | return Err; |
805 | addTemplateSpecialization(I, std::move(TSI)); |
806 | return llvm::Error::success(); |
807 | } |
808 | case BI_TEMPLATE_PARAM_BLOCK_ID: { |
809 | TemplateParamInfo TPI; |
810 | if (auto Err = readBlock(ID, I: &TPI)) |
811 | return Err; |
812 | addTemplateParam(I, std::move(TPI)); |
813 | return llvm::Error::success(); |
814 | } |
815 | case BI_TYPEDEF_BLOCK_ID: { |
816 | TypedefInfo TI; |
817 | if (auto Err = readBlock(ID, I: &TI)) |
818 | return Err; |
819 | addChild(I, std::move(TI)); |
820 | return llvm::Error::success(); |
821 | } |
822 | default: |
823 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
824 | S: "invalid subblock type"); |
825 | } |
826 | } |
827 | |
828 | ClangDocBitcodeReader::Cursor |
829 | ClangDocBitcodeReader::skipUntilRecordOrBlock(unsigned &BlockOrRecordID) { |
830 | llvm::TimeTraceScope("Reducing infos", "skipUntilRecordOrBlock"); |
831 | BlockOrRecordID = 0; |
832 | |
833 | while (!Stream.AtEndOfStream()) { |
834 | Expected<unsigned> MaybeCode = Stream.ReadCode(); |
835 | if (!MaybeCode) { |
836 | // FIXME this drops the error on the floor. |
837 | consumeError(Err: MaybeCode.takeError()); |
838 | return Cursor::BadBlock; |
839 | } |
840 | |
841 | unsigned Code = MaybeCode.get(); |
842 | if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) { |
843 | BlockOrRecordID = Code; |
844 | return Cursor::Record; |
845 | } |
846 | switch (static_cast<llvm::bitc::FixedAbbrevIDs>(Code)) { |
847 | case llvm::bitc::ENTER_SUBBLOCK: |
848 | if (Expected<unsigned> MaybeID = Stream.ReadSubBlockID()) |
849 | BlockOrRecordID = MaybeID.get(); |
850 | else { |
851 | // FIXME this drops the error on the floor. |
852 | consumeError(Err: MaybeID.takeError()); |
853 | } |
854 | return Cursor::BlockBegin; |
855 | case llvm::bitc::END_BLOCK: |
856 | if (Stream.ReadBlockEnd()) |
857 | return Cursor::BadBlock; |
858 | return Cursor::BlockEnd; |
859 | case llvm::bitc::DEFINE_ABBREV: |
860 | if (llvm::Error Err = Stream.ReadAbbrevRecord()) { |
861 | // FIXME this drops the error on the floor. |
862 | consumeError(Err: std::move(Err)); |
863 | } |
864 | continue; |
865 | case llvm::bitc::UNABBREV_RECORD: |
866 | return Cursor::BadBlock; |
867 | case llvm::bitc::FIRST_APPLICATION_ABBREV: |
868 | llvm_unreachable("Unexpected abbrev id."); |
869 | } |
870 | } |
871 | llvm_unreachable("Premature stream end."); |
872 | } |
873 | |
874 | llvm::Error ClangDocBitcodeReader::validateStream() { |
875 | if (Stream.AtEndOfStream()) |
876 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
877 | S: "premature end of stream"); |
878 | |
879 | // Sniff for the signature. |
880 | for (int Idx = 0; Idx != 4; ++Idx) { |
881 | Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(NumBits: 8); |
882 | if (!MaybeRead) |
883 | return MaybeRead.takeError(); |
884 | if (MaybeRead.get() != BitCodeConstants::Signature[Idx]) |
885 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
886 | S: "invalid bitcode signature"); |
887 | } |
888 | return llvm::Error::success(); |
889 | } |
890 | |
891 | llvm::Error ClangDocBitcodeReader::readBlockInfoBlock() { |
892 | llvm::TimeTraceScope("Reducing infos", "readBlockInfoBlock"); |
893 | Expected<std::optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo = |
894 | Stream.ReadBlockInfoBlock(); |
895 | if (!MaybeBlockInfo) |
896 | return MaybeBlockInfo.takeError(); |
897 | BlockInfo = MaybeBlockInfo.get(); |
898 | if (!BlockInfo) |
899 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
900 | S: "unable to parse BlockInfoBlock"); |
901 | Stream.setBlockInfo(&*BlockInfo); |
902 | return llvm::Error::success(); |
903 | } |
904 | |
905 | template <typename T> |
906 | llvm::Expected<std::unique_ptr<Info>> |
907 | ClangDocBitcodeReader::createInfo(unsigned ID) { |
908 | llvm::TimeTraceScope("Reducing infos", "createInfo"); |
909 | std::unique_ptr<Info> I = std::make_unique<T>(); |
910 | if (auto Err = readBlock(ID, static_cast<T *>(I.get()))) |
911 | return std::move(Err); |
912 | return std::unique_ptr<Info>{std::move(I)}; |
913 | } |
914 | |
915 | llvm::Expected<std::unique_ptr<Info>> |
916 | ClangDocBitcodeReader::readBlockToInfo(unsigned ID) { |
917 | llvm::TimeTraceScope("Reducing infos", "readBlockToInfo"); |
918 | switch (ID) { |
919 | case BI_NAMESPACE_BLOCK_ID: |
920 | return createInfo<NamespaceInfo>(ID); |
921 | case BI_RECORD_BLOCK_ID: |
922 | return createInfo<RecordInfo>(ID); |
923 | case BI_ENUM_BLOCK_ID: |
924 | return createInfo<EnumInfo>(ID); |
925 | case BI_TYPEDEF_BLOCK_ID: |
926 | return createInfo<TypedefInfo>(ID); |
927 | case BI_FUNCTION_BLOCK_ID: |
928 | return createInfo<FunctionInfo>(ID); |
929 | default: |
930 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
931 | S: "cannot create info"); |
932 | } |
933 | } |
934 | |
935 | // Entry point |
936 | llvm::Expected<std::vector<std::unique_ptr<Info>>> |
937 | ClangDocBitcodeReader::readBitcode() { |
938 | std::vector<std::unique_ptr<Info>> Infos; |
939 | if (auto Err = validateStream()) |
940 | return std::move(Err); |
941 | |
942 | // Read the top level blocks. |
943 | while (!Stream.AtEndOfStream()) { |
944 | Expected<unsigned> MaybeCode = Stream.ReadCode(); |
945 | if (!MaybeCode) |
946 | return MaybeCode.takeError(); |
947 | if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK) |
948 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
949 | S: "no blocks in input"); |
950 | Expected<unsigned> MaybeID = Stream.ReadSubBlockID(); |
951 | if (!MaybeID) |
952 | return MaybeID.takeError(); |
953 | unsigned ID = MaybeID.get(); |
954 | switch (ID) { |
955 | // NamedType and Comment blocks should not appear at the top level |
956 | case BI_TYPE_BLOCK_ID: |
957 | case BI_FIELD_TYPE_BLOCK_ID: |
958 | case BI_MEMBER_TYPE_BLOCK_ID: |
959 | case BI_COMMENT_BLOCK_ID: |
960 | case BI_REFERENCE_BLOCK_ID: |
961 | return llvm::createStringError(EC: llvm::inconvertibleErrorCode(), |
962 | S: "invalid top level block"); |
963 | case BI_NAMESPACE_BLOCK_ID: |
964 | case BI_RECORD_BLOCK_ID: |
965 | case BI_ENUM_BLOCK_ID: |
966 | case BI_TYPEDEF_BLOCK_ID: |
967 | case BI_FUNCTION_BLOCK_ID: { |
968 | auto InfoOrErr = readBlockToInfo(ID); |
969 | if (!InfoOrErr) |
970 | return InfoOrErr.takeError(); |
971 | Infos.emplace_back(args: std::move(InfoOrErr.get())); |
972 | continue; |
973 | } |
974 | case BI_VERSION_BLOCK_ID: |
975 | if (auto Err = readBlock(ID, I: VersionNumber)) |
976 | return std::move(Err); |
977 | continue; |
978 | case llvm::bitc::BLOCKINFO_BLOCK_ID: |
979 | if (auto Err = readBlockInfoBlock()) |
980 | return std::move(Err); |
981 | continue; |
982 | default: |
983 | if (llvm::Error Err = Stream.SkipBlock()) { |
984 | // FIXME this drops the error on the floor. |
985 | consumeError(Err: std::move(Err)); |
986 | } |
987 | continue; |
988 | } |
989 | } |
990 | return std::move(Infos); |
991 | } |
992 | |
993 | } // namespace doc |
994 | } // namespace clang |
995 |
Definitions
- decodeRecord
- decodeRecord
- decodeRecord
- decodeRecord
- decodeRecord
- decodeRecord
- decodeRecord
- decodeRecord
- decodeRecord
- decodeRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- parseRecord
- getCommentInfo
- getCommentInfo
- getCommentInfo
- getCommentInfo
- getCommentInfo
- getCommentInfo
- getCommentInfo
- getCommentInfo
- getCommentInfo
- addTypeInfo
- addTypeInfo
- addTypeInfo
- addTypeInfo
- addTypeInfo
- addTypeInfo
- addTypeInfo
- addReference
- addReference
- addReference
- addReference
- addReference
- addReference
- addReference
- addReference
- addReference
- addChild
- addChild
- addChild
- addChild
- addChild
- addChild
- addChild
- addChild
- addChild
- addChild
- addTemplateParam
- addTemplateParam
- addTemplateParam
- addTemplate
- addTemplate
- addTemplate
- addTemplateSpecialization
- addTemplateSpecialization
- readRecord
- readRecord
- readBlock
- readSubBlock
- skipUntilRecordOrBlock
- validateStream
- readBlockInfoBlock
- createInfo
- readBlockToInfo
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more