xref: /llvm-project/clang/lib/Frontend/TestModuleFileExtension.cpp (revision 0cf6f7b128dd457711ba5c0ebfcb8143dc1632f8)
16623e1f1SDouglas Gregor //===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===//
26623e1f1SDouglas Gregor //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66623e1f1SDouglas Gregor //
76623e1f1SDouglas Gregor //===----------------------------------------------------------------------===//
86623e1f1SDouglas Gregor #include "TestModuleFileExtension.h"
96623e1f1SDouglas Gregor #include "clang/Frontend/FrontendDiagnostic.h"
106623e1f1SDouglas Gregor #include "clang/Serialization/ASTReader.h"
116623e1f1SDouglas Gregor #include "llvm/ADT/Hashing.h"
12e0308279SFrancis Visoiu Mistrih #include "llvm/Bitstream/BitstreamWriter.h"
136623e1f1SDouglas Gregor #include "llvm/Support/raw_ostream.h"
143ee9b16bSNAKAMURA Takumi #include <cstdio>
156623e1f1SDouglas Gregor using namespace clang;
166623e1f1SDouglas Gregor using namespace clang::serialization;
176623e1f1SDouglas Gregor 
184295ae96SJan Svoboda char TestModuleFileExtension::ID = 0;
194295ae96SJan Svoboda 
~Writer()206623e1f1SDouglas Gregor TestModuleFileExtension::Writer::~Writer() { }
216623e1f1SDouglas Gregor 
writeExtensionContents(Sema & SemaRef,llvm::BitstreamWriter & Stream)226623e1f1SDouglas Gregor void TestModuleFileExtension::Writer::writeExtensionContents(
238f64ca15SDouglas Gregor        Sema &SemaRef,
246623e1f1SDouglas Gregor        llvm::BitstreamWriter &Stream) {
256623e1f1SDouglas Gregor   using namespace llvm;
266623e1f1SDouglas Gregor 
276623e1f1SDouglas Gregor   // Write an abbreviation for this record.
28b44f0bfbSDavid Blaikie   auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
296623e1f1SDouglas Gregor   Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID));
306623e1f1SDouglas Gregor   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of characters
316623e1f1SDouglas Gregor   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));   // message
32b44f0bfbSDavid Blaikie   auto Abbrev = Stream.EmitAbbrev(std::move(Abv));
336623e1f1SDouglas Gregor 
346623e1f1SDouglas Gregor   // Write a message into the extension block.
356623e1f1SDouglas Gregor   SmallString<64> Message;
366623e1f1SDouglas Gregor   {
376623e1f1SDouglas Gregor     auto Ext = static_cast<TestModuleFileExtension *>(getExtension());
386623e1f1SDouglas Gregor     raw_svector_ostream OS(Message);
396623e1f1SDouglas Gregor     OS << "Hello from " << Ext->BlockName << " v" << Ext->MajorVersion << "."
406623e1f1SDouglas Gregor        << Ext->MinorVersion;
416623e1f1SDouglas Gregor   }
4230934738SBenjamin Kramer   uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, Message.size()};
436623e1f1SDouglas Gregor   Stream.EmitRecordWithBlob(Abbrev, Record, Message);
446623e1f1SDouglas Gregor }
456623e1f1SDouglas Gregor 
Reader(ModuleFileExtension * Ext,const llvm::BitstreamCursor & InStream)466623e1f1SDouglas Gregor TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
476623e1f1SDouglas Gregor                                         const llvm::BitstreamCursor &InStream)
486623e1f1SDouglas Gregor   : ModuleFileExtensionReader(Ext), Stream(InStream)
496623e1f1SDouglas Gregor {
506623e1f1SDouglas Gregor   // Read the extension block.
516623e1f1SDouglas Gregor   SmallVector<uint64_t, 4> Record;
526623e1f1SDouglas Gregor   while (true) {
530e828958SJF Bastien     llvm::Expected<llvm::BitstreamEntry> MaybeEntry =
540e828958SJF Bastien         Stream.advanceSkippingSubblocks();
550e828958SJF Bastien     if (!MaybeEntry)
560e828958SJF Bastien       (void)MaybeEntry.takeError();
570e828958SJF Bastien     llvm::BitstreamEntry Entry = MaybeEntry.get();
580e828958SJF Bastien 
596623e1f1SDouglas Gregor     switch (Entry.Kind) {
606623e1f1SDouglas Gregor     case llvm::BitstreamEntry::SubBlock:
616623e1f1SDouglas Gregor     case llvm::BitstreamEntry::EndBlock:
626623e1f1SDouglas Gregor     case llvm::BitstreamEntry::Error:
636623e1f1SDouglas Gregor       return;
646623e1f1SDouglas Gregor 
656623e1f1SDouglas Gregor     case llvm::BitstreamEntry::Record:
666623e1f1SDouglas Gregor       break;
676623e1f1SDouglas Gregor     }
686623e1f1SDouglas Gregor 
696623e1f1SDouglas Gregor     Record.clear();
706623e1f1SDouglas Gregor     StringRef Blob;
710e828958SJF Bastien     Expected<unsigned> MaybeRecCode =
720e828958SJF Bastien         Stream.readRecord(Entry.ID, Record, &Blob);
730e828958SJF Bastien     if (!MaybeRecCode)
740e828958SJF Bastien       fprintf(stderr, "Failed reading rec code: %s\n",
750e828958SJF Bastien               toString(MaybeRecCode.takeError()).c_str());
760e828958SJF Bastien     switch (MaybeRecCode.get()) {
776623e1f1SDouglas Gregor     case FIRST_EXTENSION_RECORD_ID: {
786623e1f1SDouglas Gregor       StringRef Message = Blob.substr(0, Record[0]);
796623e1f1SDouglas Gregor       fprintf(stderr, "Read extension block message: %s\n",
806623e1f1SDouglas Gregor               Message.str().c_str());
816623e1f1SDouglas Gregor       break;
826623e1f1SDouglas Gregor     }
836623e1f1SDouglas Gregor     }
846623e1f1SDouglas Gregor   }
856623e1f1SDouglas Gregor }
866623e1f1SDouglas Gregor 
~Reader()876623e1f1SDouglas Gregor TestModuleFileExtension::Reader::~Reader() { }
886623e1f1SDouglas Gregor 
~TestModuleFileExtension()896623e1f1SDouglas Gregor TestModuleFileExtension::~TestModuleFileExtension() { }
906623e1f1SDouglas Gregor 
916623e1f1SDouglas Gregor ModuleFileExtensionMetadata
getExtensionMetadata() const926623e1f1SDouglas Gregor TestModuleFileExtension::getExtensionMetadata() const {
936623e1f1SDouglas Gregor   return { BlockName, MajorVersion, MinorVersion, UserInfo };
946623e1f1SDouglas Gregor }
956623e1f1SDouglas Gregor 
hashExtension(ExtensionHashBuilder & HBuilder) const96655bea42SAlexandre Rames void TestModuleFileExtension::hashExtension(
97655bea42SAlexandre Rames     ExtensionHashBuilder &HBuilder) const {
986623e1f1SDouglas Gregor   if (Hashed) {
99655bea42SAlexandre Rames     HBuilder.add(BlockName);
100655bea42SAlexandre Rames     HBuilder.add(MajorVersion);
101655bea42SAlexandre Rames     HBuilder.add(MinorVersion);
102655bea42SAlexandre Rames     HBuilder.add(UserInfo);
1036623e1f1SDouglas Gregor   }
1046623e1f1SDouglas Gregor }
1056623e1f1SDouglas Gregor 
1066623e1f1SDouglas Gregor std::unique_ptr<ModuleFileExtensionWriter>
createExtensionWriter(ASTWriter &)1076623e1f1SDouglas Gregor TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
1086623e1f1SDouglas Gregor   return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
1096623e1f1SDouglas Gregor }
1106623e1f1SDouglas Gregor 
1116623e1f1SDouglas Gregor std::unique_ptr<ModuleFileExtensionReader>
createExtensionReader(const ModuleFileExtensionMetadata & Metadata,ASTReader & Reader,serialization::ModuleFile & Mod,const llvm::BitstreamCursor & Stream)1126623e1f1SDouglas Gregor TestModuleFileExtension::createExtensionReader(
1136623e1f1SDouglas Gregor   const ModuleFileExtensionMetadata &Metadata,
1146623e1f1SDouglas Gregor   ASTReader &Reader, serialization::ModuleFile &Mod,
1156623e1f1SDouglas Gregor   const llvm::BitstreamCursor &Stream)
1166623e1f1SDouglas Gregor {
1176623e1f1SDouglas Gregor   assert(Metadata.BlockName == BlockName && "Wrong block name");
1186623e1f1SDouglas Gregor   if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) !=
1196623e1f1SDouglas Gregor         std::make_pair(MajorVersion, MinorVersion)) {
1206623e1f1SDouglas Gregor     Reader.getDiags().Report(Mod.ImportLoc,
1216623e1f1SDouglas Gregor                              diag::err_test_module_file_extension_version)
1226623e1f1SDouglas Gregor       << BlockName << Metadata.MajorVersion << Metadata.MinorVersion
1236623e1f1SDouglas Gregor       << MajorVersion << MinorVersion;
1246623e1f1SDouglas Gregor     return nullptr;
1256623e1f1SDouglas Gregor   }
1266623e1f1SDouglas Gregor 
1276623e1f1SDouglas Gregor   return std::unique_ptr<ModuleFileExtensionReader>(
1286623e1f1SDouglas Gregor                                                     new TestModuleFileExtension::Reader(this, Stream));
1296623e1f1SDouglas Gregor }
1305e8a246aSJan Svoboda 
str() const13108ccea01SJan Svoboda std::string TestModuleFileExtension::str() const {
13208ccea01SJan Svoboda   std::string Buffer;
13308ccea01SJan Svoboda   llvm::raw_string_ostream OS(Buffer);
13408ccea01SJan Svoboda   OS << BlockName << ":" << MajorVersion << ":" << MinorVersion << ":" << Hashed
13508ccea01SJan Svoboda      << ":" << UserInfo;
136*0cf6f7b1SLogan Smith   return Buffer;
1375e8a246aSJan Svoboda }
138