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/Bitstream/BitstreamWriter.h"
12#include "llvm/Support/raw_ostream.h"
13#include <cstdio>
14using namespace clang;
15using namespace clang::serialization;
16
17char TestModuleFileExtension::ID = 0;
18
19TestModuleFileExtension::Writer::~Writer() { }
20
21void TestModuleFileExtension::Writer::writeExtensionContents(
22 Sema &SemaRef,
23 llvm::BitstreamWriter &Stream) {
24 using namespace llvm;
25
26 // Write an abbreviation for this record.
27 auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
28 Abv->Add(OpInfo: BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID));
29 Abv->Add(OpInfo: BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of characters
30 Abv->Add(OpInfo: BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // message
31 auto Abbrev = Stream.EmitAbbrev(Abbv: std::move(Abv));
32
33 // Write a message into the extension block.
34 SmallString<64> Message;
35 {
36 auto Ext = static_cast<TestModuleFileExtension *>(getExtension());
37 raw_svector_ostream OS(Message);
38 OS << "Hello from " << Ext->BlockName << " v" << Ext->MajorVersion << "."
39 << Ext->MinorVersion;
40 }
41 uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, Message.size()};
42 Stream.EmitRecordWithBlob(Abbrev, Vals: Record, Blob: Message);
43}
44
45TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
46 const llvm::BitstreamCursor &InStream)
47 : ModuleFileExtensionReader(Ext), Stream(InStream)
48{
49 // Read the extension block.
50 SmallVector<uint64_t, 4> Record;
51 while (true) {
52 llvm::Expected<llvm::BitstreamEntry> MaybeEntry =
53 Stream.advanceSkippingSubblocks();
54 if (!MaybeEntry)
55 (void)MaybeEntry.takeError();
56 llvm::BitstreamEntry Entry = MaybeEntry.get();
57
58 switch (Entry.Kind) {
59 case llvm::BitstreamEntry::SubBlock:
60 case llvm::BitstreamEntry::EndBlock:
61 case llvm::BitstreamEntry::Error:
62 return;
63
64 case llvm::BitstreamEntry::Record:
65 break;
66 }
67
68 Record.clear();
69 StringRef Blob;
70 Expected<unsigned> MaybeRecCode =
71 Stream.readRecord(AbbrevID: Entry.ID, Vals&: Record, Blob: &Blob);
72 if (!MaybeRecCode)
73 fprintf(stderr, format: "Failed reading rec code: %s\n",
74 toString(E: MaybeRecCode.takeError()).c_str());
75 switch (MaybeRecCode.get()) {
76 case FIRST_EXTENSION_RECORD_ID: {
77 StringRef Message = Blob.substr(Start: 0, N: Record[0]);
78 fprintf(stderr, format: "Read extension block message: %s\n",
79 Message.str().c_str());
80 break;
81 }
82 }
83 }
84}
85
86TestModuleFileExtension::Reader::~Reader() { }
87
88TestModuleFileExtension::~TestModuleFileExtension() { }
89
90ModuleFileExtensionMetadata
91TestModuleFileExtension::getExtensionMetadata() const {
92 return { .BlockName: BlockName, .MajorVersion: MajorVersion, .MinorVersion: MinorVersion, .UserInfo: UserInfo };
93}
94
95void TestModuleFileExtension::hashExtension(
96 ExtensionHashBuilder &HBuilder) const {
97 if (Hashed) {
98 HBuilder.add(Value: BlockName);
99 HBuilder.add(Value: MajorVersion);
100 HBuilder.add(Value: MinorVersion);
101 HBuilder.add(Value: UserInfo);
102 }
103}
104
105std::unique_ptr<ModuleFileExtensionWriter>
106TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
107 return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
108}
109
110std::unique_ptr<ModuleFileExtensionReader>
111TestModuleFileExtension::createExtensionReader(
112 const ModuleFileExtensionMetadata &Metadata,
113 ASTReader &Reader, serialization::ModuleFile &Mod,
114 const llvm::BitstreamCursor &Stream)
115{
116 assert(Metadata.BlockName == BlockName && "Wrong block name");
117 if (std::make_pair(x: Metadata.MajorVersion, y: Metadata.MinorVersion) !=
118 std::make_pair(x&: MajorVersion, y&: MinorVersion)) {
119 Reader.getDiags().Report(Mod.ImportLoc,
120 diag::err_test_module_file_extension_version)
121 << BlockName << Metadata.MajorVersion << Metadata.MinorVersion
122 << MajorVersion << MinorVersion;
123 return nullptr;
124 }
125
126 return std::unique_ptr<ModuleFileExtensionReader>(
127 new TestModuleFileExtension::Reader(this, Stream));
128}
129
130std::string TestModuleFileExtension::str() const {
131 std::string Buffer;
132 llvm::raw_string_ostream OS(Buffer);
133 OS << BlockName << ":" << MajorVersion << ":" << MinorVersion << ":" << Hashed
134 << ":" << UserInfo;
135 return Buffer;
136}
137

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of clang/lib/Frontend/TestModuleFileExtension.cpp