xref: /freebsd/contrib/llvm-project/clang/lib/Frontend/TestModuleFileExtension.cpp (revision 770cf0a5f02dc8983a89c6568d741fbc25baa999)
1 //===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 #include "TestModuleFileExtension.h"
9 #include "clang/Frontend/FrontendDiagnostic.h"
10 #include "clang/Serialization/ASTReader.h"
11 #include "llvm/Bitstream/BitstreamWriter.h"
12 #include "llvm/Support/raw_ostream.h"
13 #include <cstdio>
14 using namespace clang;
15 using namespace clang::serialization;
16 
17 char TestModuleFileExtension::ID = 0;
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   auto Abv = std::make_shared<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(std::move(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 
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::Expected<llvm::BitstreamEntry> MaybeEntry =
53         Stream.advanceSkippingSubblocks();
54     if (!MaybeEntry)
55       (void)MaybeEntry.takeError();
56     llvm::BitstreamEntry Entry = MaybeEntry.get();
57 
58     switch (Entry.Kind) {
59     case llvm::BitstreamEntry::SubBlock:
60     case llvm::BitstreamEntry::EndBlock:
61     case llvm::BitstreamEntry::Error:
62       return;
63 
64     case llvm::BitstreamEntry::Record:
65       break;
66     }
67 
68     Record.clear();
69     StringRef Blob;
70     Expected<unsigned> MaybeRecCode =
71         Stream.readRecord(Entry.ID, Record, &Blob);
72     if (!MaybeRecCode)
73       fprintf(stderr, "Failed reading rec code: %s\n",
74               toString(MaybeRecCode.takeError()).c_str());
75     switch (MaybeRecCode.get()) {
76     case FIRST_EXTENSION_RECORD_ID: {
77       StringRef Message = Blob.substr(0, Record[0]);
78       fprintf(stderr, "Read extension block message: %s\n",
79               Message.str().c_str());
80       break;
81     }
82     }
83   }
84 }
85 
86 TestModuleFileExtension::Reader::~Reader() { }
87 
88 TestModuleFileExtension::~TestModuleFileExtension() { }
89 
90 ModuleFileExtensionMetadata
91 TestModuleFileExtension::getExtensionMetadata() const {
92   return { BlockName, MajorVersion, MinorVersion, UserInfo };
93 }
94 
95 void TestModuleFileExtension::hashExtension(
96     ExtensionHashBuilder &HBuilder) const {
97   if (Hashed) {
98     HBuilder.add(BlockName);
99     HBuilder.add(MajorVersion);
100     HBuilder.add(MinorVersion);
101     HBuilder.add(UserInfo);
102   }
103 }
104 
105 std::unique_ptr<ModuleFileExtensionWriter>
106 TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
107   return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
108 }
109 
110 std::unique_ptr<ModuleFileExtensionReader>
111 TestModuleFileExtension::createExtensionReader(
112   const ModuleFileExtensionMetadata &Metadata,
113   ASTReader &Reader, serialization::ModuleFile &Mod,
114   const llvm::BitstreamCursor &Stream)
115 {
116   assert(Metadata.BlockName == BlockName && "Wrong block name");
117   if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) !=
118         std::make_pair(MajorVersion, MinorVersion)) {
119     Reader.getDiags().Report(Mod.ImportLoc,
120                              diag::err_test_module_file_extension_version)
121       << BlockName << Metadata.MajorVersion << Metadata.MinorVersion
122       << MajorVersion << MinorVersion;
123     return nullptr;
124   }
125 
126   return std::unique_ptr<ModuleFileExtensionReader>(
127                                                     new TestModuleFileExtension::Reader(this, Stream));
128 }
129 
130 std::string TestModuleFileExtension::str() const {
131   std::string Buffer;
132   llvm::raw_string_ostream OS(Buffer);
133   OS << BlockName << ":" << MajorVersion << ":" << MinorVersion << ":" << Hashed
134      << ":" << UserInfo;
135   return Buffer;
136 }
137