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
~Writer()19 TestModuleFileExtension::Writer::~Writer() { }
20
writeExtensionContents(Sema & SemaRef,llvm::BitstreamWriter & Stream)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
Reader(ModuleFileExtension * Ext,const llvm::BitstreamCursor & InStream)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
~Reader()79 TestModuleFileExtension::Reader::~Reader() { }
80
~TestModuleFileExtension()81 TestModuleFileExtension::~TestModuleFileExtension() { }
82
83 ModuleFileExtensionMetadata
getExtensionMetadata() const84 TestModuleFileExtension::getExtensionMetadata() const {
85 return { BlockName, MajorVersion, MinorVersion, UserInfo };
86 }
87
hashExtension(llvm::hash_code Code) const88 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>
createExtensionWriter(ASTWriter &)101 TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
102 return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
103 }
104
105 std::unique_ptr<ModuleFileExtensionReader>
createExtensionReader(const ModuleFileExtensionMetadata & Metadata,ASTReader & Reader,serialization::ModuleFile & Mod,const llvm::BitstreamCursor & Stream)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