blob: a1e2349c413ecc1cce2f306e07363e2665f364a0 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- FaultMaps.h - The "FaultMaps" section --------------------*- C++ -*-===//
2//
Andrew Walbran16937d02019-10-22 13:54:20 +01003// 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
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01006//
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
20namespace llvm {
21
22class AsmPrinter;
23class MCExpr;
24class raw_ostream;
25
26class FaultMaps {
27public:
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 void reset() {
42 FunctionInfos.clear();
43 }
44
45private:
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 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 bool operator()(const MCSymbol *LHS, const MCSymbol *RHS) const {
67 return LHS->getName() < RHS->getName();
68 }
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.
82class 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 template <typename T> static T read(const uint8_t *P, const uint8_t *E) {
101 assert(P + sizeof(T) <= E && "out of bounds read!");
102 return support::endian::read<T, support::little, 1>(P);
103 }
104
105public:
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 : P(P), E(E) {}
126
127 FaultKindType getFaultKind() const {
128 return read<FaultKindType>(P + FaultKindOffset, E);
129 }
130
131 FaultingPCOffsetType getFaultingPCOffset() const {
132 return read<FaultingPCOffsetType>(P + FaultingPCOffsetOffset, E);
133 }
134
135 HandlerPCOffsetType getHandlerPCOffset() const {
136 return read<HandlerPCOffsetType>(P + HandlerPCOffsetOffset, E);
137 }
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 FunctionInfoAccessor() = default;
159
160 explicit FunctionInfoAccessor(const uint8_t *P, const uint8_t *E)
161 : P(P), E(E) {}
162
163 FunctionAddrType getFunctionAddr() const {
164 return read<FunctionAddrType>(P + FunctionAddrOffset, E);
165 }
166
167 NumFaultingPCsType getNumFaultingPCs() const {
168 return read<NumFaultingPCsType>(P + NumFaultingPCsOffset, E);
169 }
170
171 FunctionFaultInfoAccessor getFunctionFaultInfoAt(uint32_t Index) const {
172 assert(Index < getNumFaultingPCs() && "index out of bounds!");
173 const uint8_t *Begin = P + FunctionFaultInfosOffset +
174 FunctionFaultInfoAccessor::Size * Index;
175 return FunctionFaultInfoAccessor(Begin, E);
176 }
177
178 FunctionInfoAccessor getNextFunctionInfo() const {
179 size_t MySize = FunctionInfoHeaderSize +
180 getNumFaultingPCs() * FunctionFaultInfoAccessor::Size;
181
182 const uint8_t *Begin = P + MySize;
183 assert(Begin < E && "out of bounds!");
184 return FunctionInfoAccessor(Begin, E);
185 }
186 };
187
188 explicit FaultMapParser(const uint8_t *Begin, const uint8_t *End)
189 : P(Begin), E(End) {}
190
191 FaultMapVersionType getFaultMapVersion() const {
192 auto Version = read<FaultMapVersionType>(P + FaultMapVersionOffset, E);
193 assert(Version == 1 && "only version 1 supported!");
194 return Version;
195 }
196
197 NumFunctionsType getNumFunctions() const {
198 return read<NumFunctionsType>(P + NumFunctionsOffset, E);
199 }
200
201 FunctionInfoAccessor getFirstFunctionInfo() const {
202 const uint8_t *Begin = P + FunctionInfosOffset;
203 return FunctionInfoAccessor(Begin, E);
204 }
205};
206
207raw_ostream &
208operator<<(raw_ostream &OS, const FaultMapParser::FunctionFaultInfoAccessor &);
209
210raw_ostream &operator<<(raw_ostream &OS,
211 const FaultMapParser::FunctionInfoAccessor &);
212
213raw_ostream &operator<<(raw_ostream &OS, const FaultMapParser &);
214
215} // end namespace llvm
216
217#endif // LLVM_CODEGEN_FAULTMAPS_H