diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp b/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp new file mode 100644 index 0000000..d1b20c4 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Frontend/TestModuleFileExtension.cpp @@ -0,0 +1,123 @@ +//===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include "TestModuleFileExtension.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Serialization/ASTReader.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/Bitcode/BitstreamWriter.h" +#include "llvm/Support/raw_ostream.h" +#include <cstdio> +using namespace clang; +using namespace clang::serialization; + +TestModuleFileExtension::Writer::~Writer() { } + +void TestModuleFileExtension::Writer::writeExtensionContents( + Sema &SemaRef, + llvm::BitstreamWriter &Stream) { + using namespace llvm; + + // Write an abbreviation for this record. + BitCodeAbbrev *Abv = new llvm::BitCodeAbbrev(); + Abv->Add(BitCodeAbbrevOp(FIRST_EXTENSION_RECORD_ID)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // # of characters + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // message + auto Abbrev = Stream.EmitAbbrev(Abv); + + // Write a message into the extension block. + SmallString<64> Message; + { + auto Ext = static_cast<TestModuleFileExtension *>(getExtension()); + raw_svector_ostream OS(Message); + OS << "Hello from " << Ext->BlockName << " v" << Ext->MajorVersion << "." + << Ext->MinorVersion; + } + SmallVector<uint64_t, 4> Record; + Record.push_back(FIRST_EXTENSION_RECORD_ID); + Record.push_back(Message.size()); + Stream.EmitRecordWithBlob(Abbrev, Record, Message); +} + +TestModuleFileExtension::Reader::Reader(ModuleFileExtension *Ext, + const llvm::BitstreamCursor &InStream) + : ModuleFileExtensionReader(Ext), Stream(InStream) +{ + // Read the extension block. + SmallVector<uint64_t, 4> Record; + while (true) { + llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + switch (Entry.Kind) { + case llvm::BitstreamEntry::SubBlock: + case llvm::BitstreamEntry::EndBlock: + case llvm::BitstreamEntry::Error: + return; + + case llvm::BitstreamEntry::Record: + break; + } + + Record.clear(); + StringRef Blob; + unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob); + switch (RecCode) { + case FIRST_EXTENSION_RECORD_ID: { + StringRef Message = Blob.substr(0, Record[0]); + fprintf(stderr, "Read extension block message: %s\n", + Message.str().c_str()); + break; + } + } + } +} + +TestModuleFileExtension::Reader::~Reader() { } + +TestModuleFileExtension::~TestModuleFileExtension() { } + +ModuleFileExtensionMetadata +TestModuleFileExtension::getExtensionMetadata() const { + return { BlockName, MajorVersion, MinorVersion, UserInfo }; +} + +llvm::hash_code TestModuleFileExtension::hashExtension( + llvm::hash_code Code) const { + if (Hashed) { + Code = llvm::hash_combine(Code, BlockName); + Code = llvm::hash_combine(Code, MajorVersion); + Code = llvm::hash_combine(Code, MinorVersion); + Code = llvm::hash_combine(Code, UserInfo); + } + + return Code; +} + +std::unique_ptr<ModuleFileExtensionWriter> +TestModuleFileExtension::createExtensionWriter(ASTWriter &) { + return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this)); +} + +std::unique_ptr<ModuleFileExtensionReader> +TestModuleFileExtension::createExtensionReader( + const ModuleFileExtensionMetadata &Metadata, + ASTReader &Reader, serialization::ModuleFile &Mod, + const llvm::BitstreamCursor &Stream) +{ + assert(Metadata.BlockName == BlockName && "Wrong block name"); + if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) != + std::make_pair(MajorVersion, MinorVersion)) { + Reader.getDiags().Report(Mod.ImportLoc, + diag::err_test_module_file_extension_version) + << BlockName << Metadata.MajorVersion << Metadata.MinorVersion + << MajorVersion << MinorVersion; + return nullptr; + } + + return std::unique_ptr<ModuleFileExtensionReader>( + new TestModuleFileExtension::Reader(this, Stream)); +} |