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> 16using namespace clang; 17using namespace clang::serialization; 18 19TestModuleFileExtension::Writer::~Writer() { } 20 21void 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 uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, Message.size()}; 42 Stream.EmitRecordWithBlob(Abbrev, Record, Message); 43} 44 45TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext, 46 const llvm::BitstreamCursor &InStream) 47 : ModuleFileExtensionReader(Ext), Stream(InStream) 48{ 49 // Read the extension block. 50 SmallVector<uint64_t, 4> Record; 51 while (true) { 52 llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); 53 switch (Entry.Kind) { 54 case llvm::BitstreamEntry::SubBlock: 55 case llvm::BitstreamEntry::EndBlock: 56 case llvm::BitstreamEntry::Error: 57 return; 58 59 case llvm::BitstreamEntry::Record: 60 break; 61 } 62 63 Record.clear(); 64 StringRef Blob; 65 unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); 66 switch (RecCode) { 67 case FIRST_EXTENSION_RECORD_ID: { 68 StringRef Message = Blob.substr(0, Record[0]); 69 fprintf(stderr, "Read extension block message: %s\n", 70 Message.str().c_str()); 71 break; 72 } 73 } 74 } 75} 76 77TestModuleFileExtension::Reader::~Reader() { } 78 79TestModuleFileExtension::~TestModuleFileExtension() { } 80 81ModuleFileExtensionMetadata 82TestModuleFileExtension::getExtensionMetadata() const { 83 return { BlockName, MajorVersion, MinorVersion, UserInfo }; 84} 85 86llvm::hash_code TestModuleFileExtension::hashExtension( 87 llvm::hash_code Code) const { 88 if (Hashed) { 89 Code = llvm::hash_combine(Code, BlockName); 90 Code = llvm::hash_combine(Code, MajorVersion); 91 Code = llvm::hash_combine(Code, MinorVersion); 92 Code = llvm::hash_combine(Code, UserInfo); 93 } 94 95 return Code; 96} 97 98std::unique_ptr<ModuleFileExtensionWriter> 99TestModuleFileExtension::createExtensionWriter(ASTWriter &) { 100 return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this)); 101} 102 103std::unique_ptr<ModuleFileExtensionReader> 104TestModuleFileExtension::createExtensionReader( 105 const ModuleFileExtensionMetadata &Metadata, 106 ASTReader &Reader, serialization::ModuleFile &Mod, 107 const llvm::BitstreamCursor &Stream) 108{ 109 assert(Metadata.BlockName == BlockName && "Wrong block name"); 110 if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) != 111 std::make_pair(MajorVersion, MinorVersion)) { 112 Reader.getDiags().Report(Mod.ImportLoc, 113 diag::err_test_module_file_extension_version) 114 << BlockName << Metadata.MajorVersion << Metadata.MinorVersion 115 << MajorVersion << MinorVersion; 116 return nullptr; 117 } 118 119 return std::unique_ptr<ModuleFileExtensionReader>( 120 new TestModuleFileExtension::Reader(this, Stream)); 121} 122