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