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