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