1c63244daSSanjoy Das //===---------------------------- FaultMaps.cpp ---------------------------===//
2c63244daSSanjoy Das //
3c63244daSSanjoy Das //                     The LLVM Compiler Infrastructure
4c63244daSSanjoy Das //
5c63244daSSanjoy Das // This file is distributed under the University of Illinois Open Source
6c63244daSSanjoy Das // License. See LICENSE.TXT for details.
7c63244daSSanjoy Das //
8c63244daSSanjoy Das //===----------------------------------------------------------------------===//
9c63244daSSanjoy Das 
10c63244daSSanjoy Das #include "llvm/CodeGen/FaultMaps.h"
11c63244daSSanjoy Das 
12c63244daSSanjoy Das #include "llvm/CodeGen/AsmPrinter.h"
13c63244daSSanjoy Das #include "llvm/MC/MCContext.h"
14c63244daSSanjoy Das #include "llvm/MC/MCExpr.h"
15c63244daSSanjoy Das #include "llvm/MC/MCObjectFileInfo.h"
16c63244daSSanjoy Das #include "llvm/MC/MCStreamer.h"
17c63244daSSanjoy Das #include "llvm/Support/Debug.h"
18c63244daSSanjoy Das 
19c63244daSSanjoy Das using namespace llvm;
20c63244daSSanjoy Das 
21c63244daSSanjoy Das #define DEBUG_TYPE "faultmaps"
22c63244daSSanjoy Das 
23c63244daSSanjoy Das static const int FaultMapVersion = 1;
24c63244daSSanjoy Das const char *FaultMaps::WFMP = "Fault Maps: ";
25c63244daSSanjoy Das 
26c63244daSSanjoy Das FaultMaps::FaultMaps(AsmPrinter &AP) : AP(AP) {}
27c63244daSSanjoy Das 
28baeb678aSSanjoy Das void FaultMaps::recordFaultingOp(FaultKind FaultTy,
29c63244daSSanjoy Das                                  const MCSymbol *HandlerLabel) {
30c63244daSSanjoy Das   MCContext &OutContext = AP.OutStreamer->getContext();
31c63244daSSanjoy Das   MCSymbol *FaultingLabel = OutContext.createTempSymbol();
32c63244daSSanjoy Das 
33c63244daSSanjoy Das   AP.OutStreamer->EmitLabel(FaultingLabel);
34c63244daSSanjoy Das 
35c63244daSSanjoy Das   const MCExpr *FaultingOffset = MCBinaryExpr::createSub(
36c63244daSSanjoy Das       MCSymbolRefExpr::create(FaultingLabel, OutContext),
37c63244daSSanjoy Das       MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);
38c63244daSSanjoy Das 
39c63244daSSanjoy Das   const MCExpr *HandlerOffset = MCBinaryExpr::createSub(
40c63244daSSanjoy Das       MCSymbolRefExpr::create(HandlerLabel, OutContext),
41c63244daSSanjoy Das       MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);
42c63244daSSanjoy Das 
43c63244daSSanjoy Das   FunctionInfos[AP.CurrentFnSym].emplace_back(FaultTy, FaultingOffset,
44c63244daSSanjoy Das                                               HandlerOffset);
45c63244daSSanjoy Das }
46c63244daSSanjoy Das 
47c63244daSSanjoy Das void FaultMaps::serializeToFaultMapSection() {
48c63244daSSanjoy Das   if (FunctionInfos.empty())
49c63244daSSanjoy Das     return;
50c63244daSSanjoy Das 
51c63244daSSanjoy Das   MCContext &OutContext = AP.OutStreamer->getContext();
52c63244daSSanjoy Das   MCStreamer &OS = *AP.OutStreamer;
53c63244daSSanjoy Das 
54c63244daSSanjoy Das   // Create the section.
55c63244daSSanjoy Das   MCSection *FaultMapSection =
56c63244daSSanjoy Das       OutContext.getObjectFileInfo()->getFaultMapSection();
57c63244daSSanjoy Das   OS.SwitchSection(FaultMapSection);
58c63244daSSanjoy Das 
59c63244daSSanjoy Das   // Emit a dummy symbol to force section inclusion.
60c63244daSSanjoy Das   OS.EmitLabel(OutContext.getOrCreateSymbol(Twine("__LLVM_FaultMaps")));
61c63244daSSanjoy Das 
62c63244daSSanjoy Das   DEBUG(dbgs() << "********** Fault Map Output **********\n");
63c63244daSSanjoy Das 
64c63244daSSanjoy Das   // Header
65c63244daSSanjoy Das   OS.EmitIntValue(FaultMapVersion, 1); // Version.
66c63244daSSanjoy Das   OS.EmitIntValue(0, 1);               // Reserved.
67c63244daSSanjoy Das   OS.EmitIntValue(0, 2);               // Reserved.
68c63244daSSanjoy Das 
69c63244daSSanjoy Das   DEBUG(dbgs() << WFMP << "#functions = " << FunctionInfos.size() << "\n");
70c63244daSSanjoy Das   OS.EmitIntValue(FunctionInfos.size(), 4);
71c63244daSSanjoy Das 
72c63244daSSanjoy Das   DEBUG(dbgs() << WFMP << "functions:\n");
73c63244daSSanjoy Das 
74c63244daSSanjoy Das   for (const auto &FFI : FunctionInfos)
75c63244daSSanjoy Das     emitFunctionInfo(FFI.first, FFI.second);
76c63244daSSanjoy Das }
77c63244daSSanjoy Das 
78c63244daSSanjoy Das void FaultMaps::emitFunctionInfo(const MCSymbol *FnLabel,
79c63244daSSanjoy Das                                  const FunctionFaultInfos &FFI) {
80c63244daSSanjoy Das   MCStreamer &OS = *AP.OutStreamer;
81c63244daSSanjoy Das 
82c63244daSSanjoy Das   DEBUG(dbgs() << WFMP << "  function addr: " << *FnLabel << "\n");
83c63244daSSanjoy Das   OS.EmitSymbolValue(FnLabel, 8);
84c63244daSSanjoy Das 
85c63244daSSanjoy Das   DEBUG(dbgs() << WFMP << "  #faulting PCs: " << FFI.size() << "\n");
86c63244daSSanjoy Das   OS.EmitIntValue(FFI.size(), 4);
87c63244daSSanjoy Das 
88c63244daSSanjoy Das   OS.EmitIntValue(0, 4); // Reserved
89c63244daSSanjoy Das 
90c63244daSSanjoy Das   for (auto &Fault : FFI) {
91c63244daSSanjoy Das     DEBUG(dbgs() << WFMP << "    fault type: "
92baeb678aSSanjoy Das           << faultTypeToString(Fault.Kind) << "\n");
93baeb678aSSanjoy Das     OS.EmitIntValue(Fault.Kind, 4);
94c63244daSSanjoy Das 
95c63244daSSanjoy Das     DEBUG(dbgs() << WFMP << "    faulting PC offset: "
96c63244daSSanjoy Das           << *Fault.FaultingOffsetExpr << "\n");
97c63244daSSanjoy Das     OS.EmitValue(Fault.FaultingOffsetExpr, 4);
98c63244daSSanjoy Das 
99c63244daSSanjoy Das     DEBUG(dbgs() << WFMP << "    fault handler PC offset: "
100c63244daSSanjoy Das           << *Fault.HandlerOffsetExpr << "\n");
101c63244daSSanjoy Das     OS.EmitValue(Fault.HandlerOffsetExpr, 4);
102c63244daSSanjoy Das   }
103c63244daSSanjoy Das }
104c63244daSSanjoy Das 
105c63244daSSanjoy Das 
106baeb678aSSanjoy Das const char *FaultMaps::faultTypeToString(FaultMaps::FaultKind FT) {
107c63244daSSanjoy Das   switch (FT) {
108c63244daSSanjoy Das   default:
109c63244daSSanjoy Das     llvm_unreachable("unhandled fault type!");
110c63244daSSanjoy Das 
111c63244daSSanjoy Das   case FaultMaps::FaultingLoad:
112c63244daSSanjoy Das     return "FaultingLoad";
113*2f63cbccSSanjoy Das   case FaultMaps::FaultingLoadStore:
114*2f63cbccSSanjoy Das     return "FaultingLoadStore";
115*2f63cbccSSanjoy Das   case FaultMaps::FaultingStore:
116*2f63cbccSSanjoy Das     return "FaultingStore";
117c63244daSSanjoy Das   }
118c63244daSSanjoy Das }
1193f1bc3b2SSanjoy Das 
1203f1bc3b2SSanjoy Das raw_ostream &llvm::
1213f1bc3b2SSanjoy Das operator<<(raw_ostream &OS,
1223f1bc3b2SSanjoy Das            const FaultMapParser::FunctionFaultInfoAccessor &FFI) {
1233f1bc3b2SSanjoy Das   OS << "Fault kind: "
1243f1bc3b2SSanjoy Das      << FaultMaps::faultTypeToString((FaultMaps::FaultKind)FFI.getFaultKind())
1253f1bc3b2SSanjoy Das      << ", faulting PC offset: " << FFI.getFaultingPCOffset()
1263f1bc3b2SSanjoy Das      << ", handling PC offset: " << FFI.getHandlerPCOffset();
1273f1bc3b2SSanjoy Das   return OS;
1283f1bc3b2SSanjoy Das }
1293f1bc3b2SSanjoy Das 
1303f1bc3b2SSanjoy Das raw_ostream &llvm::
1313f1bc3b2SSanjoy Das operator<<(raw_ostream &OS, const FaultMapParser::FunctionInfoAccessor &FI) {
1323f1bc3b2SSanjoy Das   OS << "FunctionAddress: " << format_hex(FI.getFunctionAddr(), 8)
1333f1bc3b2SSanjoy Das      << ", NumFaultingPCs: " << FI.getNumFaultingPCs() << "\n";
1343f1bc3b2SSanjoy Das   for (unsigned i = 0, e = FI.getNumFaultingPCs(); i != e; ++i)
1353f1bc3b2SSanjoy Das     OS << FI.getFunctionFaultInfoAt(i) << "\n";
1363f1bc3b2SSanjoy Das   return OS;
1373f1bc3b2SSanjoy Das }
1383f1bc3b2SSanjoy Das 
1393f1bc3b2SSanjoy Das raw_ostream &llvm::operator<<(raw_ostream &OS, const FaultMapParser &FMP) {
1403f1bc3b2SSanjoy Das   OS << "Version: " << format_hex(FMP.getFaultMapVersion(), 2) << "\n";
1413f1bc3b2SSanjoy Das   OS << "NumFunctions: " << FMP.getNumFunctions() << "\n";
1423f1bc3b2SSanjoy Das 
1433f1bc3b2SSanjoy Das   if (FMP.getNumFunctions() == 0)
1443f1bc3b2SSanjoy Das     return OS;
1453f1bc3b2SSanjoy Das 
1463f1bc3b2SSanjoy Das   FaultMapParser::FunctionInfoAccessor FI;
1473f1bc3b2SSanjoy Das 
1483f1bc3b2SSanjoy Das   for (unsigned i = 0, e = FMP.getNumFunctions(); i != e; ++i) {
1493f1bc3b2SSanjoy Das     FI = (i == 0) ? FMP.getFirstFunctionInfo() : FI.getNextFunctionInfo();
1503f1bc3b2SSanjoy Das     OS << FI;
1513f1bc3b2SSanjoy Das   }
1523f1bc3b2SSanjoy Das 
1533f1bc3b2SSanjoy Das   return OS;
1543f1bc3b2SSanjoy Das }
155