137 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8#include "TestModuleFileExtension.h"9#include "clang/Basic/DiagnosticFrontend.h"10#include "clang/Serialization/ASTReader.h"11#include "llvm/Bitstream/BitstreamWriter.h"12#include "llvm/Support/raw_ostream.h"13#include <cstdio>14using namespace clang;15using namespace clang::serialization;16 17char TestModuleFileExtension::ID = 0;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 auto Abv = std::make_shared<llvm::BitCodeAbbrev>();28 Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID));29 Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of characters30 Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // message31 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 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::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 86TestModuleFileExtension::Reader::~Reader() { }87 88TestModuleFileExtension::~TestModuleFileExtension() { }89 90ModuleFileExtensionMetadata91TestModuleFileExtension::getExtensionMetadata() const {92 return { BlockName, MajorVersion, MinorVersion, UserInfo };93}94 95void 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 105std::unique_ptr<ModuleFileExtensionWriter>106TestModuleFileExtension::createExtensionWriter(ASTWriter &) {107 return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));108}109 110std::unique_ptr<ModuleFileExtensionReader>111TestModuleFileExtension::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.MinorVersion122 << MajorVersion << MinorVersion;123 return nullptr;124 }125 126 return std::unique_ptr<ModuleFileExtensionReader>(127 new TestModuleFileExtension::Reader(this, Stream));128}129 130std::string TestModuleFileExtension::str() const {131 std::string Buffer;132 llvm::raw_string_ostream OS(Buffer);133 OS << BlockName << ":" << MajorVersion << ":" << MinorVersion << ":" << Hashed134 << ":" << UserInfo;135 return Buffer;136}137