1 //===- FaultMaps.cpp ------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/CodeGen/FaultMaps.h"
10 #include "llvm/ADT/Twine.h"
11 #include "llvm/CodeGen/AsmPrinter.h"
12 #include "llvm/MC/MCContext.h"
13 #include "llvm/MC/MCExpr.h"
14 #include "llvm/MC/MCObjectFileInfo.h"
15 #include "llvm/MC/MCStreamer.h"
16 #include "llvm/Support/Debug.h"
17 #include "llvm/Support/ErrorHandling.h"
21 #define DEBUG_TYPE "faultmaps"
23 static const int FaultMapVersion
= 1;
24 const char *FaultMaps::WFMP
= "Fault Maps: ";
26 FaultMaps::FaultMaps(AsmPrinter
&AP
) : AP(AP
) {}
28 void FaultMaps::recordFaultingOp(FaultKind FaultTy
,
29 const MCSymbol
*FaultingLabel
,
30 const MCSymbol
*HandlerLabel
) {
31 MCContext
&OutContext
= AP
.OutStreamer
->getContext();
33 const MCExpr
*FaultingOffset
= MCBinaryExpr::createSub(
34 MCSymbolRefExpr::create(FaultingLabel
, OutContext
),
35 MCSymbolRefExpr::create(AP
.CurrentFnSymForSize
, OutContext
), OutContext
);
37 const MCExpr
*HandlerOffset
= MCBinaryExpr::createSub(
38 MCSymbolRefExpr::create(HandlerLabel
, OutContext
),
39 MCSymbolRefExpr::create(AP
.CurrentFnSymForSize
, OutContext
), OutContext
);
41 FunctionInfos
[AP
.CurrentFnSym
].emplace_back(FaultTy
, FaultingOffset
,
45 void FaultMaps::serializeToFaultMapSection() {
46 if (FunctionInfos
.empty())
49 MCContext
&OutContext
= AP
.OutStreamer
->getContext();
50 MCStreamer
&OS
= *AP
.OutStreamer
;
52 // Create the section.
53 MCSection
*FaultMapSection
=
54 OutContext
.getObjectFileInfo()->getFaultMapSection();
55 OS
.switchSection(FaultMapSection
);
57 // Emit a dummy symbol to force section inclusion.
58 OS
.emitLabel(OutContext
.getOrCreateSymbol(Twine("__LLVM_FaultMaps")));
60 LLVM_DEBUG(dbgs() << "********** Fault Map Output **********\n");
63 OS
.emitIntValue(FaultMapVersion
, 1); // Version.
64 OS
.emitIntValue(0, 1); // Reserved.
65 OS
.emitInt16(0); // Reserved.
67 LLVM_DEBUG(dbgs() << WFMP
<< "#functions = " << FunctionInfos
.size() << "\n");
68 OS
.emitInt32(FunctionInfos
.size());
70 LLVM_DEBUG(dbgs() << WFMP
<< "functions:\n");
72 for (const auto &FFI
: FunctionInfos
)
73 emitFunctionInfo(FFI
.first
, FFI
.second
);
76 void FaultMaps::emitFunctionInfo(const MCSymbol
*FnLabel
,
77 const FunctionFaultInfos
&FFI
) {
78 MCStreamer
&OS
= *AP
.OutStreamer
;
80 LLVM_DEBUG(dbgs() << WFMP
<< " function addr: " << *FnLabel
<< "\n");
81 OS
.emitSymbolValue(FnLabel
, 8);
83 LLVM_DEBUG(dbgs() << WFMP
<< " #faulting PCs: " << FFI
.size() << "\n");
84 OS
.emitInt32(FFI
.size());
86 OS
.emitInt32(0); // Reserved
88 for (const auto &Fault
: FFI
) {
89 LLVM_DEBUG(dbgs() << WFMP
<< " fault type: "
90 << faultTypeToString(Fault
.Kind
) << "\n");
91 OS
.emitInt32(Fault
.Kind
);
93 LLVM_DEBUG(dbgs() << WFMP
<< " faulting PC offset: "
94 << *Fault
.FaultingOffsetExpr
<< "\n");
95 OS
.emitValue(Fault
.FaultingOffsetExpr
, 4);
97 LLVM_DEBUG(dbgs() << WFMP
<< " fault handler PC offset: "
98 << *Fault
.HandlerOffsetExpr
<< "\n");
99 OS
.emitValue(Fault
.HandlerOffsetExpr
, 4);
103 const char *FaultMaps::faultTypeToString(FaultMaps::FaultKind FT
) {
106 llvm_unreachable("unhandled fault type!");
107 case FaultMaps::FaultingLoad
:
108 return "FaultingLoad";
109 case FaultMaps::FaultingLoadStore
:
110 return "FaultingLoadStore";
111 case FaultMaps::FaultingStore
:
112 return "FaultingStore";