1 //===- FormatUtil.h ------------------------------------------- *- C++ --*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_DEBUGINFO_PDB_NATIVE_FORMATUTIL_H 10 #define LLVM_DEBUGINFO_PDB_NATIVE_FORMATUTIL_H 11 12 #include "llvm/ADT/ArrayRef.h" 13 #include "llvm/ADT/STLForwardCompat.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/DebugInfo/CodeView/CodeView.h" 16 #include "llvm/Support/Endian.h" 17 #include "llvm/Support/FormatAdapters.h" 18 #include "llvm/Support/FormatVariadic.h" 19 20 #include <string> 21 #include <type_traits> 22 23 namespace llvm { 24 namespace pdb { 25 26 #define PUSH_MASKED_FLAG(Enum, Mask, TheOpt, Value, Text) \ 27 if (Enum::TheOpt == (Value & Mask)) \ 28 Opts.push_back(Text); 29 30 #define PUSH_FLAG(Enum, TheOpt, Value, Text) \ 31 PUSH_MASKED_FLAG(Enum, Enum::TheOpt, TheOpt, Value, Text) 32 33 #define RETURN_CASE(Enum, X, Ret) \ 34 case Enum::X: \ 35 return Ret; 36 37 template <typename T> std::string formatUnknownEnum(T Value) { 38 return formatv("unknown ({0})", llvm::to_underlying(Value)).str(); 39 } 40 41 std::string formatSegmentOffset(uint16_t Segment, uint32_t Offset); 42 43 enum class CharacteristicStyle { 44 HeaderDefinition, // format as windows header definition 45 Descriptive, // format as human readable words 46 }; 47 std::string formatSectionCharacteristics( 48 uint32_t IndentLevel, uint32_t C, uint32_t FlagsPerLine, 49 StringRef Separator, 50 CharacteristicStyle Style = CharacteristicStyle::HeaderDefinition); 51 52 std::string typesetItemList(ArrayRef<std::string> Opts, uint32_t IndentLevel, 53 uint32_t GroupSize, StringRef Sep); 54 55 std::string typesetStringList(uint32_t IndentLevel, 56 ArrayRef<StringRef> Strings); 57 58 std::string formatChunkKind(codeview::DebugSubsectionKind Kind, 59 bool Friendly = true); 60 std::string formatSymbolKind(codeview::SymbolKind K); 61 std::string formatTypeLeafKind(codeview::TypeLeafKind K); 62 63 /// Returns the number of digits in the given integer. 64 inline int NumDigits(uint64_t N) { 65 if (N < 10ULL) 66 return 1; 67 if (N < 100ULL) 68 return 2; 69 if (N < 1000ULL) 70 return 3; 71 if (N < 10000ULL) 72 return 4; 73 if (N < 100000ULL) 74 return 5; 75 if (N < 1000000ULL) 76 return 6; 77 if (N < 10000000ULL) 78 return 7; 79 if (N < 100000000ULL) 80 return 8; 81 if (N < 1000000000ULL) 82 return 9; 83 if (N < 10000000000ULL) 84 return 10; 85 if (N < 100000000000ULL) 86 return 11; 87 if (N < 1000000000000ULL) 88 return 12; 89 if (N < 10000000000000ULL) 90 return 13; 91 if (N < 100000000000000ULL) 92 return 14; 93 if (N < 1000000000000000ULL) 94 return 15; 95 if (N < 10000000000000000ULL) 96 return 16; 97 if (N < 100000000000000000ULL) 98 return 17; 99 if (N < 1000000000000000000ULL) 100 return 18; 101 if (N < 10000000000000000000ULL) 102 return 19; 103 return 20; 104 } 105 106 namespace detail { 107 template <typename T> 108 struct EndianAdapter final 109 : public FormatAdapter<support::detail::packed_endian_specific_integral< 110 T, llvm::endianness::little, support::unaligned>> { 111 using EndianType = support::detail::packed_endian_specific_integral< 112 T, llvm::endianness::little, support::unaligned>; 113 114 explicit EndianAdapter(EndianType &&Item) 115 : FormatAdapter<EndianType>(std::move(Item)) {} 116 117 void format(llvm::raw_ostream &Stream, StringRef Style) override { 118 format_provider<T>::format(static_cast<T>(this->Item), Stream, Style); 119 } 120 }; 121 } // namespace detail 122 123 template <typename T> 124 detail::EndianAdapter<T> fmtle(support::detail::packed_endian_specific_integral< 125 T, llvm::endianness::little, support::unaligned> 126 Value) { 127 return detail::EndianAdapter<T>(std::move(Value)); 128 } 129 } // namespace pdb 130 } // namespace llvm 131 #endif 132