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); }
static void emitBlockID(unsigned ID, const char *Name, llvm::BitstreamWriter &Stream, SmallVectorImpl<uint64_t> &Record) { Record.clear(); Record.push_back(ID); Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID, Record); // Emit the block name if present. if (!Name || Name[0] == 0) return; Record.clear(); while (*Name) Record.push_back(*Name++); Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_BLOCKNAME, Record); }
void GlobalModuleIndexBuilder::emitBlockInfoBlock(llvm::BitstreamWriter &Stream) { SmallVector<uint64_t, 64> Record; Stream.EnterSubblock(llvm::bitc::BLOCKINFO_BLOCK_ID, 3); #define BLOCK(X) emitBlockID(X ## _ID, #X, Stream, Record) #define RECORD(X) emitRecordID(X, #X, Stream, Record) BLOCK(GLOBAL_INDEX_BLOCK); RECORD(INDEX_METADATA); RECORD(MODULE); RECORD(IDENTIFIER_INDEX); #undef RECORD #undef BLOCK Stream.ExitBlock(); }
static void emitRecordID(unsigned ID, const char *Name, llvm::BitstreamWriter &Stream, SmallVectorImpl<uint64_t> &Record) { Record.clear(); Record.push_back(ID); while (*Name) Record.push_back(*Name++); Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Record); }
void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { using namespace llvm; // Emit the file header. Stream.Emit((unsigned)'B', 8); Stream.Emit((unsigned)'C', 8); Stream.Emit((unsigned)'G', 8); Stream.Emit((unsigned)'I', 8); // Write the block-info block, which describes the records in this bitcode // file. emitBlockInfoBlock(Stream); Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3); // Write the metadata. SmallVector<uint64_t, 2> Record; Record.push_back(CurrentVersion); Stream.EmitRecord(INDEX_METADATA, Record); // Write the set of known module files. for (ModuleFilesMap::iterator M = ModuleFiles.begin(), MEnd = ModuleFiles.end(); M != MEnd; ++M) { Record.clear(); Record.push_back(M->second.ID); Record.push_back(M->first->getSize()); Record.push_back(M->first->getModificationTime()); // File name StringRef Name(M->first->getName()); Record.push_back(Name.size()); Record.append(Name.begin(), Name.end()); // Dependencies Record.push_back(M->second.Dependencies.size()); Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end()); Stream.EmitRecord(MODULE, Record); } // Write the identifier -> module file mapping. { llvm::OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; IdentifierIndexWriterTrait Trait; // Populate the hash table. for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(), IEnd = InterestingIdentifiers.end(); I != IEnd; ++I) { Generator.insert(I->first(), I->second, Trait); } // Create the on-disk hash table in a buffer. SmallString<4096> IdentifierTable; uint32_t BucketOffset; { using namespace llvm::support; llvm::raw_svector_ostream Out(IdentifierTable); // Make sure that no bucket is at offset 0 endian::Writer<little>(Out).write<uint32_t>(0); BucketOffset = Generator.Emit(Out, Trait); } // Create a blob abbreviation BitCodeAbbrev *Abbrev = new BitCodeAbbrev(); Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned IDTableAbbrev = Stream.EmitAbbrev(Abbrev); // Write the identifier table Record.clear(); Record.push_back(IDENTIFIER_INDEX); Record.push_back(BucketOffset); Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable.str()); } Stream.ExitBlock(); }
bool GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { for (auto MapEntry : ImportedModuleFiles) { auto *File = MapEntry.first; ImportedModuleFileInfo &Info = MapEntry.second; if (getModuleFileInfo(File).Signature) { if (getModuleFileInfo(File).Signature != Info.StoredSignature) // Verify Signature. return true; } else if (Info.StoredSize != File->getSize() || Info.StoredModTime != File->getModificationTime()) // Verify Size and ModTime. return true; } using namespace llvm; llvm::TimeTraceScope TimeScope("Module WriteIndex", StringRef("")); // Emit the file header. Stream.Emit((unsigned)'B', 8); Stream.Emit((unsigned)'C', 8); Stream.Emit((unsigned)'G', 8); Stream.Emit((unsigned)'I', 8); // Write the block-info block, which describes the records in this bitcode // file. emitBlockInfoBlock(Stream); Stream.EnterSubblock(GLOBAL_INDEX_BLOCK_ID, 3); // Write the metadata. SmallVector<uint64_t, 2> Record; Record.push_back(CurrentVersion); Stream.EmitRecord(INDEX_METADATA, Record); // Write the set of known module files. for (ModuleFilesMap::iterator M = ModuleFiles.begin(), MEnd = ModuleFiles.end(); M != MEnd; ++M) { Record.clear(); Record.push_back(M->second.ID); Record.push_back(M->first->getSize()); Record.push_back(M->first->getModificationTime()); // File name StringRef Name(M->first->getName()); Record.push_back(Name.size()); Record.append(Name.begin(), Name.end()); // Dependencies Record.push_back(M->second.Dependencies.size()); Record.append(M->second.Dependencies.begin(), M->second.Dependencies.end()); Stream.EmitRecord(MODULE, Record); } // Write the identifier -> module file mapping. { llvm::OnDiskChainedHashTableGenerator<IdentifierIndexWriterTrait> Generator; IdentifierIndexWriterTrait Trait; // Populate the hash table. for (InterestingIdentifierMap::iterator I = InterestingIdentifiers.begin(), IEnd = InterestingIdentifiers.end(); I != IEnd; ++I) { Generator.insert(I->first(), I->second, Trait); } // Create the on-disk hash table in a buffer. SmallString<4096> IdentifierTable; uint32_t BucketOffset; { using namespace llvm::support; llvm::raw_svector_ostream Out(IdentifierTable); // Make sure that no bucket is at offset 0 endian::write<uint32_t>(Out, 0, little); BucketOffset = Generator.Emit(Out, Trait); } // Create a blob abbreviation auto Abbrev = std::make_shared<BitCodeAbbrev>(); Abbrev->Add(BitCodeAbbrevOp(IDENTIFIER_INDEX)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); unsigned IDTableAbbrev = Stream.EmitAbbrev(std::move(Abbrev)); // Write the identifier table uint64_t Record[] = {IDENTIFIER_INDEX, BucketOffset}; Stream.EmitRecordWithBlob(IDTableAbbrev, Record, IdentifierTable); } Stream.ExitBlock(); return false; }