/// ParseBlock - Read a block, updating statistics, etc. static bool ParseBlock(BitstreamCursor &Stream, unsigned BlockID, unsigned IndentLevel) { std::string Indent(IndentLevel*2, ' '); uint64_t BlockBitStart = Stream.GetCurrentBitNo(); // Get the statistics for this BlockID. PerBlockIDStats &BlockStats = BlockIDStats[BlockID]; BlockStats.NumInstances++; // BLOCKINFO is a special part of the stream. if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { if (Dump) outs() << Indent << "<BLOCKINFO_BLOCK/>\n"; if (Stream.ReadBlockInfoBlock()) return Error("Malformed BlockInfoBlock"); uint64_t BlockBitEnd = Stream.GetCurrentBitNo(); BlockStats.NumBits += BlockBitEnd-BlockBitStart; return false; } unsigned NumWords = 0; if (Stream.EnterSubBlock(BlockID, &NumWords)) return Error("Malformed block record"); const char *BlockName = 0; if (Dump) { outs() << Indent << "<"; if ((BlockName = GetBlockName(BlockID, *Stream.getBitStreamReader()))) outs() << BlockName; else outs() << "UnknownBlock" << BlockID; if (NonSymbolic && BlockName) outs() << " BlockID=" << BlockID; outs() << " NumWords=" << NumWords << " BlockCodeSize=" << Stream.getAbbrevIDWidth() << ">\n"; } SmallVector<uint64_t, 64> Record; // Read all the records for this block. while (1) { if (Stream.AtEndOfStream()) return Error("Premature end of bitstream"); uint64_t RecordStartBit = Stream.GetCurrentBitNo(); BitstreamEntry Entry = Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs); switch (Entry.Kind) { case BitstreamEntry::Error: return Error("malformed bitcode file"); case BitstreamEntry::EndBlock: { uint64_t BlockBitEnd = Stream.GetCurrentBitNo(); BlockStats.NumBits += BlockBitEnd-BlockBitStart; if (Dump) { outs() << Indent << "</"; if (BlockName) outs() << BlockName << ">\n"; else outs() << "UnknownBlock" << BlockID << ">\n"; } return false; } case BitstreamEntry::SubBlock: { uint64_t SubBlockBitStart = Stream.GetCurrentBitNo(); if (ParseBlock(Stream, Entry.ID, IndentLevel+1)) return true; ++BlockStats.NumSubBlocks; uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo(); // Don't include subblock sizes in the size of this block. BlockBitStart += SubBlockBitEnd-SubBlockBitStart; continue; } case BitstreamEntry::Record: // The interesting case. break; } if (Entry.ID == bitc::DEFINE_ABBREV) { Stream.ReadAbbrevRecord(); ++BlockStats.NumAbbrevs; continue; } Record.clear(); ++BlockStats.NumRecords; StringRef Blob; unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob); // Increment the # occurrences of this code. if (BlockStats.CodeFreq.size() <= Code) BlockStats.CodeFreq.resize(Code+1); BlockStats.CodeFreq[Code].NumInstances++; BlockStats.CodeFreq[Code].TotalBits += Stream.GetCurrentBitNo()-RecordStartBit; if (Entry.ID != bitc::UNABBREV_RECORD) { BlockStats.CodeFreq[Code].NumAbbrev++; ++BlockStats.NumAbbreviatedRecords; } if (Dump) { outs() << Indent << " <"; if (const char *CodeName = GetCodeName(Code, BlockID, *Stream.getBitStreamReader())) outs() << CodeName; else outs() << "UnknownCode" << Code; if (NonSymbolic && GetCodeName(Code, BlockID, *Stream.getBitStreamReader())) outs() << " codeid=" << Code; if (Entry.ID != bitc::UNABBREV_RECORD) outs() << " abbrevid=" << Entry.ID; for (unsigned i = 0, e = Record.size(); i != e; ++i) outs() << " op" << i << "=" << (int64_t)Record[i]; outs() << "/>"; if (Blob.data()) { outs() << " blob data = "; bool BlobIsPrintable = true; for (unsigned i = 0, e = Blob.size(); i != e; ++i) if (!isprint(static_cast<unsigned char>(Blob[i]))) { BlobIsPrintable = false; break; } if (BlobIsPrintable) outs() << "'" << Blob << "'"; else outs() << "unprintable, " << Blob.size() << " bytes."; } outs() << "\n"; } } }
/// ParseBlock - Read a block, updating statistics, etc. static bool ParseBlock(BitstreamCursor &Stream, unsigned IndentLevel) { std::string Indent(IndentLevel*2, ' '); uint64_t BlockBitStart = Stream.GetCurrentBitNo(); unsigned BlockID = Stream.ReadSubBlockID(); // Get the statistics for this BlockID. PerBlockIDStats &BlockStats = BlockIDStats[BlockID]; BlockStats.NumInstances++; // BLOCKINFO is a special part of the stream. if (BlockID == bitc::BLOCKINFO_BLOCK_ID) { if (Dump) errs() << Indent << "<BLOCKINFO_BLOCK/>\n"; if (Stream.ReadBlockInfoBlock()) return Error("Malformed BlockInfoBlock"); uint64_t BlockBitEnd = Stream.GetCurrentBitNo(); BlockStats.NumBits += BlockBitEnd-BlockBitStart; return false; } unsigned NumWords = 0; if (Stream.EnterSubBlock(BlockID, &NumWords)) return Error("Malformed block record"); const char *BlockName = 0; if (Dump) { errs() << Indent << "<"; if ((BlockName = GetBlockName(BlockID, *Stream.getBitStreamReader()))) errs() << BlockName; else errs() << "UnknownBlock" << BlockID; if (NonSymbolic && BlockName) errs() << " BlockID=" << BlockID; errs() << " NumWords=" << NumWords << " BlockCodeSize=" << Stream.GetAbbrevIDWidth() << ">\n"; } SmallVector<uint64_t, 64> Record; // Read all the records for this block. while (1) { if (Stream.AtEndOfStream()) return Error("Premature end of bitstream"); uint64_t RecordStartBit = Stream.GetCurrentBitNo(); // Read the code for this record. unsigned AbbrevID = Stream.ReadCode(); switch (AbbrevID) { case bitc::END_BLOCK: { if (Stream.ReadBlockEnd()) return Error("Error at end of block"); uint64_t BlockBitEnd = Stream.GetCurrentBitNo(); BlockStats.NumBits += BlockBitEnd-BlockBitStart; if (Dump) { errs() << Indent << "</"; if (BlockName) errs() << BlockName << ">\n"; else errs() << "UnknownBlock" << BlockID << ">\n"; } return false; } case bitc::ENTER_SUBBLOCK: { uint64_t SubBlockBitStart = Stream.GetCurrentBitNo(); if (ParseBlock(Stream, IndentLevel+1)) return true; ++BlockStats.NumSubBlocks; uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo(); // Don't include subblock sizes in the size of this block. BlockBitStart += SubBlockBitEnd-SubBlockBitStart; break; } case bitc::DEFINE_ABBREV: Stream.ReadAbbrevRecord(); ++BlockStats.NumAbbrevs; break; default: Record.clear(); ++BlockStats.NumRecords; if (AbbrevID != bitc::UNABBREV_RECORD) ++BlockStats.NumAbbreviatedRecords; const char *BlobStart = 0; unsigned BlobLen = 0; unsigned Code = Stream.ReadRecord(AbbrevID, Record, BlobStart, BlobLen); // Increment the # occurrences of this code. if (BlockStats.CodeFreq.size() <= Code) BlockStats.CodeFreq.resize(Code+1); BlockStats.CodeFreq[Code].NumInstances++; BlockStats.CodeFreq[Code].TotalBits += Stream.GetCurrentBitNo()-RecordStartBit; if (AbbrevID != bitc::UNABBREV_RECORD) BlockStats.CodeFreq[Code].NumAbbrev++; if (Dump) { errs() << Indent << " <"; if (const char *CodeName = GetCodeName(Code, BlockID, *Stream.getBitStreamReader())) errs() << CodeName; else errs() << "UnknownCode" << Code; if (NonSymbolic && GetCodeName(Code, BlockID, *Stream.getBitStreamReader())) errs() << " codeid=" << Code; if (AbbrevID != bitc::UNABBREV_RECORD) errs() << " abbrevid=" << AbbrevID; for (unsigned i = 0, e = Record.size(); i != e; ++i) errs() << " op" << i << "=" << (int64_t)Record[i]; errs() << "/>"; if (BlobStart) { errs() << " blob data = "; bool BlobIsPrintable = true; for (unsigned i = 0; i != BlobLen; ++i) if (!isprint(BlobStart[i])) { BlobIsPrintable = false; break; } if (BlobIsPrintable) errs() << "'" << std::string(BlobStart, BlobStart+BlobLen) <<"'"; else errs() << "unprintable, " << BlobLen << " bytes."; } errs() << "\n"; } break; } } }