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 | , // 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 | |