xref: /freebsd/contrib/llvm-project/clang/lib/Frontend/TestModuleFileExtension.cpp (revision 21817992b3314c908ab50f0bb88d2ee750b9c4ac)
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  char TestModuleFileExtension::ID = 0;
19  
20  TestModuleFileExtension::Writer::~Writer() { }
21  
22  void TestModuleFileExtension::Writer::writeExtensionContents(
23         Sema &SemaRef,
24         llvm::BitstreamWriter &Stream) {
25    using namespace llvm;
26  
27    // Write an abbreviation for this record.
28    auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
29    Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID));
30    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of characters
31    Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));   // message
32    auto Abbrev = Stream.EmitAbbrev(std::move(Abv));
33  
34    // Write a message into the extension block.
35    SmallString<64> Message;
36    {
37      auto Ext = static_cast<TestModuleFileExtension *>(getExtension());
38      raw_svector_ostream OS(Message);
39      OS << "Hello from " << Ext->BlockName << " v" << Ext->MajorVersion << "."
40         << Ext->MinorVersion;
41    }
42    uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, Message.size()};
43    Stream.EmitRecordWithBlob(Abbrev, Record, Message);
44  }
45  
46  TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
47                                          const llvm::BitstreamCursor &InStream)
48    : ModuleFileExtensionReader(Ext), Stream(InStream)
49  {
50    // Read the extension block.
51    SmallVector<uint64_t, 4> Record;
52    while (true) {
53      llvm::Expected<llvm::BitstreamEntry> MaybeEntry =
54          Stream.advanceSkippingSubblocks();
55      if (!MaybeEntry)
56        (void)MaybeEntry.takeError();
57      llvm::BitstreamEntry Entry = MaybeEntry.get();
58  
59      switch (Entry.Kind) {
60      case llvm::BitstreamEntry::SubBlock:
61      case llvm::BitstreamEntry::EndBlock:
62      case llvm::BitstreamEntry::Error:
63        return;
64  
65      case llvm::BitstreamEntry::Record:
66        break;
67      }
68  
69      Record.clear();
70      StringRef Blob;
71      Expected<unsigned> MaybeRecCode =
72          Stream.readRecord(Entry.ID, Record, &Blob);
73      if (!MaybeRecCode)
74        fprintf(stderr, "Failed reading rec code: %s\n",
75                toString(MaybeRecCode.takeError()).c_str());
76      switch (MaybeRecCode.get()) {
77      case FIRST_EXTENSION_RECORD_ID: {
78        StringRef Message = Blob.substr(0, Record[0]);
79        fprintf(stderr, "Read extension block message: %s\n",
80                Message.str().c_str());
81        break;
82      }
83      }
84    }
85  }
86  
87  TestModuleFileExtension::Reader::~Reader() { }
88  
89  TestModuleFileExtension::~TestModuleFileExtension() { }
90  
91  ModuleFileExtensionMetadata
92  TestModuleFileExtension::getExtensionMetadata() const {
93    return { BlockName, MajorVersion, MinorVersion, UserInfo };
94  }
95  
96  void TestModuleFileExtension::hashExtension(
97      ExtensionHashBuilder &HBuilder) const {
98    if (Hashed) {
99      HBuilder.add(BlockName);
100      HBuilder.add(MajorVersion);
101      HBuilder.add(MinorVersion);
102      HBuilder.add(UserInfo);
103    }
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  
131  std::string TestModuleFileExtension::str() const {
132    std::string Buffer;
133    llvm::raw_string_ostream OS(Buffer);
134    OS << BlockName << ":" << MajorVersion << ":" << MinorVersion << ":" << Hashed
135       << ":" << UserInfo;
136    return Buffer;
137  }
138