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