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"
11 #include "llvm/ADT/Twine.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"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/Format.h"
20 #include "llvm/Support/raw_ostream.h"
24 #define DEBUG_TYPE "faultmaps"
26 static const int FaultMapVersion
= 1;
27 const char *FaultMaps::WFMP
= "Fault Maps: ";
29 FaultMaps::FaultMaps(AsmPrinter
&AP
) : AP(AP
) {}
31 void FaultMaps::recordFaultingOp(FaultKind FaultTy
,
32 const MCSymbol
*HandlerLabel
) {
33 MCContext
&OutContext
= AP
.OutStreamer
->getContext();
34 MCSymbol
*FaultingLabel
= OutContext
.createTempSymbol();
36 AP
.OutStreamer
->EmitLabel(FaultingLabel
);
38 const MCExpr
*FaultingOffset
= MCBinaryExpr::createSub(
39 MCSymbolRefExpr::create(FaultingLabel
, OutContext
),
40 MCSymbolRefExpr::create(AP
.CurrentFnSymForSize
, OutContext
), OutContext
);
42 const MCExpr
*HandlerOffset
= MCBinaryExpr::createSub(
43 MCSymbolRefExpr::create(HandlerLabel
, OutContext
),
44 MCSymbolRefExpr::create(AP
.CurrentFnSymForSize
, OutContext
), OutContext
);
46 FunctionInfos
[AP
.CurrentFnSym
].emplace_back(FaultTy
, FaultingOffset
,
50 void FaultMaps::serializeToFaultMapSection() {
51 if (FunctionInfos
.empty())
54 MCContext
&OutContext
= AP
.OutStreamer
->getContext();
55 MCStreamer
&OS
= *AP
.OutStreamer
;
57 // Create the section.
58 MCSection
*FaultMapSection
=
59 OutContext
.getObjectFileInfo()->getFaultMapSection();
60 OS
.SwitchSection(FaultMapSection
);
62 // Emit a dummy symbol to force section inclusion.
63 OS
.EmitLabel(OutContext
.getOrCreateSymbol(Twine("__LLVM_FaultMaps")));
65 LLVM_DEBUG(dbgs() << "********** Fault Map Output **********\n");
68 OS
.EmitIntValue(FaultMapVersion
, 1); // Version.
69 OS
.EmitIntValue(0, 1); // Reserved.
70 OS
.EmitIntValue(0, 2); // Reserved.
72 LLVM_DEBUG(dbgs() << WFMP
<< "#functions = " << FunctionInfos
.size() << "\n");
73 OS
.EmitIntValue(FunctionInfos
.size(), 4);
75 LLVM_DEBUG(dbgs() << WFMP
<< "functions:\n");
77 for (const auto &FFI
: FunctionInfos
)
78 emitFunctionInfo(FFI
.first
, FFI
.second
);
81 void FaultMaps::emitFunctionInfo(const MCSymbol
*FnLabel
,
82 const FunctionFaultInfos
&FFI
) {
83 MCStreamer
&OS
= *AP
.OutStreamer
;
85 LLVM_DEBUG(dbgs() << WFMP
<< " function addr: " << *FnLabel
<< "\n");
86 OS
.EmitSymbolValue(FnLabel
, 8);
88 LLVM_DEBUG(dbgs() << WFMP
<< " #faulting PCs: " << FFI
.size() << "\n");
89 OS
.EmitIntValue(FFI
.size(), 4);
91 OS
.EmitIntValue(0, 4); // Reserved
93 for (auto &Fault
: FFI
) {
94 LLVM_DEBUG(dbgs() << WFMP
<< " fault type: "
95 << faultTypeToString(Fault
.Kind
) << "\n");
96 OS
.EmitIntValue(Fault
.Kind
, 4);
98 LLVM_DEBUG(dbgs() << WFMP
<< " faulting PC offset: "
99 << *Fault
.FaultingOffsetExpr
<< "\n");
100 OS
.EmitValue(Fault
.FaultingOffsetExpr
, 4);
102 LLVM_DEBUG(dbgs() << WFMP
<< " fault handler PC offset: "
103 << *Fault
.HandlerOffsetExpr
<< "\n");
104 OS
.EmitValue(Fault
.HandlerOffsetExpr
, 4);
108 const char *FaultMaps::faultTypeToString(FaultMaps::FaultKind FT
) {
111 llvm_unreachable("unhandled fault type!");
112 case FaultMaps::FaultingLoad
:
113 return "FaultingLoad";
114 case FaultMaps::FaultingLoadStore
:
115 return "FaultingLoadStore";
116 case FaultMaps::FaultingStore
:
117 return "FaultingStore";
122 operator<<(raw_ostream
&OS
,
123 const FaultMapParser::FunctionFaultInfoAccessor
&FFI
) {
125 << FaultMaps::faultTypeToString((FaultMaps::FaultKind
)FFI
.getFaultKind())
126 << ", faulting PC offset: " << FFI
.getFaultingPCOffset()
127 << ", handling PC offset: " << FFI
.getHandlerPCOffset();
132 operator<<(raw_ostream
&OS
, const FaultMapParser::FunctionInfoAccessor
&FI
) {
133 OS
<< "FunctionAddress: " << format_hex(FI
.getFunctionAddr(), 8)
134 << ", NumFaultingPCs: " << FI
.getNumFaultingPCs() << "\n";
135 for (unsigned i
= 0, e
= FI
.getNumFaultingPCs(); i
!= e
; ++i
)
136 OS
<< FI
.getFunctionFaultInfoAt(i
) << "\n";
140 raw_ostream
&llvm::operator<<(raw_ostream
&OS
, const FaultMapParser
&FMP
) {
141 OS
<< "Version: " << format_hex(FMP
.getFaultMapVersion(), 2) << "\n";
142 OS
<< "NumFunctions: " << FMP
.getNumFunctions() << "\n";
144 if (FMP
.getNumFunctions() == 0)
147 FaultMapParser::FunctionInfoAccessor FI
;
149 for (unsigned i
= 0, e
= FMP
.getNumFunctions(); i
!= e
; ++i
) {
150 FI
= (i
== 0) ? FMP
.getFirstFunctionInfo() : FI
.getNextFunctionInfo();