1 //===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===//
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
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"
15 using namespace clang;
16 using namespace clang::serialization;
18 TestModuleFileExtension::Writer::~Writer() { }
20 void TestModuleFileExtension::Writer::writeExtensionContents(
22 llvm::BitstreamWriter &Stream) {
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));
32 // Write a message into the extension block.
33 SmallString<64> Message;
35 auto Ext = static_cast<TestModuleFileExtension *>(getExtension());
36 raw_svector_ostream OS(Message);
37 OS << "Hello from " << Ext->BlockName << " v" << Ext->MajorVersion << "."
40 uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, Message.size()};
41 Stream.EmitRecordWithBlob(Abbrev, Record, Message);
44 TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
45 const llvm::BitstreamCursor &InStream)
46 : ModuleFileExtensionReader(Ext), Stream(InStream)
48 // Read the extension block.
49 SmallVector<uint64_t, 4> Record;
51 llvm::Expected<llvm::BitstreamEntry> MaybeEntry =
52 Stream.advanceSkippingSubblocks();
54 (void)MaybeEntry.takeError();
55 llvm::BitstreamEntry Entry = MaybeEntry.get();
58 case llvm::BitstreamEntry::SubBlock:
59 case llvm::BitstreamEntry::EndBlock:
60 case llvm::BitstreamEntry::Error:
63 case llvm::BitstreamEntry::Record:
69 Expected<unsigned> MaybeRecCode =
70 Stream.readRecord(Entry.ID, Record, &Blob);
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());
85 TestModuleFileExtension::Reader::~Reader() { }
87 TestModuleFileExtension::~TestModuleFileExtension() { }
89 ModuleFileExtensionMetadata
90 TestModuleFileExtension::getExtensionMetadata() const {
91 return { BlockName, MajorVersion, MinorVersion, UserInfo };
94 llvm::hash_code TestModuleFileExtension::hashExtension(
95 llvm::hash_code Code) const {
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);
106 std::unique_ptr<ModuleFileExtensionWriter>
107 TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
108 return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
111 std::unique_ptr<ModuleFileExtensionReader>
112 TestModuleFileExtension::createExtensionReader(
113 const ModuleFileExtensionMetadata &Metadata,
114 ASTReader &Reader, serialization::ModuleFile &Mod,
115 const llvm::BitstreamCursor &Stream)
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;
127 return std::unique_ptr<ModuleFileExtensionReader>(
128 new TestModuleFileExtension::Reader(this, Stream));