mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-14 15:39:00 +00:00
a0be0b1390
Summary: This change allows usage of store instruction for implicit null check. Memory Aliasing Analisys is not used and change conservatively supposes that any store and load may access the same memory. As a result re-ordering of store-store, store-load and load-store is prohibited. Patch by Serguei Katkov! Reviewers: reames, sanjoy Reviewed By: sanjoy Subscribers: atrick, llvm-commits Differential Revision: https://reviews.llvm.org/D29400 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@294338 91177308-0d34-0410-b5e6-96231b3b80d8
155 lines
4.8 KiB
C++
155 lines
4.8 KiB
C++
//===---------------------------- FaultMaps.cpp ---------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/CodeGen/FaultMaps.h"
|
|
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
|
#include "llvm/MC/MCContext.h"
|
|
#include "llvm/MC/MCExpr.h"
|
|
#include "llvm/MC/MCObjectFileInfo.h"
|
|
#include "llvm/MC/MCStreamer.h"
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
using namespace llvm;
|
|
|
|
#define DEBUG_TYPE "faultmaps"
|
|
|
|
static const int FaultMapVersion = 1;
|
|
const char *FaultMaps::WFMP = "Fault Maps: ";
|
|
|
|
FaultMaps::FaultMaps(AsmPrinter &AP) : AP(AP) {}
|
|
|
|
void FaultMaps::recordFaultingOp(FaultKind FaultTy,
|
|
const MCSymbol *HandlerLabel) {
|
|
MCContext &OutContext = AP.OutStreamer->getContext();
|
|
MCSymbol *FaultingLabel = OutContext.createTempSymbol();
|
|
|
|
AP.OutStreamer->EmitLabel(FaultingLabel);
|
|
|
|
const MCExpr *FaultingOffset = MCBinaryExpr::createSub(
|
|
MCSymbolRefExpr::create(FaultingLabel, OutContext),
|
|
MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);
|
|
|
|
const MCExpr *HandlerOffset = MCBinaryExpr::createSub(
|
|
MCSymbolRefExpr::create(HandlerLabel, OutContext),
|
|
MCSymbolRefExpr::create(AP.CurrentFnSymForSize, OutContext), OutContext);
|
|
|
|
FunctionInfos[AP.CurrentFnSym].emplace_back(FaultTy, FaultingOffset,
|
|
HandlerOffset);
|
|
}
|
|
|
|
void FaultMaps::serializeToFaultMapSection() {
|
|
if (FunctionInfos.empty())
|
|
return;
|
|
|
|
MCContext &OutContext = AP.OutStreamer->getContext();
|
|
MCStreamer &OS = *AP.OutStreamer;
|
|
|
|
// Create the section.
|
|
MCSection *FaultMapSection =
|
|
OutContext.getObjectFileInfo()->getFaultMapSection();
|
|
OS.SwitchSection(FaultMapSection);
|
|
|
|
// Emit a dummy symbol to force section inclusion.
|
|
OS.EmitLabel(OutContext.getOrCreateSymbol(Twine("__LLVM_FaultMaps")));
|
|
|
|
DEBUG(dbgs() << "********** Fault Map Output **********\n");
|
|
|
|
// Header
|
|
OS.EmitIntValue(FaultMapVersion, 1); // Version.
|
|
OS.EmitIntValue(0, 1); // Reserved.
|
|
OS.EmitIntValue(0, 2); // Reserved.
|
|
|
|
DEBUG(dbgs() << WFMP << "#functions = " << FunctionInfos.size() << "\n");
|
|
OS.EmitIntValue(FunctionInfos.size(), 4);
|
|
|
|
DEBUG(dbgs() << WFMP << "functions:\n");
|
|
|
|
for (const auto &FFI : FunctionInfos)
|
|
emitFunctionInfo(FFI.first, FFI.second);
|
|
}
|
|
|
|
void FaultMaps::emitFunctionInfo(const MCSymbol *FnLabel,
|
|
const FunctionFaultInfos &FFI) {
|
|
MCStreamer &OS = *AP.OutStreamer;
|
|
|
|
DEBUG(dbgs() << WFMP << " function addr: " << *FnLabel << "\n");
|
|
OS.EmitSymbolValue(FnLabel, 8);
|
|
|
|
DEBUG(dbgs() << WFMP << " #faulting PCs: " << FFI.size() << "\n");
|
|
OS.EmitIntValue(FFI.size(), 4);
|
|
|
|
OS.EmitIntValue(0, 4); // Reserved
|
|
|
|
for (auto &Fault : FFI) {
|
|
DEBUG(dbgs() << WFMP << " fault type: "
|
|
<< faultTypeToString(Fault.Kind) << "\n");
|
|
OS.EmitIntValue(Fault.Kind, 4);
|
|
|
|
DEBUG(dbgs() << WFMP << " faulting PC offset: "
|
|
<< *Fault.FaultingOffsetExpr << "\n");
|
|
OS.EmitValue(Fault.FaultingOffsetExpr, 4);
|
|
|
|
DEBUG(dbgs() << WFMP << " fault handler PC offset: "
|
|
<< *Fault.HandlerOffsetExpr << "\n");
|
|
OS.EmitValue(Fault.HandlerOffsetExpr, 4);
|
|
}
|
|
}
|
|
|
|
|
|
const char *FaultMaps::faultTypeToString(FaultMaps::FaultKind FT) {
|
|
switch (FT) {
|
|
default:
|
|
llvm_unreachable("unhandled fault type!");
|
|
|
|
case FaultMaps::FaultingLoad:
|
|
return "FaultingLoad";
|
|
case FaultMaps::FaultingLoadStore:
|
|
return "FaultingLoadStore";
|
|
case FaultMaps::FaultingStore:
|
|
return "FaultingStore";
|
|
}
|
|
}
|
|
|
|
raw_ostream &llvm::
|
|
operator<<(raw_ostream &OS,
|
|
const FaultMapParser::FunctionFaultInfoAccessor &FFI) {
|
|
OS << "Fault kind: "
|
|
<< FaultMaps::faultTypeToString((FaultMaps::FaultKind)FFI.getFaultKind())
|
|
<< ", faulting PC offset: " << FFI.getFaultingPCOffset()
|
|
<< ", handling PC offset: " << FFI.getHandlerPCOffset();
|
|
return OS;
|
|
}
|
|
|
|
raw_ostream &llvm::
|
|
operator<<(raw_ostream &OS, const FaultMapParser::FunctionInfoAccessor &FI) {
|
|
OS << "FunctionAddress: " << format_hex(FI.getFunctionAddr(), 8)
|
|
<< ", NumFaultingPCs: " << FI.getNumFaultingPCs() << "\n";
|
|
for (unsigned i = 0, e = FI.getNumFaultingPCs(); i != e; ++i)
|
|
OS << FI.getFunctionFaultInfoAt(i) << "\n";
|
|
return OS;
|
|
}
|
|
|
|
raw_ostream &llvm::operator<<(raw_ostream &OS, const FaultMapParser &FMP) {
|
|
OS << "Version: " << format_hex(FMP.getFaultMapVersion(), 2) << "\n";
|
|
OS << "NumFunctions: " << FMP.getNumFunctions() << "\n";
|
|
|
|
if (FMP.getNumFunctions() == 0)
|
|
return OS;
|
|
|
|
FaultMapParser::FunctionInfoAccessor FI;
|
|
|
|
for (unsigned i = 0, e = FMP.getNumFunctions(); i != e; ++i) {
|
|
FI = (i == 0) ? FMP.getFirstFunctionInfo() : FI.getNextFunctionInfo();
|
|
OS << FI;
|
|
}
|
|
|
|
return OS;
|
|
}
|