xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Frontend/TestModuleFileExtension.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg #include "TestModuleFileExtension.h"
97330f729Sjoerg #include "clang/Frontend/FrontendDiagnostic.h"
107330f729Sjoerg #include "clang/Serialization/ASTReader.h"
117330f729Sjoerg #include "llvm/ADT/Hashing.h"
127330f729Sjoerg #include "llvm/Bitstream/BitstreamWriter.h"
137330f729Sjoerg #include "llvm/Support/raw_ostream.h"
147330f729Sjoerg #include <cstdio>
157330f729Sjoerg using namespace clang;
167330f729Sjoerg using namespace clang::serialization;
177330f729Sjoerg 
18*e038c9c4Sjoerg char TestModuleFileExtension::ID = 0;
19*e038c9c4Sjoerg 
~Writer()207330f729Sjoerg TestModuleFileExtension::Writer::~Writer() { }
217330f729Sjoerg 
writeExtensionContents(Sema & SemaRef,llvm::BitstreamWriter & Stream)227330f729Sjoerg void TestModuleFileExtension::Writer::writeExtensionContents(
237330f729Sjoerg        Sema &SemaRef,
247330f729Sjoerg        llvm::BitstreamWriter &Stream) {
257330f729Sjoerg   using namespace llvm;
267330f729Sjoerg 
277330f729Sjoerg   // Write an abbreviation for this record.
287330f729Sjoerg   auto Abv = std::make_shared<llvm::BitCodeAbbrev>();
297330f729Sjoerg   Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID));
307330f729Sjoerg   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of characters
317330f729Sjoerg   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob));   // message
327330f729Sjoerg   auto Abbrev = Stream.EmitAbbrev(std::move(Abv));
337330f729Sjoerg 
347330f729Sjoerg   // Write a message into the extension block.
357330f729Sjoerg   SmallString<64> Message;
367330f729Sjoerg   {
377330f729Sjoerg     auto Ext = static_cast<TestModuleFileExtension *>(getExtension());
387330f729Sjoerg     raw_svector_ostream OS(Message);
397330f729Sjoerg     OS << "Hello from " << Ext->BlockName << " v" << Ext->MajorVersion << "."
407330f729Sjoerg        << Ext->MinorVersion;
417330f729Sjoerg   }
427330f729Sjoerg   uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, Message.size()};
437330f729Sjoerg   Stream.EmitRecordWithBlob(Abbrev, Record, Message);
447330f729Sjoerg }
457330f729Sjoerg 
Reader(ModuleFileExtension * Ext,const llvm::BitstreamCursor & InStream)467330f729Sjoerg TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
477330f729Sjoerg                                         const llvm::BitstreamCursor &InStream)
487330f729Sjoerg   : ModuleFileExtensionReader(Ext), Stream(InStream)
497330f729Sjoerg {
507330f729Sjoerg   // Read the extension block.
517330f729Sjoerg   SmallVector<uint64_t, 4> Record;
527330f729Sjoerg   while (true) {
537330f729Sjoerg     llvm::Expected<llvm::BitstreamEntry> MaybeEntry =
547330f729Sjoerg         Stream.advanceSkippingSubblocks();
557330f729Sjoerg     if (!MaybeEntry)
567330f729Sjoerg       (void)MaybeEntry.takeError();
577330f729Sjoerg     llvm::BitstreamEntry Entry = MaybeEntry.get();
587330f729Sjoerg 
597330f729Sjoerg     switch (Entry.Kind) {
607330f729Sjoerg     case llvm::BitstreamEntry::SubBlock:
617330f729Sjoerg     case llvm::BitstreamEntry::EndBlock:
627330f729Sjoerg     case llvm::BitstreamEntry::Error:
637330f729Sjoerg       return;
647330f729Sjoerg 
657330f729Sjoerg     case llvm::BitstreamEntry::Record:
667330f729Sjoerg       break;
677330f729Sjoerg     }
687330f729Sjoerg 
697330f729Sjoerg     Record.clear();
707330f729Sjoerg     StringRef Blob;
717330f729Sjoerg     Expected<unsigned> MaybeRecCode =
727330f729Sjoerg         Stream.readRecord(Entry.ID, Record, &Blob);
737330f729Sjoerg     if (!MaybeRecCode)
747330f729Sjoerg       fprintf(stderr, "Failed reading rec code: %s\n",
757330f729Sjoerg               toString(MaybeRecCode.takeError()).c_str());
767330f729Sjoerg     switch (MaybeRecCode.get()) {
777330f729Sjoerg     case FIRST_EXTENSION_RECORD_ID: {
787330f729Sjoerg       StringRef Message = Blob.substr(0, Record[0]);
797330f729Sjoerg       fprintf(stderr, "Read extension block message: %s\n",
807330f729Sjoerg               Message.str().c_str());
817330f729Sjoerg       break;
827330f729Sjoerg     }
837330f729Sjoerg     }
847330f729Sjoerg   }
857330f729Sjoerg }
867330f729Sjoerg 
~Reader()877330f729Sjoerg TestModuleFileExtension::Reader::~Reader() { }
887330f729Sjoerg 
~TestModuleFileExtension()897330f729Sjoerg TestModuleFileExtension::~TestModuleFileExtension() { }
907330f729Sjoerg 
917330f729Sjoerg ModuleFileExtensionMetadata
getExtensionMetadata() const927330f729Sjoerg TestModuleFileExtension::getExtensionMetadata() const {
937330f729Sjoerg   return { BlockName, MajorVersion, MinorVersion, UserInfo };
947330f729Sjoerg }
957330f729Sjoerg 
hashExtension(llvm::hash_code Code) const967330f729Sjoerg llvm::hash_code TestModuleFileExtension::hashExtension(
977330f729Sjoerg                   llvm::hash_code Code) const {
987330f729Sjoerg   if (Hashed) {
997330f729Sjoerg     Code = llvm::hash_combine(Code, BlockName);
1007330f729Sjoerg     Code = llvm::hash_combine(Code, MajorVersion);
1017330f729Sjoerg     Code = llvm::hash_combine(Code, MinorVersion);
1027330f729Sjoerg     Code = llvm::hash_combine(Code, UserInfo);
1037330f729Sjoerg   }
1047330f729Sjoerg 
1057330f729Sjoerg   return Code;
1067330f729Sjoerg }
1077330f729Sjoerg 
1087330f729Sjoerg std::unique_ptr<ModuleFileExtensionWriter>
createExtensionWriter(ASTWriter &)1097330f729Sjoerg TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
1107330f729Sjoerg   return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
1117330f729Sjoerg }
1127330f729Sjoerg 
1137330f729Sjoerg std::unique_ptr<ModuleFileExtensionReader>
createExtensionReader(const ModuleFileExtensionMetadata & Metadata,ASTReader & Reader,serialization::ModuleFile & Mod,const llvm::BitstreamCursor & Stream)1147330f729Sjoerg TestModuleFileExtension::createExtensionReader(
1157330f729Sjoerg   const ModuleFileExtensionMetadata &Metadata,
1167330f729Sjoerg   ASTReader &Reader, serialization::ModuleFile &Mod,
1177330f729Sjoerg   const llvm::BitstreamCursor &Stream)
1187330f729Sjoerg {
1197330f729Sjoerg   assert(Metadata.BlockName == BlockName && "Wrong block name");
1207330f729Sjoerg   if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) !=
1217330f729Sjoerg         std::make_pair(MajorVersion, MinorVersion)) {
1227330f729Sjoerg     Reader.getDiags().Report(Mod.ImportLoc,
1237330f729Sjoerg                              diag::err_test_module_file_extension_version)
1247330f729Sjoerg       << BlockName << Metadata.MajorVersion << Metadata.MinorVersion
1257330f729Sjoerg       << MajorVersion << MinorVersion;
1267330f729Sjoerg     return nullptr;
1277330f729Sjoerg   }
1287330f729Sjoerg 
1297330f729Sjoerg   return std::unique_ptr<ModuleFileExtensionReader>(
1307330f729Sjoerg                                                     new TestModuleFileExtension::Reader(this, Stream));
1317330f729Sjoerg }
132*e038c9c4Sjoerg 
str() const133*e038c9c4Sjoerg std::string TestModuleFileExtension::str() const {
134*e038c9c4Sjoerg   std::string Buffer;
135*e038c9c4Sjoerg   llvm::raw_string_ostream OS(Buffer);
136*e038c9c4Sjoerg   OS << BlockName << ":" << MajorVersion << ":" << MinorVersion << ":" << Hashed
137*e038c9c4Sjoerg      << ":" << UserInfo;
138*e038c9c4Sjoerg   return OS.str();
139*e038c9c4Sjoerg }
140