reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
//===-- TestModuleFileExtension.cpp - Module Extension Tester -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "TestModuleFileExtension.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Serialization/ASTReader.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/Bitstream/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.
  auto Abv = std::make_shared<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(std::move(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;
  }
  uint64_t Record[] = {FIRST_EXTENSION_RECORD_ID, 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::Expected<llvm::BitstreamEntry> MaybeEntry =
        Stream.advanceSkippingSubblocks();
    if (!MaybeEntry)
      (void)MaybeEntry.takeError();
    llvm::BitstreamEntry Entry = MaybeEntry.get();

    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;
    Expected<unsigned> MaybeRecCode =
        Stream.readRecord(Entry.ID, Record, &Blob);
    if (!MaybeRecCode)
      fprintf(stderr, "Failed reading rec code: %s\n",
              toString(MaybeRecCode.takeError()).c_str());
    switch (MaybeRecCode.get()) {
    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));
}