clang  3.8.0
TestModuleFileExtension.cpp
Go to the documentation of this file.
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 //===----------------------------------------------------------------------===//
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 
19 TestModuleFileExtension::Writer::~Writer() { }
20 
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  }
42  Record.push_back(FIRST_EXTENSION_RECORD_ID);
43  Record.push_back(Message.size());
44  Stream.EmitRecordWithBlob(Abbrev, Record, Message);
45 }
46 
47 TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext,
48  const llvm::BitstreamCursor &InStream)
49  : ModuleFileExtensionReader(Ext), Stream(InStream)
50 {
51  // Read the extension block.
53  while (true) {
54  llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
55  switch (Entry.Kind) {
56  case llvm::BitstreamEntry::SubBlock:
57  case llvm::BitstreamEntry::EndBlock:
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) {
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 
79 TestModuleFileExtension::Reader::~Reader() { }
80 
81 TestModuleFileExtension::~TestModuleFileExtension() { }
82 
84 TestModuleFileExtension::getExtensionMetadata() const {
85  return { BlockName, MajorVersion, MinorVersion, UserInfo };
86 }
87 
88 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>
101 TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
102  return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
103 }
104 
105 std::unique_ptr<ModuleFileExtensionReader>
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 }
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Definition: Diagnostic.h:1117
SourceLocation ImportLoc
The source location where this module was first imported.
A module file extension used for testing purposes.
DiagnosticsEngine & getDiags() const
Definition: ASTReader.h:1329
The first record ID allocated to the extensions themselves.
Definition: ASTBitCodes.h:322
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:259
Abstract base class that reads a module file extension block from a module file.
Information about a module that has been loaded by the ASTReader.
unsigned MajorVersion
The major version of the extension data.
unsigned MinorVersion
The minor version of the extension data.
Reads an AST files chain containing the contents of a translation unit.
Definition: ASTReader.h:311
std::string BlockName
The name used to identify this particular extension block within the resulting module file...
Metadata for a module file extension.
Writes an AST file containing the contents of a translation unit.
Definition: ASTWriter.h:84
An abstract superclass that describes a custom extension to the module/precompiled header file format...