17a7e6055SDimitry Andric //===- FaultMaps.cpp ------------------------------------------------------===//
28f0fd8f6SDimitry Andric //
38f0fd8f6SDimitry Andric // The LLVM Compiler Infrastructure
48f0fd8f6SDimitry Andric //
58f0fd8f6SDimitry Andric // This file is distributed under the University of Illinois Open Source
68f0fd8f6SDimitry Andric // License. See LICENSE.TXT for details.
78f0fd8f6SDimitry Andric //
88f0fd8f6SDimitry Andric //===----------------------------------------------------------------------===//
98f0fd8f6SDimitry Andric
10db17bf38SDimitry Andric #include "llvm/CodeGen/FaultMaps.h"
117a7e6055SDimitry Andric #include "llvm/ADT/Twine.h"
128f0fd8f6SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h"
138f0fd8f6SDimitry Andric #include "llvm/MC/MCContext.h"
148f0fd8f6SDimitry Andric #include "llvm/MC/MCExpr.h"
158f0fd8f6SDimitry Andric #include "llvm/MC/MCObjectFileInfo.h"
168f0fd8f6SDimitry Andric #include "llvm/MC/MCStreamer.h"
178f0fd8f6SDimitry Andric #include "llvm/Support/Debug.h"
187a7e6055SDimitry Andric #include "llvm/Support/ErrorHandling.h"
197a7e6055SDimitry Andric #include "llvm/Support/Format.h"
207a7e6055SDimitry Andric #include "llvm/Support/raw_ostream.h"
218f0fd8f6SDimitry Andric
228f0fd8f6SDimitry Andric using namespace llvm;
238f0fd8f6SDimitry Andric
248f0fd8f6SDimitry Andric #define DEBUG_TYPE "faultmaps"
258f0fd8f6SDimitry Andric
268f0fd8f6SDimitry Andric static const int FaultMapVersion = 1;
278f0fd8f6SDimitry Andric const char *FaultMaps::WFMP = "Fault Maps: ";
288f0fd8f6SDimitry Andric
FaultMaps(AsmPrinter & AP)298f0fd8f6SDimitry Andric FaultMaps::FaultMaps(AsmPrinter &AP) : AP(AP) {}
308f0fd8f6SDimitry Andric
recordFaultingOp(FaultKind FaultTy,const MCSymbol * HandlerLabel)318f0fd8f6SDimitry Andric void FaultMaps::recordFaultingOp(FaultKind FaultTy,
328f0fd8f6SDimitry Andric const MCSymbol *HandlerLabel) {
338f0fd8f6SDimitry Andric MCContext &OutContext = AP.OutStreamer->getContext();
348f0fd8f6SDimitry Andric MCSymbol *FaultingLabel = OutContext.createTempSymbol();
358f0fd8f6SDimitry Andric
368f0fd8f6SDimitry Andric AP.OutStreamer->EmitLabel(FaultingLabel);
378f0fd8f6SDimitry Andric
388f0fd8f6SDimitry Andric const MCExpr *FaultingOffset = MCBinaryExpr::createSub(
398f0fd8f6SDimitry Andric MCSymbolRefExpr::create(FaultingLabel, OutContext),
408f0fd8f6SDimitry Andric MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);
418f0fd8f6SDimitry Andric
428f0fd8f6SDimitry Andric const MCExpr *HandlerOffset = MCBinaryExpr::createSub(
438f0fd8f6SDimitry Andric MCSymbolRefExpr::create(HandlerLabel, OutContext),
448f0fd8f6SDimitry Andric MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);
458f0fd8f6SDimitry Andric
468f0fd8f6SDimitry Andric FunctionInfos[AP.CurrentFnSym].emplace_back(FaultTy, FaultingOffset,
478f0fd8f6SDimitry Andric HandlerOffset);
488f0fd8f6SDimitry Andric }
498f0fd8f6SDimitry Andric
serializeToFaultMapSection()508f0fd8f6SDimitry Andric void FaultMaps::serializeToFaultMapSection() {
518f0fd8f6SDimitry Andric if (FunctionInfos.empty())
528f0fd8f6SDimitry Andric return;
538f0fd8f6SDimitry Andric
548f0fd8f6SDimitry Andric MCContext &OutContext = AP.OutStreamer->getContext();
558f0fd8f6SDimitry Andric MCStreamer &OS = *AP.OutStreamer;
568f0fd8f6SDimitry Andric
578f0fd8f6SDimitry Andric // Create the section.
588f0fd8f6SDimitry Andric MCSection *FaultMapSection =
598f0fd8f6SDimitry Andric OutContext.getObjectFileInfo()->getFaultMapSection();
608f0fd8f6SDimitry Andric OS.SwitchSection(FaultMapSection);
618f0fd8f6SDimitry Andric
628f0fd8f6SDimitry Andric // Emit a dummy symbol to force section inclusion.
638f0fd8f6SDimitry Andric OS.EmitLabel(OutContext.getOrCreateSymbol(Twine("__LLVM_FaultMaps")));
648f0fd8f6SDimitry Andric
65*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "********** Fault Map Output **********\n");
668f0fd8f6SDimitry Andric
678f0fd8f6SDimitry Andric // Header
688f0fd8f6SDimitry Andric OS.EmitIntValue(FaultMapVersion, 1); // Version.
698f0fd8f6SDimitry Andric OS.EmitIntValue(0, 1); // Reserved.
708f0fd8f6SDimitry Andric OS.EmitIntValue(0, 2); // Reserved.
718f0fd8f6SDimitry Andric
72*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << WFMP << "#functions = " << FunctionInfos.size() << "\n");
738f0fd8f6SDimitry Andric OS.EmitIntValue(FunctionInfos.size(), 4);
748f0fd8f6SDimitry Andric
75*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << WFMP << "functions:\n");
768f0fd8f6SDimitry Andric
778f0fd8f6SDimitry Andric for (const auto &FFI : FunctionInfos)
788f0fd8f6SDimitry Andric emitFunctionInfo(FFI.first, FFI.second);
798f0fd8f6SDimitry Andric }
808f0fd8f6SDimitry Andric
emitFunctionInfo(const MCSymbol * FnLabel,const FunctionFaultInfos & FFI)818f0fd8f6SDimitry Andric void FaultMaps::emitFunctionInfo(const MCSymbol *FnLabel,
828f0fd8f6SDimitry Andric const FunctionFaultInfos &FFI) {
838f0fd8f6SDimitry Andric MCStreamer &OS = *AP.OutStreamer;
848f0fd8f6SDimitry Andric
85*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << WFMP << " function addr: " << *FnLabel << "\n");
868f0fd8f6SDimitry Andric OS.EmitSymbolValue(FnLabel, 8);
878f0fd8f6SDimitry Andric
88*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << WFMP << " #faulting PCs: " << FFI.size() << "\n");
898f0fd8f6SDimitry Andric OS.EmitIntValue(FFI.size(), 4);
908f0fd8f6SDimitry Andric
918f0fd8f6SDimitry Andric OS.EmitIntValue(0, 4); // Reserved
928f0fd8f6SDimitry Andric
938f0fd8f6SDimitry Andric for (auto &Fault : FFI) {
94*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << WFMP << " fault type: "
958f0fd8f6SDimitry Andric << faultTypeToString(Fault.Kind) << "\n");
968f0fd8f6SDimitry Andric OS.EmitIntValue(Fault.Kind, 4);
978f0fd8f6SDimitry Andric
98*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << WFMP << " faulting PC offset: "
998f0fd8f6SDimitry Andric << *Fault.FaultingOffsetExpr << "\n");
1008f0fd8f6SDimitry Andric OS.EmitValue(Fault.FaultingOffsetExpr, 4);
1018f0fd8f6SDimitry Andric
102*4ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << WFMP << " fault handler PC offset: "
1038f0fd8f6SDimitry Andric << *Fault.HandlerOffsetExpr << "\n");
1048f0fd8f6SDimitry Andric OS.EmitValue(Fault.HandlerOffsetExpr, 4);
1058f0fd8f6SDimitry Andric }
1068f0fd8f6SDimitry Andric }
1078f0fd8f6SDimitry Andric
faultTypeToString(FaultMaps::FaultKind FT)1088f0fd8f6SDimitry Andric const char *FaultMaps::faultTypeToString(FaultMaps::FaultKind FT) {
1098f0fd8f6SDimitry Andric switch (FT) {
1108f0fd8f6SDimitry Andric default:
1118f0fd8f6SDimitry Andric llvm_unreachable("unhandled fault type!");
1128f0fd8f6SDimitry Andric case FaultMaps::FaultingLoad:
1138f0fd8f6SDimitry Andric return "FaultingLoad";
1147a7e6055SDimitry Andric case FaultMaps::FaultingLoadStore:
1157a7e6055SDimitry Andric return "FaultingLoadStore";
1167a7e6055SDimitry Andric case FaultMaps::FaultingStore:
1177a7e6055SDimitry Andric return "FaultingStore";
1188f0fd8f6SDimitry Andric }
1198f0fd8f6SDimitry Andric }
1203dac3a9bSDimitry Andric
1213dac3a9bSDimitry Andric raw_ostream &llvm::
operator <<(raw_ostream & OS,const FaultMapParser::FunctionFaultInfoAccessor & FFI)1223dac3a9bSDimitry Andric operator<<(raw_ostream &OS,
1233dac3a9bSDimitry Andric const FaultMapParser::FunctionFaultInfoAccessor &FFI) {
1243dac3a9bSDimitry Andric OS << "Fault kind: "
1253dac3a9bSDimitry Andric << FaultMaps::faultTypeToString((FaultMaps::FaultKind)FFI.getFaultKind())
1263dac3a9bSDimitry Andric << ", faulting PC offset: " << FFI.getFaultingPCOffset()
1273dac3a9bSDimitry Andric << ", handling PC offset: " << FFI.getHandlerPCOffset();
1283dac3a9bSDimitry Andric return OS;
1293dac3a9bSDimitry Andric }
1303dac3a9bSDimitry Andric
1313dac3a9bSDimitry Andric raw_ostream &llvm::
operator <<(raw_ostream & OS,const FaultMapParser::FunctionInfoAccessor & FI)1323dac3a9bSDimitry Andric operator<<(raw_ostream &OS, const FaultMapParser::FunctionInfoAccessor &FI) {
1333dac3a9bSDimitry Andric OS << "FunctionAddress: " << format_hex(FI.getFunctionAddr(), 8)
1343dac3a9bSDimitry Andric << ", NumFaultingPCs: " << FI.getNumFaultingPCs() << "\n";
1353dac3a9bSDimitry Andric for (unsigned i = 0, e = FI.getNumFaultingPCs(); i != e; ++i)
1363dac3a9bSDimitry Andric OS << FI.getFunctionFaultInfoAt(i) << "\n";
1373dac3a9bSDimitry Andric return OS;
1383dac3a9bSDimitry Andric }
1393dac3a9bSDimitry Andric
operator <<(raw_ostream & OS,const FaultMapParser & FMP)1403dac3a9bSDimitry Andric raw_ostream &llvm::operator<<(raw_ostream &OS, const FaultMapParser &FMP) {
1413dac3a9bSDimitry Andric OS << "Version: " << format_hex(FMP.getFaultMapVersion(), 2) << "\n";
1423dac3a9bSDimitry Andric OS << "NumFunctions: " << FMP.getNumFunctions() << "\n";
1433dac3a9bSDimitry Andric
1443dac3a9bSDimitry Andric if (FMP.getNumFunctions() == 0)
1453dac3a9bSDimitry Andric return OS;
1463dac3a9bSDimitry Andric
1473dac3a9bSDimitry Andric FaultMapParser::FunctionInfoAccessor FI;
1483dac3a9bSDimitry Andric
1493dac3a9bSDimitry Andric for (unsigned i = 0, e = FMP.getNumFunctions(); i != e; ++i) {
1503dac3a9bSDimitry Andric FI = (i == 0) ? FMP.getFirstFunctionInfo() : FI.getNextFunctionInfo();
1513dac3a9bSDimitry Andric OS << FI;
1523dac3a9bSDimitry Andric }
1533dac3a9bSDimitry Andric
1543dac3a9bSDimitry Andric return OS;
1553dac3a9bSDimitry Andric }
156