xref: /freebsd-src/contrib/llvm-project/clang/lib/Frontend/TestModuleFileExtension.cpp (revision 0eae32dcef82f6f06de6419a0d623d7def0cc8f6)
10b57cec5SDimitry Andric //===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric #include "TestModuleFileExtension.h"
90b57cec5SDimitry Andric #include "clang/Frontend/FrontendDiagnostic.h"
100b57cec5SDimitry Andric #include "clang/Serialization/ASTReader.h"
110b57cec5SDimitry Andric #include "llvm/ADT/Hashing.h"
120b57cec5SDimitry Andric #include "llvm/Bitstream/BitstreamWriter.h"
130b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
140b57cec5SDimitry Andric #include <cstdio>
150b57cec5SDimitry Andric using namespace clang;
160b57cec5SDimitry Andric using namespace clang::serialization;
170b57cec5SDimitry Andric 
18fe6060f1SDimitry Andric char TestModuleFileExtension::ID = 0;
19fe6060f1SDimitry Andric 
~Writer()200b57cec5SDimitry Andric TestModuleFileExtension::Writer::~Writer() { }
210b57cec5SDimitry Andric 
writeExtensionContents(Sema & SemaRef,llvm::BitstreamWriter & Stream)220b57cec5SDimitry Andric void TestModuleFileExtension::Writer::writeExtensionContents(
230b57cec5SDimitry Andric        Sema &SemaRef,
240b57cec5SDimitry Andric        llvm::BitstreamWriter &Stream) {
250b57cec5SDimitry Andric   using namespace llvm;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric   // Write an abbreviation for this record.
280b57cec5SDimitry Andric   auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
290b57cec5SDimitry Andric   Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID));
300b57cec5SDimitry Andric   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of characters
310b57cec5SDimitry Andric   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));   // message
320b57cec5SDimitry Andric   auto Abbrev = Stream.EmitAbbrev(std::move(Abv));
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric   // Write a message into the extension block.
350b57cec5SDimitry Andric   SmallString<64> Message;
360b57cec5SDimitry Andric   {
370b57cec5SDimitry Andric     auto Ext = static_cast<TestModuleFileExtension *>(getExtension());
380b57cec5SDimitry Andric     raw_svector_ostream OS(Message);
390b57cec5SDimitry Andric     OS << "Hello from " << Ext->BlockName << " v" << Ext->MajorVersion << "."
400b57cec5SDimitry Andric        << Ext->MinorVersion;
410b57cec5SDimitry Andric   }
420b57cec5SDimitry Andric   uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, Message.size()};
430b57cec5SDimitry Andric   Stream.EmitRecordWithBlob(Abbrev, Record, Message);
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric 
Reader(ModuleFileExtension * Ext,const llvm::BitstreamCursor & InStream)460b57cec5SDimitry Andric TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
470b57cec5SDimitry Andric                                         const llvm::BitstreamCursor &InStream)
480b57cec5SDimitry Andric   : ModuleFileExtensionReader(Ext), Stream(InStream)
490b57cec5SDimitry Andric {
500b57cec5SDimitry Andric   // Read the extension block.
510b57cec5SDimitry Andric   SmallVector<uint64_t, 4> Record;
520b57cec5SDimitry Andric   while (true) {
530b57cec5SDimitry Andric     llvm::Expected<llvm::BitstreamEntry> MaybeEntry =
540b57cec5SDimitry Andric         Stream.advanceSkippingSubblocks();
550b57cec5SDimitry Andric     if (!MaybeEntry)
560b57cec5SDimitry Andric       (void)MaybeEntry.takeError();
570b57cec5SDimitry Andric     llvm::BitstreamEntry Entry = MaybeEntry.get();
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric     switch (Entry.Kind) {
600b57cec5SDimitry Andric     case llvm::BitstreamEntry::SubBlock:
610b57cec5SDimitry Andric     case llvm::BitstreamEntry::EndBlock:
620b57cec5SDimitry Andric     case llvm::BitstreamEntry::Error:
630b57cec5SDimitry Andric       return;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric     case llvm::BitstreamEntry::Record:
660b57cec5SDimitry Andric       break;
670b57cec5SDimitry Andric     }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric     Record.clear();
700b57cec5SDimitry Andric     StringRef Blob;
710b57cec5SDimitry Andric     Expected<unsigned> MaybeRecCode =
720b57cec5SDimitry Andric         Stream.readRecord(Entry.ID, Record, &Blob);
730b57cec5SDimitry Andric     if (!MaybeRecCode)
740b57cec5SDimitry Andric       fprintf(stderr, "Failed reading rec code: %s\n",
750b57cec5SDimitry Andric               toString(MaybeRecCode.takeError()).c_str());
760b57cec5SDimitry Andric     switch (MaybeRecCode.get()) {
770b57cec5SDimitry Andric     case FIRST_EXTENSION_RECORD_ID: {
780b57cec5SDimitry Andric       StringRef Message = Blob.substr(0, Record[0]);
790b57cec5SDimitry Andric       fprintf(stderr, "Read extension block message: %s\n",
800b57cec5SDimitry Andric               Message.str().c_str());
810b57cec5SDimitry Andric       break;
820b57cec5SDimitry Andric     }
830b57cec5SDimitry Andric     }
840b57cec5SDimitry Andric   }
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
~Reader()870b57cec5SDimitry Andric TestModuleFileExtension::Reader::~Reader() { }
880b57cec5SDimitry Andric 
~TestModuleFileExtension()890b57cec5SDimitry Andric TestModuleFileExtension::~TestModuleFileExtension() { }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric ModuleFileExtensionMetadata
getExtensionMetadata() const920b57cec5SDimitry Andric TestModuleFileExtension::getExtensionMetadata() const {
930b57cec5SDimitry Andric   return { BlockName, MajorVersion, MinorVersion, UserInfo };
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
hashExtension(ExtensionHashBuilder & HBuilder) const96349cc55cSDimitry Andric void TestModuleFileExtension::hashExtension(
97349cc55cSDimitry Andric     ExtensionHashBuilder &HBuilder) const {
980b57cec5SDimitry Andric   if (Hashed) {
99349cc55cSDimitry Andric     HBuilder.add(BlockName);
100349cc55cSDimitry Andric     HBuilder.add(MajorVersion);
101349cc55cSDimitry Andric     HBuilder.add(MinorVersion);
102349cc55cSDimitry Andric     HBuilder.add(UserInfo);
1030b57cec5SDimitry Andric   }
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric std::unique_ptr<ModuleFileExtensionWriter>
createExtensionWriter(ASTWriter &)1070b57cec5SDimitry Andric TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
1080b57cec5SDimitry Andric   return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric std::unique_ptr<ModuleFileExtensionReader>
createExtensionReader(const ModuleFileExtensionMetadata & Metadata,ASTReader & Reader,serialization::ModuleFile & Mod,const llvm::BitstreamCursor & Stream)1120b57cec5SDimitry Andric TestModuleFileExtension::createExtensionReader(
1130b57cec5SDimitry Andric   const ModuleFileExtensionMetadata &Metadata,
1140b57cec5SDimitry Andric   ASTReader &Reader, serialization::ModuleFile &Mod,
1150b57cec5SDimitry Andric   const llvm::BitstreamCursor &Stream)
1160b57cec5SDimitry Andric {
1170b57cec5SDimitry Andric   assert(Metadata.BlockName == BlockName && "Wrong block name");
1180b57cec5SDimitry Andric   if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) !=
1190b57cec5SDimitry Andric         std::make_pair(MajorVersion, MinorVersion)) {
1200b57cec5SDimitry Andric     Reader.getDiags().Report(Mod.ImportLoc,
1210b57cec5SDimitry Andric                              diag::err_test_module_file_extension_version)
1220b57cec5SDimitry Andric       << BlockName << Metadata.MajorVersion << Metadata.MinorVersion
1230b57cec5SDimitry Andric       << MajorVersion << MinorVersion;
1240b57cec5SDimitry Andric     return nullptr;
1250b57cec5SDimitry Andric   }
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   return std::unique_ptr<ModuleFileExtensionReader>(
1280b57cec5SDimitry Andric                                                     new TestModuleFileExtension::Reader(this, Stream));
1290b57cec5SDimitry Andric }
130fe6060f1SDimitry Andric 
str() const131fe6060f1SDimitry Andric std::string TestModuleFileExtension::str() const {
132fe6060f1SDimitry Andric   std::string Buffer;
133fe6060f1SDimitry Andric   llvm::raw_string_ostream OS(Buffer);
134fe6060f1SDimitry Andric   OS << BlockName << ":" << MajorVersion << ":" << MinorVersion << ":" << Hashed
135fe6060f1SDimitry Andric      << ":" << UserInfo;
136*0eae32dcSDimitry Andric   return Buffer;
137fe6060f1SDimitry Andric }
138