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