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( 228f64ca15SDouglas Gregor Sema &SemaRef, 236623e1f1SDouglas Gregor llvm::BitstreamWriter &Stream) { 246623e1f1SDouglas Gregor using namespace llvm; 256623e1f1SDouglas Gregor 266623e1f1SDouglas Gregor // Write an abbreviation for this record. 27*b44f0bfbSDavid Blaikie auto Abv = std::make_shared<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 31*b44f0bfbSDavid Blaikie auto Abbrev = Stream.EmitAbbrev(std::move(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 } 4130934738SBenjamin Kramer uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, Message.size()}; 426623e1f1SDouglas Gregor Stream.EmitRecordWithBlob(Abbrev, Record, Message); 436623e1f1SDouglas Gregor } 446623e1f1SDouglas Gregor 456623e1f1SDouglas Gregor TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext, 466623e1f1SDouglas Gregor const llvm::BitstreamCursor &InStream) 476623e1f1SDouglas Gregor : ModuleFileExtensionReader(Ext), Stream(InStream) 486623e1f1SDouglas Gregor { 496623e1f1SDouglas Gregor // Read the extension block. 506623e1f1SDouglas Gregor SmallVector<uint64_t, 4> Record; 516623e1f1SDouglas Gregor while (true) { 526623e1f1SDouglas Gregor llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); 536623e1f1SDouglas Gregor switch (Entry.Kind) { 546623e1f1SDouglas Gregor case llvm::BitstreamEntry::SubBlock: 556623e1f1SDouglas Gregor case llvm::BitstreamEntry::EndBlock: 566623e1f1SDouglas Gregor case llvm::BitstreamEntry::Error: 576623e1f1SDouglas Gregor return; 586623e1f1SDouglas Gregor 596623e1f1SDouglas Gregor case llvm::BitstreamEntry::Record: 606623e1f1SDouglas Gregor break; 616623e1f1SDouglas Gregor } 626623e1f1SDouglas Gregor 636623e1f1SDouglas Gregor Record.clear(); 646623e1f1SDouglas Gregor StringRef Blob; 656623e1f1SDouglas Gregor unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); 666623e1f1SDouglas Gregor switch (RecCode) { 676623e1f1SDouglas Gregor case FIRST_EXTENSION_RECORD_ID: { 686623e1f1SDouglas Gregor StringRef Message = Blob.substr(0, Record[0]); 696623e1f1SDouglas Gregor fprintf(stderr, "Read extension block message: %s\n", 706623e1f1SDouglas Gregor Message.str().c_str()); 716623e1f1SDouglas Gregor break; 726623e1f1SDouglas Gregor } 736623e1f1SDouglas Gregor } 746623e1f1SDouglas Gregor } 756623e1f1SDouglas Gregor } 766623e1f1SDouglas Gregor 776623e1f1SDouglas Gregor TestModuleFileExtension::Reader::~Reader() { } 786623e1f1SDouglas Gregor 796623e1f1SDouglas Gregor TestModuleFileExtension::~TestModuleFileExtension() { } 806623e1f1SDouglas Gregor 816623e1f1SDouglas Gregor ModuleFileExtensionMetadata 826623e1f1SDouglas Gregor TestModuleFileExtension::getExtensionMetadata() const { 836623e1f1SDouglas Gregor return { BlockName, MajorVersion, MinorVersion, UserInfo }; 846623e1f1SDouglas Gregor } 856623e1f1SDouglas Gregor 866623e1f1SDouglas Gregor llvm::hash_code TestModuleFileExtension::hashExtension( 876623e1f1SDouglas Gregor llvm::hash_code Code) const { 886623e1f1SDouglas Gregor if (Hashed) { 896623e1f1SDouglas Gregor Code = llvm::hash_combine(Code, BlockName); 906623e1f1SDouglas Gregor Code = llvm::hash_combine(Code, MajorVersion); 916623e1f1SDouglas Gregor Code = llvm::hash_combine(Code, MinorVersion); 926623e1f1SDouglas Gregor Code = llvm::hash_combine(Code, UserInfo); 936623e1f1SDouglas Gregor } 946623e1f1SDouglas Gregor 956623e1f1SDouglas Gregor return Code; 966623e1f1SDouglas Gregor } 976623e1f1SDouglas Gregor 986623e1f1SDouglas Gregor std::unique_ptr<ModuleFileExtensionWriter> 996623e1f1SDouglas Gregor TestModuleFileExtension::createExtensionWriter(ASTWriter &) { 1006623e1f1SDouglas Gregor return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this)); 1016623e1f1SDouglas Gregor } 1026623e1f1SDouglas Gregor 1036623e1f1SDouglas Gregor std::unique_ptr<ModuleFileExtensionReader> 1046623e1f1SDouglas Gregor TestModuleFileExtension::createExtensionReader( 1056623e1f1SDouglas Gregor const ModuleFileExtensionMetadata &Metadata, 1066623e1f1SDouglas Gregor ASTReader &Reader, serialization::ModuleFile &Mod, 1076623e1f1SDouglas Gregor const llvm::BitstreamCursor &Stream) 1086623e1f1SDouglas Gregor { 1096623e1f1SDouglas Gregor assert(Metadata.BlockName == BlockName && "Wrong block name"); 1106623e1f1SDouglas Gregor if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) != 1116623e1f1SDouglas Gregor std::make_pair(MajorVersion, MinorVersion)) { 1126623e1f1SDouglas Gregor Reader.getDiags().Report(Mod.ImportLoc, 1136623e1f1SDouglas Gregor diag::err_test_module_file_extension_version) 1146623e1f1SDouglas Gregor << BlockName << Metadata.MajorVersion << Metadata.MinorVersion 1156623e1f1SDouglas Gregor << MajorVersion << MinorVersion; 1166623e1f1SDouglas Gregor return nullptr; 1176623e1f1SDouglas Gregor } 1186623e1f1SDouglas Gregor 1196623e1f1SDouglas Gregor return std::unique_ptr<ModuleFileExtensionReader>( 1206623e1f1SDouglas Gregor new TestModuleFileExtension::Reader(this, Stream)); 1216623e1f1SDouglas Gregor } 122