25static std::optional<const char *>
31 return "BLOCKINFO_BLOCK";
37 BlockInfo.getBlockInfo(BlockID)) {
38 if (!
Info->Name.empty())
39 return Info->Name.c_str();
49 return "OPERAND_BUNDLE_TAGS_BLOCK";
51 return "MODULE_BLOCK";
53 return "PARAMATTR_BLOCK";
55 return "PARAMATTR_GROUP_BLOCK_ID";
57 return "TYPE_BLOCK_ID";
59 return "CONSTANTS_BLOCK";
61 return "FUNCTION_BLOCK";
63 return "IDENTIFICATION_BLOCK_ID";
65 return "VALUE_SYMTAB";
67 return "METADATA_BLOCK";
69 return "METADATA_KIND_BLOCK";
71 return "METADATA_ATTACHMENT_BLOCK";
73 return "USELIST_BLOCK_ID";
75 return "GLOBALVAL_SUMMARY_BLOCK";
77 return "FULL_LTO_GLOBALVAL_SUMMARY_BLOCK";
79 return "MODULE_STRTAB_BLOCK";
81 return "STRTAB_BLOCK";
83 return "SYMTAB_BLOCK";
88static std::optional<const char *>
103 return "SETRECORDNAME";
111 BlockInfo.getBlockInfo(BlockID)) {
112 for (
const std::pair<unsigned, std::string> &RN :
Info->RecordNames)
113 if (RN.first == CodeID)
114 return RN.second.c_str();
120#define STRINGIFY_CODE(PREFIX, CODE) \
121 case bitc::PREFIX##_##CODE: \
227 return "CST_CODE_BLOCKADDRESS";
397 return "USELIST_CODE_DEFAULT";
399 return "USELIST_CODE_BB";
407 return "OPERAND_BUNDLE_TAG";
428 OS <<
format(
"%.2f/%.2fB/%luW", Bits, Bits / 8, (
unsigned long)(Bits / 32));
431 OS <<
format(
"%lub/%.2fB/%luW", (
unsigned long)Bits, (
double)Bits / 8,
432 (
unsigned long)(Bits / 32));
436 auto tryRead = [&Stream](
char &Dest,
size_t size) ->
Error {
438 Dest = MaybeWord.get();
440 return MaybeWord.takeError();
445 if (
Error Err = tryRead(Signature[0], 8))
446 return std::move(Err);
447 if (
Error Err = tryRead(Signature[1], 8))
448 return std::move(Err);
451 if (Signature[0] ==
'C' && Signature[1] ==
'P') {
452 if (
Error Err = tryRead(Signature[2], 8))
453 return std::move(Err);
454 if (
Error Err = tryRead(Signature[3], 8))
455 return std::move(Err);
456 if (Signature[2] ==
'C' && Signature[3] ==
'H')
458 }
else if (Signature[0] ==
'D' && Signature[1] ==
'I') {
459 if (
Error Err = tryRead(Signature[2], 8))
460 return std::move(Err);
461 if (
Error Err = tryRead(Signature[3], 8))
462 return std::move(Err);
463 if (Signature[2] ==
'A' && Signature[3] ==
'G')
465 }
else if (Signature[0] ==
'R' && Signature[1] ==
'M') {
466 if (
Error Err = tryRead(Signature[2], 8))
467 return std::move(Err);
468 if (
Error Err = tryRead(Signature[3], 8))
469 return std::move(Err);
470 if (Signature[2] ==
'R' && Signature[3] ==
'K')
473 if (
Error Err = tryRead(Signature[2], 4))
474 return std::move(Err);
475 if (
Error Err = tryRead(Signature[3], 4))
476 return std::move(Err);
477 if (
Error Err = tryRead(Signature[4], 4))
478 return std::move(Err);
479 if (
Error Err = tryRead(Signature[5], 4))
480 return std::move(Err);
481 if (Signature[0] ==
'B' && Signature[1] ==
'C' && Signature[2] == 0x0 &&
482 Signature[3] == 0xC && Signature[4] == 0xE && Signature[5] == 0xD)
491 const unsigned char *BufPtr = (
const unsigned char *)Bytes.
data();
492 const unsigned char *EndBufPtr = BufPtr + Bytes.
size();
498 return reportError(
"Invalid bitcode wrapper header");
507 O->OS <<
"<BITCODE_WRAPPER_HEADER"
512 <<
" CPUType=" <<
format_hex(CPUType, 10) <<
"/>\n";
516 return reportError(
"Invalid bitcode wrapper header");
536 if (Record.
size() != 2)
538 "Decoding metadata strings blob needs two record entries.");
540 unsigned NumStrings = Record[0];
541 unsigned StringsOffset = Record[1];
542 OS <<
" num-strings = " << NumStrings <<
" {\n";
544 StringRef Lengths = Blob.
slice(0, StringsOffset);
545 SimpleBitstreamCursor
R(Lengths);
546 StringRef Strings = Blob.
drop_front(StringsOffset);
548 if (
R.AtEndOfStream())
557 OS << Indent <<
" '";
561 }
while (--NumStrings);
563 OS << Indent <<
" }";
568 std::optional<StringRef> BlockInfoBuffer)
571 BlockInfoStream.emplace(*BlockInfoBuffer);
575 std::optional<StringRef> CheckHash) {
579 Stream.setBlockInfo(&BlockInfo);
583 if (BlockInfoStream) {
593 return reportError(
"Invalid record at top-level in block info file");
599 std::optional<BitstreamBlockInfo> NewBlockInfo;
602 .moveInto(NewBlockInfo))
605 return reportError(
"Malformed BlockInfoBlock in block info file");
606 BlockInfo = std::move(*NewBlockInfo);
616 while (!Stream.AtEndOfStream()) {
627 if (
Error E = parseBlock(MaybeBlockID.
get(), 0, O, CheckHash))
636 std::optional<StringRef> Filename) {
637 uint64_t BufferSizeBits = Stream.getBitcodeBytes().size() * CHAR_BIT;
641 O.OS <<
"of " << Filename->data() <<
":\n";
642 O.OS <<
" Total size: ";
645 O.OS <<
" Stream type: ";
646 switch (CurStreamType) {
654 O.OS <<
"Clang Serialized AST\n";
657 O.OS <<
"Clang Serialized Diagnostics\n";
660 O.OS <<
"LLVM Remarks\n";
663 O.OS <<
" # Toplevel Blocks: " << NumTopBlocks <<
"\n";
667 O.OS <<
"Per-block Summary:\n";
668 for (
const auto &Stat : BlockIDStats) {
669 O.OS <<
" Block ID #" << Stat.first;
670 if (std::optional<const char *> BlockName =
672 O.OS <<
" (" << *BlockName <<
")";
675 const PerBlockIDStats &
Stats = Stat.second;
676 O.OS <<
" Num Instances: " <<
Stats.NumInstances <<
"\n";
677 O.OS <<
" Total Size: ";
680 double pct = (
Stats.NumBits * 100.0) / BufferSizeBits;
681 O.OS <<
" Percent of file: " <<
format(
"%2.4f%%", pct) <<
"\n";
682 if (
Stats.NumInstances > 1) {
683 O.OS <<
" Average Size: ";
686 O.OS <<
" Tot/Avg SubBlocks: " <<
Stats.NumSubBlocks <<
"/"
687 <<
Stats.NumSubBlocks / (double)
Stats.NumInstances <<
"\n";
688 O.OS <<
" Tot/Avg Abbrevs: " <<
Stats.NumAbbrevs <<
"/"
689 <<
Stats.NumAbbrevs / (double)
Stats.NumInstances <<
"\n";
690 O.OS <<
" Tot/Avg Records: " <<
Stats.NumRecords <<
"/"
691 <<
Stats.NumRecords / (double)
Stats.NumInstances <<
"\n";
693 O.OS <<
" Num SubBlocks: " <<
Stats.NumSubBlocks <<
"\n";
694 O.OS <<
" Num Abbrevs: " <<
Stats.NumAbbrevs <<
"\n";
695 O.OS <<
" Num Records: " <<
Stats.NumRecords <<
"\n";
697 if (
Stats.NumRecords) {
698 double pct = (
Stats.NumAbbreviatedRecords * 100.0) /
Stats.NumRecords;
699 O.OS <<
" Percent Abbrevs: " <<
format(
"%2.4f%%", pct) <<
"\n";
704 if (O.Histogram && !
Stats.CodeFreq.empty()) {
705 std::vector<std::pair<unsigned, unsigned>> FreqPairs;
706 for (
unsigned i = 0, e =
Stats.CodeFreq.size(); i != e; ++i)
707 if (
unsigned Freq =
Stats.CodeFreq[i].NumInstances)
708 FreqPairs.push_back(std::make_pair(Freq, i));
710 std::reverse(FreqPairs.begin(), FreqPairs.end());
712 O.OS <<
"\tRecord Histogram:\n";
713 O.OS <<
"\t\t Count # Bits b/Rec % Abv Record Kind\n";
714 for (
const auto &FreqPair : FreqPairs) {
715 const PerRecordStats &RecStats =
Stats.CodeFreq[FreqPair.second];
717 O.OS <<
format(
"\t\t%7d %9lu", RecStats.NumInstances,
718 (
unsigned long)RecStats.TotalBits);
720 if (RecStats.NumInstances > 1)
722 (
double)RecStats.TotalBits / RecStats.NumInstances);
726 if (RecStats.NumAbbrev)
727 O.OS <<
format(
" %7.2f", (
double)RecStats.NumAbbrev /
728 RecStats.NumInstances * 100);
733 if (std::optional<const char *> CodeName =
GetCodeName(
734 FreqPair.second, Stat.first, BlockInfo, CurStreamType))
735 O.OS << *CodeName <<
"\n";
737 O.OS <<
"UnknownCode" << FreqPair.second <<
"\n";
744Error BitcodeAnalyzer::parseBlock(
unsigned BlockID,
unsigned IndentLevel,
745 std::optional<BCDumpOptions> O,
746 std::optional<StringRef> CheckHash) {
747 std::string Indent(IndentLevel * 2,
' ');
751 PerBlockIDStats &BlockStats = BlockIDStats[BlockID];
753 BlockStats.NumInstances++;
756 bool DumpRecords = O.has_value();
758 if (O && !O->DumpBlockinfo)
759 O->OS << Indent <<
"<BLOCKINFO_BLOCK/>\n";
760 std::optional<BitstreamBlockInfo> NewBlockInfo;
762 .moveInto(NewBlockInfo))
766 BlockInfo = std::move(*NewBlockInfo);
771 DumpRecords = O && O->DumpBlockinfo;
774 unsigned NumWords = 0;
781 std::optional<const char *> BlockName;
783 O->OS << Indent <<
"<";
784 if ((BlockName =
GetBlockName(BlockID, BlockInfo, CurStreamType)))
787 O->OS <<
"UnknownBlock" << BlockID;
789 if (!O->Symbolic && BlockName)
790 O->OS <<
" BlockID=" << BlockID;
792 O->OS <<
" NumWords=" << NumWords
796 SmallVector<uint64_t, 64> Record;
799 uint64_t MetadataIndexOffset = 0;
803 if (Stream.AtEndOfStream())
806 uint64_t RecordStartBit = Stream.GetCurrentBitNo();
808 BitstreamEntry
Entry;
813 switch (
Entry.Kind) {
817 uint64_t BlockBitEnd = Stream.GetCurrentBitNo();
818 BlockStats.NumBits += BlockBitEnd - BlockBitStart;
820 O->OS << Indent <<
"</";
822 O->OS << *BlockName <<
">\n";
824 O->OS <<
"UnknownBlock" << BlockID <<
">\n";
830 uint64_t SubBlockBitStart = Stream.GetCurrentBitNo();
831 if (
Error E = parseBlock(
Entry.ID, IndentLevel + 1, O, CheckHash))
833 ++BlockStats.NumSubBlocks;
834 uint64_t SubBlockBitEnd = Stream.GetCurrentBitNo();
837 BlockBitStart += SubBlockBitEnd - SubBlockBitStart;
846 if (
Error Err = Stream.ReadAbbrevRecord())
848 ++BlockStats.NumAbbrevs;
854 ++BlockStats.NumRecords;
857 uint64_t CurrentRecordPos = Stream.GetCurrentBitNo();
859 if (
Error E = Stream.readRecord(
Entry.ID, Record, &Blob).moveInto(Code))
863 if (BlockStats.CodeFreq.size() <= Code)
864 BlockStats.CodeFreq.resize(Code + 1);
865 BlockStats.CodeFreq[
Code].NumInstances++;
866 BlockStats.CodeFreq[
Code].TotalBits +=
867 Stream.GetCurrentBitNo() - RecordStartBit;
869 BlockStats.CodeFreq[
Code].NumAbbrev++;
870 ++BlockStats.NumAbbreviatedRecords;
874 O->OS << Indent <<
" <";
875 std::optional<const char *> CodeName =
876 GetCodeName(Code, BlockID, BlockInfo, CurStreamType);
880 O->OS <<
"UnknownCode" <<
Code;
881 if (!
O->Symbolic && CodeName)
882 O->OS <<
" codeid=" <<
Code;
883 const BitCodeAbbrev *Abbv =
nullptr;
885 Expected<const BitCodeAbbrev *> MaybeAbbv = Stream.getAbbrev(
Entry.ID);
888 Abbv = MaybeAbbv.
get();
889 O->OS <<
" abbrevid=" <<
Entry.ID;
892 for (
unsigned i = 0, e = Record.
size(); i != e; ++i)
893 O->OS <<
" op" << i <<
"=" << (int64_t)Record[i];
899 if (Record.
size() != 2)
900 O->OS <<
"(Invalid record)";
902 auto Offset = Record[0] + (Record[1] << 32);
903 MetadataIndexOffset = Stream.GetCurrentBitNo() +
Offset;
907 O->OS <<
" (offset ";
908 if (MetadataIndexOffset == RecordStartBit)
911 O->OS <<
"mismatch: " << MetadataIndexOffset <<
" vs "
912 << RecordStartBit <<
")";
919 if (Record.
size() != 5)
920 O->OS <<
" (invalid)";
924 std::array<uint8_t, 20> Hash;
925 Hasher.
update(*CheckHash);
927 int BlockSize = (CurrentRecordPos / 8) - BlockEntryPos;
928 auto Ptr = Stream.getPointerToByte(BlockEntryPos,
BlockSize);
932 std::array<uint8_t, 20> RecordedHash;
934 for (
auto &Val : Record) {
935 assert(!(Val >> 32) &&
"Unexpected high bits set");
939 if (Hash == RecordedHash)
942 O->OS <<
" (!mismatch!)";
953 assert(i + 2 == e &&
"Array op not second to last");
955 bool ArrayIsPrintable =
true;
956 for (
unsigned j = i - 1, je = Record.size(); j != je; ++j) {
957 if (!
isPrint(
static_cast<unsigned char>(Record[j]))) {
958 ArrayIsPrintable =
false;
961 Str += (char)Record[j];
963 if (ArrayIsPrintable)
964 O->OS <<
" record string = '" << Str <<
"'";
971 if (
Error E = decodeMetadataStringsBlob(Indent, Record, Blob,
O->OS))
974 O->OS <<
" blob data = ";
975 if (
O->ShowBinaryBlobs) {
977 O->OS.write_escaped(Blob,
true) <<
"'";
979 bool BlobIsPrintable =
true;
981 if (!
isPrint(
static_cast<unsigned char>(
C))) {
982 BlobIsPrintable =
false;
987 O->OS <<
"'" << Blob <<
"'";
989 O->OS <<
"unprintable, " << Blob.size() <<
" bytes.";
998 if (
Error Err = Stream.JumpToBit(CurrentRecordPos))
1000 if (Expected<unsigned> Skipped = Stream.skipRecord(
Entry.ID))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define STRINGIFY_CODE(PREFIX, CODE)
static bool canDecodeBlob(unsigned Code, unsigned BlockID)
static std::optional< const char * > GetBlockName(unsigned BlockID, const BitstreamBlockInfo &BlockInfo, CurStreamTypeType CurStreamType)
Return a symbolic block name if known, otherwise return null.
static Expected< CurStreamTypeType > ReadSignature(BitstreamCursor &Stream)
static std::optional< const char * > GetCodeName(unsigned CodeID, unsigned BlockID, const BitstreamBlockInfo &BlockInfo, CurStreamTypeType CurStreamType)
Return a symbolic code name if known, otherwise return null.
static void printSize(raw_ostream &OS, double Bits)
static Expected< CurStreamTypeType > analyzeHeader(std::optional< BCDumpOptions > O, BitstreamCursor &Stream)
static Error reportError(StringRef Message)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
#define FUNCTION(NAME, NARG, ROUND_MODE, INTRINSIC)
#define KIND(ENUM, FIELD)
#define ENTRY(ASMNAME, ENUM)
block placement Basic Block Placement Stats
static const int BlockSize
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
unsigned getNumOperandInfos() const
const BitCodeAbbrevOp & getOperandInfo(unsigned N) const
LLVM_ABI BitcodeAnalyzer(StringRef Buffer, std::optional< StringRef > BlockInfoBuffer=std::nullopt)
LLVM_ABI Error analyze(std::optional< BCDumpOptions > O=std::nullopt, std::optional< StringRef > CheckHash=std::nullopt)
Analyze the bitcode file.
LLVM_ABI void printStats(BCDumpOptions O, std::optional< StringRef > Filename=std::nullopt)
Print stats about the bitcode file.
This class maintains the abbreviations read from a block info block.
This represents a position within a bitcode file, implemented on top of a SimpleBitstreamCursor.
Error JumpToBit(uint64_t BitNo)
Reset the stream to the specified bit number.
uint64_t GetCurrentBitNo() const
Return the bit # of the bit we are reading.
Expected< unsigned > ReadSubBlockID()
Having read the ENTER_SUBBLOCK code, read the BlockID for the block.
ArrayRef< uint8_t > getBitcodeBytes() const
Expected< word_t > Read(unsigned NumBits)
LLVM_ABI Error EnterSubBlock(unsigned BlockID, unsigned *NumWordsP=nullptr)
Having read the ENTER_SUBBLOCK abbrevid, and enter the block.
Error SkipBlock()
Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip over the body of this block.
uint64_t getCurrentByteNo() const
@ AF_DontAutoprocessAbbrevs
If this flag is used, abbrev entries are returned just like normal records.
Expected< unsigned > ReadCode()
LLVM_ABI Expected< std::optional< BitstreamBlockInfo > > ReadBlockInfoBlock(bool ReadBlockInfoNames=false)
Read and return a block info block from the bitstream.
unsigned getAbbrevIDWidth() const
Return the number of bits used to encode an abbrev #.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
reference get()
Returns a reference to the stored T value.
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Digest more data.
LLVM_ABI std::array< uint8_t, 20 > result()
Return the current raw 160-bits SHA1 for the digested data since the last call to init().
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
StringRef slice(size_t Start, size_t End) const
Return a reference to the substring from [Start, End).
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
This class implements an extremely fast bulk output stream that can only output to a stream.
raw_ostream & write_escaped(StringRef Str, bool UseHexEscapes=false)
Output Str, turning '\', '\t', ' ', '"', and anything that doesn't satisfy llvm::isPrint into an esca...
@ C
The default llvm calling convention, compatible with C.
@ BLOCKINFO_CODE_BLOCKNAME
@ BLOCKINFO_CODE_SETRECORDNAME
@ PARAMATTR_GROUP_BLOCK_ID
@ IDENTIFICATION_BLOCK_ID
@ GLOBALVAL_SUMMARY_BLOCK_ID
@ FULL_LTO_GLOBALVAL_SUMMARY_BLOCK_ID
@ OPERAND_BUNDLE_TAGS_BLOCK_ID
@ BLOCKINFO_BLOCK_ID
BLOCKINFO_BLOCK is used to define metadata about blocks, for example, standard abbrevs that should be...
@ FIRST_APPLICATION_BLOCKID
@ DEFINE_ABBREV
DEFINE_ABBREV - Defines an abbrev for the current block.
@ PARAMATTR_CODE_ENTRY_OLD
@ PARAMATTR_GRP_CODE_ENTRY
@ Skipped
Validation was skipped, as it was not needed.
NodeAddr< CodeNode * > Code
void write32be(void *P, uint32_t V)
uint32_t read32le(const void *P)
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false)
format_hex - Output N as a fixed width hexadecimal.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
CurStreamTypeType
CurStreamTypeType - A type for CurStreamType.
@ ClangSerializedDiagnosticsBitstream
@ ClangSerializedASTBitstream
DWARFExpression::Operation Op
bool SkipBitcodeWrapperHeader(const unsigned char *&BufPtr, const unsigned char *&BufEnd, bool VerifyBufferSize)
SkipBitcodeWrapperHeader - Some systems wrap bc files with a special header for padding or other reas...
bool isPrint(char C)
Checks whether character C is printable.
bool isBitcodeWrapper(const unsigned char *BufPtr, const unsigned char *BufEnd)
isBitcodeWrapper - Return true if the given bytes are the magic bytes for an LLVM IR bitcode wrapper.
This contains information emitted to BLOCKINFO_BLOCK blocks.