1 //===---------------------------- FaultMaps.cpp ---------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/CodeGen/FaultMaps.h"
12 #include "llvm/CodeGen/AsmPrinter.h"
13 #include "llvm/MC/MCContext.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCObjectFileInfo.h"
16 #include "llvm/MC/MCStreamer.h"
17 #include "llvm/Support/Debug.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
*HandlerLabel
) {
30 MCContext
&OutContext
= AP
.OutStreamer
->getContext();
31 MCSymbol
*FaultingLabel
= OutContext
.createTempSymbol();
33 AP
.OutStreamer
->EmitLabel(FaultingLabel
);
35 const MCExpr
*FaultingOffset
= MCBinaryExpr::createSub(
36 MCSymbolRefExpr::create(FaultingLabel
, OutContext
),
37 MCSymbolRefExpr::create(AP
.CurrentFnSymForSize
, OutContext
), OutContext
);
39 const MCExpr
*HandlerOffset
= MCBinaryExpr::createSub(
40 MCSymbolRefExpr::create(HandlerLabel
, OutContext
),
41 MCSymbolRefExpr::create(AP
.CurrentFnSymForSize
, OutContext
), OutContext
);
43 FunctionInfos
[AP
.CurrentFnSym
].emplace_back(FaultTy
, FaultingOffset
,
47 void FaultMaps::serializeToFaultMapSection() {
48 if (FunctionInfos
.empty())
51 MCContext
&OutContext
= AP
.OutStreamer
->getContext();
52 MCStreamer
&OS
= *AP
.OutStreamer
;
54 // Create the section.
55 MCSection
*FaultMapSection
=
56 OutContext
.getObjectFileInfo()->getFaultMapSection();
57 OS
.SwitchSection(FaultMapSection
);
59 // Emit a dummy symbol to force section inclusion.
60 OS
.EmitLabel(OutContext
.getOrCreateSymbol(Twine("__LLVM_FaultMaps")));
62 DEBUG(dbgs() << "********** Fault Map Output **********\n");
65 OS
.EmitIntValue(FaultMapVersion
, 1); // Version.
66 OS
.EmitIntValue(0, 1); // Reserved.
67 OS
.EmitIntValue(0, 2); // Reserved.
69 DEBUG(dbgs() << WFMP
<< "#functions = " << FunctionInfos
.size() << "\n");
70 OS
.EmitIntValue(FunctionInfos
.size(), 4);
72 DEBUG(dbgs() << WFMP
<< "functions:\n");
74 for (const auto &FFI
: FunctionInfos
)
75 emitFunctionInfo(FFI
.first
, FFI
.second
);
78 void FaultMaps::emitFunctionInfo(const MCSymbol
*FnLabel
,
79 const FunctionFaultInfos
&FFI
) {
80 MCStreamer
&OS
= *AP
.OutStreamer
;
82 DEBUG(dbgs() << WFMP
<< " function addr: " << *FnLabel
<< "\n");
83 OS
.EmitSymbolValue(FnLabel
, 8);
85 DEBUG(dbgs() << WFMP
<< " #faulting PCs: " << FFI
.size() << "\n");
86 OS
.EmitIntValue(FFI
.size(), 4);
88 OS
.EmitIntValue(0, 4); // Reserved
90 for (auto &Fault
: FFI
) {
91 DEBUG(dbgs() << WFMP
<< " fault type: "
92 << faultTypeToString(Fault
.Kind
) << "\n");
93 OS
.EmitIntValue(Fault
.Kind
, 4);
95 DEBUG(dbgs() << WFMP
<< " faulting PC offset: "
96 << *Fault
.FaultingOffsetExpr
<< "\n");
97 OS
.EmitValue(Fault
.FaultingOffsetExpr
, 4);
99 DEBUG(dbgs() << WFMP
<< " fault handler PC offset: "
100 << *Fault
.HandlerOffsetExpr
<< "\n");
101 OS
.EmitValue(Fault
.HandlerOffsetExpr
, 4);
106 const char *FaultMaps::faultTypeToString(FaultMaps::FaultKind FT
) {
109 llvm_unreachable("unhandled fault type!");
111 case FaultMaps::FaultingLoad
:
112 return "FaultingLoad";
117 operator<<(raw_ostream
&OS
,
118 const FaultMapParser::FunctionFaultInfoAccessor
&FFI
) {
120 << FaultMaps::faultTypeToString((FaultMaps::FaultKind
)FFI
.getFaultKind())
121 << ", faulting PC offset: " << FFI
.getFaultingPCOffset()
122 << ", handling PC offset: " << FFI
.getHandlerPCOffset();
127 operator<<(raw_ostream
&OS
, const FaultMapParser::FunctionInfoAccessor
&FI
) {
128 OS
<< "FunctionAddress: " << format_hex(FI
.getFunctionAddr(), 8)
129 << ", NumFaultingPCs: " << FI
.getNumFaultingPCs() << "\n";
130 for (unsigned i
= 0, e
= FI
.getNumFaultingPCs(); i
!= e
; ++i
)
131 OS
<< FI
.getFunctionFaultInfoAt(i
) << "\n";
135 raw_ostream
&llvm::operator<<(raw_ostream
&OS
, const FaultMapParser
&FMP
) {
136 OS
<< "Version: " << format_hex(FMP
.getFaultMapVersion(), 2) << "\n";
137 OS
<< "NumFunctions: " << FMP
.getNumFunctions() << "\n";
139 if (FMP
.getNumFunctions() == 0)
142 FaultMapParser::FunctionInfoAccessor FI
;
144 for (unsigned i
= 0, e
= FMP
.getNumFunctions(); i
!= e
; ++i
) {
145 FI
= (i
== 0) ? FMP
.getFirstFunctionInfo() : FI
.getNextFunctionInfo();