Home | History | Annotate | Download | only in Frontend
      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 //===----------------------------------------------------------------------===//
      9 #include "TestModuleFileExtension.h"
     10 #include "clang/Frontend/FrontendDiagnostic.h"
     11 #include "clang/Serialization/ASTReader.h"
     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   }
     41   SmallVector<uint64_t, 4> Record;
     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.
     52   SmallVector<uint64_t, 4> Record;
     53   while (true) {
     54     llvm::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
     55     switch (Entry.Kind) {
     56     case llvm::BitstreamEntry::SubBlock:
     57     case llvm::BitstreamEntry::EndBlock:
     58     case llvm::BitstreamEntry::Error:
     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) {
     69     case FIRST_EXTENSION_RECORD_ID: {
     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 
     83 ModuleFileExtensionMetadata
     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 }
    124