xref: /freebsd/contrib/llvm-project/clang/lib/Frontend/TestModuleFileExtension.cpp (revision 80e63e0a9023ba28d73c3753002726674835e414)
1  //===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===//
2  //
3  // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4  // See https://llvm.org/LICENSE.txt for license information.
5  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6  //
7  //===----------------------------------------------------------------------===//
8  #include "TestModuleFileExtension.h"
9  #include "clang/Frontend/FrontendDiagnostic.h"
10  #include "clang/Serialization/ASTReader.h"
11  #include "llvm/ADT/Hashing.h"
12  #include "llvm/Bitstream/BitstreamWriter.h"
13  #include "llvm/Support/raw_ostream.h"
14  #include <cstdio>
15  using namespace clang;
16  using namespace clang::serialization;
17  
18  TestModuleFileExtension::Writer::~Writer() { }
19  
20  void TestModuleFileExtension::Writer::writeExtensionContents(
21         Sema &SemaRef,
22         llvm::BitstreamWriter &Stream) {
23    using namespace llvm;
24  
25    // Write an abbreviation for this record.
26    auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
27    Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID));
28    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of characters
29    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));   // message
30    auto Abbrev = Stream.EmitAbbrev(std::move(Abv));
31  
32    // Write a message into the extension block.
33    SmallString<64> Message;
34    {
35      auto Ext = static_cast<TestModuleFileExtension *>(getExtension());
36      raw_svector_ostream OS(Message);
37      OS << "Hello from " << Ext->BlockName << " v" << Ext->MajorVersion << "."
38         << Ext->MinorVersion;
39    }
40    uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, Message.size()};
41    Stream.EmitRecordWithBlob(Abbrev, Record, Message);
42  }
43  
44  TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
45                                          const llvm::BitstreamCursor &InStream)
46    : ModuleFileExtensionReader(Ext), Stream(InStream)
47  {
48    // Read the extension block.
49    SmallVector<uint64_t, 4> Record;
50    while (true) {
51      llvm::Expected<llvm::BitstreamEntry> MaybeEntry =
52          Stream.advanceSkippingSubblocks();
53      if (!MaybeEntry)
54        (void)MaybeEntry.takeError();
55      llvm::BitstreamEntry Entry = MaybeEntry.get();
56  
57      switch (Entry.Kind) {
58      case llvm::BitstreamEntry::SubBlock:
59      case llvm::BitstreamEntry::EndBlock:
60      case llvm::BitstreamEntry::Error:
61        return;
62  
63      case llvm::BitstreamEntry::Record:
64        break;
65      }
66  
67      Record.clear();
68      StringRef Blob;
69      Expected<unsigned> MaybeRecCode =
70          Stream.readRecord(Entry.ID, Record, &Blob);
71      if (!MaybeRecCode)
72        fprintf(stderr, "Failed reading rec code: %s\n",
73                toString(MaybeRecCode.takeError()).c_str());
74      switch (MaybeRecCode.get()) {
75      case FIRST_EXTENSION_RECORD_ID: {
76        StringRef Message = Blob.substr(0, Record[0]);
77        fprintf(stderr, "Read extension block message: %s\n",
78                Message.str().c_str());
79        break;
80      }
81      }
82    }
83  }
84  
85  TestModuleFileExtension::Reader::~Reader() { }
86  
87  TestModuleFileExtension::~TestModuleFileExtension() { }
88  
89  ModuleFileExtensionMetadata
90  TestModuleFileExtension::getExtensionMetadata() const {
91    return { BlockName, MajorVersion, MinorVersion, UserInfo };
92  }
93  
94  llvm::hash_code TestModuleFileExtension::hashExtension(
95                    llvm::hash_code Code) const {
96    if (Hashed) {
97      Code = llvm::hash_combine(Code, BlockName);
98      Code = llvm::hash_combine(Code, MajorVersion);
99      Code = llvm::hash_combine(Code, MinorVersion);
100      Code = llvm::hash_combine(Code, UserInfo);
101    }
102  
103    return Code;
104  }
105  
106  std::unique_ptr<ModuleFileExtensionWriter>
107  TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
108    return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
109  }
110  
111  std::unique_ptr<ModuleFileExtensionReader>
112  TestModuleFileExtension::createExtensionReader(
113    const ModuleFileExtensionMetadata &Metadata,
114    ASTReader &Reader, serialization::ModuleFile &Mod,
115    const llvm::BitstreamCursor &Stream)
116  {
117    assert(Metadata.BlockName == BlockName && "Wrong block name");
118    if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) !=
119          std::make_pair(MajorVersion, MinorVersion)) {
120      Reader.getDiags().Report(Mod.ImportLoc,
121                               diag::err_test_module_file_extension_version)
122        << BlockName << Metadata.MajorVersion << Metadata.MinorVersion
123        << MajorVersion << MinorVersion;
124      return nullptr;
125    }
126  
127    return std::unique_ptr<ModuleFileExtensionReader>(
128                                                      new TestModuleFileExtension::Reader(this, Stream));
129  }
130