150
|
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 }
|