From e6205d51f72b21d12732cb141c574543da249b8d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkrystian@gmail.com> Date: Tue, 1 Oct 2024 10:08:22 -0400 Subject: [PATCH] refactor: drop bitcode support --- .github/check_info_nodes_support.sh | 23 - docs/modules/ROOT/pages/contribute.adoc | 12 +- include/mrdocs/Metadata/Javadoc.hpp | 6 +- src/lib/AST/ASTVisitor.cpp | 17 +- src/lib/AST/AnyBlock.hpp | 2119 ---------------------- src/lib/AST/Bitcode.hpp | 48 - src/lib/AST/BitcodeIDs.hpp | 170 -- src/lib/AST/BitcodeReader.cpp | 194 -- src/lib/AST/BitcodeReader.hpp | 83 - src/lib/AST/BitcodeWriter.cpp | 1364 -------------- src/lib/AST/BitcodeWriter.hpp | 228 --- src/lib/Gen/bitcode/BitcodeGenerator.cpp | 154 -- src/lib/Gen/bitcode/BitcodeGenerator.hpp | 60 - src/lib/Lib/CorpusImpl.cpp | 46 +- src/lib/Lib/ExecutionContext.cpp | 82 - src/lib/Lib/ExecutionContext.hpp | 94 - src/lib/Support/GeneratorsImpl.cpp | 5 - test-files/golden-tests/enum.xml | 6 +- 18 files changed, 23 insertions(+), 4688 deletions(-) delete mode 100644 src/lib/AST/AnyBlock.hpp delete mode 100644 src/lib/AST/Bitcode.hpp delete mode 100644 src/lib/AST/BitcodeIDs.hpp delete mode 100644 src/lib/AST/BitcodeReader.cpp delete mode 100644 src/lib/AST/BitcodeReader.hpp delete mode 100644 src/lib/AST/BitcodeWriter.cpp delete mode 100644 src/lib/AST/BitcodeWriter.hpp delete mode 100644 src/lib/Gen/bitcode/BitcodeGenerator.cpp delete mode 100644 src/lib/Gen/bitcode/BitcodeGenerator.hpp diff --git a/.github/check_info_nodes_support.sh b/.github/check_info_nodes_support.sh index 7eeeb72d5..375811816 100644 --- a/.github/check_info_nodes_support.sh +++ b/.github/check_info_nodes_support.sh @@ -109,29 +109,6 @@ while IFS= read -r line; do print_message "* \`build$name()\` not found in \`src/lib/AST/ASTVisitor.cpp\`" fi - # `src/lib/AST/AnyBlock.hpp` should define the `${name}Block` type - # Look for the string `${name}Block` in the file - if ! grep -q "${name}Block" "$MRDOCS_ROOT/src/lib/AST/AnyBlock.hpp"; then - print_message_once "## ${name}Info" - print_message "* \`${name}Block\` not found in \`src/lib/AST/AnyBlock.hpp\`" - fi - - # `src/lib/AST/BitcodeWriter.hpp` should define `void emitBlock(X const& I);` - # Look for the string `void emitBlock(${name}Info const& I);` in the file - # When looking for the string `void emitBlock(${name}Info const& I);` in the file, - # we need to use regex to account for the following: - # 1) Remove the leading and trailing spaces - # 2) Consecutive spaces should be replaced with a single space - # 3) Newlines should be removed - # 4) The variable name `I` can be anything - BITCODE_WRITE_REL_PATH="src/lib/AST/BitcodeWriter.hpp" - BITCODE_WRITE_PATH="$MRDOCS_ROOT/$BITCODE_WRITE_REL_PATH" - regex="void[[:space:]]+emitBlock[[:space:]]*\(${name}Info[[:space:]]*const[[:space:]]*&[[:space:]]*[a-zA-Z_][a-zA-Z0-9_]*[[:space:]]*\);" - if ! grep -Pzo "$regex" "$BITCODE_WRITE_PATH" > /dev/null; then - print_message_once "## ${name}Info" - print_message "The function \`void emitBlock(${name}Info const& I);\` is not defined in \`$BITCODE_WRITE_REL_PATH\`." - fi - # `src/lib/Gen/xml/XMLWriter.cpp` should define `XMLWriter::writeX()` # Just look for the string `write$name` in this file if ! grep -q "write$name" "$MRDOCS_ROOT/src/lib/Gen/xml/XMLWriter.cpp"; then diff --git a/docs/modules/ROOT/pages/contribute.adoc b/docs/modules/ROOT/pages/contribute.adoc index e459a765a..3d4cd01f1 100644 --- a/docs/modules/ROOT/pages/contribute.adoc +++ b/docs/modules/ROOT/pages/contribute.adoc @@ -105,7 +105,7 @@ include::partial$InfoNodes.inc[] `Info` can not only represent direct AST symbols but also {cpp} constructs that need to be inferred from these symbols. Nodes in the first category will typically be created in the initial extraction step, and nodes in the second category will be created in the finalization step. -When defining a new `Info` type, it is important to consider how this type will be supported in all other modules of the codebase, including the AST visitor, the bitcode writer, generators, tests, and the documentation. +When defining a new `Info` type, it is important to consider how this type will be supported in all other modules of the codebase, including the AST visitor, generators, tests, and the documentation. The script `.github/check_info_nodes_support.sh` will attempt to infer whether most of these features have been implemented for each node type. ==== Clang LibTooling @@ -145,19 +145,13 @@ It is during this stage that USRs (universal symbol references) are generated an Except for built-in types, *all* entities referenced in the corpus will be traversed and be assigned a `SymbolID`; including those from the standard library. This is necessary to generate the full interface for user-defined types. -==== Bitcode - -To maximize the size of the code base MrDocs is capable of processing, `Info` -types generated during traversal are serialized to a compressed bitcode representation. - -The `ASTVisitor` reports each new `Info` object to the `BitcodeExecutionContext` (`src/lib/Lib/ExecutionContext.cpp`) which serializes it to the bitcode file. - ==== Finalizing the Corpus After running the AST traversal on all translation units, `CorpusImpl::build` contains finalization steps for the `Corpus` object. At this point, we process C++ constructs that are not directly represented in the AST. -The first finalization step happens in `BitcodeExecutionContext::reportEnd` (`src/lib/Lib/ExecutionContext.cpp`), where the `Info` objects with the same `SymbolID` are merged. +The first finalization step happens in `CorpusImpl::build` (`src/lib/Lib/CorpusImpl.cpp`), where the `Info` objects from a single translation unit +are merged into a map containing the merged results from all other TUs. The merging step is necessary as there may be multiple identical definitions of the same entity. For instance, this represents the case where a function is declared at different points in the code base and might have different attributes or comments. At this step, the doc comments are also finalized. diff --git a/include/mrdocs/Metadata/Javadoc.hpp b/include/mrdocs/Metadata/Javadoc.hpp index 496419cd9..fe81182e1 100644 --- a/include/mrdocs/Metadata/Javadoc.hpp +++ b/include/mrdocs/Metadata/Javadoc.hpp @@ -90,11 +90,7 @@ using List = std::vector<std::unique_ptr<T>>; of the the doc comment specification. @note When a new tag is added, the `visit` function overloads - must be updated to handle the new tag. If the new object - contains new fields, `BitcodeWriter::emitBlock(doc::Node const& I)` - must include logic to serialize the new fields, and - `BitcodeReader::readBlock` must include logic to deserialize - the new fields. + must be updated to handle the new tag. @see https://en.wikipedia.org/wiki/Javadoc[Javadoc - Wikipedia] @see https://docs.oracle.com/javase/1.5.0/docs/tooldocs/solaris/javadoc.html[Javadoc Documentation] diff --git a/src/lib/AST/ASTVisitor.cpp b/src/lib/AST/ASTVisitor.cpp index 1d489998d..3ea94710a 100644 --- a/src/lib/AST/ASTVisitor.cpp +++ b/src/lib/AST/ASTVisitor.cpp @@ -12,7 +12,6 @@ #include "ASTVisitor.hpp" #include "ASTVisitorHelpers.hpp" -#include "Bitcode.hpp" #include "ParseJavadoc.hpp" #include "lib/Support/Path.hpp" #include "lib/Support/Debug.hpp" @@ -163,17 +162,11 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( // //------------------------------------------------ -/** Convert AST to our metadata and serialize to bitcode. - - An instance of this object visits the AST - for exactly one translation unit. The AST is - extracted and converted into our metadata, and - this metadata is then serialized into bitcode. - The resulting bitcode is inserted into the tool - results, keyed by ID. Each ID can have multiple - serialized bitcodes, as the same declaration - in a particular include file can be seen by - more than one translation unit. +/** Convert AST to metadata representation. + + An instance of this object traverses the AST + for a translation unit and translate AST nodes + into our metadata. */ class ASTVisitor { diff --git a/src/lib/AST/AnyBlock.hpp b/src/lib/AST/AnyBlock.hpp deleted file mode 100644 index 161f5fc9e..000000000 --- a/src/lib/AST/AnyBlock.hpp +++ /dev/null @@ -1,2119 +0,0 @@ -// -// This is a derivative work. originally part of the LLVM Project. -// Licensed under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) -// -// Official repository: https://github.com/cppalliance/mrdocs -// - -#ifndef MRDOCS_LIB_AST_ANYBLOCK_HPP -#define MRDOCS_LIB_AST_ANYBLOCK_HPP - -#include "BitcodeReader.hpp" - -namespace clang { -namespace mrdocs { - -// bool -inline -Error -decodeRecord( - Record const& R, - bool& Field, - llvm::StringRef Blob) -{ - Field = R[0] != 0; - return Error::success(); -} - -// 32 bit integral types -template<class IntTy> -requires std::integral<IntTy> -Error -decodeRecord( - Record const& R, - IntTy& v, - llvm::StringRef Blob) -{ - v = 0; - if (R[0] > (std::numeric_limits<IntTy>::max)()) - return formatError("integer overflow"); - v = static_cast<IntTy>(R[0]); - return Error::success(); -} - -// integral types wider than 32 bits -template<class IntTy> -requires (std::integral<IntTy> && - sizeof(IntTy) > 4) -Error -decodeRecord( - Record const& R, - IntTy& v, - llvm::StringRef Blob) -{ - v = static_cast<IntTy>( - static_cast<std::uint64_t>(R[0]) | - (static_cast<std::uint64_t>(R[1]) << 32)); - return Error::success(); -} - -// enumerations -template<class Enum> -requires std::is_enum_v<Enum> -Error -decodeRecord( - Record const& R, - Enum& value, - llvm::StringRef blob) -{ - static_assert(! std::same_as<Enum, InfoKind>); - std::underlying_type_t<Enum> temp; - if(auto err = decodeRecord(R, temp, blob)) - return err; - value = static_cast<Enum>(temp); - return Error::success(); -} - -// container of char -template<class Field> -requires std::is_same_v< - typename Field::value_type, char> -Error -decodeRecord( - const Record& R, - Field& f, - llvm::StringRef blob) - requires requires - { - f.assign(blob.begin(), blob.end()); - } -{ - f.assign(blob.begin(), blob.end()); - return Error::success(); -} - -// range<SymbolID> -inline -Error -decodeRecord( - Record const& R, - std::vector<SymbolID>& f, - llvm::StringRef blob) -{ - auto src = R.begin(); - auto n = *src++; - f.resize(n); - auto* dest = &f[0]; - while(n--) - { - *dest++ = SymbolID(src); - src += BitCodeConstants::USRHashSize; - } - return Error::success(); -} - -inline -Error -decodeRecord( - const Record& R, - SymbolID& Field, - llvm::StringRef Blob) -{ - if (R[0] != BitCodeConstants::USRHashSize) - return formatError("USR digest size={}", R[0]); - - Field = SymbolID(&R[1]); - return Error::success(); -} - -inline -Error -decodeRecord( - Record const& R, - OptionalLocation& Field, - llvm::StringRef Blob) -{ - if (R[0] > INT_MAX) - return formatError("integer value {} too large", R[0]); - Location& loc = Field.emplace(); - loc.LineNumber = R[0]; - loc.Kind = static_cast<FileKind>(R[1]); - loc.Documented = static_cast<bool>(R[2]); - loc.Path.append(Blob.substr(0, R[3])); - loc.Filename.append(Blob.substr(R[3], R[4] - R[3])); - return Error::success(); -} - -inline -Error -decodeRecord( - const Record& R, - std::vector<Location>& Field, - llvm::StringRef Blob) -{ - if (R[0] > INT_MAX) - return formatError("integer {} is too large", R[0]); - Location& loc = Field.emplace_back(); - loc.LineNumber = R[0]; - loc.Kind = static_cast<FileKind>(R[1]); - loc.Documented = static_cast<bool>(R[2]); - loc.Path.append(Blob.substr(0, R[3])); - loc.Filename.append(Blob.substr(R[3], R[4] - R[3])); - return Error::success(); -} - - -inline -Error -decodeRecord( - Record const& R, - std::initializer_list<BitFieldFullValue*> values, - llvm::StringRef Blob) -{ - auto n = R[0]; - if(n != values.size()) - return formatError("wrong size={} for Bitfields[{}]", n, values.size()); - - auto itr = values.begin(); - for(std::size_t i = 0; i < values.size(); ++i) - { - - auto const v = R[i + 1]; - if(v > (std::numeric_limits<std::uint32_t>::max)()) - return formatError("{} is out of range for Bits", v); - **itr++ = v; - } - return Error::success(); -} - -inline -Error -decodeRecord( - Record const& R, - NoexceptInfo& I, - llvm::StringRef Blob) -{ - I.Implicit = R[0]; - I.Kind = static_cast<NoexceptKind>(R[1]); - I.Operand = Blob; - return Error::success(); -} - -inline -Error -decodeRecord( - Record const& R, - ExplicitInfo& I, - llvm::StringRef Blob) -{ - I.Implicit = R[0]; - I.Kind = static_cast<ExplicitKind>(R[1]); - I.Operand = Blob; - return Error::success(); -} - -//------------------------------------------------ - -struct BitcodeReader::AnyBlock -{ - virtual ~AnyBlock() = default; - - virtual - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) - { - return formatError("unexpected record with ID={}", ID); - } - - virtual - Error - readSubBlock(unsigned ID) - { - return formatError("unexpected sub-block with ID={}", ID); - } -}; - -//------------------------------------------------ - -class VersionBlock - : public BitcodeReader::AnyBlock -{ -public: - unsigned V; - - Error - parseRecord(Record const& R, - unsigned ID, llvm::StringRef Blob) override - { - switch(ID) - { - case VERSION: - if(auto err = decodeRecord(R, V, Blob)) - return err; - if(V != BitcodeVersion) - return formatError("wrong ID for Version"); - return Error::success(); - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } -}; - -//------------------------------------------------ - -/** A doc::List<doc::Node> -*/ -class JavadocNodesBlock - : public BitcodeReader::AnyBlock -{ - BitcodeReader& br_; - Javadoc& jd_; - -public: - doc::List<doc::Node> nodes; - - JavadocNodesBlock( - BitcodeReader& br, - Javadoc& jd) noexcept - : br_(br) - , jd_(jd) - { - } - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch (ID) - { - case JAVADOC_NODE_ADMONISH: - { - doc::Admonish admonish = doc::Admonish::none; - if(auto err = decodeRecord(R, admonish, Blob)) - return err; - auto node = nodes.back().get(); - if(node->kind != doc::Kind::admonition) - return formatError("admonish on wrong kind"); - static_cast<doc::Admonition*>(node)->admonish = admonish; - return Error::success(); - } - - case JAVADOC_NODE_PART: - { - doc::Parts parts = doc::Parts::all; - if(auto err = decodeRecord(R, parts, Blob)) - return err; - auto node = nodes.back().get(); - if(node->kind != doc::Kind::copied) - return formatError("part on wrong kind"); - static_cast<doc::Copied*>(node)->parts = parts; - return Error::success(); - } - - case JAVADOC_NODE_SYMBOLREF: - { - SymbolID id; - if(auto err = decodeRecord(R, id, Blob)) - return err; - auto node = nodes.back().get(); - if(node->kind != doc::Kind::reference && - node->kind != doc::Kind::copied) - return formatError("reference on wrong kind"); - static_cast<doc::Reference*>(node)->id = id; - return Error::success(); - } - - case JAVADOC_PARAM_DIRECTION: - { - doc::ParamDirection direction = - doc::ParamDirection::none; - if(auto err = decodeRecord(R, direction, Blob)) - return err; - auto node = nodes.back().get(); - if(node->kind != doc::Kind::param) - return formatError("direction on wrong kind"); - auto param = static_cast<doc::Param*>(node); - param->direction = direction; - return Error::success(); - } - - case JAVADOC_NODE_HREF: - { - switch(auto node = nodes.back().get(); - node->kind) - { - case doc::Kind::link: - static_cast<doc::Link*>(node)->href = Blob.str(); - return Error::success(); - default: - return formatError("href on wrong kind"); - } - } - - case JAVADOC_NODE_KIND: - { - doc::Kind kind{}; - if(auto err = decodeRecord(R, kind, Blob)) - return err; - switch(kind) - { - case doc::Kind::admonition: - nodes.emplace_back(std::make_unique<doc::Admonition>()); - break; - case doc::Kind::brief: - nodes.emplace_back(std::make_unique<doc::Brief>()); - break; - case doc::Kind::code: - nodes.emplace_back(std::make_unique<doc::Code>()); - break; - case doc::Kind::heading: - nodes.emplace_back(std::make_unique<doc::Heading>()); - break; - case doc::Kind::paragraph: - nodes.emplace_back(std::make_unique<doc::Paragraph>()); - break; - case doc::Kind::link: - nodes.emplace_back(std::make_unique<doc::Link>()); - break; - case doc::Kind::reference: - nodes.emplace_back(std::make_unique<doc::Reference>()); - break; - case doc::Kind::copied: - nodes.emplace_back(std::make_unique<doc::Copied>()); - break; - case doc::Kind::list_item: - nodes.emplace_back(std::make_unique<doc::ListItem>()); - break; - case doc::Kind::param: - nodes.emplace_back(std::make_unique<doc::Param>()); - break; - case doc::Kind::returns: - nodes.emplace_back(std::make_unique<doc::Returns>()); - break; - case doc::Kind::styled: - nodes.emplace_back(std::make_unique<doc::Styled>()); - break; - case doc::Kind::text: - nodes.emplace_back(std::make_unique<doc::Text>()); - break; - case doc::Kind::tparam: - nodes.emplace_back(std::make_unique<doc::TParam>()); - break; - case doc::Kind::throws: - nodes.emplace_back(std::make_unique<doc::Throws>()); - break; - case doc::Kind::details: - nodes.emplace_back(std::make_unique<doc::Details>()); - break; - case doc::Kind::see: - nodes.emplace_back(std::make_unique<doc::See>()); - break; - case doc::Kind::precondition: - nodes.emplace_back(std::make_unique<doc::Precondition>()); - break; - case doc::Kind::postcondition: - nodes.emplace_back(std::make_unique<doc::Postcondition>()); - break; - default: - return formatError("unknown doc::Kind"); - } - return Error::success(); - } - - case JAVADOC_NODE_STRING: - { - switch(auto node = nodes.back().get(); - node->kind) - { - case doc::Kind::heading: - static_cast<doc::Heading*>(node)->string = Blob.str(); - return Error::success(); - case doc::Kind::text: - case doc::Kind::styled: - case doc::Kind::link: - case doc::Kind::reference: - case doc::Kind::copied: - static_cast<doc::Text*>( - node)->string = Blob.str(); - return Error::success(); - case doc::Kind::param: - static_cast<doc::Param*>( - node)->name = Blob.str(); - return Error::success(); - case doc::Kind::tparam: - static_cast<doc::TParam*>( - node)->name = Blob.str(); - return Error::success(); - case doc::Kind::throws: - static_cast<doc::Throws*>( - node)->exception = Blob.str(); - return Error::success(); - default: - return formatError("string on wrong kind"); - } - } - - case JAVADOC_NODE_STYLE: - { - doc::Style style = doc::Style::none; - if(auto err = decodeRecord(R, style, Blob)) - return err; - auto node = nodes.back().get(); - if(node->kind != doc::Kind::styled) - return formatError("style on wrong kind"); - static_cast<doc::Styled*>( - node)->style = style; - return Error::success(); - - } - - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_JAVADOC_LIST_BLOCK_ID: - { - auto node = nodes.back().get(); - if(node->kind == doc::Kind::text || - node->kind == doc::Kind::styled) - return formatError("text node cannot have list"); - - JavadocNodesBlock B(br_, jd_); - if(auto err = br_.readBlock(B, ID)) - return err; - static_cast<doc::Block*>(node)->append( - std::move(B.nodes)); - return Error::success(); - } - - case BI_JAVADOC_NODE_BLOCK_ID: - { - return br_.readBlock(*this, ID); - } - - default: - return AnyBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class JavadocBlock - : public BitcodeReader::AnyBlock -{ - BitcodeReader& br_; - std::unique_ptr<Javadoc>& I_; - -public: - JavadocBlock( - std::unique_ptr<Javadoc>& I, - BitcodeReader& br) - : br_(br) - , I_(I) - { - I_ = std::make_unique<Javadoc>(); - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_JAVADOC_LIST_BLOCK_ID: - { - JavadocNodesBlock B(br_, *I_); - if(auto err = br_.readBlock(B, ID)) - return err; - I_->append(std::move(B.nodes)); - return Error::success(); - } - default: - return AnyBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -template<typename InfoTy> -class InfoPartBlock - : public BitcodeReader::AnyBlock -{ -protected: - BitcodeReader& br_; - std::unique_ptr<InfoTy>& I_; - -public: - InfoPartBlock( - std::unique_ptr<InfoTy>& I, - BitcodeReader& br) noexcept - : br_(br) - , I_(I) - { - } - - Error - parseRecord(Record const& R, - unsigned ID, llvm::StringRef Blob) override - { - switch(ID) - { - case INFO_PART_ID: - { - SymbolID id = SymbolID::invalid; - if(auto err = decodeRecord(R, id, Blob)) - return err; - I_ = std::make_unique<InfoTy>(id); - return Error::success(); - } - case INFO_PART_ACCESS: - return decodeRecord(R, I_->Access, Blob); - case INFO_PART_IMPLICIT: - return decodeRecord(R, I_->Implicit, Blob); - case INFO_PART_NAME: - return decodeRecord(R, I_->Name, Blob); - case INFO_PART_PARENTS: - return decodeRecord(R, I_->Namespace, Blob); - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_JAVADOC_BLOCK_ID: - { - JavadocBlock B(I_->javadoc, br_); - return br_.readBlock(B, ID); - } - default: - return AnyBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class SourceInfoBlock - : public BitcodeReader::AnyBlock -{ -protected: - BitcodeReader& br_; - SourceInfo& I; - -public: - SourceInfoBlock( - SourceInfo& I, - BitcodeReader& br) noexcept - : br_(br) - , I(I) - { - } - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case SOURCE_INFO_DEFLOC: - return decodeRecord(R, I.DefLoc, Blob); - case SOURCE_INFO_LOC: - return decodeRecord(R, I.Loc, Blob); - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } -}; - -//------------------------------------------------ - - - -class LookupBlock - : public BitcodeReader::AnyBlock -{ -protected: - BitcodeReader& br_; - ScopeInfo& I; - std::string Name; - -public: - LookupBlock( - ScopeInfo& I, - BitcodeReader& br) noexcept - : br_(br) - , I(I) - { - } - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case LOOKUP_NAME: - return decodeRecord(R, Name, Blob); - case LOOKUP_MEMBERS: - return decodeRecord(R, - I.Lookups.try_emplace( - std::move(Name)).first->second, Blob); - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } -}; - -class ScopeInfoBlock - : public BitcodeReader::AnyBlock -{ -protected: - BitcodeReader& br_; - ScopeInfo& I; - -public: - ScopeInfoBlock( - ScopeInfo& I, - BitcodeReader& br) noexcept - : br_(br) - , I(I) - { - } - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case SCOPE_INFO_MEMBERS: - return decodeRecord(R, I.Members, Blob); - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_LOOKUP_INFO_ID: - { - LookupBlock B(I, br_); - return br_.readBlock(B, ID); - } - default: - return AnyBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class ExprBlock - : public BitcodeReader::AnyBlock -{ -private: - -protected: - BitcodeReader& br_; - ExprInfo& I_; - void(*on_value)( - ExprInfo&, - std::uint64_t) = nullptr; - -public: - ExprBlock( - ExprInfo& I, - BitcodeReader& br) noexcept - : br_(br) - , I_(I) - { - } - - template<typename T> - ExprBlock( - ConstantExprInfo<T>& I, - BitcodeReader& br) noexcept - : br_(br) - , I_(I) - , on_value([]( - ExprInfo& expr, std::uint64_t val) - { - static_cast<ConstantExprInfo<T>&>( - expr).Value.emplace(val); - }) - { - } - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case EXPR_WRITTEN: - return decodeRecord(R, I_.Written, Blob); - case EXPR_VALUE: - { - if(! on_value) - return Error("EXPR_VALUE for expression without value"); - std::uint64_t value = 0; - if(auto err = decodeRecord(R, value, Blob)) - return err; - on_value(I_, value); - return Error::success(); - - } - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock(unsigned ID) override - { - switch(ID) - { - // if this has a BI_EXPR_BLOCK_ID child, it means - // that this is the child of some block which is - // a proxy for an EXPR_BLOCK. in such cases, just - // forward the result to the caller - case BI_EXPR_BLOCK_ID: - return br_.readBlock(*this, ID); - default: - return AnyBlock::readSubBlock(ID); - }; - } -}; - -//------------------------------------------------ - -class TypeInfoBlock - : public BitcodeReader::AnyBlock -{ -protected: - BitcodeReader& br_; - std::unique_ptr<TypeInfo>& I_; - -public: - TypeInfoBlock( - std::unique_ptr<TypeInfo>& I, - BitcodeReader& br) noexcept - : br_(br) - , I_(I) - { - } - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case TYPEINFO_KIND: - { - TypeKind k{}; - if(auto err = decodeRecord(R, k, Blob)) - return err; - switch(k) - { - case TypeKind::Named: - I_ = std::make_unique<NamedTypeInfo>(); - break; - case TypeKind::Decltype: - I_ = std::make_unique<DecltypeTypeInfo>(); - break; - case TypeKind::Auto: - I_ = std::make_unique<AutoTypeInfo>(); - break; - case TypeKind::LValueReference: - I_ = std::make_unique<LValueReferenceTypeInfo>(); - break; - case TypeKind::RValueReference: - I_ = std::make_unique<RValueReferenceTypeInfo>(); - break; - case TypeKind::Pointer: - I_ = std::make_unique<PointerTypeInfo>(); - break; - case TypeKind::MemberPointer: - I_ = std::make_unique<MemberPointerTypeInfo>(); - break; - case TypeKind::Array: - I_ = std::make_unique<ArrayTypeInfo>(); - break; - case TypeKind::Function: - I_ = std::make_unique<FunctionTypeInfo>(); - break; - default: - return Error("invalid TypeInfo kind"); - } - return Error::success(); - } - case TYPEINFO_IS_PACK: - if(auto err = decodeRecord(R, I_->IsPackExpansion, Blob)) - return err; - return Error::success(); - case TYPEINFO_CVQUAL: - return visit(*I_, [&]<typename T>(T& t) - { - if constexpr(requires { t.CVQualifiers; }) - return decodeRecord(R, t.CVQualifiers, Blob); - else - return Error("wrong TypeInfo kind"); - }); - case TYPEINFO_REFQUAL: - if(! I_->isFunction()) - return Error("wrong TypeInfo kind"); - return decodeRecord(R, static_cast< - FunctionTypeInfo&>(*I_).RefQualifier, Blob); - case TYPEINFO_NOEXCEPT: - if(! I_->isFunction()) - return Error("wrong TypeInfo kind"); - return decodeRecord(R, static_cast< - FunctionTypeInfo&>(*I_).ExceptionSpec, Blob); - case TYPEINFO_IS_VARIADIC: - if(! I_->isFunction()) - return Error("wrong TypeInfo kind"); - return decodeRecord(R, static_cast< - FunctionTypeInfo&>(*I_).IsVariadic, Blob); - case TYPEINFO_AUTO_KEYWORD: - if(! I_->isAuto()) - return Error("wrong TypeInfo kind"); - return decodeRecord(R, static_cast< - AutoTypeInfo&>(*I_).Keyword, Blob); - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock(unsigned ID) override; -}; - -//------------------------------------------------ - -class BaseBlock - : public BitcodeReader::AnyBlock -{ - BitcodeReader& br_; - BaseInfo& I_; - -public: - explicit - BaseBlock( - BaseInfo& I, - BitcodeReader& br) noexcept - : br_(br) - , I_(I) - { - } - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case BASE_ACCESS: - return decodeRecord(R, I_.Access, Blob); - case BASE_IS_VIRTUAL: - return decodeRecord(R, I_.IsVirtual, Blob); - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_TYPEINFO_BLOCK_ID: - { - TypeInfoBlock B(I_.Type, br_); - return br_.readBlock(B, ID); - } - default: - return AnyBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class TemplateArgBlock - : public BitcodeReader::AnyBlock -{ - BitcodeReader& br_; - std::unique_ptr<TArg>& I_; - -public: - TemplateArgBlock( - std::unique_ptr<TArg>& I, - BitcodeReader& br) noexcept - : br_(br) - , I_(I) - { - } - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case TEMPLATE_ARG_KIND: - { - TArgKind kind{}; - if(auto err = decodeRecord(R, kind, Blob)) - return err; - switch(kind) - { - case TArgKind::Type: - I_ = std::make_unique<TypeTArg>(); - break; - case TArgKind::NonType: - I_ = std::make_unique<NonTypeTArg>(); - break; - case TArgKind::Template: - I_= std::make_unique<TemplateTArg>(); - break; - default: - return formatError("invalid template argument kind"); - } - return Error::success(); - } - case TEMPLATE_ARG_IS_PACK: - { - return decodeRecord(R, I_->IsPackExpansion, Blob); - } - case TEMPLATE_ARG_TEMPLATE: - { - if(! I_->isTemplate()) - return formatError("only TemplateTArgs may reference a template"); - return decodeRecord(R, - static_cast<TemplateTArg&>( - *I_.get()).Template, Blob); - } - case TEMPLATE_ARG_NAME: - { - if(! I_->isTemplate()) - return formatError("only TemplateTArgs may have a template name"); - return decodeRecord(R, - static_cast<TemplateTArg&>( - *I_.get()).Name, Blob); - } - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_TYPEINFO_BLOCK_ID: - { - if(! I_->isType()) - return formatError("only TypeTArgs may have types"); - TypeInfoBlock B(static_cast<TypeTArg&>( - *I_.get()).Type, br_); - return br_.readBlock(B, ID); - } - case BI_EXPR_BLOCK_ID: - { - if(! I_->isNonType()) - return formatError("only NonTypeTArgs may have expressions"); - ExprBlock B(static_cast<NonTypeTArg&>( - *I_.get()).Value, br_); - return br_.readBlock(B, ID); - } - default: - return AnyBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class TemplateParamBlock - : public BitcodeReader::AnyBlock -{ - BitcodeReader& br_; - std::unique_ptr<TParam>& I_; - -public: - TemplateParamBlock( - std::unique_ptr<TParam>& I, - BitcodeReader& br) noexcept - : br_(br) - , I_(I) - { - } - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case TEMPLATE_PARAM_KIND: - { - TParamKind kind{}; - if(auto err = decodeRecord(R, kind, Blob)) - return err; - switch(kind) - { - case TParamKind::Type: - I_ = std::make_unique<TypeTParam>(); - break; - case TParamKind::NonType: - I_ = std::make_unique<NonTypeTParam>(); - break; - case TParamKind::Template: - I_= std::make_unique<TemplateTParam>(); - break; - default: - return formatError("invalid template parameter kind"); - } - return Error::success(); - } - case TEMPLATE_PARAM_NAME: - { - return decodeRecord(R, I_->Name, Blob); - } - case TEMPLATE_PARAM_IS_PACK: - { - return decodeRecord(R, I_->IsParameterPack, Blob); - } - case TEMPLATE_PARAM_KEY_KIND: - { - if(! I_->isType()) - return formatError("only TypeTParams have a key kind"); - return decodeRecord(R, static_cast< - TypeTParam&>(*I_.get()).KeyKind, Blob); - } - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock(unsigned ID) override; -}; - -//------------------------------------------------ - -class NameInfoBlock - : public BitcodeReader::AnyBlock -{ -protected: - BitcodeReader& br_; - std::unique_ptr<NameInfo>& I; - -public: - NameInfoBlock( - std::unique_ptr<NameInfo>& I, - BitcodeReader& br) noexcept - : br_(br) - , I(I) - { - } - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case NAME_INFO_KIND: - { - NameKind kind{}; - if(auto err = decodeRecord(R, kind, Blob)) - return err; - if(kind == NameKind::Specialization) - I = std::make_unique<SpecializationNameInfo>(); - else - I = std::make_unique<NameInfo>(); - return Error::success(); - } - case NAME_INFO_ID: - return decodeRecord(R, I->id, Blob); - case NAME_INFO_NAME: - return decodeRecord(R, I->Name, Blob); - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_NAME_INFO_ID: - { - NameInfoBlock B(I->Prefix, br_); - return br_.readBlock(B, ID); - } - case BI_TEMPLATE_ARG_BLOCK_ID: - { - SpecializationNameInfo* S = - static_cast<SpecializationNameInfo*>(I.get()); - TemplateArgBlock B(S->TemplateArgs.emplace_back(), br_); - return br_.readBlock(B, ID); - } - default: - return AnyBlock::readSubBlock(ID); - } - } -}; - -Error -TemplateParamBlock:: -readSubBlock( - unsigned ID) -{ - switch(ID) - { - case BI_TEMPLATE_PARAM_BLOCK_ID: - { - if(! I_->isTemplate()) - return formatError("only TemplateTParam may have template parameters"); - TemplateParamBlock B( - static_cast<TemplateTParam&>( - *I_.get()).Params.emplace_back(), br_); - return br_.readBlock(B, ID); - } - case BI_TEMPLATE_ARG_BLOCK_ID: - { - TemplateArgBlock B(I_->Default, br_); - return br_.readBlock(B, ID); - } - case BI_TYPEINFO_BLOCK_ID: - { - if(! I_->isNonType()) - return formatError("only NonTypeTParams may have a type"); - TypeInfoBlock B(static_cast< - NonTypeTParam&>(*I_.get()).Type, br_); - return br_.readBlock(B, ID); - } - case BI_NAME_INFO_ID: - { - if(! I_->isType()) - return formatError("only TypeTypeTParams may have a type constraint"); - NameInfoBlock B(static_cast< - TypeTParam&>(*I_.get()).Constraint, br_); - return br_.readBlock(B, ID); - } - default: - return AnyBlock::readSubBlock(ID); - } -} - -//------------------------------------------------ - -class TemplateBlock - : public BitcodeReader::AnyBlock -{ - BitcodeReader& br_; - TemplateInfo& I_; - -public: - explicit - TemplateBlock( - TemplateInfo& I, - BitcodeReader& br) noexcept - : br_(br) - , I_(I) - { - } - - Error - parseRecord(Record const& R, - unsigned ID, llvm::StringRef Blob) override - { - switch(ID) - { - case TEMPLATE_PRIMARY_USR: - return decodeRecord(R, I_.Primary, Blob); - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_TEMPLATE_ARG_BLOCK_ID: - { - TemplateArgBlock A( - I_.Args.emplace_back(), br_); - return br_.readBlock(A, ID); - } - case BI_TEMPLATE_PARAM_BLOCK_ID: - { - TemplateParamBlock P( - I_.Params.emplace_back(), br_); - return br_.readBlock(P, ID); - } - case BI_EXPR_BLOCK_ID: - { - ExprBlock E(I_.Requires, br_); - return br_.readBlock(E, ID); - } - default: - return AnyBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -Error -TypeInfoBlock:: -readSubBlock(unsigned ID) -{ - switch(ID) - { - // if the subblock ID is BI_TYPEINFO_BLOCK_ID, - // it means that the block is a subblock of a - // BI_TYPEINFO_CHILD_BLOCK_ID, BI_TYPEINFO_PARENT_BLOCK_ID, - // or BI_TYPEINFO_PARAM_BLOCK_ID and should "forward" - // the result to the caller - case BI_TYPEINFO_BLOCK_ID: - return br_.readBlock(*this, ID); - case BI_TYPEINFO_CHILD_BLOCK_ID: - return visit(*I_, [&]<typename T>(T& t) - { - std::unique_ptr<TypeInfo>* child = nullptr; - if constexpr(requires { t.PointeeType; }) - child = &t.PointeeType; - else if constexpr(T::isArray()) - child = &t.ElementType; - else if constexpr(T::isFunction()) - child = &t.ReturnType; - - if(! child) - return Error("wrong TypeInfo kind"); - TypeInfoBlock B(*child, br_); - return br_.readBlock(B, ID); - }); - case BI_TYPEINFO_PARENT_BLOCK_ID: - return visit(*I_, [&]<typename T>(T& t) - { - if constexpr(requires { t.ParentType; }) - { - TypeInfoBlock B(t.ParentType, br_); - return br_.readBlock(B, ID); - } - return Error("wrong TypeInfo kind"); - }); - - case BI_TYPEINFO_PARAM_BLOCK_ID: - { - if(! I_->isFunction()) - return Error("wrong TypeInfo kind"); - auto& I = static_cast<FunctionTypeInfo&>(*I_); - TypeInfoBlock B(I.ParamTypes.emplace_back(), br_); - return br_.readBlock(B, ID); - } - case BI_EXPR_BLOCK_ID: - { - if(I_->isArray()) - { - auto& I = static_cast<ArrayTypeInfo&>(*I_); - ExprBlock B(I.Bounds, br_); - return br_.readBlock(B, ID); - } - else if(I_->isDecltype()) - { - auto& I = static_cast<DecltypeTypeInfo&>(*I_); - ExprBlock B(I.Operand, br_); - return br_.readBlock(B, ID); - } - return Error("wrong TypeInfo kind"); - } - case BI_NAME_INFO_ID: - { - std::unique_ptr<NameInfo>* NI = nullptr; - visit(*I_, [&]<typename T>(T& t) - { - if constexpr(requires { t.Name; }) - NI = &t.Name; - if constexpr(requires { t.Constraint; }) - NI = &t.Constraint; - }); - if(! NI) - return Error("wrong TypeInfo kind"); - NameInfoBlock B(*NI, br_); - return br_.readBlock(B, ID); - } - default: - return AnyBlock::readSubBlock(ID); - } -} - -//------------------------------------------------ - -class FunctionParamBlock - : public BitcodeReader::AnyBlock -{ - BitcodeReader& br_; - Param& I_; - -public: - FunctionParamBlock( - Param& I, - BitcodeReader& br) noexcept - : br_(br) - , I_(I) - { - } - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case FUNCTION_PARAM_NAME: - return decodeRecord(R, I_.Name, Blob); - case FUNCTION_PARAM_DEFAULT: - return decodeRecord(R, I_.Default, Blob); - /* - case FUNCTION_PARAM_IS_PACK: - return decodeRecord(R, I_.IsParameterPack, Blob); - */ - default: - return AnyBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_TYPEINFO_BLOCK_ID: - { - TypeInfoBlock B(I_.Type, br_); - return br_.readBlock(B, ID); - } - default: - return AnyBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -template<class T> -class TopLevelBlock - : public BitcodeReader::AnyBlock -{ -protected: - BitcodeReader& br_; - -public: - std::unique_ptr<T> I = nullptr; - - explicit - TopLevelBlock( - BitcodeReader& br) - : br_(br) - { - } - - Error readSubBlock(unsigned ID) override; -}; - -//------------------------------------------------ - -class NamespaceBlock - : public TopLevelBlock<NamespaceInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case NAMESPACE_BITS: - return decodeRecord(R, {&I->specs.raw}, Blob); - case NAMESPACE_USING_DIRECTIVES: - return decodeRecord(R, I->UsingDirectives, Blob); - default: - return TopLevelBlock::parseRecord(R, ID, Blob); - } - } -}; - -//------------------------------------------------ - -class RecordBlock - : public TopLevelBlock<RecordInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case RECORD_KEY_KIND: - return decodeRecord(R, I->KeyKind, Blob); - case RECORD_IS_TYPE_DEF: - return decodeRecord(R, I->IsTypeDef, Blob); - case RECORD_BITS: - return decodeRecord(R, {&I->specs.raw}, Blob); - default: - return TopLevelBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_BASE_BLOCK_ID: - { - BaseBlock B(I->Bases.emplace_back(), br_); - return br_.readBlock(B, ID); - } - case BI_TEMPLATE_BLOCK_ID: - { - I->Template = std::make_unique<TemplateInfo>(); - TemplateBlock B(*I->Template, br_); - return br_.readBlock(B, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class FunctionBlock - : public TopLevelBlock<FunctionInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - parseRecord(Record const& R, - unsigned ID, llvm::StringRef Blob) override - { - switch(ID) - { - case FUNCTION_BITS: - return decodeRecord(R, {&I->specs0.raw, &I->specs1.raw}, Blob); - case FUNCTION_CLASS: - return decodeRecord(R, I->Class, Blob); - case FUNCTION_NOEXCEPT: - return decodeRecord(R, I->Noexcept, Blob); - case FUNCTION_EXPLICIT: - return decodeRecord(R, I->Explicit, Blob); - default: - return TopLevelBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_TYPEINFO_BLOCK_ID: - { - TypeInfoBlock B(I->ReturnType, br_); - return br_.readBlock(B, ID); - } - case BI_FUNCTION_PARAM_BLOCK_ID: - { - FunctionParamBlock B(I->Params.emplace_back(), br_); - return br_.readBlock(B, ID); - } - case BI_TEMPLATE_BLOCK_ID: - { - I->Template = std::make_unique<TemplateInfo>(); - TemplateBlock B(*I->Template, br_); - return br_.readBlock(B, ID); - } - case BI_EXPR_BLOCK_ID: - { - ExprBlock E(I->Requires, br_); - return br_.readBlock(E, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class GuideBlock - : public TopLevelBlock<GuideInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - parseRecord(Record const& R, - unsigned ID, llvm::StringRef Blob) override - { - switch(ID) - { - case GUIDE_EXPLICIT: - return decodeRecord(R, I->Explicit, Blob); - default: - return TopLevelBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_TYPEINFO_BLOCK_ID: - { - TypeInfoBlock B(I->Deduced, br_); - return br_.readBlock(B, ID); - } - case BI_FUNCTION_PARAM_BLOCK_ID: - { - FunctionParamBlock B(I->Params.emplace_back(), br_); - return br_.readBlock(B, ID); - } - case BI_TEMPLATE_BLOCK_ID: - { - I->Template = std::make_unique<TemplateInfo>(); - TemplateBlock B(*I->Template, br_); - return br_.readBlock(B, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class TypedefBlock - : public TopLevelBlock<TypedefInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - parseRecord(Record const& R, - unsigned ID, llvm::StringRef Blob) override - { - switch(ID) - { - case TYPEDEF_IS_USING: - return decodeRecord(R, I->IsUsing, Blob); - default: - return TopLevelBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_TYPEINFO_BLOCK_ID: - { - TypeInfoBlock B(I->Type, br_); - return br_.readBlock(B, ID); - } - case BI_TEMPLATE_BLOCK_ID: - { - I->Template = std::make_unique<TemplateInfo>(); - TemplateBlock B(*I->Template, br_); - return br_.readBlock(B, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class EnumBlock - : public TopLevelBlock<EnumInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - parseRecord(Record const& R, - unsigned ID, llvm::StringRef Blob) override - { - switch(ID) - { - case ENUM_SCOPED: - return decodeRecord(R, I->Scoped, Blob); - default: - return TopLevelBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_TYPEINFO_BLOCK_ID: - { - TypeInfoBlock B(I->UnderlyingType, br_); - return br_.readBlock(B, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class VariableBlock - : public TopLevelBlock<VariableInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - parseRecord(Record const& R, - unsigned ID, llvm::StringRef Blob) override - { - switch(ID) - { - case VARIABLE_BITS: - return decodeRecord(R, {&I->specs.raw}, Blob); - default: - return TopLevelBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_EXPR_BLOCK_ID: - { - ExprBlock B(I->Initializer, br_); - return br_.readBlock(B, ID); - } - case BI_TYPEINFO_BLOCK_ID: - { - TypeInfoBlock B(I->Type, br_); - return br_.readBlock(B, ID); - } - case BI_TEMPLATE_BLOCK_ID: - { - I->Template = std::make_unique<TemplateInfo>(); - TemplateBlock B(*I->Template, br_); - return br_.readBlock(B, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class FieldBlock - : public TopLevelBlock<FieldInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case FIELD_ATTRIBUTES: - return decodeRecord(R, {&I->specs.raw}, Blob); - case FIELD_IS_MUTABLE: - return decodeRecord(R, I->IsMutable, Blob); - case FIELD_IS_BITFIELD: - return decodeRecord(R, I->IsBitfield, Blob); - default: - return TopLevelBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_TYPEINFO_BLOCK_ID: - { - TypeInfoBlock B(I->Type, br_); - return br_.readBlock(B, ID); - } - case BI_EXPR_BLOCK_ID: - { - ExprBlock B(I->Default, br_); - return br_.readBlock(B, ID); - } - case BI_BITFIELD_WIDTH_BLOCK_ID: - { - ExprBlock B(I->BitfieldWidth, br_); - return br_.readBlock(B, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class SpecializationBlock - : public TopLevelBlock<SpecializationInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case SPECIALIZATION_PRIMARY: - return decodeRecord(R, I->Primary, Blob); - default: - return TopLevelBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_TEMPLATE_ARG_BLOCK_ID: - { - TemplateArgBlock B(I->Args.emplace_back(), br_); - return br_.readBlock(B, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class FriendBlock - : public TopLevelBlock<FriendInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case FRIEND_SYMBOL: - return decodeRecord(R, I->FriendSymbol, Blob); - default: - return TopLevelBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_TYPEINFO_BLOCK_ID: - { - TypeInfoBlock B(I->FriendType, br_); - return br_.readBlock(B, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class AliasBlock - : public TopLevelBlock<AliasInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_NAME_INFO_ID: - { - NameInfoBlock B(I->AliasedSymbol, br_); - return br_.readBlock(B, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class UsingBlock - : public TopLevelBlock<UsingInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - case USING_SYMBOLS: - return decodeRecord(R, I->UsingSymbols, Blob); - case USING_CLASS: - return decodeRecord(R, I->Class, Blob); - default: - return TopLevelBlock::parseRecord(R, ID, Blob); - } - } - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_NAME_INFO_ID: - { - NameInfoBlock B(I->Qualifier, br_); - return br_.readBlock(B, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -class EnumeratorBlock - : public TopLevelBlock<EnumeratorInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - #if 0 - Error - parseRecord( - Record const& R, - unsigned ID, - llvm::StringRef Blob) override - { - switch(ID) - { - default: - return TopLevelBlock::parseRecord(R, ID, Blob); - } - } - #endif - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_EXPR_BLOCK_ID: - { - ExprBlock B(I->Initializer, br_); - return br_.readBlock(B, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -//------------------------------------------------ - -template<class T> -Error -TopLevelBlock<T>:: -readSubBlock( - unsigned ID) -{ - switch(ID) - { - case BI_INFO_PART_ID: - { - if constexpr(std::derived_from<T, Info>) - { - InfoPartBlock<T> B(I, br_); - return br_.readBlock(B, ID); - } - break; - } - case BI_SOURCE_INFO_ID: - { - if constexpr(std::derived_from<T, SourceInfo>) - { - SourceInfoBlock B(*I.get(), br_); - return br_.readBlock(B, ID); - } - break; - } - case BI_SCOPE_INFO_ID: - { - if constexpr(std::derived_from<T, ScopeInfo>) - { - ScopeInfoBlock B(*I.get(), br_); - return br_.readBlock(B, ID); - } - break; - } - default: - break; - } - return AnyBlock::readSubBlock(ID); -} - -//------------------------------------------------ - -class ConceptBlock - : public TopLevelBlock<ConceptInfo> -{ -public: - using TopLevelBlock::TopLevelBlock; - - Error - readSubBlock( - unsigned ID) override - { - switch(ID) - { - case BI_EXPR_BLOCK_ID: - { - ExprBlock E(I->Constraint, br_); - return br_.readBlock(E, ID); - } - case BI_TEMPLATE_BLOCK_ID: - { - I->Template = std::make_unique<TemplateInfo>(); - TemplateBlock T(*I->Template, br_); - return br_.readBlock(T, ID); - } - default: - return TopLevelBlock::readSubBlock(ID); - } - } -}; - -} // mrdocs -} // clang - -#endif diff --git a/src/lib/AST/Bitcode.hpp b/src/lib/AST/Bitcode.hpp deleted file mode 100644 index 19d215688..000000000 --- a/src/lib/AST/Bitcode.hpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// This is a derivative work. originally part of the LLVM Project. -// Licensed under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// -// Official repository: https://github.com/cppalliance/mrdocs -// - -#ifndef MRDOCS_LIB_AST_BITCODE_HPP -#define MRDOCS_LIB_AST_BITCODE_HPP - -#include <mrdocs/Platform.hpp> -#include <mrdocs/Metadata/Info.hpp> -#include <mrdocs/Support/Error.hpp> -#include <llvm/ADT/SmallString.h> -#include <llvm/ADT/StringRef.h> -#include <memory> -#include <vector> - -namespace clang { -namespace mrdocs { - -/** Return the serialized bitcode for a metadata node. - - This function writes an Info variant to the buffer - as bitcode. -*/ -llvm::SmallString<0> -writeBitcode(Info const& I); - -/** Return an array of Info read from a bitstream. - - This function reads a bitstream and returns an array - of Info objects. The bitstream must have been written - by `writeBitcode`. - - @note Each bitcode might contain multiple Info objects. -*/ -mrdocs::Expected<std::vector<std::unique_ptr<Info>>> -readBitcode(llvm::StringRef bitcode); - -} // mrdocs -} // clang - -#endif diff --git a/src/lib/AST/BitcodeIDs.hpp b/src/lib/AST/BitcodeIDs.hpp deleted file mode 100644 index 62c4aceb5..000000000 --- a/src/lib/AST/BitcodeIDs.hpp +++ /dev/null @@ -1,170 +0,0 @@ -// -// This is a derivative work. originally part of the LLVM Project. -// Licensed under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) -// -// Official repository: https://github.com/cppalliance/mrdocs -// - -#ifndef MRDOCS_LIB_AST_BITCODEIDS_HPP -#define MRDOCS_LIB_AST_BITCODEIDS_HPP - -#include <mrdocs/Platform.hpp> -#include <llvm/Bitstream/BitCodeEnums.h> - -namespace clang { -namespace mrdocs { - -// Current version number of clang-doc bitcode. -// Should be bumped when removing or changing BlockIds, RecordIDs, or -// BitCodeConstants, though they can be added without breaking it. -static const unsigned BitcodeVersion = 3; - -struct BitCodeConstants -{ - static constexpr unsigned RecordSize = 32U; - static constexpr unsigned SignatureBitSize = 8U; - static constexpr unsigned SubblockIDSize = 4U; - static constexpr unsigned BoolSize = 1U; - static constexpr unsigned IntSize = 16U; - static constexpr unsigned StringLengthSize = 16U; // up to 32767 chars - static constexpr unsigned FilenameLengthSize = 16U; - static constexpr unsigned LineNumberSize = 32U; - static constexpr unsigned USRLengthSize = 6U; - static constexpr unsigned USRBitLengthSize = 8U; - static constexpr unsigned USRHashSize = 20; - static constexpr unsigned char Signature[4] = {'M', 'R', 'D', 'X'}; -}; - -/** List of block identifiers. - - New IDs need to be added to both the enum - here and the relevant IdNameMap in the - implementation file. -*/ -enum BlockID -{ - BI_VERSION_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID, - - BI_INFO_PART_ID, - BI_SOURCE_INFO_ID, - BI_SCOPE_INFO_ID, - - BI_NAME_INFO_ID, - BI_LOOKUP_INFO_ID, - BI_BASE_BLOCK_ID, - BI_EXPR_BLOCK_ID, - BI_BITFIELD_WIDTH_BLOCK_ID, - BI_FUNCTION_PARAM_BLOCK_ID, - - // Javadoc - BI_JAVADOC_BLOCK_ID, - BI_JAVADOC_LIST_BLOCK_ID, - BI_JAVADOC_NODE_BLOCK_ID, - - // Info types - #define INFO_UC(Type) BI_##Type##_BLOCK_ID, - #include <mrdocs/Metadata/InfoNodes.inc> - - // Templates - BI_TEMPLATE_ARG_BLOCK_ID, - BI_TEMPLATE_BLOCK_ID, - BI_TEMPLATE_PARAM_BLOCK_ID, - - // Type info - BI_TYPEINFO_BLOCK_ID, - BI_TYPEINFO_PARENT_BLOCK_ID, - BI_TYPEINFO_CHILD_BLOCK_ID, - BI_TYPEINFO_PARAM_BLOCK_ID, - - BI_LAST, - BI_FIRST = BI_VERSION_BLOCK_ID -}; - -// New IDs need to be added to the enum here, and to the relevant IdNameMap and -// initialization list in the implementation file. -enum RecordID -{ - VERSION = 1, - - INFO_PART_ID, - INFO_PART_ACCESS, - INFO_PART_IMPLICIT, - INFO_PART_NAME, - INFO_PART_PARENTS, - SOURCE_INFO_DEFLOC, - SOURCE_INFO_LOC, - SCOPE_INFO_MEMBERS, - LOOKUP_NAME, - LOOKUP_MEMBERS, - - NAME_INFO_KIND, - NAME_INFO_ID, - NAME_INFO_NAME, - - NAMESPACE_BITS, - NAMESPACE_USING_DIRECTIVES, - TYPEINFO_KIND, - TYPEINFO_IS_PACK, - TYPEINFO_CVQUAL, - TYPEINFO_NOEXCEPT, - TYPEINFO_REFQUAL, - TYPEINFO_IS_VARIADIC, - TYPEINFO_AUTO_KEYWORD, - BASE_ACCESS, - BASE_IS_VIRTUAL, - FIELD_ATTRIBUTES, - FIELD_DEFAULT, - FIELD_IS_MUTABLE, - FIELD_IS_BITFIELD, - FRIEND_SYMBOL, - FUNCTION_BITS, - FUNCTION_CLASS, - FUNCTION_NOEXCEPT, - FUNCTION_EXPLICIT, - FUNCTION_PARAM_NAME, - FUNCTION_PARAM_DEFAULT, - GUIDE_EXPLICIT, - JAVADOC_NODE_ADMONISH, - JAVADOC_NODE_HREF, - JAVADOC_NODE_KIND, - JAVADOC_NODE_STRING, - JAVADOC_NODE_STYLE, - JAVADOC_NODE_PART, - JAVADOC_NODE_SYMBOLREF, - JAVADOC_PARAM_DIRECTION, - ENUM_SCOPED, - EXPR_WRITTEN, - EXPR_VALUE, - RECORD_BITS, - RECORD_IS_TYPE_DEF, - RECORD_KEY_KIND, - TEMPLATE_ARG_KIND, - TEMPLATE_ARG_IS_PACK, - TEMPLATE_ARG_TEMPLATE, - TEMPLATE_ARG_NAME, - TEMPLATE_PARAM_IS_PACK, - TEMPLATE_PARAM_KIND, - TEMPLATE_PARAM_NAME, - TEMPLATE_PARAM_KEY_KIND, - TEMPLATE_PRIMARY_USR, - SPECIALIZATION_PRIMARY, - TYPEDEF_IS_USING, - VARIABLE_BITS, - USING_SYMBOLS, - USING_CLASS, - RI_LAST, - RI_FIRST = VERSION -}; - -static constexpr unsigned BlockIdCount = BI_LAST - BI_FIRST; -static constexpr unsigned RecordIDCount = RI_LAST - RI_FIRST; - -} // mrdocs -} // clang - -#endif diff --git a/src/lib/AST/BitcodeReader.cpp b/src/lib/AST/BitcodeReader.cpp deleted file mode 100644 index b15b6712a..000000000 --- a/src/lib/AST/BitcodeReader.cpp +++ /dev/null @@ -1,194 +0,0 @@ -// -// This is a derivative work. originally part of the LLVM Project. -// Licensed under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// -// Official repository: https://github.com/cppalliance/mrdocs -// - -#include "AnyBlock.hpp" -#include "BitcodeReader.hpp" -#include "lib/Support/Debug.hpp" -#include "lib/Support/Error.hpp" -#include <mrdocs/Support/Error.hpp> - -namespace clang { -namespace mrdocs { - -// Entry point -mrdocs::Expected<std::vector<std::unique_ptr<Info>>> -BitcodeReader:: -getInfos() -{ - std::vector<std::unique_ptr<Info>> Infos; - if (auto err = validateStream()) - { - return Unexpected(err); - } - - // Read the top level blocks. - while (!Stream.AtEndOfStream()) - { - llvm::Expected<unsigned> MaybeCode = Stream.ReadCode(); - if (!MaybeCode) - return Unexpected(toError(MaybeCode.takeError())); - if (MaybeCode.get() != llvm::bitc::ENTER_SUBBLOCK) - return Unexpected(formatError("no blocks in input")); - llvm::Expected<unsigned> MaybeID = Stream.ReadSubBlockID(); - if (!MaybeID) - return Unexpected(toError(MaybeID.takeError())); - unsigned ID = MaybeID.get(); - switch (ID) - { - // Top level Version is first - case BI_VERSION_BLOCK_ID: - { - VersionBlock B; - if (auto err = readBlock(B, ID)) - return Unexpected(std::move(err)); - continue; - } - case llvm::bitc::BLOCKINFO_BLOCK_ID: - { - if (auto err = readBlockInfoBlock()) - return Unexpected(std::move(err)); - continue; - } - // Top level Info blocks - #define INFO_PASCAL_AND_UC(Type, TypeUC) \ - case BI_##TypeUC##_BLOCK_ID: \ - { \ - MRDOCS_TRY(auto I, readInfo<Type##Block>(ID)); \ - Infos.emplace_back(std::move(I)); \ - continue; \ - } - #include <mrdocs/Metadata/InfoNodes.inc> - default: - // return formatError("invalid top level block"); - if (llvm::Error err = Stream.SkipBlock()) - { - // FIXME this drops the error on the floor. - consumeError(std::move(err)); - } - continue; - } - } - return std::move(Infos); -} - -//------------------------------------------------ - -Error -BitcodeReader:: -validateStream() -{ - if (Stream.AtEndOfStream()) - return formatError("premature end of stream"); - - // Sniff for the signature. - for (int i = 0; i != 4; ++i) - { - llvm::Expected<llvm::SimpleBitstreamCursor::word_t> MaybeRead = Stream.Read(8); - if (!MaybeRead) - return toError(MaybeRead.takeError()); - else if (MaybeRead.get() != BitCodeConstants::Signature[i]) - return formatError("invalid bitcode signature"); - } - return Error::success(); -} - -Error -BitcodeReader:: -readBlockInfoBlock() -{ - llvm::Expected<std::optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo = - Stream.ReadBlockInfoBlock(); - if (!MaybeBlockInfo) - return toError(MaybeBlockInfo.takeError()); - BlockInfo = MaybeBlockInfo.get(); - if (!BlockInfo) - return formatError("unable to parse BlockInfoBlock"); - Stream.setBlockInfo(&*BlockInfo); - return Error::success(); -} - -//------------------------------------------------ - -template<class T> -mrdocs::Expected<std::unique_ptr<Info>> -BitcodeReader:: -readInfo( - unsigned ID) -{ - T B(*this); - if(auto err = readBlock(B, ID)) - return Unexpected(err); - return std::unique_ptr<Info>(B.I.release()); -} - -Error -BitcodeReader:: -readBlock( - AnyBlock& B, unsigned ID) -{ - if (auto err = Stream.EnterSubBlock(ID)) - return toError(std::move(err)); - blockStack_.push_back(&B); - Record RecordData; - for(;;) - { - llvm::Expected<llvm::BitstreamEntry> MaybeEntry = Stream.advance(); - if(! MaybeEntry) - return toError(MaybeEntry.takeError()); - switch(llvm::BitstreamEntry Entry = MaybeEntry.get(); Entry.Kind) - { - case llvm::BitstreamEntry::Record: - { - llvm::StringRef Blob; - llvm::Expected<unsigned> MaybeRecordID = - Stream.readRecord(Entry.ID, RecordData, &Blob); - if (! MaybeRecordID) - return toError(MaybeRecordID.takeError()); - if(auto err = blockStack_.back()->parseRecord( - RecordData, MaybeRecordID.get(), Blob)) - return err; - RecordData.clear(); - continue; - } - case llvm::BitstreamEntry::SubBlock: - { - if(auto err = blockStack_.back()->readSubBlock(Entry.ID)) - { - if(auto skip_err = Stream.SkipBlock()) - return toError(std::move(skip_err)); - return err; - } - continue; - } - case llvm::BitstreamEntry::EndBlock: - blockStack_.pop_back(); - return Error::success(); - case llvm::BitstreamEntry::Error: - return formatError("bad block found"); - default: - MRDOCS_UNREACHABLE(); - } - } -} - -//------------------------------------------------ - -// Calls readBlock to read each block in the given bitcode. -mrdocs::Expected<std::vector<std::unique_ptr<Info>>> -readBitcode(llvm::StringRef bitcode) -{ - llvm::BitstreamCursor Stream(bitcode); - BitcodeReader reader(Stream); - return reader.getInfos(); -} - -} // mrdocs -} // clang diff --git a/src/lib/AST/BitcodeReader.hpp b/src/lib/AST/BitcodeReader.hpp deleted file mode 100644 index 142b9ebd9..000000000 --- a/src/lib/AST/BitcodeReader.hpp +++ /dev/null @@ -1,83 +0,0 @@ -// -// This is a derivative work. originally part of the LLVM Project. -// Licensed under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// -// Official repository: https://github.com/cppalliance/mrdocs -// - -#ifndef MRDOCS_LIB_AST_BITCODEREADER_HPP -#define MRDOCS_LIB_AST_BITCODEREADER_HPP - -// -// This file implements a reader for parsing the -// mrdocs internal representation from LLVM bitcode. -// The reader takes in a stream of bits and generates -// the set of infos that it represents. -// - -#include "BitcodeIDs.hpp" -#include <mrdocs/Metadata.hpp> -#include <mrdocs/Support/Error.hpp> -#include <llvm/ADT/SmallVector.h> -#include <llvm/Bitstream/BitstreamReader.h> -#include <optional> - -namespace clang { -namespace mrdocs { - -using Record = llvm::SmallVector<uint64_t, 1024>; - -// Class to read bitstream into an InfoSet collection -class BitcodeReader -{ -public: - BitcodeReader( - llvm::BitstreamCursor& Stream) - : Stream(Stream) - { - } - - // Main entry point, calls readBlock to read each block in the given stream. - auto - getInfos() -> - mrdocs::Expected<std::vector<std::unique_ptr<Info>>>; -public: - struct AnyBlock; - - enum class Cursor - { - BadBlock = 1, - Record, - BlockEnd, - BlockBegin - }; - - Error validateStream(); - Error readBlockInfoBlock(); - - /** Return the next decoded Info from the stream. - */ - template<class T> - mrdocs::Expected<std::unique_ptr<Info>> - readInfo(unsigned ID); - - /** Read a single block. - - Calls readRecord on each record found. - */ - Error readBlock(AnyBlock& B, unsigned ID); - -public: - llvm::BitstreamCursor& Stream; - std::optional<llvm::BitstreamBlockInfo> BlockInfo; - std::vector<AnyBlock*> blockStack_; -}; - -} // mrdocs -} // clang - -#endif diff --git a/src/lib/AST/BitcodeWriter.cpp b/src/lib/AST/BitcodeWriter.cpp deleted file mode 100644 index 20c014d6c..000000000 --- a/src/lib/AST/BitcodeWriter.cpp +++ /dev/null @@ -1,1364 +0,0 @@ -// -// This is a derivative work. originally part of the LLVM Project. -// Licensed under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// Copyright (c) 2023 Krystian Stasiowski (sdkrystian@gmail.com) -// -// Official repository: https://github.com/cppalliance/mrdocs -// - -#include "Bitcode.hpp" -#include "BitcodeWriter.hpp" -#include <memory> - -namespace clang { -namespace mrdocs { - -//------------------------------------------------ - -// Since id enums are not zero-indexed, we need to transform the given id into -// its associated index. -struct BlockIdToIndexFunctor -{ - using argument_type = unsigned; - unsigned operator()(unsigned ID) const - { - return ID - BI_FIRST; - } -}; - -struct RecordIDToIndexFunctor -{ - using argument_type = unsigned; - unsigned operator()(unsigned ID) const - { - return ID - RI_FIRST; - } -}; - -//------------------------------------------------ -// -// Abbrev -// -//------------------------------------------------ - -using AbbrevDsc = void (*)(std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev); - -static void AbbrevGen( - std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev, - std::initializer_list<llvm::BitCodeAbbrevOp> Ops) -{ - for (const auto& Op : Ops) - Abbrev->Add(Op); -} - -static void Integer32Abbrev( - std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev) -{ - AbbrevGen(Abbrev, { - // 0. 32-bit signed or unsigned integer - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, 32) }); -} - -static void Integer32ArrayAbbrev( - std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev) -{ - AbbrevGen(Abbrev, { - // 0. VBR integer (number of 32-bit integers) - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, 2), - // 1. Fixed-size array of 32-bit integers - llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array), - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, 32) }); -} - -static void Integer64Abbrev( - std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev) -{ - AbbrevGen(Abbrev, { - // 0. 64-bit signed or unsigned integer - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, 32), - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, 32), - }); -} - -#if 0 -static void Integer16Abbrev( - std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev) -{ - AbbrevGen(Abbrev, { - // 0. 16-bit signed or unsigned integer - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, 16) }); -} -#endif - -static void BoolAbbrev( - std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev) -{ - AbbrevGen(Abbrev, { - // 0. Boolean - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, - BitCodeConstants::BoolSize) }); -} - -static void SymbolIDAbbrev( - std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev) -{ - AbbrevGen(Abbrev, { - // 0. Fixed-size integer (length of the sha1'd USR) - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, - BitCodeConstants::USRLengthSize), - // 1. Fixed-size array of Char6 (USR) - llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array), - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, - BitCodeConstants::USRBitLengthSize) }); -} - -static void SymbolIDsAbbrev( - std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev) -{ - AbbrevGen(Abbrev, { - // 0. VBR integer (number of IDs) - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::VBR, 32), - // 1. Fixed-size array of 20-byte IDs - llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Array), - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, 8) }); -} - -static void StringAbbrev( - std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev) -{ - AbbrevGen(Abbrev, { - // 0. Fixed-size integer (length of the following string) - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, - BitCodeConstants::StringLengthSize), - // 1. The string blob - llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob) }); -} - -// Assumes that the file will not have more than 65535 lines. -static void LocationAbbrev( - std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev) -{ - AbbrevGen(Abbrev, { - // 0. Fixed-size integer (line number) - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, - BitCodeConstants::LineNumberSize), - // 1. File kind - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, 3), - // 2. Whether this declaration has docs - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, 1), - // 3. Fixed-size integer, length of the path - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, - BitCodeConstants::StringLengthSize), - // 4. Fixed-size integer, length of the path + filename - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, - BitCodeConstants::StringLengthSize), - // 5. The string blob - llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob) }); -} - -// Assumes that the file will not have more than 65535 lines. -static void NoexceptAbbrev( - std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev) -{ - AbbrevGen(Abbrev, { - // NoexceptInfo::Implicit - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, - BitCodeConstants::BoolSize), - // NoexceptInfo::Kind - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, 2), - // NoexceptInfo::Operand - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, - BitCodeConstants::StringLengthSize), - // 5. The string blob - llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob) }); -} - -static void ExplicitAbbrev( - std::shared_ptr<llvm::BitCodeAbbrev>& Abbrev) -{ - AbbrevGen(Abbrev, { - // ExplicitInfo::Implicit - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, - BitCodeConstants::BoolSize), - // ExplicitInfo::Kind - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, 2), - // ExplicitInfo::Operand - llvm::BitCodeAbbrevOp( - llvm::BitCodeAbbrevOp::Fixed, - BitCodeConstants::StringLengthSize), - // 5. The string blob - llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob) }); -} - -//------------------------------------------------ - -struct RecordIDDsc -{ - llvm::StringRef Name; - AbbrevDsc Abbrev = nullptr; - - RecordIDDsc() = default; - RecordIDDsc(llvm::StringRef Name, AbbrevDsc Abbrev) - : Name(Name), Abbrev(Abbrev) - { - } - - // Is this 'description' valid? - operator bool() const - { - return Abbrev != nullptr && Name.data() != nullptr && !Name.empty(); - } -}; - -static -llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor> const -BlockIdNameMap = []() -{ - llvm::IndexedMap<llvm::StringRef, BlockIdToIndexFunctor> BlockIdNameMap; - BlockIdNameMap.resize(BlockIdCount); - - // There is no init-list constructor for the IndexedMap, so have to - // improvise - static const std::vector<std::pair<BlockID, const char* const>> Inits = { - {BI_VERSION_BLOCK_ID, "VersionBlock"}, - - {BI_INFO_PART_ID, "InfoPart"}, - {BI_SOURCE_INFO_ID, "SourceInfoBlock"}, - {BI_SCOPE_INFO_ID, "ScopeInfoBlock"}, - - {BI_NAME_INFO_ID, "NameInfoBlock"}, - {BI_LOOKUP_INFO_ID, "LookupInfoBlock"}, - {BI_BASE_BLOCK_ID, "BaseBlock"}, - {BI_EXPR_BLOCK_ID, "ExprBlock"}, - {BI_BITFIELD_WIDTH_BLOCK_ID, "BitfieldWidthBlock"}, - {BI_FUNCTION_PARAM_BLOCK_ID, "FunctionParamBlock"}, - - {BI_JAVADOC_BLOCK_ID, "JavadocBlock"}, - {BI_JAVADOC_LIST_BLOCK_ID, "JavadocListBlock"}, - {BI_JAVADOC_NODE_BLOCK_ID, "JavadocNodeBlock"}, - - #define INFO_PASCAL_AND_UC(Type, UC_Type) \ - {BI_##UC_Type##_BLOCK_ID, #Type "Block"}, - #include <mrdocs/Metadata/InfoNodes.inc> - - {BI_TEMPLATE_ARG_BLOCK_ID, "TemplateArgBlock"}, - {BI_TEMPLATE_BLOCK_ID, "TemplateBlock"}, - {BI_TEMPLATE_PARAM_BLOCK_ID, "TemplateParamBlock"}, - - {BI_TYPEINFO_BLOCK_ID, "TypeInfoBlock"}, - {BI_TYPEINFO_PARENT_BLOCK_ID, "TypeInfoParentBlock"}, - {BI_TYPEINFO_CHILD_BLOCK_ID, "TypeInfoChildBlock"}, - {BI_TYPEINFO_PARAM_BLOCK_ID, "TypeInfoParamBlock"}, - }; - MRDOCS_ASSERT(Inits.size() == BlockIdCount); - for (const auto& Init : Inits) - BlockIdNameMap[Init.first] = Init.second; - MRDOCS_ASSERT(BlockIdNameMap.size() == BlockIdCount); - return BlockIdNameMap; -}(); - -static -llvm::IndexedMap<RecordIDDsc, RecordIDToIndexFunctor> const -RecordIDNameMap = []() -{ - llvm::IndexedMap<RecordIDDsc, RecordIDToIndexFunctor> RecordIDNameMap; - RecordIDNameMap.resize(RecordIDCount); - - // There is no init-list constructor for the IndexedMap, so have to - // improvise - static const std::vector<std::pair<RecordID, RecordIDDsc>> Inits = { - {VERSION, {"Version", &Integer32Abbrev}}, - {BASE_ACCESS, {"BaseAccess", &Integer32Abbrev}}, - {BASE_IS_VIRTUAL, {"BaseIsVirtual", &BoolAbbrev}}, - {ENUM_SCOPED, {"Scoped", &BoolAbbrev}}, - {EXPR_WRITTEN, {"ExprWritten", &StringAbbrev}}, - {EXPR_VALUE, {"ExprValue", &Integer64Abbrev}}, - {FIELD_DEFAULT, {"DefaultValue", &StringAbbrev}}, - {FIELD_ATTRIBUTES, {"FieldAttributes", &Integer32ArrayAbbrev}}, - {FIELD_IS_MUTABLE, {"FieldIsMutable", &BoolAbbrev}}, - {FIELD_IS_BITFIELD, {"FieldIsBitfield", &BoolAbbrev}}, - {FRIEND_SYMBOL, {"FriendSymbol", &SymbolIDAbbrev}}, - {FUNCTION_BITS, {"Bits", &Integer32ArrayAbbrev}}, - {FUNCTION_CLASS, {"FunctionClass", &Integer32Abbrev}}, - {FUNCTION_NOEXCEPT, {"FunctionNoexcept", &NoexceptAbbrev}}, - {FUNCTION_EXPLICIT, {"FunctionExplicit", &ExplicitAbbrev}}, - {FUNCTION_PARAM_NAME, {"Name", &StringAbbrev}}, - {FUNCTION_PARAM_DEFAULT, {"Default", &StringAbbrev}}, - {GUIDE_EXPLICIT, {"GuideExplicit", &ExplicitAbbrev}}, - {INFO_PART_ACCESS, {"InfoAccess", &Integer32Abbrev}}, - {INFO_PART_ID, {"InfoID", &SymbolIDAbbrev}}, - {INFO_PART_IMPLICIT, {"InfoImplicit", &BoolAbbrev}}, - {INFO_PART_NAME, {"InfoName", &StringAbbrev}}, - {INFO_PART_PARENTS, {"InfoParents", &SymbolIDsAbbrev}}, - {JAVADOC_NODE_ADMONISH, {"JavadocNodeAdmonish", &Integer32Abbrev}}, - {JAVADOC_NODE_HREF, {"JavadocNodeHref", &StringAbbrev}}, - {JAVADOC_NODE_KIND, {"JavadocNodeKind", &Integer32Abbrev}}, - {JAVADOC_NODE_STRING, {"JavadocNodeString", &StringAbbrev}}, - {JAVADOC_NODE_STYLE, {"JavadocNodeStyle", &Integer32Abbrev}}, - {JAVADOC_NODE_PART, {"JavadocNodePart", &Integer32Abbrev}}, - {JAVADOC_NODE_SYMBOLREF, {"JavadocNodeSymbol", &SymbolIDAbbrev}}, - {JAVADOC_PARAM_DIRECTION, {"JavadocParamDirection", &Integer32Abbrev}}, - {NAMESPACE_BITS, {"NamespaceBits", &Integer32ArrayAbbrev}}, - {NAMESPACE_USING_DIRECTIVES, {"NamespaceUsingDirectives", &SymbolIDsAbbrev}}, - {NAME_INFO_KIND, {"NameKind", &Integer32Abbrev}}, - {NAME_INFO_ID, {"NameID", &SymbolIDAbbrev}}, - {NAME_INFO_NAME, {"NameName", &StringAbbrev}}, - {RECORD_KEY_KIND, {"KeyKind", &Integer32Abbrev}}, - {RECORD_IS_TYPE_DEF, {"IsTypeDef", &BoolAbbrev}}, - {RECORD_BITS, {"Bits", &Integer32ArrayAbbrev}}, - {SPECIALIZATION_PRIMARY, {"SpecializationPrimary", &SymbolIDAbbrev}}, - {SCOPE_INFO_MEMBERS, {"ScopeMembers", &SymbolIDsAbbrev}}, - {LOOKUP_NAME, {"LookupName", &StringAbbrev}}, - {LOOKUP_MEMBERS, {"LookupMembers", &SymbolIDsAbbrev}}, - {SOURCE_INFO_DEFLOC, {"SourceDefLoc", &LocationAbbrev}}, - {SOURCE_INFO_LOC, {"SourceLoc", &LocationAbbrev}}, - {TEMPLATE_PRIMARY_USR, {"Primary", &SymbolIDAbbrev}}, - {TEMPLATE_ARG_KIND, {"TArgKind", &Integer32Abbrev}}, - {TEMPLATE_ARG_IS_PACK, {"IsPack", &BoolAbbrev}}, - {TEMPLATE_ARG_TEMPLATE, {"TemplateID", &SymbolIDAbbrev}}, - {TEMPLATE_ARG_NAME, {"TemplateName", &StringAbbrev}}, - {TEMPLATE_PARAM_KIND, {"Kind", &Integer32Abbrev}}, - {TEMPLATE_PARAM_NAME, {"Name", &StringAbbrev}}, - {TEMPLATE_PARAM_IS_PACK, {"IsPack", &BoolAbbrev}}, - {TEMPLATE_PARAM_KEY_KIND,{"TParamKeyKind", &Integer32Abbrev}}, - {TYPEINFO_KIND, {"TypeinfoKind", &Integer32Abbrev}}, - {TYPEINFO_IS_PACK, {"TypeinfoIsPack", &BoolAbbrev}}, - {TYPEINFO_CVQUAL, {"TypeinfoCV", &Integer32Abbrev}}, - {TYPEINFO_NOEXCEPT, {"TypeinfoNoexcept", &NoexceptAbbrev}}, - {TYPEINFO_REFQUAL, {"TypeinfoRefqual", &Integer32Abbrev}}, - {TYPEINFO_IS_VARIADIC, {"TypeinfoIsVariadic", &BoolAbbrev}}, - {TYPEINFO_AUTO_KEYWORD, {"TypeinfoAutoKeyword", &Integer32Abbrev}}, - {TYPEDEF_IS_USING, {"IsUsing", &BoolAbbrev}}, - {VARIABLE_BITS, {"Bits", &Integer32ArrayAbbrev}}, - {USING_SYMBOLS, {"UsingSymbols", &SymbolIDsAbbrev}}, - {USING_CLASS, {"UsingClass", &Integer32Abbrev}}, - }; - // MRDOCS_ASSERT(Inits.size() == RecordIDCount); - for (const auto& Init : Inits) - { - RecordIDNameMap[Init.first] = Init.second; - MRDOCS_ASSERT((Init.second.Name.size() + 1) <= BitCodeConstants::RecordSize); - } - // MRDOCS_ASSERT(RecordIDNameMap.size() == RecordIDCount); - return RecordIDNameMap; -}(); - -//------------------------------------------------ - -static -std::vector<std::pair<BlockID, std::vector<RecordID>>> const -RecordsByBlock{ - // Version Block - {BI_VERSION_BLOCK_ID, {VERSION}}, - // Info part - {BI_INFO_PART_ID, - {INFO_PART_ID, INFO_PART_ACCESS, INFO_PART_IMPLICIT, - INFO_PART_NAME, INFO_PART_PARENTS}}, - // SourceInfo - {BI_SOURCE_INFO_ID, - {SOURCE_INFO_DEFLOC, SOURCE_INFO_LOC}}, - // ScopeInfo - {BI_SCOPE_INFO_ID, - {SCOPE_INFO_MEMBERS}}, - // Lookup entry - {BI_LOOKUP_INFO_ID, - {LOOKUP_NAME, LOOKUP_MEMBERS}}, - // BaseInfo - {BI_BASE_BLOCK_ID, - {BASE_ACCESS, BASE_IS_VIRTUAL}}, - // EnumInfo - {BI_ENUM_BLOCK_ID, - {ENUM_SCOPED}}, - // ExprInfo and ConstantExprInfo - {BI_EXPR_BLOCK_ID, - {EXPR_WRITTEN, EXPR_VALUE}}, - {BI_BITFIELD_WIDTH_BLOCK_ID, - {}}, - // FieldInfo - {BI_FIELD_BLOCK_ID, - {FIELD_DEFAULT, FIELD_ATTRIBUTES, - FIELD_IS_MUTABLE, FIELD_IS_BITFIELD}}, - // FunctionInfo - {BI_FUNCTION_BLOCK_ID, - {FUNCTION_BITS, FUNCTION_CLASS, FUNCTION_NOEXCEPT, - FUNCTION_EXPLICIT}}, - // Param - {BI_FUNCTION_PARAM_BLOCK_ID, - {FUNCTION_PARAM_NAME, FUNCTION_PARAM_DEFAULT}}, - // Javadoc - {BI_JAVADOC_BLOCK_ID, - {}}, - // doc::List<doc::Node> - {BI_JAVADOC_LIST_BLOCK_ID, - {}}, - // doc::Node - {BI_JAVADOC_NODE_BLOCK_ID, - {JAVADOC_NODE_KIND, JAVADOC_NODE_HREF, JAVADOC_NODE_STRING, - JAVADOC_NODE_STYLE, JAVADOC_NODE_ADMONISH, JAVADOC_PARAM_DIRECTION, - JAVADOC_NODE_PART, JAVADOC_NODE_SYMBOLREF}}, - // NamespaceInfo - {BI_NAMESPACE_BLOCK_ID, - {NAMESPACE_BITS, NAMESPACE_USING_DIRECTIVES}}, - // RecordInfo - {BI_RECORD_BLOCK_ID, - {RECORD_KEY_KIND, RECORD_IS_TYPE_DEF, RECORD_BITS}}, - // TArg - {BI_TEMPLATE_ARG_BLOCK_ID, - {TEMPLATE_ARG_KIND, TEMPLATE_ARG_IS_PACK, - TEMPLATE_ARG_TEMPLATE, TEMPLATE_ARG_NAME}}, - // TemplateInfo - {BI_TEMPLATE_BLOCK_ID, - {TEMPLATE_PRIMARY_USR}}, - // TParam - {BI_TEMPLATE_PARAM_BLOCK_ID, - {TEMPLATE_PARAM_KIND, TEMPLATE_PARAM_NAME, - TEMPLATE_PARAM_IS_PACK, TEMPLATE_PARAM_KEY_KIND}}, - // SpecializationInfo - {BI_SPECIALIZATION_BLOCK_ID, - {SPECIALIZATION_PRIMARY}}, - // FriendInfo - {BI_FRIEND_BLOCK_ID, - {FRIEND_SYMBOL}}, - // AliasInfo - {BI_ALIAS_BLOCK_ID, - {}}, - // UsingInfo - {BI_USING_BLOCK_ID, - {USING_SYMBOLS, USING_CLASS}}, - // EnumeratorInfo - {BI_ENUMERATOR_BLOCK_ID, - {}}, - // ConceptInfo - {BI_CONCEPT_BLOCK_ID, - {}}, - // TypeInfo - {BI_TYPEINFO_BLOCK_ID, - {TYPEINFO_KIND, TYPEINFO_IS_PACK, TYPEINFO_CVQUAL, - TYPEINFO_NOEXCEPT, TYPEINFO_REFQUAL, TYPEINFO_IS_VARIADIC, - TYPEINFO_AUTO_KEYWORD}}, - {BI_TYPEINFO_PARENT_BLOCK_ID, - {}}, - {BI_TYPEINFO_CHILD_BLOCK_ID, - {}}, - {BI_TYPEINFO_PARAM_BLOCK_ID, - {}}, - // TypedefInfo - {BI_TYPEDEF_BLOCK_ID, - {TYPEDEF_IS_USING}}, - // VariableInfo - {BI_VARIABLE_BLOCK_ID, {VARIABLE_BITS}}, - // GuideInfo - {BI_GUIDE_BLOCK_ID, {GUIDE_EXPLICIT}}, - {BI_NAME_INFO_ID, - {NAME_INFO_KIND, NAME_INFO_ID, NAME_INFO_NAME}}, - }; -//------------------------------------------------ - -BitcodeWriter:: -BitcodeWriter( - llvm::BitstreamWriter &Stream) - : Stream(Stream) -{ - emitHeader(); - emitBlockInfoBlock(); - emitVersionBlock(); -} - -bool -BitcodeWriter:: -dispatchInfoForWrite(const Info& I) -{ - visit(I, [this](const auto& info) - { - emitBlock(info); - }); - return false; -} - -//------------------------------------------------ - -// Validation and Overview Blocks - -/// Emits the magic number header to check -/// that its the right format, in this case, 'DOCS'. -void -BitcodeWriter:: -emitHeader() -{ - for (char C : BitCodeConstants::Signature) - Stream.Emit((unsigned)C, BitCodeConstants::SignatureBitSize); -} - -void -BitcodeWriter:: -emitBlockInfoBlock() -{ - Stream.EnterBlockInfoBlock(); - for (const auto& Block : RecordsByBlock) - { - MRDOCS_ASSERT(Block.second.size() < (1U << BitCodeConstants::SubblockIDSize)); - emitBlockInfo(Block.first, Block.second); - } - Stream.ExitBlock(); -} - -void -BitcodeWriter:: -emitVersionBlock() -{ - StreamSubBlockGuard Block(Stream, BI_VERSION_BLOCK_ID); - emitRecord(BitcodeVersion, VERSION); -} - -// AbbreviationMap - -constexpr unsigned char BitCodeConstants::Signature[]; - -void -BitcodeWriter:: -AbbreviationMap:: -add(RecordID RID, - unsigned AbbrevID) -{ - MRDOCS_ASSERT(RecordIDNameMap[RID] && "Unknown RecordID."); - //MRDOCS_ASSERT((Abbrevs.find(RID) == Abbrevs.end()) && "Abbreviation already added."); - Abbrevs[RID] = AbbrevID; -} - -unsigned -BitcodeWriter:: -AbbreviationMap:: -get(RecordID RID) const -{ - MRDOCS_ASSERT(RecordIDNameMap[RID] && "Unknown RecordID."); - MRDOCS_ASSERT((Abbrevs.find(RID) != Abbrevs.end()) && "Unknown abbreviation."); - return Abbrevs.lookup(RID); -} - -/// Emits a block ID and the block name to the BLOCKINFO block. -void -BitcodeWriter:: -emitBlockID(BlockID BID) -{ - const auto& BlockIdName = BlockIdNameMap[BID]; - MRDOCS_ASSERT(BlockIdName.data() && BlockIdName.size() && "Unknown BlockID."); - - Record.clear(); - Record.push_back(BID); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, - llvm::ArrayRef<unsigned char>(BlockIdName.bytes_begin(), - BlockIdName.bytes_end())); -} - -/// Emits a record name to the BLOCKINFO block. -void -BitcodeWriter:: -emitRecordID(RecordID ID) -{ - MRDOCS_ASSERT(RecordIDNameMap[ID] && "Unknown RecordID."); - prepRecordData(ID); - Record.append(RecordIDNameMap[ID].Name.begin(), - RecordIDNameMap[ID].Name.end()); - Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); -} - -// Abbreviations - -void -BitcodeWriter:: -emitAbbrev( - RecordID ID, BlockID Block) -{ - MRDOCS_ASSERT(RecordIDNameMap[ID] && "Unknown abbreviation."); - auto Abbrev = std::make_shared<llvm::BitCodeAbbrev>(); - Abbrev->Add(llvm::BitCodeAbbrevOp(ID)); - RecordIDNameMap[ID].Abbrev(Abbrev); - Abbrevs.add(ID, Stream.EmitBlockInfoAbbrev(Block, std::move(Abbrev))); -} - -//------------------------------------------------ -// -// Records -// -//------------------------------------------------ - -// Integer -template<class Integer> -requires std::integral<Integer> -void -BitcodeWriter:: -emitRecord( - Integer Value, RecordID ID) -{ - constexpr std::size_t width = sizeof(Integer); - static_assert(width == 4 || width == 8, - "unsupported integer width"); - - MRDOCS_ASSERT(RecordIDNameMap[ID]); - if (!prepRecordData(ID, Value)) - return; - if constexpr(width == 8) - { - MRDOCS_ASSERT(RecordIDNameMap[ID].Abbrev == &Integer64Abbrev); - Record.push_back(static_cast<RecordValue>(Value)); - Record.push_back(static_cast<RecordValue>( - static_cast<std::uint64_t>(Value) >> 32)); - } - else if constexpr(width == 4) - { - MRDOCS_ASSERT(RecordIDNameMap[ID].Abbrev == &Integer32Abbrev); - Record.push_back(static_cast<RecordValue>(Value)); - } -#if 0 - else if constexpr(width == 2) - { - MRDOCS_ASSERT(RecordIDNameMap[ID].Abbrev == &Integer16Abbrev); - } -#endif - - - Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record); -} - -// enum -template<class Enum> -requires std::is_enum_v<Enum> -void -BitcodeWriter:: -emitRecord( - Enum Value, RecordID ID) -{ - emitRecord(static_cast<std::underlying_type_t<Enum>>(Value), ID); -} - -// Bits -void -BitcodeWriter:: -emitRecord( - std::initializer_list<BitFieldFullValue> values, - RecordID ID) -{ - MRDOCS_ASSERT(RecordIDNameMap[ID]); - MRDOCS_ASSERT(RecordIDNameMap[ID].Abbrev == &Integer32ArrayAbbrev); - if (!prepRecordData(ID, true)) - return; - Record.push_back(values.size()); - for(std::uint32_t value : values) - Record.push_back(value); - Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record); -} - -// SymbolIDs -void -BitcodeWriter:: -emitRecord( - std::vector<SymbolID> const& Values, RecordID ID) -{ - MRDOCS_ASSERT(RecordIDNameMap[ID]); - MRDOCS_ASSERT(RecordIDNameMap[ID].Abbrev == &SymbolIDsAbbrev); - if (!prepRecordData(ID, Values.begin() != Values.end())) - return; - Record.push_back(Values.size()); - for(auto const& Sym : Values) - Record.append(Sym.begin(), Sym.end()); - Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record); -} - -// SymbolID -void -BitcodeWriter:: -emitRecord( - SymbolID const& Sym, - RecordID ID) -{ - MRDOCS_ASSERT(RecordIDNameMap[ID] && "Unknown RecordID."); - MRDOCS_ASSERT(RecordIDNameMap[ID].Abbrev == &SymbolIDAbbrev && - "Abbrev type mismatch."); - if (!prepRecordData(ID, !! Sym)) - return; - MRDOCS_ASSERT(Sym.size() == 20); - Record.push_back(Sym.size()); - Record.append(Sym.begin(), Sym.end()); - Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record); -} - -void -BitcodeWriter:: -emitRecord( - llvm::StringRef Str, RecordID ID) -{ - MRDOCS_ASSERT(RecordIDNameMap[ID] && "Unknown RecordID."); - MRDOCS_ASSERT(RecordIDNameMap[ID].Abbrev == &StringAbbrev && - "Abbrev type mismatch."); - if (!prepRecordData(ID, !Str.empty())) - return; - MRDOCS_ASSERT(Str.size() < (1U << BitCodeConstants::StringLengthSize)); - Record.push_back(Str.size()); - Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, Str); -} - -void -BitcodeWriter:: -emitRecord( - Location const& Loc, RecordID ID) -{ - MRDOCS_ASSERT(RecordIDNameMap[ID] && "Unknown RecordID."); - MRDOCS_ASSERT(RecordIDNameMap[ID].Abbrev == &LocationAbbrev && - "Abbrev type mismatch."); - if (!prepRecordData(ID, true)) - return; - // FIXME: Assert that the line number - // is of the appropriate size. - Record.push_back(Loc.LineNumber); - Record.push_back(to_underlying(Loc.Kind)); - Record.push_back(Loc.Documented); - MRDOCS_ASSERT(Loc.Path.size() + Loc.Filename.size() < - (1U << BitCodeConstants::StringLengthSize)); - Record.push_back(Loc.Path.size()); - Record.push_back(Loc.Path.size() + Loc.Filename.size()); - Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, - Loc.Path + Loc.Filename); -} - -void -BitcodeWriter:: -emitRecord( - NoexceptInfo const& I, RecordID ID) -{ - MRDOCS_ASSERT(RecordIDNameMap[ID] && "Unknown RecordID."); - MRDOCS_ASSERT(RecordIDNameMap[ID].Abbrev == &NoexceptAbbrev && - "Abbrev type mismatch."); - if (!prepRecordData(ID, true)) - return; - - Record.push_back(I.Implicit); - Record.push_back(to_underlying(I.Kind)); - Record.push_back(I.Operand.size()); - Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, I.Operand); -} - -void -BitcodeWriter:: -emitRecord( - ExplicitInfo const& I, RecordID ID) -{ - MRDOCS_ASSERT(RecordIDNameMap[ID] && "Unknown RecordID."); - MRDOCS_ASSERT(RecordIDNameMap[ID].Abbrev == &ExplicitAbbrev && - "Abbrev type mismatch."); - if (!prepRecordData(ID, true)) - return; - - Record.push_back(I.Implicit); - Record.push_back(to_underlying(I.Kind)); - Record.push_back(I.Operand.size()); - Stream.EmitRecordWithBlob(Abbrevs.get(ID), Record, I.Operand); -} - -void -BitcodeWriter:: -emitRecord( - bool Val, RecordID ID) -{ - MRDOCS_ASSERT(RecordIDNameMap[ID] && "Unknown RecordID."); - MRDOCS_ASSERT(RecordIDNameMap[ID].Abbrev == &BoolAbbrev && "Abbrev type mismatch."); - if (!prepRecordData(ID, Val)) - return; - Record.push_back(Val); - Stream.EmitRecordWithAbbrev(Abbrevs.get(ID), Record); -} - -bool -BitcodeWriter:: -prepRecordData( - RecordID ID, bool ShouldEmit) -{ - MRDOCS_ASSERT(RecordIDNameMap[ID] && "Unknown RecordID."); - if (!ShouldEmit) - return false; - Record.clear(); - Record.push_back(ID); - return true; -} - -//------------------------------------------------ - -void -BitcodeWriter:: -emitBlockInfo( - BlockID BID, - std::vector<RecordID> const& RIDs) -{ - MRDOCS_ASSERT(RIDs.size() < (1U << BitCodeConstants::SubblockIDSize)); - emitBlockID(BID); - for (RecordID RID : RIDs) - { - emitRecordID(RID); - emitAbbrev(RID, BID); - } -} - -//------------------------------------------------ -// -// emitBlock -// -//------------------------------------------------ - -template<class T> -void -BitcodeWriter:: -emitBlock( - const doc::List<T>& list) -{ - StreamSubBlockGuard Block( - Stream, BI_JAVADOC_LIST_BLOCK_ID); - for(const auto& node : list) - emitBlock(*node); -} - -void -BitcodeWriter:: -emitInfoPart( - Info const& I) -{ - StreamSubBlockGuard Block(Stream, BI_INFO_PART_ID); - emitRecord(I.id, INFO_PART_ID); - emitRecord(I.Access, INFO_PART_ACCESS); - emitRecord(I.Implicit, INFO_PART_IMPLICIT); - emitRecord(I.Name, INFO_PART_NAME); - emitRecord(I.Namespace, INFO_PART_PARENTS); - emitBlock(I.javadoc); -} - -void -BitcodeWriter:: -emitSourceInfo( - const SourceInfo& S) -{ - StreamSubBlockGuard Block(Stream, BI_SOURCE_INFO_ID); - if(S.DefLoc) - emitRecord(*S.DefLoc, SOURCE_INFO_DEFLOC); - for(const auto& L : S.Loc) - emitRecord(L, SOURCE_INFO_LOC); -} - -void -BitcodeWriter:: -emitScopeInfo( - const ScopeInfo& S) -{ - StreamSubBlockGuard Block(Stream, BI_SCOPE_INFO_ID); - emitRecord(S.Members, SCOPE_INFO_MEMBERS); - for(const auto& [name, symbols] : S.Lookups) - emitLookup(name, symbols); -} - -void -BitcodeWriter:: -emitLookup(llvm::StringRef Name, std::vector<SymbolID> const& Members) -{ - StreamSubBlockGuard Block(Stream, BI_LOOKUP_INFO_ID); - emitRecord(Name, LOOKUP_NAME); - emitRecord(Members, LOOKUP_MEMBERS); -} - -void -BitcodeWriter:: -emitBlock( - BaseInfo const& I) -{ - StreamSubBlockGuard Block(Stream, BI_BASE_BLOCK_ID); - emitRecord(I.Access, BASE_ACCESS); - emitRecord(I.IsVirtual, BASE_IS_VIRTUAL); - emitBlock(I.Type); -} - -void -BitcodeWriter:: -emitBlock( - FieldInfo const& F) -{ - StreamSubBlockGuard Block(Stream, BI_FIELD_BLOCK_ID); - emitInfoPart(F); - emitSourceInfo(F); - emitBlock(F.Type); - emitBlock(F.Default); - emitRecord({F.specs.raw}, FIELD_ATTRIBUTES); - emitRecord(F.IsMutable, FIELD_IS_MUTABLE); - emitRecord(F.IsBitfield, FIELD_IS_BITFIELD); - emitBlock(F.BitfieldWidth, BI_BITFIELD_WIDTH_BLOCK_ID); -} - -void -BitcodeWriter:: -emitBlock( - const Param& P) -{ - StreamSubBlockGuard Block(Stream, BI_FUNCTION_PARAM_BLOCK_ID); - emitRecord(P.Name, FUNCTION_PARAM_NAME); - emitRecord(P.Default, FUNCTION_PARAM_DEFAULT); - emitBlock(P.Type); -} - -void -BitcodeWriter:: -emitBlock( - FunctionInfo const& I) -{ - StreamSubBlockGuard Block(Stream, BI_FUNCTION_BLOCK_ID); - emitInfoPart(I); - emitSourceInfo(I); - if (I.Template) - emitBlock(*I.Template); - emitRecord({I.specs0.raw, I.specs1.raw}, FUNCTION_BITS); - emitRecord(I.Class, FUNCTION_CLASS); - emitBlock(I.ReturnType); - for (const auto& N : I.Params) - emitBlock(N); - emitRecord(I.Noexcept, FUNCTION_NOEXCEPT); - emitRecord(I.Explicit, FUNCTION_EXPLICIT); - emitBlock(I.Requires); -} - -void -BitcodeWriter:: -emitBlock( - GuideInfo const& I) -{ - StreamSubBlockGuard Block(Stream, BI_GUIDE_BLOCK_ID); - emitInfoPart(I); - emitSourceInfo(I); - if (I.Template) - emitBlock(*I.Template); - emitRecord(I.Explicit, GUIDE_EXPLICIT); - emitBlock(I.Deduced); - for (const auto& N : I.Params) - emitBlock(N); -} - -void -BitcodeWriter:: -emitBlock( - std::unique_ptr<Javadoc> const& jd) -{ - if(! jd) - return; - // If the unique_ptr<Javadoc> has a value then we - // always want to emit it, even if it is empty. - StreamSubBlockGuard Block(Stream, BI_JAVADOC_BLOCK_ID); - emitBlock(jd->getBlocks()); -} - -void -BitcodeWriter:: -emitBlock( - doc::Node const& I) -{ - StreamSubBlockGuard Block( - Stream, BI_JAVADOC_NODE_BLOCK_ID); - emitRecord(I.kind, JAVADOC_NODE_KIND); - visit(I, [&]<typename NodeTy>(const NodeTy& J) - { - if constexpr(requires { J.href; }) - emitRecord(J.href, JAVADOC_NODE_HREF); - if constexpr(requires { J.string; }) - emitRecord(J.string, JAVADOC_NODE_STRING); - if constexpr(requires { J.style; }) - emitRecord(J.style, JAVADOC_NODE_STYLE); - if constexpr(requires { J.admonish; }) - emitRecord(J.admonish, JAVADOC_NODE_ADMONISH); - if constexpr(requires { J.direction; }) - emitRecord(J.direction, JAVADOC_PARAM_DIRECTION); - if constexpr(requires { J.parts; }) - emitRecord(J.parts, JAVADOC_NODE_PART); - if constexpr(requires { J.id; }) - emitRecord(J.id, JAVADOC_NODE_SYMBOLREF); - if constexpr(requires { J.name; }) - emitRecord(J.name, JAVADOC_NODE_STRING); - if constexpr(requires { J.exception; }) - emitRecord(J.exception, JAVADOC_NODE_STRING); - if constexpr(requires { J.children; }) - emitBlock(J.children); - }); -} - -template<typename ExprInfoTy> - requires std::derived_from<ExprInfoTy, ExprInfo> -void -BitcodeWriter:: -emitBlock( - ExprInfoTy const& E) -{ - StreamSubBlockGuard Block(Stream, BI_EXPR_BLOCK_ID); - emitRecord(E.Written, EXPR_WRITTEN); - if constexpr(requires { E.Value; }) - { - if(E.Value) - emitRecord(*E.Value, EXPR_VALUE); - } -} - -template<typename ExprInfoTy> - requires std::derived_from<ExprInfoTy, ExprInfo> -void -BitcodeWriter:: -emitBlock( - ExprInfoTy const& E, - BlockID ID) -{ - StreamSubBlockGuard Block(Stream, ID); - emitBlock(E); -} - -void -BitcodeWriter:: -emitBlock( - std::unique_ptr<TypeInfo> const& TI, - BlockID ID) -{ - if(! TI) - return; - StreamSubBlockGuard Block(Stream, ID); - emitBlock(TI); -} - -void -BitcodeWriter:: -emitBlock( - std::unique_ptr<TypeInfo> const& TI) -{ - if(! TI) - return; - // If the unique_ptr<Javadoc> has a value then we - // always want to emit it, even if it is empty. - StreamSubBlockGuard Block(Stream, BI_TYPEINFO_BLOCK_ID); - - emitRecord(TI->Kind, TYPEINFO_KIND); - emitRecord(TI->IsPackExpansion, TYPEINFO_IS_PACK); - visit(*TI, [&]<typename T>(const T& t) - { - if constexpr(requires { t.CVQualifiers; }) - emitRecord(t.CVQualifiers, TYPEINFO_CVQUAL); - - if constexpr(requires { t.ParentType; }) - emitBlock(t.ParentType, BI_TYPEINFO_PARENT_BLOCK_ID); - - if constexpr(requires { t.PointeeType; }) - emitBlock(t.PointeeType, BI_TYPEINFO_CHILD_BLOCK_ID); - - if constexpr(T::isArray()) - { - emitBlock(t.ElementType, BI_TYPEINFO_CHILD_BLOCK_ID); - emitBlock(t.Bounds); - } - - if constexpr(T::isDecltype()) - { - emitBlock(t.Operand); - } - - if constexpr(T::isAuto()) - { - emitRecord(t.Keyword, TYPEINFO_AUTO_KEYWORD); - if(t.Constraint) - emitBlock(*t.Constraint); - } - - if constexpr(T::isFunction()) - { - emitBlock(t.ReturnType, BI_TYPEINFO_CHILD_BLOCK_ID); - for(const auto& P : t.ParamTypes) - emitBlock(P, BI_TYPEINFO_PARAM_BLOCK_ID); - - emitRecord(t.RefQualifier, TYPEINFO_REFQUAL); - emitRecord(t.ExceptionSpec, TYPEINFO_NOEXCEPT); - emitRecord(t.IsVariadic, TYPEINFO_IS_VARIADIC); - } - - if constexpr(T::isNamed()) - { - if(t.Name) - emitBlock(*t.Name); - } - }); -} - -void -BitcodeWriter:: -emitBlock( - NamespaceInfo const& I) -{ - StreamSubBlockGuard Block(Stream, BI_NAMESPACE_BLOCK_ID); - emitInfoPart(I); - emitScopeInfo(I); - emitRecord({I.specs.raw}, NAMESPACE_BITS); - emitRecord(I.UsingDirectives, NAMESPACE_USING_DIRECTIVES); -} - -void -BitcodeWriter:: -emitBlock( - RecordInfo const& I) -{ - StreamSubBlockGuard Block(Stream, BI_RECORD_BLOCK_ID); - emitInfoPart(I); - emitSourceInfo(I); - emitScopeInfo(I); - if (I.Template) - emitBlock(*I.Template); - emitRecord(I.KeyKind, RECORD_KEY_KIND); - emitRecord(I.IsTypeDef, RECORD_IS_TYPE_DEF); - emitRecord({I.specs.raw}, RECORD_BITS); - for (const auto& B : I.Bases) - emitBlock(B); -} - -void -BitcodeWriter:: -emitBlock( - EnumInfo const& I) -{ - StreamSubBlockGuard Block(Stream, BI_ENUM_BLOCK_ID); - emitInfoPart(I); - emitSourceInfo(I); - emitScopeInfo(I); - emitRecord(I.Scoped, ENUM_SCOPED); - emitBlock(I.UnderlyingType); -} - -void -BitcodeWriter:: -emitBlock( - const SpecializationInfo& I) -{ - StreamSubBlockGuard Block(Stream, BI_SPECIALIZATION_BLOCK_ID); - emitInfoPart(I); - emitScopeInfo(I); - emitRecord(I.Primary, SPECIALIZATION_PRIMARY); - for(const auto& targ : I.Args) - emitBlock(targ); -} - - -void -BitcodeWriter:: -emitBlock( - const FriendInfo& I) -{ - StreamSubBlockGuard Block(Stream, BI_FRIEND_BLOCK_ID); - emitInfoPart(I); - emitSourceInfo(I); - emitRecord(I.FriendSymbol, FRIEND_SYMBOL); - emitBlock(I.FriendType); -} - -void -BitcodeWriter:: -emitBlock( - AliasInfo const& I) -{ - StreamSubBlockGuard Block(Stream, BI_ALIAS_BLOCK_ID); - emitInfoPart(I); - emitSourceInfo(I); - MRDOCS_ASSERT(I.AliasedSymbol); - emitBlock(*I.AliasedSymbol); -} - -void -BitcodeWriter:: -emitBlock( - UsingInfo const& I) -{ - StreamSubBlockGuard Block(Stream, BI_USING_BLOCK_ID); - emitInfoPart(I); - emitSourceInfo(I); - emitRecord(I.Class, USING_CLASS); - emitRecord(I.UsingSymbols, USING_SYMBOLS); - if (I.Qualifier) - emitBlock(*I.Qualifier); -} - -void -BitcodeWriter:: -emitBlock( - const EnumeratorInfo& I) -{ - StreamSubBlockGuard Block(Stream, BI_ENUMERATOR_BLOCK_ID); - emitInfoPart(I); - emitSourceInfo(I); - emitBlock(I.Initializer); -} - -void -BitcodeWriter:: -emitBlock( - const ConceptInfo& I) -{ - StreamSubBlockGuard Block(Stream, BI_CONCEPT_BLOCK_ID); - emitInfoPart(I); - emitSourceInfo(I); - emitBlock(*I.Template); - emitBlock(I.Constraint); -} - -void -BitcodeWriter:: -emitBlock( - const TemplateInfo& T) -{ - StreamSubBlockGuard Block(Stream, BI_TEMPLATE_BLOCK_ID); - emitRecord(T.Primary, TEMPLATE_PRIMARY_USR); - emitBlock(T.Requires); - for(const auto& targ : T.Args) - emitBlock(targ); - for(const auto& tparam : T.Params) - emitBlock(tparam); -} - -void -BitcodeWriter:: -emitBlock(NameInfo const& I) -{ - StreamSubBlockGuard Block(Stream, BI_NAME_INFO_ID); - emitRecord(I.Kind, NAME_INFO_KIND); - emitRecord(I.id, NAME_INFO_ID); - emitRecord(I.Name, NAME_INFO_NAME); - if(I.Prefix) - emitBlock(*I.Prefix); - if(I.Kind == NameKind::Specialization) - { - for(const auto& targ : static_cast< - const SpecializationNameInfo&>(I).TemplateArgs) - emitBlock(targ); - } -} - -void -BitcodeWriter:: -emitBlock( - const std::unique_ptr<TParam>& T) -{ - StreamSubBlockGuard Block(Stream, BI_TEMPLATE_PARAM_BLOCK_ID); - visit(*T, [&]<typename T>(const T& P) - { - emitRecord(P.Kind, TEMPLATE_PARAM_KIND); - emitRecord(P.Name, TEMPLATE_PARAM_NAME); - emitRecord(P.IsParameterPack, TEMPLATE_PARAM_IS_PACK); - - if(P.Default) - emitBlock(P.Default); - - if constexpr(T::isType()) - { - emitRecord(P.KeyKind, TEMPLATE_PARAM_KEY_KIND); - if(P.Constraint) - emitBlock(*P.Constraint); - } - if constexpr(T::isNonType()) - { - emitBlock(P.Type); - } - if constexpr(T::isTemplate()) - { - for(const auto& P : P.Params) - emitBlock(P); - } - }); -} - -void -BitcodeWriter:: -emitBlock( - const std::unique_ptr<TArg>& T) -{ - StreamSubBlockGuard Block(Stream, BI_TEMPLATE_ARG_BLOCK_ID); - visit(*T, [&]<typename T>(const T& A) - { - emitRecord(A.Kind, TEMPLATE_ARG_KIND); - emitRecord(A.IsPackExpansion, TEMPLATE_ARG_IS_PACK); - - if constexpr(T::isType()) - { - emitBlock(A.Type); - } - else if constexpr(T::isNonType()) - { - emitBlock(A.Value); - } - else if constexpr(T::isTemplate()) - { - emitRecord(A.Template, TEMPLATE_ARG_TEMPLATE); - emitRecord(A.Name, TEMPLATE_ARG_NAME); - } - }); -} - -void -BitcodeWriter:: -emitBlock( - TypedefInfo const& I) -{ - StreamSubBlockGuard Block(Stream, BI_TYPEDEF_BLOCK_ID); - emitInfoPart(I); - emitSourceInfo(I); - emitRecord(I.IsUsing, TYPEDEF_IS_USING); - emitBlock(I.Type); - if(I.Template) - emitBlock(*I.Template); -} - -void -BitcodeWriter:: -emitBlock( - VariableInfo const& I) -{ - StreamSubBlockGuard Block(Stream, BI_VARIABLE_BLOCK_ID); - emitInfoPart(I); - emitSourceInfo(I); - if(I.Template) - emitBlock(*I.Template); - emitBlock(I.Type); - emitBlock(I.Initializer); - emitRecord({I.specs.raw}, VARIABLE_BITS); -} - -//------------------------------------------------ - -llvm::SmallString<0> -writeBitcode(Info const& info) -{ - llvm::SmallString<0> buffer; - llvm::BitstreamWriter stream(buffer); - BitcodeWriter writer(stream); - writer.dispatchInfoForWrite(info); - return buffer; -} - -} // mrdocs -} // clang diff --git a/src/lib/AST/BitcodeWriter.hpp b/src/lib/AST/BitcodeWriter.hpp deleted file mode 100644 index 0c4dac3cb..000000000 --- a/src/lib/AST/BitcodeWriter.hpp +++ /dev/null @@ -1,228 +0,0 @@ -// -// This is a derivative work. originally part of the LLVM Project. -// Licensed under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// -// Official repository: https://github.com/cppalliance/mrdocs -// - -#ifndef MRDOCS_LIB_AST_BITCODEWRITER_HPP -#define MRDOCS_LIB_AST_BITCODEWRITER_HPP - -// -// This file implements a writer for serializing the -// mrdocs internal representation to LLVM bitcode. The -// writer takes in a stream and emits the generated -// bitcode to that stream. -// -#include "BitcodeIDs.hpp" -#include <mrdocs/Metadata.hpp> -#include <llvm/ADT/DenseMap.h> -#include <llvm/ADT/IndexedMap.h> -#include <llvm/ADT/StringRef.h> -#include <llvm/Bitstream/BitstreamWriter.h> -#include <initializer_list> -#include <vector> - -namespace clang { -namespace mrdocs { - -/** A writer for serializing the mrdocs' `Info` representation to LLVM bitcode. - - This class takes in a llvm::BitstreamWriter stream and - emits the generated bitcode to that stream. - - The function `dispatchInfoForWrite` is used to dispatch - the appropriate write function for the given `Info` object. - - After calling `dispatchInfoForWrite`, the buffer used to - create the initial llvm::BitstreamWriter will be populated with - the serialized bitcode for the given `Info` object. - - */ -class BitcodeWriter -{ -public: - // Static size is the maximum length of - // the block/record names we're pushing - // to this + 1. - // - using RecordValue = std::uint32_t; - using RecordType = llvm::SmallVector< - RecordValue, BitCodeConstants::RecordSize>; - - explicit - BitcodeWriter(llvm::BitstreamWriter &Stream); - - /** Write a specific Info to a bitcode stream. - - This function takes in an `Info` object and - emits the generated bitcode to the internal - llvm::BitstreamWriter stream. - - The function will dispatch the appropriate - write function for the given `Info` object. - - After calling `dispatchInfoForWrite`, the - buffer used to create the initial - llvm::BitstreamWriter will be populated with - the serialized bitcode for the given - `Info` object. - - @param I The info to write. - */ - bool dispatchInfoForWrite(const Info& I); - - void emitHeader(); - void emitBlockInfoBlock(); - void emitVersionBlock(); - - - // Emission of validation and overview blocks. - void emitRecordID(RecordID ID); - void emitBlockID(BlockID ID); - void emitBlockInfo(BlockID BID, const std::vector<RecordID> &RIDs); - - //-------------------------------------------- - // - // Records - // - //-------------------------------------------- - - template<class Integer> - requires std::integral<Integer> - void emitRecord(Integer Value, RecordID ID); - - template<class Enum> - requires std::is_enum_v<Enum> - void emitRecord(Enum Value, RecordID ID); - - void emitRecord( - std::vector<SymbolID> const& Values, - RecordID ID); - - void emitRecord(SymbolID const& Str, RecordID ID); - void emitRecord(llvm::StringRef Str, RecordID ID); - void emitRecord(Location const& Loc, RecordID ID); - void emitRecord(NoexceptInfo const& I, RecordID ID); - void emitRecord(ExplicitInfo const& I, RecordID ID); - void emitRecord(bool Value, RecordID ID); - void emitRecord(std::initializer_list<BitFieldFullValue> values, RecordID ID); - - bool prepRecordData(RecordID ID, bool ShouldEmit = true); - - //-------------------------------------------- - - // Emission of appropriate abbreviation type. - void emitAbbrev(RecordID ID, BlockID Block); - - //-------------------------------------------- - // - // emitRecord - // - //-------------------------------------------- - - //-------------------------------------------- - // - // Block emission - // - //-------------------------------------------- - - template<typename T> - void emitBlock(doc::List<T> const& list); - - void emitInfoPart(Info const& I); - void emitSourceInfo(SourceInfo const& S); - void emitScopeInfo(ScopeInfo const& S); - void - emitLookup( - llvm::StringRef Name, - std::vector<SymbolID> const& Members); - - void emitBlock(BaseInfo const& I); - void emitBlock(EnumInfo const& I); - void emitBlock(FunctionInfo const& I); - void emitBlock(GuideInfo const& I); - void emitBlock(Param const& I); - void emitBlock(std::unique_ptr<Javadoc> const& jd); - void emitBlock(doc::Node const& I); - void emitBlock(NamespaceInfo const& I); - void emitBlock(RecordInfo const& I); - void emitBlock(SpecializationInfo const& T); - void emitBlock(TemplateInfo const& T); - void emitBlock(std::unique_ptr<TParam> const& T); - void emitBlock(std::unique_ptr<TArg> const& T); - void emitBlock(TypedefInfo const& I); - void emitBlock(VariableInfo const& I); - void emitBlock(FieldInfo const& I); - void emitBlock(FriendInfo const& I); - void emitBlock(EnumeratorInfo const& I); - void emitBlock(NameInfo const& I); - void emitBlock(AliasInfo const& I); - void emitBlock(UsingInfo const& I); - void emitBlock(ConceptInfo const& I); - - void emitBlock(std::unique_ptr<TypeInfo> const& TI); - void emitBlock(std::unique_ptr<TypeInfo> const& TI, BlockID ID); - - template<typename ExprInfoTy> - requires std::derived_from<ExprInfoTy, ExprInfo> - void emitBlock(ExprInfoTy const& E); - template<typename ExprInfoTy> - requires std::derived_from<ExprInfoTy, ExprInfo> - void emitBlock(ExprInfoTy const& E, BlockID ID); - - //-------------------------------------------- - -private: - class AbbreviationMap - { - llvm::DenseMap<unsigned, unsigned> Abbrevs; - - public: - AbbreviationMap() - : Abbrevs(RecordIDCount) - { - } - - void add(RecordID RID, unsigned AbbrevID); - unsigned get(RecordID RID) const; - }; - - class StreamSubBlockGuard - { - llvm::BitstreamWriter &Stream; - - public: - ~StreamSubBlockGuard() - { - Stream.ExitBlock(); - } - - StreamSubBlockGuard( - llvm::BitstreamWriter &Stream_, - BlockID ID) - : Stream(Stream_) - { - // NOTE: SubBlockIDSize could theoretically - // be calculated on the fly, based on the - // initialization list of records in each block. - Stream.EnterSubblock(ID, BitCodeConstants::SubblockIDSize); - } - - StreamSubBlockGuard(StreamSubBlockGuard &) = delete; - StreamSubBlockGuard &operator=(StreamSubBlockGuard &) = delete; - }; - - RecordType Record; - llvm::BitstreamWriter& Stream; - AbbreviationMap Abbrevs; -}; - -} // mrdocs -} // clang - -#endif diff --git a/src/lib/Gen/bitcode/BitcodeGenerator.cpp b/src/lib/Gen/bitcode/BitcodeGenerator.cpp deleted file mode 100644 index cbf85df8c..000000000 --- a/src/lib/Gen/bitcode/BitcodeGenerator.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// -// This is a derivative work. originally part of the LLVM Project. -// Licensed under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// -// Official repository: https://github.com/cppalliance/mrdocs -// - -#include "BitcodeGenerator.hpp" -#include "lib/Support/Error.hpp" -#include "lib/Support/LegibleNames.hpp" -#include "lib/AST/Bitcode.hpp" -#include <mrdocs/Support/ThreadPool.hpp> -#include <mrdocs/Metadata.hpp> -#include <llvm/Support/FileSystem.h> -#include <llvm/Support/Path.h> - -namespace clang { -namespace mrdocs { -namespace bitcode { - -class MultiFileBuilder -{ - Corpus const& corpus_; - std::string_view outputPath_; - LegibleNames names_; - TaskGroup taskGroup_; - -public: - MultiFileBuilder( - std::string_view outputPath, - Corpus const& corpus) - : corpus_(corpus) - , outputPath_(outputPath) - , names_(corpus_, true) - , taskGroup_(corpus.config.threadPool()) - { - } - - Error - build() - { - corpus_.traverse( - corpus_.globalNamespace(), *this); - auto errors = taskGroup_.wait(); - if(! errors.empty()) - return Error(errors); - return Error::success(); - } - - template<class T> - void operator()(T const& I) - { - namespace fs = llvm::sys::fs; - namespace path = llvm::sys::path; - - taskGroup_.async( - [&] - { - llvm::SmallString<512> filePath(outputPath_); - path::append(filePath, names_.getUnqualified(I.id)); - filePath.append(".bc"); - std::error_code ec; - llvm::raw_fd_ostream os(filePath, ec, fs::CD_CreateAlways); - if(ec) - Error(ec).Throw(); - auto bc = writeBitcode(I); - if((ec = os.error())) - Error(ec).Throw(); - os.write(bc.data(), bc.size()); - if((ec = os.error())) - Error(ec).Throw(); - }); - - if constexpr( - T::isRecord() || - T::isNamespace() || - T::isEnum()) - corpus_.traverse(I, *this); - } -}; - -//------------------------------------------------ - -class SingleFileBuilder -{ - Corpus const& corpus_; - std::ostream& os_; - -public: - SingleFileBuilder( - std::ostream& os, - Corpus const& corpus) - : corpus_(corpus) - , os_(os) - { - } - - Error - build() - { - corpus_.traverse(corpus_.globalNamespace(), *this); - return Error::success(); - } - - template<class T> - void - operator()(T const& I) - { - auto bc = writeBitcode(I); - os_.write(bc.data(), bc.size()); - if constexpr( - T::isRecord() || - T::isNamespace() || - T::isEnum()) - corpus_.traverse(I, *this); - } -}; - -//------------------------------------------------ - -Error -BitcodeGenerator:: -build( - std::string_view outputPath, - Corpus const& corpus) const -{ - return MultiFileBuilder(outputPath, corpus).build(); -} - -Error -BitcodeGenerator:: -buildOne( - std::ostream& os, - Corpus const& corpus) const -{ - return SingleFileBuilder(os, corpus).build(); -} - -} // xml - -//------------------------------------------------ - -std::unique_ptr<Generator> -makeBitcodeGenerator() -{ - return std::make_unique<bitcode::BitcodeGenerator>(); -} - -} // mrdocs -} // clang diff --git a/src/lib/Gen/bitcode/BitcodeGenerator.hpp b/src/lib/Gen/bitcode/BitcodeGenerator.hpp deleted file mode 100644 index bb5e510c4..000000000 --- a/src/lib/Gen/bitcode/BitcodeGenerator.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// This is a derivative work. originally part of the LLVM Project. -// Licensed under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// Copyright (c) 2023 Vinnie Falco (vinnie.falco@gmail.com) -// -// Official repository: https://github.com/cppalliance/mrdocs -// - -#ifndef MRDOCS_LIB_GEN_BITCODE_BITCODEGENERATOR_HPP -#define MRDOCS_LIB_GEN_BITCODE_BITCODEGENERATOR_HPP - -#include <mrdocs/Platform.hpp> -#include <mrdocs/Generator.hpp> -#include <mrdocs/MetadataFwd.hpp> -#include <mrdocs/Metadata/Javadoc.hpp> -#include <optional> - -namespace clang { -namespace mrdocs { -namespace bitcode { - -struct BitcodeGenerator : Generator -{ - std::string_view - id() const noexcept override - { - return "bitcode"; - } - - std::string_view - displayName() const noexcept override - { - return "LLVM Bitstream container"; - } - - std::string_view - fileExtension() const noexcept override - { - return "bc"; - } - - Error - build( - std::string_view outputPath, - Corpus const& corpus) const override; - - Error - buildOne( - std::ostream& os, - Corpus const& corpus) const override; -}; - -} // bitcode -} // mrdocs -} // clang - -#endif diff --git a/src/lib/Lib/CorpusImpl.cpp b/src/lib/Lib/CorpusImpl.cpp index ef1fbc74a..86e7390a5 100644 --- a/src/lib/Lib/CorpusImpl.cpp +++ b/src/lib/Lib/CorpusImpl.cpp @@ -121,12 +121,8 @@ build( // results of the AST traversal. // Any new Info objects will be added to the // InfoSet in the execution context. - #define USE_BITCODE - #ifdef USE_BITCODE - BitcodeExecutionContext context(*config); - #else - InfoExecutionContext context(*config); - #endif + InfoExecutionContext context(*config); + // Create an `ASTActionFactory` to create multiple // `ASTAction`s that extract the AST for each translation unit. std::unique_ptr<tooling::FrontendActionFactory> action = @@ -161,8 +157,7 @@ build( // ------------------------------------------ // Run the process file task on all files // ------------------------------------------ - // Traverse the AST for all translation units - // and emit serializd bitcode into tool results. + // Traverse the AST for all translation units. // This operation happens on a thread pool. report::print(reportLevel, "Extracting declarations"); @@ -217,34 +212,15 @@ build( "Warning: mapping failed because ", err); } - #ifdef USE_BITCODE - report::format(reportLevel, - "Extracted {} declarations in {}", - context.getBitcode().size(), - format_duration(clock_type::now() - start_time)); - start_time = clock_type::now(); - - // First reducing phase (reduce all decls into one info per decl). - report::format(reportLevel, - "Reducing declarations"); - - MRDOCS_TRY(corpus->info_, context.results()); - report::format(reportLevel, - "Reduced {} symbols in {}", - corpus->info_.size(), - format_duration(clock_type::now() - start_time)); - #undef USE_BITCODE - #else - auto results = context.results(); - if(! results) - return Unexpected(results.error()); - corpus->info_ = std::move(results.value()); + auto results = context.results(); + if(! results) + return Unexpected(results.error()); + corpus->info_ = std::move(results.value()); - report::format(reportLevel, - "Extracted {} declarations in {}", - corpus->info_.size(), - format_duration(clock_type::now() - start_time)); - #endif + report::format(reportLevel, + "Extracted {} declarations in {}", + corpus->info_.size(), + format_duration(clock_type::now() - start_time)); // ------------------------------------------ // Finalize corpus diff --git a/src/lib/Lib/ExecutionContext.cpp b/src/lib/Lib/ExecutionContext.cpp index 729e94539..20c2100fc 100644 --- a/src/lib/Lib/ExecutionContext.cpp +++ b/src/lib/Lib/ExecutionContext.cpp @@ -12,7 +12,6 @@ // #include "ExecutionContext.hpp" -#include "lib/AST/Bitcode.hpp" #include "lib/Metadata/Reduce.hpp" #include <mrdocs/Metadata.hpp> #include <ranges> @@ -108,7 +107,6 @@ reportEnd(report::Level level) diags_.reportTotals(level); } - mrdocs::Expected<InfoSet> InfoExecutionContext:: results() @@ -116,85 +114,5 @@ results() return std::move(info_); } -// ---------------------------------------------------------------- -// BitcodeExecutionContext -// ---------------------------------------------------------------- - -void -BitcodeExecutionContext:: -report( - InfoSet&& results, - Diagnostics&& diags) -{ - InfoSet info = std::move(results); - std::lock_guard<std::mutex> lock(mutex_); - for (auto& I : info) - { - llvm::SmallString<0> bitcode = writeBitcode(*I); - auto [it, created] = bitcode_.try_emplace(I->id); - auto& bitcodes = it->second; - if (created || std::ranges::find(bitcodes, bitcode) == bitcodes.end()) - { - bitcodes.emplace_back(std::move(bitcode)); - } - } - - diags_.mergeAndReport(std::move(diags)); -} - -void -BitcodeExecutionContext:: -reportEnd(report::Level level) -{ - diags_.reportTotals(level); -} - -mrdocs::Expected<InfoSet> -BitcodeExecutionContext:: -results() -{ - InfoSet result; - auto errors = config_.threadPool().forEach( - bitcode_, - [&](auto& Group) - { - auto& [id, bitcodes] = Group; - - // One or more Info for the same symbol ID - std::vector<std::unique_ptr<Info>> Infos; - - // Each Bitcode can have multiple Infos - for(auto& bitcode : bitcodes) - { - Expected<std::vector<std::unique_ptr<Info>>> infos = - readBitcode(bitcode); - if (infos.has_value()) - { - std::move( - infos->begin(), - infos->end(), - std::back_inserter(Infos)); - } - else - { - report::error("Failed to read bitcode: {}", infos.error()); - } - } - Expected<std::unique_ptr<Info>> merged = mergeInfos(Infos); - std::unique_ptr<Info> I = std::move(merged.value()); - MRDOCS_ASSERT(I); - MRDOCS_ASSERT(id == I->id); - std::lock_guard<std::mutex> lock(mutex_); - result.emplace(std::move(I)); - }); - - if (!errors.empty()) - { - return Unexpected(errors); - } - return result; -} - - } // mrdocs } // clang diff --git a/src/lib/Lib/ExecutionContext.hpp b/src/lib/Lib/ExecutionContext.hpp index 2e917a42d..565316ec4 100644 --- a/src/lib/Lib/ExecutionContext.hpp +++ b/src/lib/Lib/ExecutionContext.hpp @@ -148,100 +148,6 @@ class InfoExecutionContext results() override; }; -// ---------------------------------------------------------------- - -/** An execution context which stores the InfoSet as bitcode. - - It stores the `InfoSet` and `Diagnostics` - objects, and returns them when `results` - is called. - - Unlike InfoExecutionContext, which stores - symbols in an `InfoSet` (a set of `Info`s), - this class stores the symbols as bitcode. - - Each symbol is converted to bitcode and - and stored in a map of `SymbolID` to - a vector of `SmallString`s with the - bitcodes. - - The execution context will keep all - unique bitcodes associated with a - symbol ID. - - */ -class BitcodeExecutionContext - : public ExecutionContext -{ - std::mutex mutex_; - Diagnostics diags_; - - std::unordered_map< - SymbolID, - std::vector< - llvm::SmallString<0>>> bitcode_; - -public: - using ExecutionContext::ExecutionContext; - - /** Adds symbols and diagnostics to the context. - - This function is called to report the results - of an execution. - - The `InfoSet` is converted to bitcode and - merged into the existing set of results. - - If the symbol ID already exists, it checks - if the exact same bitcode is already present. - If not, the bitcode is appended to the list - of bitcodes for that Symbol ID. This means - duplicate IDs are not merged. - - Any new diagnostics are appended to the - existing diagnostics and new messages - are printed to the console. - - @param info The results to report. - @param diags The diagnostics to report. - */ - void - report( - InfoSet&& info, - Diagnostics&& diags) override; - - /// @copydoc ExecutionContext::reportEnd - void - reportEnd(report::Level level) override; - - /** Returns the results of the execution. - - The results are returned as a set of - `Info` objects. - - The function desearializes the bitcodes - for each symbol ID and merge them into - a single `Info` in parallel. - - @return The results of the execution. - */ - mrdocs::Expected<InfoSet> - results() override; - - /** Returns the bitcode map. - - The results are returned as a map of - `SymbolID` to a vector of `SmallString`. - - @return The results of the execution. - */ - auto& getBitcode() - { - return bitcode_; - } -}; - - } // mrdocs } // clang diff --git a/src/lib/Support/GeneratorsImpl.cpp b/src/lib/Support/GeneratorsImpl.cpp index c19ec9dfb..06decd972 100644 --- a/src/lib/Support/GeneratorsImpl.cpp +++ b/src/lib/Support/GeneratorsImpl.cpp @@ -18,10 +18,6 @@ extern std::unique_ptr<Generator> makeAdocGenerator(); -extern -std::unique_ptr<Generator> -makeBitcodeGenerator(); - extern std::unique_ptr<Generator> makeXMLGenerator(); @@ -48,7 +44,6 @@ GeneratorsImpl() { Error err; err = insert(makeAdocGenerator()); - err = insert(makeBitcodeGenerator()); err = insert(makeXMLGenerator()); err = insert(makeHTMLGenerator()); } diff --git a/test-files/golden-tests/enum.xml b/test-files/golden-tests/enum.xml index 2211b40dc..ea87cfff4 100644 --- a/test-files/golden-tests/enum.xml +++ b/test-files/golden-tests/enum.xml @@ -40,7 +40,7 @@ <type name="char"/> </base> <file path="enum.cpp" line="19" class="def"/> - <enumerator name="e2" initializer="" id="WhHxTXqItGXwZujc82O1Xfzbaz4="> + <enumerator name="e2" initializer="0" id="WhHxTXqItGXwZujc82O1Xfzbaz4="> <file path="enum.cpp" line="21" class="def"/> </enumerator> <enumerator name="e3" initializer="1" id="Rifzp55QTXd/noKg5TyWoEJWlpE="> @@ -60,7 +60,7 @@ <text>E2 description.</text> </para> </doc> - <enumerator name="e4" initializer="" id="RyRlkoU0rHCqW5D5O8YXfJrvfaw="> + <enumerator name="e4" initializer="0" id="RyRlkoU0rHCqW5D5O8YXfJrvfaw="> <file path="enum.cpp" line="35" class="def"/> <doc> <para> @@ -88,7 +88,7 @@ <type name="char"/> </base> <file path="enum.cpp" line="43" class="def"/> - <enumerator name="e6" initializer="" id="m/aInWQVfzBhSp/BbwL1S6HYfgI="> + <enumerator name="e6" initializer="0" id="m/aInWQVfzBhSp/BbwL1S6HYfgI="> <file path="enum.cpp" line="45" class="def"/> </enumerator> <enumerator name="e7" initializer="1" id="s6xZcC+IxMf8dGaSjBuD4CkmAuU=">