[PATCH] D41102: Setup clang-doc frontend framework

Roman Lebedev via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 22 14:41:22 PST 2018


lebedev.ri added a comment.

An idea on how to further generalize/cleanup `emitBlockInfoBlock()`.

While *i think* will help, i'm not sure how to further consolidate the `BlockIdNameMap`/`RecordIdNameMap` and the actual `emitBlock(*)`...



================
Comment at: clang-doc/BitcodeWriter.cpp:55
+    }();
+
+static const IndexedMap<StringRef, RecordIdToIndexFunctor> RecordIdNameMap =
----------------
After thinking, i think the solution is to turn the lambdas in `emit{String,...}Abbrev()` into static functions, and store not a stringref in RecordIdNameMap, but a struct with stringref + pointer to one of the functions.
Since `RecordIdNameMap` is only used in `emitRecordID()`, which is only used in `emitBlockInfoBlock()`, i think it should not be too intrusive..

So
```
// Or, decltype(&StringAbbrev), or std::function?
using AbbrevDsc = void (*)(std::shared_ptr<BitCodeAbbrev> &Abbrev);

static void StringAbbrev(std::shared_ptr<BitCodeAbbrev> &Abbrev) {
    Abbrev->Add(
        BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                        BitCodeConstants::LineNumFixedSize));  // String size
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));       // String
};
static void LocationAbbrev(std::shared_ptr<BitCodeAbbrev> &Abbrev) {
    Abbrev->Add(
        BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                        BitCodeConstants::LineNumFixedSize));  // Line number
    Abbrev->Add(
        BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                        BitCodeConstants::LineNumFixedSize));  // Filename size
    Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));       // Filename
}
static void IntAbbrev = [](std::shared_ptr<BitCodeAbbrev> &Abbrev) {
    Abbrev->Add(
        BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
                        BitCodeConstants::LineNumFixedSize));  // Integer
};

struct RecordIdDsc {
  StringRef Name;
  AbbrevDsc Abbrev;

  RecordIdDsc() = default;

  RecordIdDsc(StringRef Name_, AbbrevDsc Abbrev_) : Name(Name_), Abbrev(Abbrev_) {}
}

static const IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> RecordIdNameMap =
    []() {
      IndexedMap<RecordIdDsc, RecordIdToIndexFunctor> RecordIdNameMap;
      static constexpr unsigned ExpectedSize = RI_LAST - RI_FIRST + 1;
      RecordIdNameMap.resize(ExpectedSize);

      // There is no init-list constructor for the IndexedMap, so have to
      // improvise
      static constexpr std::initializer_list<
          std::pair<RecordId, RecordIdDsc>>
          inits = {{VERSION, {"Version", &IntAbbrev}},
....
```


================
Comment at: clang-doc/BitcodeWriter.cpp:156
+  prepRecordData(ID);
+  for (const char C : RecordIdNameMap[ID]) Record.push_back(C);
+  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record);
----------------
```
for (const char C : RecordIdNameMap[ID].Name) Record.push_back(C);
```


================
Comment at: clang-doc/BitcodeWriter.cpp:162
+
+template <typename Lambda>
+void ClangDocBitcodeWriter::emitAbbrev(RecordId ID, BlockId Block, Lambda &&L) {
----------------
```
void ClangDocBitcodeWriter::emitAbbrev(RecordId ID, BlockId Block) {
  auto Abbrev = std::make_shared<BitCodeAbbrev>();
  Abbrev->Add(BitCodeAbbrevOp(ID));
  RecordIdNameMap[ID].Abbrev(Abbrev);
  Abbrevs.add(ID, Stream.EmitBlockInfoAbbrev(Block, std::move(Abbrev)));
}
```


================
Comment at: clang-doc/BitcodeWriter.cpp:170
+
+void ClangDocBitcodeWriter::emitStringAbbrev(RecordId ID, BlockId Block) {
+  auto EmitString = [](std::shared_ptr<BitCodeAbbrev> &Abbrev) {
----------------
Those three will be gone


================
Comment at: clang-doc/BitcodeWriter.cpp:253
+        COMMENT_ARG, COMMENT_POSITION})
+    emitStringAbbrev(RID, BI_COMMENT_BLOCK_ID);
+  emitIntAbbrev(COMMENT_SELFCLOSING, BI_COMMENT_BLOCK_ID);
----------------
So now this is
```
  for (RecordId RID :
       {COMMENT_KIND, COMMENT_TEXT, COMMENT_NAME, COMMENT_DIRECTION,
        COMMENT_PARAMNAME, COMMENT_CLOSENAME, COMMENT_ATTRKEY, COMMENT_ATTRVAL,
        COMMENT_ARG, COMMENT_POSITION, COMMENT_SELFCLOSING, COMMENT_EXPLICIT})
    emitAbbrev(RID, BI_COMMENT_BLOCK_ID);
```


================
Comment at: clang-doc/BitcodeWriter.cpp:273
+    emitRecordID(RID);
+  emitStringAbbrev(MEMBER_TYPE_TYPE, BI_MEMBER_TYPE_BLOCK_ID);
+  emitStringAbbrev(MEMBER_TYPE_NAME, BI_MEMBER_TYPE_BLOCK_ID);
----------------
```
  for (RecordId RID : {MEMBER_TYPE_TYPE, MEMBER_TYPE_NAME, MEMBER_TYPE_ACCESS})
    emitAbbrev(RID, BI_MEMBER_TYPE_BLOCK_ID);
```
and so on


================
Comment at: clang-doc/BitcodeWriter.cpp:277
+
+  // Namespace Block
+  emitBlockID(BI_NAMESPACE_BLOCK_ID);
----------------
And The Next Pattern:
```
emitBlockID(BI_{STUFF}_BLOCK_ID); // <- same BI_{STUFF}_BLOCK_ID
for (RecordId RID : {STUFF_FOO, STUFF_BAR, STUFF_BAZ, ...}) // <- same init-list
  emitRecordID(RID);
for (RecordId RID : {STUFF_FOO, STUFF_BAR, STUFF_BAZ, ...}) // <- same init-list
  emitAbbrev(RID, BI_{STUFF}_BLOCK_ID); // <- same BI_{STUFF}_BLOCK_ID
```

I think it can be generalized as:
```
std::initializer_list<std::pair<BlockId, std::initializer_list<RecordId>>> TheBlocks {
...
  // Namespace Block
  {BI_NAMESPACE_BLOCK_ID, {NAMESPACE_NAME, NAMESPACE_NAMESPACE}},
...
};

for(const auto& Block : TheBlocks) {
  emitBlockID(Block.first);

  for(const auto& Record : Block.second)
    emitRecordID(Record);

  for(const auto& Record : Block.second)
    emitAbbrev(Record, Block.first);
}
```


================
Comment at: clang-doc/BitcodeWriter.h:209
+
+  void emitStringAbbrev(RecordId ID, BlockId Block);
+  void emitLocationAbbrev(RecordId ID, BlockId Block);
----------------
One more piece of the puzzle.
It seems, there is only one abbrev type (i.e. loc/string/int) for a given `RecordId`, yes?
If so, i believe one more mapping can be added somehow, to go from a given `RecordId` to the appropriate abbrev type.


https://reviews.llvm.org/D41102





More information about the cfe-commits mailing list