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