/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/include/llvm/CodeGen/FaultMaps.h
Line | Count | Source |
1 | | //===- FaultMaps.h - The "FaultMaps" section --------------------*- 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_CODEGEN_FAULTMAPS_H |
10 | | #define LLVM_CODEGEN_FAULTMAPS_H |
11 | | |
12 | | #include "llvm/MC/MCSymbol.h" |
13 | | #include "llvm/Support/Endian.h" |
14 | | #include <cassert> |
15 | | #include <cstddef> |
16 | | #include <cstdint> |
17 | | #include <map> |
18 | | #include <vector> |
19 | | |
20 | | namespace llvm { |
21 | | |
22 | | class AsmPrinter; |
23 | | class MCExpr; |
24 | | class raw_ostream; |
25 | | |
26 | | class FaultMaps { |
27 | | public: |
28 | | enum FaultKind { |
29 | | FaultingLoad = 1, |
30 | | FaultingLoadStore, |
31 | | FaultingStore, |
32 | | FaultKindMax |
33 | | }; |
34 | | |
35 | | explicit FaultMaps(AsmPrinter &AP); |
36 | | |
37 | | static const char *faultTypeToString(FaultKind); |
38 | | |
39 | | void recordFaultingOp(FaultKind FaultTy, const MCSymbol *HandlerLabel); |
40 | | void serializeToFaultMapSection(); |
41 | 12.1k | void reset() { |
42 | 12.1k | FunctionInfos.clear(); |
43 | 12.1k | } |
44 | | |
45 | | private: |
46 | | static const char *WFMP; |
47 | | |
48 | | struct FaultInfo { |
49 | | FaultKind Kind = FaultKindMax; |
50 | | const MCExpr *FaultingOffsetExpr = nullptr; |
51 | | const MCExpr *HandlerOffsetExpr = nullptr; |
52 | | |
53 | | FaultInfo() = default; |
54 | | |
55 | | explicit FaultInfo(FaultMaps::FaultKind Kind, const MCExpr *FaultingOffset, |
56 | | const MCExpr *HandlerOffset) |
57 | | : Kind(Kind), FaultingOffsetExpr(FaultingOffset), |
58 | 25 | HandlerOffsetExpr(HandlerOffset) {} |
59 | | }; |
60 | | |
61 | | using FunctionFaultInfos = std::vector<FaultInfo>; |
62 | | |
63 | | // We'd like to keep a stable iteration order for FunctionInfos to help |
64 | | // FileCheck based testing. |
65 | | struct MCSymbolComparator { |
66 | 77 | bool operator()(const MCSymbol *LHS, const MCSymbol *RHS) const { |
67 | 77 | return LHS->getName() < RHS->getName(); |
68 | 77 | } |
69 | | }; |
70 | | |
71 | | std::map<const MCSymbol *, FunctionFaultInfos, MCSymbolComparator> |
72 | | FunctionInfos; |
73 | | AsmPrinter &AP; |
74 | | |
75 | | void emitFunctionInfo(const MCSymbol *FnLabel, const FunctionFaultInfos &FFI); |
76 | | }; |
77 | | |
78 | | /// A parser for the __llvm_faultmaps section generated by the FaultMaps class |
79 | | /// above. This parser is version locked with with the __llvm_faultmaps section |
80 | | /// generated by the version of LLVM that includes it. No guarantees are made |
81 | | /// with respect to forward or backward compatibility. |
82 | | class FaultMapParser { |
83 | | using FaultMapVersionType = uint8_t; |
84 | | using Reserved0Type = uint8_t; |
85 | | using Reserved1Type = uint16_t; |
86 | | using NumFunctionsType = uint32_t; |
87 | | |
88 | | static const size_t FaultMapVersionOffset = 0; |
89 | | static const size_t Reserved0Offset = |
90 | | FaultMapVersionOffset + sizeof(FaultMapVersionType); |
91 | | static const size_t Reserved1Offset = Reserved0Offset + sizeof(Reserved0Type); |
92 | | static const size_t NumFunctionsOffset = |
93 | | Reserved1Offset + sizeof(Reserved1Type); |
94 | | static const size_t FunctionInfosOffset = |
95 | | NumFunctionsOffset + sizeof(NumFunctionsType); |
96 | | |
97 | | const uint8_t *P; |
98 | | const uint8_t *E; |
99 | | |
100 | 54 | template <typename T> static T read(const uint8_t *P, const uint8_t *E) { |
101 | 54 | assert(P + sizeof(T) <= E && "out of bounds read!"); |
102 | 54 | return support::endian::read<T, support::little, 1>(P); |
103 | 54 | } unsigned int llvm::FaultMapParser::read<unsigned int>(unsigned char const*, unsigned char const*) Line | Count | Source | 100 | 44 | template <typename T> static T read(const uint8_t *P, const uint8_t *E) { | 101 | 44 | assert(P + sizeof(T) <= E && "out of bounds read!"); | 102 | 44 | return support::endian::read<T, support::little, 1>(P); | 103 | 44 | } |
unsigned long long llvm::FaultMapParser::read<unsigned long long>(unsigned char const*, unsigned char const*) Line | Count | Source | 100 | 6 | template <typename T> static T read(const uint8_t *P, const uint8_t *E) { | 101 | 6 | assert(P + sizeof(T) <= E && "out of bounds read!"); | 102 | 6 | return support::endian::read<T, support::little, 1>(P); | 103 | 6 | } |
unsigned char llvm::FaultMapParser::read<unsigned char>(unsigned char const*, unsigned char const*) Line | Count | Source | 100 | 4 | template <typename T> static T read(const uint8_t *P, const uint8_t *E) { | 101 | 4 | assert(P + sizeof(T) <= E && "out of bounds read!"); | 102 | 4 | return support::endian::read<T, support::little, 1>(P); | 103 | 4 | } |
|
104 | | |
105 | | public: |
106 | | class FunctionFaultInfoAccessor { |
107 | | using FaultKindType = uint32_t; |
108 | | using FaultingPCOffsetType = uint32_t; |
109 | | using HandlerPCOffsetType = uint32_t; |
110 | | |
111 | | static const size_t FaultKindOffset = 0; |
112 | | static const size_t FaultingPCOffsetOffset = |
113 | | FaultKindOffset + sizeof(FaultKindType); |
114 | | static const size_t HandlerPCOffsetOffset = |
115 | | FaultingPCOffsetOffset + sizeof(FaultingPCOffsetType); |
116 | | |
117 | | const uint8_t *P; |
118 | | const uint8_t *E; |
119 | | |
120 | | public: |
121 | | static const size_t Size = |
122 | | HandlerPCOffsetOffset + sizeof(HandlerPCOffsetType); |
123 | | |
124 | | explicit FunctionFaultInfoAccessor(const uint8_t *P, const uint8_t *E) |
125 | 6 | : P(P), E(E) {} |
126 | | |
127 | 6 | FaultKindType getFaultKind() const { |
128 | 6 | return read<FaultKindType>(P + FaultKindOffset, E); |
129 | 6 | } |
130 | | |
131 | 6 | FaultingPCOffsetType getFaultingPCOffset() const { |
132 | 6 | return read<FaultingPCOffsetType>(P + FaultingPCOffsetOffset, E); |
133 | 6 | } |
134 | | |
135 | 6 | HandlerPCOffsetType getHandlerPCOffset() const { |
136 | 6 | return read<HandlerPCOffsetType>(P + HandlerPCOffsetOffset, E); |
137 | 6 | } |
138 | | }; |
139 | | |
140 | | class FunctionInfoAccessor { |
141 | | using FunctionAddrType = uint64_t; |
142 | | using NumFaultingPCsType = uint32_t; |
143 | | using ReservedType = uint32_t; |
144 | | |
145 | | static const size_t FunctionAddrOffset = 0; |
146 | | static const size_t NumFaultingPCsOffset = |
147 | | FunctionAddrOffset + sizeof(FunctionAddrType); |
148 | | static const size_t ReservedOffset = |
149 | | NumFaultingPCsOffset + sizeof(NumFaultingPCsType); |
150 | | static const size_t FunctionFaultInfosOffset = |
151 | | ReservedOffset + sizeof(ReservedType); |
152 | | static const size_t FunctionInfoHeaderSize = FunctionFaultInfosOffset; |
153 | | |
154 | | const uint8_t *P = nullptr; |
155 | | const uint8_t *E = nullptr; |
156 | | |
157 | | public: |
158 | 3 | FunctionInfoAccessor() = default; |
159 | | |
160 | | explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E) |
161 | 6 | : P(P), E(E) {} |
162 | | |
163 | 6 | FunctionAddrType getFunctionAddr() const { |
164 | 6 | return read<FunctionAddrType>(P + FunctionAddrOffset, E); |
165 | 6 | } |
166 | | |
167 | 15 | NumFaultingPCsType getNumFaultingPCs() const { |
168 | 15 | return read<NumFaultingPCsType>(P + NumFaultingPCsOffset, E); |
169 | 15 | } |
170 | | |
171 | 6 | FunctionFaultInfoAccessor getFunctionFaultInfoAt(uint32_t Index) const { |
172 | 6 | assert(Index < getNumFaultingPCs() && "index out of bounds!"); |
173 | 6 | const uint8_t *Begin = P + FunctionFaultInfosOffset + |
174 | 6 | FunctionFaultInfoAccessor::Size * Index; |
175 | 6 | return FunctionFaultInfoAccessor(Begin, E); |
176 | 6 | } |
177 | | |
178 | 3 | FunctionInfoAccessor getNextFunctionInfo() const { |
179 | 3 | size_t MySize = FunctionInfoHeaderSize + |
180 | 3 | getNumFaultingPCs() * FunctionFaultInfoAccessor::Size; |
181 | 3 | |
182 | 3 | const uint8_t *Begin = P + MySize; |
183 | 3 | assert(Begin < E && "out of bounds!"); |
184 | 3 | return FunctionInfoAccessor(Begin, E); |
185 | 3 | } |
186 | | }; |
187 | | |
188 | | explicit FaultMapParser(const uint8_t *Begin, const uint8_t *End) |
189 | | : P(Begin), E(End) {} |
190 | | |
191 | 4 | FaultMapVersionType getFaultMapVersion() const { |
192 | 4 | auto Version = read<FaultMapVersionType>(P + FaultMapVersionOffset, E); |
193 | 4 | assert(Version == 1 && "only version 1 supported!"); |
194 | 4 | return Version; |
195 | 4 | } |
196 | | |
197 | 11 | NumFunctionsType getNumFunctions() const { |
198 | 11 | return read<NumFunctionsType>(P + NumFunctionsOffset, E); |
199 | 11 | } |
200 | | |
201 | 3 | FunctionInfoAccessor getFirstFunctionInfo() const { |
202 | 3 | const uint8_t *Begin = P + FunctionInfosOffset; |
203 | 3 | return FunctionInfoAccessor(Begin, E); |
204 | 3 | } |
205 | | }; |
206 | | |
207 | | raw_ostream & |
208 | | operator<<(raw_ostream &OS, const FaultMapParser::FunctionFaultInfoAccessor &); |
209 | | |
210 | | raw_ostream &operator<<(raw_ostream &OS, |
211 | | const FaultMapParser::FunctionInfoAccessor &); |
212 | | |
213 | | raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &); |
214 | | |
215 | | } // end namespace llvm |
216 | | |
217 | | #endif // LLVM_CODEGEN_FAULTMAPS_H |