BitcodeWriter.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. //===-- BitcodeWriter.cpp - ClangDoc Bitcode Writer ------------*- 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. #include "BitcodeWriter.h"
  9. #include "llvm/ADT/IndexedMap.h"
  10. #include <initializer_list>
  11. namespace clang {
  12. namespace doc {
  13. // Empty SymbolID for comparison, so we don't have to construct one every time.
  14. static const SymbolID EmptySID = SymbolID();
  15. // Since id enums are not zero-indexed, we need to transform the given id into
  16. // its associated index.
  17. struct BlockIdToIndexFunctor {
  18. using argument_type = unsigned;
  19. unsigned operator()(unsigned ID) const { return ID - BI_FIRST; }
  20. };
  21. struct RecordIdToIndexFunctor {
  22. using argument_type = unsigned;
  23. unsigned operator()(unsigned ID) const { return ID - RI_FIRST; }
  24. };
  25. using AbbrevDsc = void (*)(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev);
  26. static void AbbrevGen(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev,
  27. const std::initializer_list<llvm::BitCodeAbbrevOp> Ops) {
  28. for (const auto &Op : Ops)
  29. Abbrev->Add(Op);
  30. }
  31. static void BoolAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
  32. AbbrevGen(Abbrev,
  33. {// 0. Boolean
  34. llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
  35. BitCodeConstants::BoolSize)});
  36. }
  37. static void IntAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
  38. AbbrevGen(Abbrev,
  39. {// 0. Fixed-size integer
  40. llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
  41. BitCodeConstants::IntSize)});
  42. }
  43. static void SymbolIDAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
  44. AbbrevGen(Abbrev,
  45. {// 0. Fixed-size integer (length of the sha1'd USR)
  46. llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
  47. BitCodeConstants::USRLengthSize),
  48. // 1. Fixed-size array of Char6 (USR)
  49. llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array),
  50. llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
  51. BitCodeConstants::USRBitLengthSize)});
  52. }
  53. static void StringAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
  54. AbbrevGen(Abbrev,
  55. {// 0. Fixed-size integer (length of the following string)
  56. llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
  57. BitCodeConstants::StringLengthSize),
  58. // 1. The string blob
  59. llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});
  60. }
  61. // Assumes that the file will not have more than 65535 lines.
  62. static void LocationAbbrev(std::shared_ptr<llvm::BitCodeAbbrev> &Abbrev) {
  63. AbbrevGen(
  64. Abbrev,
  65. {// 0. Fixed-size integer (line number)
  66. llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
  67. BitCodeConstants::LineNumberSize),
  68. // 1. Boolean (IsFileInRootDir)
  69. llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
  70. BitCodeConstants::BoolSize),
  71. // 2. Fixed-size integer (length of the following string (filename))
  72. llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Fixed,
  73. BitCodeConstants::StringLengthSize),
  74. // 3. The string blob
  75. llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)});
  76. }
  77. struct RecordIdDsc {
  78. llvm::StringRef Name;
  79. AbbrevDsc Abbrev = nullptr;
  80. RecordIdDsc() = default;
  81. RecordIdDsc(llvm::StringRef Name, AbbrevDsc Abbrev)
  82. : Name(Name), Abbrev(Abbrev) {}
  83. // Is this 'description' valid?
  84. operator bool() const {
  85. return Abbrev != nullptr && Name.data() != nullptr && !Name.empty();
  86. }
  87. };
  88. static const llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor>
  89. BlockIdNameMap = []() {
  90. llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor> BlockIdNameMap;
  91. BlockIdNameMap.resize(BlockIdCount);
  92. // There is no init-list constructor for the IndexedMap, so have to
  93. // improvise
  94. static const std::vector<std::pair<BlockId, const char *const>> Inits = {
  95. {BI_VERSION_BLOCK_ID, "VersionBlock"},
  96. {BI_NAMESPACE_BLOCK_ID, "NamespaceBlock"},
  97. {BI_ENUM_BLOCK_ID, "EnumBlock"},
  98. {BI_ENUM_VALUE_BLOCK_ID, "EnumValueBlock"},
  99. {BI_TYPEDEF_BLOCK_ID, "TypedefBlock"},
  100. {BI_TYPE_BLOCK_ID, "TypeBlock"},
  101. {BI_FIELD_TYPE_BLOCK_ID, "FieldTypeBlock"},
  102. {BI_MEMBER_TYPE_BLOCK_ID, "MemberTypeBlock"},
  103. {BI_RECORD_BLOCK_ID, "RecordBlock"},
  104. {BI_BASE_RECORD_BLOCK_ID, "BaseRecordBlock"},
  105. {BI_FUNCTION_BLOCK_ID, "FunctionBlock"},
  106. {BI_COMMENT_BLOCK_ID, "CommentBlock"},
  107. {BI_REFERENCE_BLOCK_ID, "ReferenceBlock"},
  108. {BI_TEMPLATE_BLOCK_ID, "TemplateBlock"},
  109. {BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, "TemplateSpecializationBlock"},
  110. {BI_TEMPLATE_PARAM_BLOCK_ID, "TemplateParamBlock"}};
  111. assert(Inits.size() == BlockIdCount);
  112. for (const auto &Init : Inits)
  113. BlockIdNameMap[Init.first] = Init.second;
  114. assert(BlockIdNameMap.size() == BlockIdCount);
  115. return BlockIdNameMap;
  116. }();
  117. static const llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor>
  118. RecordIdNameMap = []() {
  119. llvm::IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> RecordIdNameMap;
  120. RecordIdNameMap.resize(RecordIdCount);
  121. // There is no init-list constructor for the IndexedMap, so have to
  122. // improvise
  123. static const std::vector<std::pair<RecordId, RecordIdDsc>> Inits = {
  124. {VERSION, {"Version", &IntAbbrev}},
  125. {COMMENT_KIND, {"Kind", &StringAbbrev}},
  126. {COMMENT_TEXT, {"Text", &StringAbbrev}},
  127. {COMMENT_NAME, {"Name", &StringAbbrev}},
  128. {COMMENT_DIRECTION, {"Direction", &StringAbbrev}},
  129. {COMMENT_PARAMNAME, {"ParamName", &StringAbbrev}},
  130. {COMMENT_CLOSENAME, {"CloseName", &StringAbbrev}},
  131. {COMMENT_SELFCLOSING, {"SelfClosing", &BoolAbbrev}},
  132. {COMMENT_EXPLICIT, {"Explicit", &BoolAbbrev}},
  133. {COMMENT_ATTRKEY, {"AttrKey", &StringAbbrev}},
  134. {COMMENT_ATTRVAL, {"AttrVal", &StringAbbrev}},
  135. {COMMENT_ARG, {"Arg", &StringAbbrev}},
  136. {FIELD_TYPE_NAME, {"Name", &StringAbbrev}},
  137. {FIELD_DEFAULT_VALUE, {"DefaultValue", &StringAbbrev}},
  138. {MEMBER_TYPE_NAME, {"Name", &StringAbbrev}},
  139. {MEMBER_TYPE_ACCESS, {"Access", &IntAbbrev}},
  140. {NAMESPACE_USR, {"USR", &SymbolIDAbbrev}},
  141. {NAMESPACE_NAME, {"Name", &StringAbbrev}},
  142. {NAMESPACE_PATH, {"Path", &StringAbbrev}},
  143. {ENUM_USR, {"USR", &SymbolIDAbbrev}},
  144. {ENUM_NAME, {"Name", &StringAbbrev}},
  145. {ENUM_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
  146. {ENUM_LOCATION, {"Location", &LocationAbbrev}},
  147. {ENUM_SCOPED, {"Scoped", &BoolAbbrev}},
  148. {ENUM_VALUE_NAME, {"Name", &StringAbbrev}},
  149. {ENUM_VALUE_VALUE, {"Value", &StringAbbrev}},
  150. {ENUM_VALUE_EXPR, {"Expr", &StringAbbrev}},
  151. {RECORD_USR, {"USR", &SymbolIDAbbrev}},
  152. {RECORD_NAME, {"Name", &StringAbbrev}},
  153. {RECORD_PATH, {"Path", &StringAbbrev}},
  154. {RECORD_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
  155. {RECORD_LOCATION, {"Location", &LocationAbbrev}},
  156. {RECORD_TAG_TYPE, {"TagType", &IntAbbrev}},
  157. {RECORD_IS_TYPE_DEF, {"IsTypeDef", &BoolAbbrev}},
  158. {BASE_RECORD_USR, {"USR", &SymbolIDAbbrev}},
  159. {BASE_RECORD_NAME, {"Name", &StringAbbrev}},
  160. {BASE_RECORD_PATH, {"Path", &StringAbbrev}},
  161. {BASE_RECORD_TAG_TYPE, {"TagType", &IntAbbrev}},
  162. {BASE_RECORD_IS_VIRTUAL, {"IsVirtual", &BoolAbbrev}},
  163. {BASE_RECORD_ACCESS, {"Access", &IntAbbrev}},
  164. {BASE_RECORD_IS_PARENT, {"IsParent", &BoolAbbrev}},
  165. {FUNCTION_USR, {"USR", &SymbolIDAbbrev}},
  166. {FUNCTION_NAME, {"Name", &StringAbbrev}},
  167. {FUNCTION_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
  168. {FUNCTION_LOCATION, {"Location", &LocationAbbrev}},
  169. {FUNCTION_ACCESS, {"Access", &IntAbbrev}},
  170. {FUNCTION_IS_METHOD, {"IsMethod", &BoolAbbrev}},
  171. {REFERENCE_USR, {"USR", &SymbolIDAbbrev}},
  172. {REFERENCE_NAME, {"Name", &StringAbbrev}},
  173. {REFERENCE_QUAL_NAME, {"QualName", &StringAbbrev}},
  174. {REFERENCE_TYPE, {"RefType", &IntAbbrev}},
  175. {REFERENCE_PATH, {"Path", &StringAbbrev}},
  176. {REFERENCE_FIELD, {"Field", &IntAbbrev}},
  177. {TEMPLATE_PARAM_CONTENTS, {"Contents", &StringAbbrev}},
  178. {TEMPLATE_SPECIALIZATION_OF, {"SpecializationOf", &SymbolIDAbbrev}},
  179. {TYPEDEF_USR, {"USR", &SymbolIDAbbrev}},
  180. {TYPEDEF_NAME, {"Name", &StringAbbrev}},
  181. {TYPEDEF_DEFLOCATION, {"DefLocation", &LocationAbbrev}},
  182. {TYPEDEF_IS_USING, {"IsUsing", &BoolAbbrev}}};
  183. assert(Inits.size() == RecordIdCount);
  184. for (const auto &Init : Inits) {
  185. RecordIdNameMap[Init.first] = Init.second;
  186. assert((Init.second.Name.size() + 1) <= BitCodeConstants::RecordSize);
  187. }
  188. assert(RecordIdNameMap.size() == RecordIdCount);
  189. return RecordIdNameMap;
  190. }();
  191. static const std::vector<std::pair<BlockId, std::vector<RecordId>>>
  192. RecordsByBlock{
  193. // Version Block
  194. {BI_VERSION_BLOCK_ID, {VERSION}},
  195. // Comment Block
  196. {BI_COMMENT_BLOCK_ID,
  197. {COMMENT_KIND, COMMENT_TEXT, COMMENT_NAME, COMMENT_DIRECTION,
  198. COMMENT_PARAMNAME, COMMENT_CLOSENAME, COMMENT_SELFCLOSING,
  199. COMMENT_EXPLICIT, COMMENT_ATTRKEY, COMMENT_ATTRVAL, COMMENT_ARG}},
  200. // Type Block
  201. {BI_TYPE_BLOCK_ID, {}},
  202. // FieldType Block
  203. {BI_FIELD_TYPE_BLOCK_ID, {FIELD_TYPE_NAME, FIELD_DEFAULT_VALUE}},
  204. // MemberType Block
  205. {BI_MEMBER_TYPE_BLOCK_ID, {MEMBER_TYPE_NAME, MEMBER_TYPE_ACCESS}},
  206. // Enum Block
  207. {BI_ENUM_BLOCK_ID,
  208. {ENUM_USR, ENUM_NAME, ENUM_DEFLOCATION, ENUM_LOCATION, ENUM_SCOPED}},
  209. // Enum Value Block
  210. {BI_ENUM_VALUE_BLOCK_ID,
  211. {ENUM_VALUE_NAME, ENUM_VALUE_VALUE, ENUM_VALUE_EXPR}},
  212. // Typedef Block
  213. {BI_TYPEDEF_BLOCK_ID,
  214. {TYPEDEF_USR, TYPEDEF_NAME, TYPEDEF_DEFLOCATION, TYPEDEF_IS_USING}},
  215. // Namespace Block
  216. {BI_NAMESPACE_BLOCK_ID,
  217. {NAMESPACE_USR, NAMESPACE_NAME, NAMESPACE_PATH}},
  218. // Record Block
  219. {BI_RECORD_BLOCK_ID,
  220. {RECORD_USR, RECORD_NAME, RECORD_PATH, RECORD_DEFLOCATION,
  221. RECORD_LOCATION, RECORD_TAG_TYPE, RECORD_IS_TYPE_DEF}},
  222. // BaseRecord Block
  223. {BI_BASE_RECORD_BLOCK_ID,
  224. {BASE_RECORD_USR, BASE_RECORD_NAME, BASE_RECORD_PATH,
  225. BASE_RECORD_TAG_TYPE, BASE_RECORD_IS_VIRTUAL, BASE_RECORD_ACCESS,
  226. BASE_RECORD_IS_PARENT}},
  227. // Function Block
  228. {BI_FUNCTION_BLOCK_ID,
  229. {FUNCTION_USR, FUNCTION_NAME, FUNCTION_DEFLOCATION, FUNCTION_LOCATION,
  230. FUNCTION_ACCESS, FUNCTION_IS_METHOD}},
  231. // Reference Block
  232. {BI_REFERENCE_BLOCK_ID,
  233. {REFERENCE_USR, REFERENCE_NAME, REFERENCE_QUAL_NAME, REFERENCE_TYPE,
  234. REFERENCE_PATH, REFERENCE_FIELD}},
  235. // Template Blocks.
  236. {BI_TEMPLATE_BLOCK_ID, {}},
  237. {BI_TEMPLATE_PARAM_BLOCK_ID, {TEMPLATE_PARAM_CONTENTS}},
  238. {BI_TEMPLATE_SPECIALIZATION_BLOCK_ID, {TEMPLATE_SPECIALIZATION_OF}}};
  239. // AbbreviationMap
  240. constexpr unsigned char BitCodeConstants::Signature[];
  241. void ClangDocBitcodeWriter::AbbreviationMap::add(RecordId RID,
  242. unsigned AbbrevID) {
  243. assert(RecordIdNameMap[RID] && "Unknown RecordId.");
  244. assert(Abbrevs.find(RID) == Abbrevs.end() && "Abbreviation already added.");
  245. Abbrevs[RID] = AbbrevID;
  246. }
  247. unsigned ClangDocBitcodeWriter::AbbreviationMap::get(RecordId RID) const {
  248. assert(RecordIdNameMap[RID] && "Unknown RecordId.");
  249. assert(Abbrevs.find(RID) != Abbrevs.end() && "Unknown abbreviation.");
  250. return Abbrevs.lookup(RID);
  251. }
  252. // Validation and Overview Blocks
  253. /// Emits the magic number header to check that its the right format,
  254. /// in this case, 'DOCS'.
  255. void ClangDocBitcodeWriter::emitHeader() {
  256. for (char C : BitCodeConstants::Signature)
  257. Stream.Emit((unsigned)C, BitCodeConstants::SignatureBitSize);
  258. }
  259. void ClangDocBitcodeWriter::emitVersionBlock() {
  260. StreamSubBlockGuard Block(Stream, BI_VERSION_BLOCK_ID);
  261. emitRecord(VersionNumber, VERSION);
  262. }
  263. /// Emits a block ID and the block name to the BLOCKINFO block.
  264. void ClangDocBitcodeWriter::emitBlockID(BlockId BID) {
  265. const auto &BlockIdName = BlockIdNameMap[BID];
  266. assert(BlockIdName.data() && BlockIdName.size() && "Unknown BlockId.");
  267. Record.clear();
  268. Record.push_back(BID);
  269. Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record);
  270. Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
  271. ArrayRef<unsigned char>(BlockIdName.bytes_begin(),
  272. BlockIdName.bytes_end()));
  273. }
  274. /// Emits a record name to the BLOCKINFO block.
  275. void ClangDocBitcodeWriter::emitRecordID(RecordId ID) {
  276. assert(RecordIdNameMap[ID] && "Unknown RecordId.");
  277. prepRecordData(ID);
  278. Record.append(RecordIdNameMap[ID].Name.begin(),
  279. RecordIdNameMap[ID].Name.end());
  280. Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
  281. }
  282. // Abbreviations
  283. void ClangDocBitcodeWriter::emitAbbrev(RecordId ID, BlockId Block) {
  284. assert(RecordIdNameMap[ID] && "Unknown abbreviation.");
  285. auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>();
  286. Abbrev->Add(llvm::BitCodeAbbrevOp(ID));
  287. RecordIdNameMap[ID].Abbrev(Abbrev);
  288. Abbrevs.add(ID, Stream.EmitBlockInfoAbbrev(Block, std::move(Abbrev)));
  289. }
  290. // Records
  291. void ClangDocBitcodeWriter::emitRecord(const SymbolID &Sym, RecordId ID) {
  292. assert(RecordIdNameMap[ID] && "Unknown RecordId.");
  293. assert(RecordIdNameMap[ID].Abbrev == &SymbolIDAbbrev &&
  294. "Abbrev type mismatch.");
  295. if (!prepRecordData(ID, Sym != EmptySID))
  296. return;
  297. assert(Sym.size() == 20);
  298. Record.push_back(Sym.size());
  299. Record.append(Sym.begin(), Sym.end());
  300. Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
  301. }
  302. void ClangDocBitcodeWriter::emitRecord(llvm::StringRef Str, RecordId ID) {
  303. assert(RecordIdNameMap[ID] && "Unknown RecordId.");
  304. assert(RecordIdNameMap[ID].Abbrev == &StringAbbrev &&
  305. "Abbrev type mismatch.");
  306. if (!prepRecordData(ID, !Str.empty()))
  307. return;
  308. assert(Str.size() < (1U << BitCodeConstants::StringLengthSize));
  309. Record.push_back(Str.size());
  310. Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Str);
  311. }
  312. void ClangDocBitcodeWriter::emitRecord(const Location &Loc, RecordId ID) {
  313. assert(RecordIdNameMap[ID] && "Unknown RecordId.");
  314. assert(RecordIdNameMap[ID].Abbrev == &LocationAbbrev &&
  315. "Abbrev type mismatch.");
  316. if (!prepRecordData(ID, true))
  317. return;
  318. // FIXME: Assert that the line number is of the appropriate size.
  319. Record.push_back(Loc.LineNumber);
  320. assert(Loc.Filename.size() < (1U << BitCodeConstants::StringLengthSize));
  321. Record.push_back(Loc.IsFileInRootDir);
  322. Record.push_back(Loc.Filename.size());
  323. Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Loc.Filename);
  324. }
  325. void ClangDocBitcodeWriter::emitRecord(bool Val, RecordId ID) {
  326. assert(RecordIdNameMap[ID] && "Unknown RecordId.");
  327. assert(RecordIdNameMap[ID].Abbrev == &BoolAbbrev && "Abbrev type mismatch.");
  328. if (!prepRecordData(ID, Val))
  329. return;
  330. Record.push_back(Val);
  331. Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
  332. }
  333. void ClangDocBitcodeWriter::emitRecord(int Val, RecordId ID) {
  334. assert(RecordIdNameMap[ID] && "Unknown RecordId.");
  335. assert(RecordIdNameMap[ID].Abbrev == &IntAbbrev && "Abbrev type mismatch.");
  336. if (!prepRecordData(ID, Val))
  337. return;
  338. // FIXME: Assert that the integer is of the appropriate size.
  339. Record.push_back(Val);
  340. Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
  341. }
  342. void ClangDocBitcodeWriter::emitRecord(unsigned Val, RecordId ID) {
  343. assert(RecordIdNameMap[ID] && "Unknown RecordId.");
  344. assert(RecordIdNameMap[ID].Abbrev == &IntAbbrev && "Abbrev type mismatch.");
  345. if (!prepRecordData(ID, Val))
  346. return;
  347. assert(Val < (1U << BitCodeConstants::IntSize));
  348. Record.push_back(Val);
  349. Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record);
  350. }
  351. void ClangDocBitcodeWriter::emitRecord(const TemplateInfo &Templ) {}
  352. bool ClangDocBitcodeWriter::prepRecordData(RecordId ID, bool ShouldEmit) {
  353. assert(RecordIdNameMap[ID] && "Unknown RecordId.");
  354. if (!ShouldEmit)
  355. return false;
  356. Record.clear();
  357. Record.push_back(ID);
  358. return true;
  359. }
  360. // BlockInfo Block
  361. void ClangDocBitcodeWriter::emitBlockInfoBlock() {
  362. Stream.EnterBlockInfoBlock();
  363. for (const auto &Block : RecordsByBlock) {
  364. assert(Block.second.size() < (1U << BitCodeConstants::SubblockIDSize));
  365. emitBlockInfo(Block.first, Block.second);
  366. }
  367. Stream.ExitBlock();
  368. }
  369. void ClangDocBitcodeWriter::emitBlockInfo(BlockId BID,
  370. const std::vector<RecordId> &RIDs) {
  371. assert(RIDs.size() < (1U << BitCodeConstants::SubblockIDSize));
  372. emitBlockID(BID);
  373. for (RecordId RID : RIDs) {
  374. emitRecordID(RID);
  375. emitAbbrev(RID, BID);
  376. }
  377. }
  378. // Block emission
  379. void ClangDocBitcodeWriter::emitBlock(const Reference &R, FieldId Field) {
  380. if (R.USR == EmptySID && R.Name.empty())
  381. return;
  382. StreamSubBlockGuard Block(Stream, BI_REFERENCE_BLOCK_ID);
  383. emitRecord(R.USR, REFERENCE_USR);
  384. emitRecord(R.Name, REFERENCE_NAME);
  385. emitRecord(R.QualName, REFERENCE_QUAL_NAME);
  386. emitRecord((unsigned)R.RefType, REFERENCE_TYPE);
  387. emitRecord(R.Path, REFERENCE_PATH);
  388. emitRecord((unsigned)Field, REFERENCE_FIELD);
  389. }
  390. void ClangDocBitcodeWriter::emitBlock(const TypeInfo &T) {
  391. StreamSubBlockGuard Block(Stream, BI_TYPE_BLOCK_ID);
  392. emitBlock(T.Type, FieldId::F_type);
  393. }
  394. void ClangDocBitcodeWriter::emitBlock(const TypedefInfo &T) {
  395. StreamSubBlockGuard Block(Stream, BI_TYPEDEF_BLOCK_ID);
  396. emitRecord(T.USR, TYPEDEF_USR);
  397. emitRecord(T.Name, TYPEDEF_NAME);
  398. for (const auto &N : T.Namespace)
  399. emitBlock(N, FieldId::F_namespace);
  400. for (const auto &CI : T.Description)
  401. emitBlock(CI);
  402. if (T.DefLoc)
  403. emitRecord(*T.DefLoc, TYPEDEF_DEFLOCATION);
  404. emitRecord(T.IsUsing, TYPEDEF_IS_USING);
  405. emitBlock(T.Underlying);
  406. }
  407. void ClangDocBitcodeWriter::emitBlock(const FieldTypeInfo &T) {
  408. StreamSubBlockGuard Block(Stream, BI_FIELD_TYPE_BLOCK_ID);
  409. emitBlock(T.Type, FieldId::F_type);
  410. emitRecord(T.Name, FIELD_TYPE_NAME);
  411. emitRecord(T.DefaultValue, FIELD_DEFAULT_VALUE);
  412. }
  413. void ClangDocBitcodeWriter::emitBlock(const MemberTypeInfo &T) {
  414. StreamSubBlockGuard Block(Stream, BI_MEMBER_TYPE_BLOCK_ID);
  415. emitBlock(T.Type, FieldId::F_type);
  416. emitRecord(T.Name, MEMBER_TYPE_NAME);
  417. emitRecord(T.Access, MEMBER_TYPE_ACCESS);
  418. for (const auto &CI : T.Description)
  419. emitBlock(CI);
  420. }
  421. void ClangDocBitcodeWriter::emitBlock(const CommentInfo &I) {
  422. StreamSubBlockGuard Block(Stream, BI_COMMENT_BLOCK_ID);
  423. for (const auto &L : std::vector<std::pair<llvm::StringRef, RecordId>>{
  424. {I.Kind, COMMENT_KIND},
  425. {I.Text, COMMENT_TEXT},
  426. {I.Name, COMMENT_NAME},
  427. {I.Direction, COMMENT_DIRECTION},
  428. {I.ParamName, COMMENT_PARAMNAME},
  429. {I.CloseName, COMMENT_CLOSENAME}})
  430. emitRecord(L.first, L.second);
  431. emitRecord(I.SelfClosing, COMMENT_SELFCLOSING);
  432. emitRecord(I.Explicit, COMMENT_EXPLICIT);
  433. for (const auto &A : I.AttrKeys)
  434. emitRecord(A, COMMENT_ATTRKEY);
  435. for (const auto &A : I.AttrValues)
  436. emitRecord(A, COMMENT_ATTRVAL);
  437. for (const auto &A : I.Args)
  438. emitRecord(A, COMMENT_ARG);
  439. for (const auto &C : I.Children)
  440. emitBlock(*C);
  441. }
  442. void ClangDocBitcodeWriter::emitBlock(const NamespaceInfo &I) {
  443. StreamSubBlockGuard Block(Stream, BI_NAMESPACE_BLOCK_ID);
  444. emitRecord(I.USR, NAMESPACE_USR);
  445. emitRecord(I.Name, NAMESPACE_NAME);
  446. emitRecord(I.Path, NAMESPACE_PATH);
  447. for (const auto &N : I.Namespace)
  448. emitBlock(N, FieldId::F_namespace);
  449. for (const auto &CI : I.Description)
  450. emitBlock(CI);
  451. for (const auto &C : I.Children.Namespaces)
  452. emitBlock(C, FieldId::F_child_namespace);
  453. for (const auto &C : I.Children.Records)
  454. emitBlock(C, FieldId::F_child_record);
  455. for (const auto &C : I.Children.Functions)
  456. emitBlock(C);
  457. for (const auto &C : I.Children.Enums)
  458. emitBlock(C);
  459. for (const auto &C : I.Children.Typedefs)
  460. emitBlock(C);
  461. }
  462. void ClangDocBitcodeWriter::emitBlock(const EnumInfo &I) {
  463. StreamSubBlockGuard Block(Stream, BI_ENUM_BLOCK_ID);
  464. emitRecord(I.USR, ENUM_USR);
  465. emitRecord(I.Name, ENUM_NAME);
  466. for (const auto &N : I.Namespace)
  467. emitBlock(N, FieldId::F_namespace);
  468. for (const auto &CI : I.Description)
  469. emitBlock(CI);
  470. if (I.DefLoc)
  471. emitRecord(*I.DefLoc, ENUM_DEFLOCATION);
  472. for (const auto &L : I.Loc)
  473. emitRecord(L, ENUM_LOCATION);
  474. emitRecord(I.Scoped, ENUM_SCOPED);
  475. if (I.BaseType)
  476. emitBlock(*I.BaseType);
  477. for (const auto &N : I.Members)
  478. emitBlock(N);
  479. }
  480. void ClangDocBitcodeWriter::emitBlock(const EnumValueInfo &I) {
  481. StreamSubBlockGuard Block(Stream, BI_ENUM_VALUE_BLOCK_ID);
  482. emitRecord(I.Name, ENUM_VALUE_NAME);
  483. emitRecord(I.Value, ENUM_VALUE_VALUE);
  484. emitRecord(I.ValueExpr, ENUM_VALUE_EXPR);
  485. }
  486. void ClangDocBitcodeWriter::emitBlock(const RecordInfo &I) {
  487. StreamSubBlockGuard Block(Stream, BI_RECORD_BLOCK_ID);
  488. emitRecord(I.USR, RECORD_USR);
  489. emitRecord(I.Name, RECORD_NAME);
  490. emitRecord(I.Path, RECORD_PATH);
  491. for (const auto &N : I.Namespace)
  492. emitBlock(N, FieldId::F_namespace);
  493. for (const auto &CI : I.Description)
  494. emitBlock(CI);
  495. if (I.DefLoc)
  496. emitRecord(*I.DefLoc, RECORD_DEFLOCATION);
  497. for (const auto &L : I.Loc)
  498. emitRecord(L, RECORD_LOCATION);
  499. emitRecord(I.TagType, RECORD_TAG_TYPE);
  500. emitRecord(I.IsTypeDef, RECORD_IS_TYPE_DEF);
  501. for (const auto &N : I.Members)
  502. emitBlock(N);
  503. for (const auto &P : I.Parents)
  504. emitBlock(P, FieldId::F_parent);
  505. for (const auto &P : I.VirtualParents)
  506. emitBlock(P, FieldId::F_vparent);
  507. for (const auto &PB : I.Bases)
  508. emitBlock(PB);
  509. for (const auto &C : I.Children.Records)
  510. emitBlock(C, FieldId::F_child_record);
  511. for (const auto &C : I.Children.Functions)
  512. emitBlock(C);
  513. for (const auto &C : I.Children.Enums)
  514. emitBlock(C);
  515. for (const auto &C : I.Children.Typedefs)
  516. emitBlock(C);
  517. if (I.Template)
  518. emitBlock(*I.Template);
  519. }
  520. void ClangDocBitcodeWriter::emitBlock(const BaseRecordInfo &I) {
  521. StreamSubBlockGuard Block(Stream, BI_BASE_RECORD_BLOCK_ID);
  522. emitRecord(I.USR, BASE_RECORD_USR);
  523. emitRecord(I.Name, BASE_RECORD_NAME);
  524. emitRecord(I.Path, BASE_RECORD_PATH);
  525. emitRecord(I.TagType, BASE_RECORD_TAG_TYPE);
  526. emitRecord(I.IsVirtual, BASE_RECORD_IS_VIRTUAL);
  527. emitRecord(I.Access, BASE_RECORD_ACCESS);
  528. emitRecord(I.IsParent, BASE_RECORD_IS_PARENT);
  529. for (const auto &M : I.Members)
  530. emitBlock(M);
  531. for (const auto &C : I.Children.Functions)
  532. emitBlock(C);
  533. }
  534. void ClangDocBitcodeWriter::emitBlock(const FunctionInfo &I) {
  535. StreamSubBlockGuard Block(Stream, BI_FUNCTION_BLOCK_ID);
  536. emitRecord(I.USR, FUNCTION_USR);
  537. emitRecord(I.Name, FUNCTION_NAME);
  538. for (const auto &N : I.Namespace)
  539. emitBlock(N, FieldId::F_namespace);
  540. for (const auto &CI : I.Description)
  541. emitBlock(CI);
  542. emitRecord(I.Access, FUNCTION_ACCESS);
  543. emitRecord(I.IsMethod, FUNCTION_IS_METHOD);
  544. if (I.DefLoc)
  545. emitRecord(*I.DefLoc, FUNCTION_DEFLOCATION);
  546. for (const auto &L : I.Loc)
  547. emitRecord(L, FUNCTION_LOCATION);
  548. emitBlock(I.Parent, FieldId::F_parent);
  549. emitBlock(I.ReturnType);
  550. for (const auto &N : I.Params)
  551. emitBlock(N);
  552. if (I.Template)
  553. emitBlock(*I.Template);
  554. }
  555. void ClangDocBitcodeWriter::emitBlock(const TemplateInfo &T) {
  556. StreamSubBlockGuard Block(Stream, BI_TEMPLATE_BLOCK_ID);
  557. for (const auto &P : T.Params)
  558. emitBlock(P);
  559. if (T.Specialization)
  560. emitBlock(*T.Specialization);
  561. }
  562. void ClangDocBitcodeWriter::emitBlock(const TemplateSpecializationInfo &T) {
  563. StreamSubBlockGuard Block(Stream, BI_TEMPLATE_SPECIALIZATION_BLOCK_ID);
  564. emitRecord(T.SpecializationOf, TEMPLATE_SPECIALIZATION_OF);
  565. for (const auto &P : T.Params)
  566. emitBlock(P);
  567. }
  568. void ClangDocBitcodeWriter::emitBlock(const TemplateParamInfo &T) {
  569. StreamSubBlockGuard Block(Stream, BI_TEMPLATE_PARAM_BLOCK_ID);
  570. emitRecord(T.Contents, TEMPLATE_PARAM_CONTENTS);
  571. }
  572. bool ClangDocBitcodeWriter::dispatchInfoForWrite(Info *I) {
  573. switch (I->IT) {
  574. case InfoType::IT_namespace:
  575. emitBlock(*static_cast<clang::doc::NamespaceInfo *>(I));
  576. break;
  577. case InfoType::IT_record:
  578. emitBlock(*static_cast<clang::doc::RecordInfo *>(I));
  579. break;
  580. case InfoType::IT_enum:
  581. emitBlock(*static_cast<clang::doc::EnumInfo *>(I));
  582. break;
  583. case InfoType::IT_function:
  584. emitBlock(*static_cast<clang::doc::FunctionInfo *>(I));
  585. break;
  586. case InfoType::IT_typedef:
  587. emitBlock(*static_cast<clang::doc::TypedefInfo *>(I));
  588. break;
  589. default:
  590. llvm::errs() << "Unexpected info, unable to write.\n";
  591. return true;
  592. }
  593. return false;
  594. }
  595. } // namespace doc
  596. } // namespace clang