• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, Message.size()};
42   Stream.EmitRecordWithBlob(Abbrev, Record, Message);
43 }
44 
Reader(ModuleFileExtension * Ext,const llvm::BitstreamCursor & InStream)45 TestModuleFileExtension::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 
~Reader()77 TestModuleFileExtension::Reader::~Reader() { }
78 
~TestModuleFileExtension()79 TestModuleFileExtension::~TestModuleFileExtension() { }
80 
81 ModuleFileExtensionMetadata
getExtensionMetadata() const82 TestModuleFileExtension::getExtensionMetadata() const {
83   return { BlockName, MajorVersion, MinorVersion, UserInfo };
84 }
85 
hashExtension(llvm::hash_code Code) const86 llvm::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 
98 std::unique_ptr<ModuleFileExtensionWriter>
createExtensionWriter(ASTWriter &)99 TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
100   return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
101 }
102 
103 std::unique_ptr<ModuleFileExtensionReader>
createExtensionReader(const ModuleFileExtensionMetadata & Metadata,ASTReader & Reader,serialization::ModuleFile & Mod,const llvm::BitstreamCursor & Stream)104 TestModuleFileExtension::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