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   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::BitstreamEntry Entry = Stream.advanceSkippingSubblocks();
     53     switch (Entry.Kind) {
     54     case llvm::BitstreamEntry::SubBlock:
     55     case llvm::BitstreamEntry::EndBlock:
     56     case llvm::BitstreamEntry::Error:
     57       return;
     58 
     59     case llvm::BitstreamEntry::Record:
     60       break;
     61     }
     62 
     63     Record.clear();
     64     StringRef Blob;
     65     unsigned RecCode = Stream.readRecord(Entry.ID, Record, &Blob);
     66     switch (RecCode) {
     67     case FIRST_EXTENSION_RECORD_ID: {
     68       StringRef Message = Blob.substr(0, Record[0]);
     69       fprintf(stderr, "Read extension block message: %s\n",
     70               Message.str().c_str());
     71       break;
     72     }
     73     }
     74   }
     75 }
     76 
     77 TestModuleFileExtension::Reader::~Reader() { }
     78 
     79 TestModuleFileExtension::~TestModuleFileExtension() { }
     80 
     81 ModuleFileExtensionMetadata
     82 TestModuleFileExtension::getExtensionMetadata() const {
     83   return { BlockName, MajorVersion, MinorVersion, UserInfo };
     84 }
     85 
     86 llvm::hash_code TestModuleFileExtension::hashExtension(
     87                   llvm::hash_code Code) const {
     88   if (Hashed) {
     89     Code = llvm::hash_combine(Code, BlockName);
     90     Code = llvm::hash_combine(Code, MajorVersion);
     91     Code = llvm::hash_combine(Code, MinorVersion);
     92     Code = llvm::hash_combine(Code, UserInfo);
     93   }
     94 
     95   return Code;
     96 }
     97 
     98 std::unique_ptr<ModuleFileExtensionWriter>
     99 TestModuleFileExtension::createExtensionWriter(ASTWriter &) {
    100   return std::unique_ptr<ModuleFileExtensionWriter>(new Writer(this));
    101 }
    102 
    103 std::unique_ptr<ModuleFileExtensionReader>
    104 TestModuleFileExtension::createExtensionReader(
    105   const ModuleFileExtensionMetadata &Metadata,
    106   ASTReader &Reader, serialization::ModuleFile &Mod,
    107   const llvm::BitstreamCursor &Stream)
    108 {
    109   assert(Metadata.BlockName == BlockName && "Wrong block name");
    110   if (std::make_pair(Metadata.MajorVersion, Metadata.MinorVersion) !=
    111         std::make_pair(MajorVersion, MinorVersion)) {
    112     Reader.getDiags().Report(Mod.ImportLoc,
    113                              diag::err_test_module_file_extension_version)
    114       << BlockName << Metadata.MajorVersion << Metadata.MinorVersion
    115       << MajorVersion << MinorVersion;
    116     return nullptr;
    117   }
    118 
    119   return std::unique_ptr<ModuleFileExtensionReader>(
    120                                                     new TestModuleFileExtension::Reader(this, Stream));
    121 }
    122