16623e1f1SDouglas Gregor //===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===// 26623e1f1SDouglas Gregor // 36623e1f1SDouglas Gregor // The LLVM Compiler Infrastructure 46623e1f1SDouglas Gregor // 56623e1f1SDouglas Gregor // This file is distributed under the University of Illinois Open Source 66623e1f1SDouglas Gregor // License. See LICENSE.TXT for details. 76623e1f1SDouglas Gregor // 86623e1f1SDouglas Gregor //===----------------------------------------------------------------------===// 96623e1f1SDouglas Gregor #include "TestModuleFileExtension.h" 106623e1f1SDouglas Gregor #include "clang/Frontend/FrontendDiagnostic.h" 116623e1f1SDouglas Gregor #include "clang/Serialization/ASTReader.h" 126623e1f1SDouglas Gregor #include "llvm/ADT/Hashing.h" 136623e1f1SDouglas Gregor #include "llvm/Bitcode/BitstreamWriter.h" 146623e1f1SDouglas Gregor #include "llvm/Support/raw_ostream.h" 153ee9b16bSNAKAMURA Takumi #include <cstdio> 166623e1f1SDouglas Gregor using namespace clang; 176623e1f1SDouglas Gregor using namespace clang::serialization; 186623e1f1SDouglas Gregor 196623e1f1SDouglas Gregor TestModuleFileExtension::Writer::~Writer() { } 206623e1f1SDouglas Gregor 216623e1f1SDouglas Gregor void TestModuleFileExtension::Writer::writeExtensionContents( 22*8f64ca15SDouglas Gregor Sema &SemaRef, 236623e1f1SDouglas Gregor llvm::BitstreamWriter &Stream) { 246623e1f1SDouglas Gregor using namespace llvm; 256623e1f1SDouglas Gregor 266623e1f1SDouglas Gregor // Write an abbreviation for this record. 276623e1f1SDouglas Gregor BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev(); 286623e1f1SDouglas Gregor Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID)); 296623e1f1SDouglas Gregor Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of characters 306623e1f1SDouglas Gregor Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // message 316623e1f1SDouglas Gregor auto Abbrev = Stream.EmitAbbrev(Abv); 326623e1f1SDouglas Gregor 336623e1f1SDouglas Gregor // Write a message into the extension block. 346623e1f1SDouglas Gregor SmallString<64> Message; 356623e1f1SDouglas Gregor { 366623e1f1SDouglas Gregor auto Ext = static_cast<TestModuleFileExtension *>(getExtension()); 376623e1f1SDouglas Gregor raw_svector_ostream OS(Message); 386623e1f1SDouglas Gregor OS << "Hello from " << Ext->BlockName << " v" << Ext->MajorVersion << "." 396623e1f1SDouglas Gregor << Ext->MinorVersion; 406623e1f1SDouglas Gregor } 416623e1f1SDouglas Gregor SmallVector<uint64_t, 4> Record; 426623e1f1SDouglas Gregor Record.push_back(FIRST_EXTENSION_RECORD_ID); 436623e1f1SDouglas Gregor Record.push_back(Message.size()); 446623e1f1SDouglas Gregor Stream.EmitRecordWithBlob(Abbrev, Record, Message); 456623e1f1SDouglas Gregor } 466623e1f1SDouglas Gregor 476623e1f1SDouglas Gregor TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext, 486623e1f1SDouglas Gregor const llvm::BitstreamCursor &InStream) 496623e1f1SDouglas Gregor : ModuleFileExtensionReader(Ext), Stream(InStream) 506623e1f1SDouglas Gregor { 516623e1f1SDouglas Gregor // Read the extension block. 526623e1f1SDouglas Gregor SmallVector<uint64_t, 4> Record; 536623e1f1SDouglas Gregor while (true) { 546623e1f1SDouglas Gregor llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); 556623e1f1SDouglas Gregor switch (Entry.Kind) { 566623e1f1SDouglas Gregor case llvm::BitstreamEntry::SubBlock: 576623e1f1SDouglas Gregor case llvm::BitstreamEntry::EndBlock: 586623e1f1SDouglas Gregor case llvm::BitstreamEntry::Error: 596623e1f1SDouglas Gregor return; 606623e1f1SDouglas Gregor 616623e1f1SDouglas Gregor case llvm::BitstreamEntry::Record: 626623e1f1SDouglas Gregor break; 636623e1f1SDouglas Gregor } 646623e1f1SDouglas Gregor 656623e1f1SDouglas Gregor Record.clear(); 666623e1f1SDouglas Gregor StringRef Blob; 676623e1f1SDouglas Gregor unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); 686623e1f1SDouglas Gregor switch (RecCode) { 696623e1f1SDouglas Gregor case FIRST_EXTENSION_RECORD_ID: { 706623e1f1SDouglas Gregor StringRef Message = Blob.substr(0, Record[0]); 716623e1f1SDouglas Gregor fprintf(stderr, "Read extension block message: %s\n", 726623e1f1SDouglas Gregor Message.str().c_str()); 736623e1f1SDouglas Gregor break; 746623e1f1SDouglas Gregor } 756623e1f1SDouglas Gregor } 766623e1f1SDouglas Gregor } 776623e1f1SDouglas Gregor } 786623e1f1SDouglas Gregor 796623e1f1SDouglas Gregor TestModuleFileExtension::Reader::~Reader() { } 806623e1f1SDouglas Gregor 816623e1f1SDouglas Gregor TestModuleFileExtension::~TestModuleFileExtension() { } 826623e1f1SDouglas Gregor 836623e1f1SDouglas Gregor ModuleFileExtensionMetadata 846623e1f1SDouglas Gregor TestModuleFileExtension::getExtensionMetadata() const { 856623e1f1SDouglas Gregor return { BlockName, MajorVersion, MinorVersion, UserInfo }; 866623e1f1SDouglas Gregor } 876623e1f1SDouglas Gregor 886623e1f1SDouglas Gregor llvm::hash_code TestModuleFileExtension::hashExtension( 896623e1f1SDouglas Gregor llvm::hash_code Code) const { 906623e1f1SDouglas Gregor if (Hashed) { 916623e1f1SDouglas Gregor Code = llvm::hash_combine(Code, BlockName); 926623e1f1SDouglas Gregor Code = llvm::hash_combine(Code, MajorVersion); 936623e1f1SDouglas Gregor Code = llvm::hash_combine(Code, MinorVersion); 946623e1f1SDouglas Gregor Code = llvm::hash_combine(Code, UserInfo); 956623e1f1SDouglas Gregor } 966623e1f1SDouglas Gregor 976623e1f1SDouglas Gregor return Code; 986623e1f1SDouglas Gregor } 996623e1f1SDouglas Gregor 1006623e1f1SDouglas Gregor std::unique_ptr<ModuleFileExtensionWriter> 1016623e1f1SDouglas Gregor TestModuleFileExtension::createExtensionWriter(ASTWriter &) { 1026623e1f1SDouglas Gregor return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this)); 1036623e1f1SDouglas Gregor } 1046623e1f1SDouglas Gregor 1056623e1f1SDouglas Gregor std::unique_ptr<ModuleFileExtensionReader> 1066623e1f1SDouglas Gregor TestModuleFileExtension::createExtensionReader( 1076623e1f1SDouglas Gregor const ModuleFileExtensionMetadata &Metadata, 1086623e1f1SDouglas Gregor ASTReader &Reader, serialization::ModuleFile &Mod, 1096623e1f1SDouglas Gregor const llvm::BitstreamCursor &Stream) 1106623e1f1SDouglas Gregor { 1116623e1f1SDouglas Gregor assert(Metadata.BlockName == BlockName && "Wrong block name"); 1126623e1f1SDouglas Gregor if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) != 1136623e1f1SDouglas Gregor std::make_pair(MajorVersion, MinorVersion)) { 1146623e1f1SDouglas Gregor Reader.getDiags().Report(Mod.ImportLoc, 1156623e1f1SDouglas Gregor diag::err_test_module_file_extension_version) 1166623e1f1SDouglas Gregor << BlockName << Metadata.MajorVersion << Metadata.MinorVersion 1176623e1f1SDouglas Gregor << MajorVersion << MinorVersion; 1186623e1f1SDouglas Gregor return nullptr; 1196623e1f1SDouglas Gregor } 1206623e1f1SDouglas Gregor 1216623e1f1SDouglas Gregor return std::unique_ptr<ModuleFileExtensionReader>( 1226623e1f1SDouglas Gregor new TestModuleFileExtension::Reader(this, Stream)); 1236623e1f1SDouglas Gregor } 124