107 lines · cpp
1//===- FaultMaps.cpp ------------------------------------------------------===//2//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-exception6//7//===----------------------------------------------------------------------===//8 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"18 19using namespace llvm;20 21#define DEBUG_TYPE "faultmaps"22 23static const int FaultMapVersion = 1;24const char *FaultMaps::WFMP = "Fault Maps: ";25 26FaultMaps::FaultMaps(AsmPrinter &AP) : AP(AP) {}27 28void FaultMaps::recordFaultingOp(FaultKind FaultTy,29 const MCSymbol *FaultingLabel,30 const MCSymbol *HandlerLabel) {31 MCContext &OutContext = AP.OutStreamer->getContext();32 33 const MCExpr *FaultingOffset = MCBinaryExpr::createSub(34 MCSymbolRefExpr::create(FaultingLabel, OutContext),35 MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);36 37 const MCExpr *HandlerOffset = MCBinaryExpr::createSub(38 MCSymbolRefExpr::create(HandlerLabel, OutContext),39 MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);40 41 FunctionInfos[AP.CurrentFnSym].emplace_back(FaultTy, FaultingOffset,42 HandlerOffset);43}44 45void FaultMaps::serializeToFaultMapSection() {46 if (FunctionInfos.empty())47 return;48 49 MCContext &OutContext = AP.OutStreamer->getContext();50 MCStreamer &OS = *AP.OutStreamer;51 52 // Create the section.53 MCSection *FaultMapSection =54 OutContext.getObjectFileInfo()->getFaultMapSection();55 OS.switchSection(FaultMapSection);56 57 // Emit a dummy symbol to force section inclusion.58 OS.emitLabel(OutContext.getOrCreateSymbol(Twine("__LLVM_FaultMaps")));59 60 LLVM_DEBUG(dbgs() << "********** Fault Map Output **********\n");61 62 // Header63 OS.emitIntValue(FaultMapVersion, 1); // Version.64 OS.emitIntValue(0, 1); // Reserved.65 OS.emitInt16(0); // Reserved.66 67 LLVM_DEBUG(dbgs() << WFMP << "#functions = " << FunctionInfos.size() << "\n");68 OS.emitInt32(FunctionInfos.size());69 70 LLVM_DEBUG(dbgs() << WFMP << "functions:\n");71 72 for (const auto &FFI : FunctionInfos)73 emitFunctionInfo(FFI.first, FFI.second);74}75 76void FaultMaps::emitFunctionInfo(const MCSymbol *FnLabel,77 const FunctionFaultInfos &FFI) {78 MCStreamer &OS = *AP.OutStreamer;79 80 LLVM_DEBUG(dbgs() << WFMP << " function addr: " << *FnLabel << "\n");81 OS.emitSymbolValue(FnLabel, 8);82 83 LLVM_DEBUG(dbgs() << WFMP << " #faulting PCs: " << FFI.size() << "\n");84 OS.emitInt32(FFI.size());85 86 OS.emitInt32(0); // Reserved87 88 for (const auto &Fault : FFI) {89 OS.emitInt32(Fault.Kind);90 OS.emitValue(Fault.FaultingOffsetExpr, 4);91 OS.emitValue(Fault.HandlerOffsetExpr, 4);92 }93}94 95const char *FaultMaps::faultTypeToString(FaultMaps::FaultKind FT) {96 switch (FT) {97 default:98 llvm_unreachable("unhandled fault type!");99 case FaultMaps::FaultingLoad:100 return "FaultingLoad";101 case FaultMaps::FaultingLoadStore:102 return "FaultingLoadStore";103 case FaultMaps::FaultingStore:104 return "FaultingStore";105 }106}107