67#define PASS_KEY "x86-lvi-load"
68#define DEBUG_TYPE PASS_KEY
70STATISTIC(NumFences,
"Number of LFENCEs inserted for LVI mitigation");
71STATISTIC(NumFunctionsConsidered,
"Number of functions analyzed");
72STATISTIC(NumFunctionsMitigated,
"Number of functions for which mitigations "
74STATISTIC(NumGadgets,
"Number of LVI gadgets detected during analysis");
77typedef int (*
OptimizeCutT)(
unsigned int *Nodes,
unsigned int NodesSize,
78 unsigned int *Edges,
int *EdgeValues,
79 int *CutEdges ,
unsigned int EdgesSize);
85 static constexpr int GadgetEdgeSentinel = -1;
86 static constexpr MachineInstr *
const ArgNodeSentinel =
nullptr;
89 using Node = GraphT::Node;
90 using Edge = GraphT::Edge;
92 MachineGadgetGraph(std::unique_ptr<
Node[]> Nodes,
93 std::unique_ptr<Edge[]> Edges, size_type NodesSize,
94 size_type EdgesSize,
int NumFences = 0,
int NumGadgets = 0)
95 : GraphT(std::move(Nodes), std::move(Edges), NodesSize, EdgesSize),
96 NumFences(NumFences), NumGadgets(NumGadgets) {}
97 static inline bool isCFGEdge(
const Edge &
E) {
98 return E.getValue() != GadgetEdgeSentinel;
100 static inline bool isGadgetEdge(
const Edge &
E) {
101 return E.getValue() == GadgetEdgeSentinel;
108 "X86 Load Value Injection (LVI) Load Hardening";
114 StringRef getPassName()
const override {
return X86LVILHPassName; }
121class X86LoadValueInjectionLoadHardeningImpl {
123 X86LoadValueInjectionLoadHardeningImpl() =
default;
131 using Edge = MachineGadgetGraph::Edge;
132 using Node = MachineGadgetGraph::Node;
133 using EdgeSet = MachineGadgetGraph::EdgeSet;
134 using NodeSet = MachineGadgetGraph::NodeSet;
140 std::unique_ptr<MachineGadgetGraph>
145 std::unique_ptr<MachineGadgetGraph> Graph)
const;
147 std::unique_ptr<MachineGadgetGraph> Graph)
const;
148 int elimMitigatedEdgesAndNodes(MachineGadgetGraph &
G,
151 std::unique_ptr<MachineGadgetGraph>
152 trimMitigatedEdges(std::unique_ptr<MachineGadgetGraph> Graph)
const;
154 EdgeSet &CutEdges )
const;
158 return MI && (
MI->getOpcode() == X86::LFENCE ||
159 (STI->useLVIControlFlowIntegrity() &&
MI->isCall()));
183 if (
Node->getValue() == MachineGadgetGraph::ArgNodeSentinel)
188 OS << *
Node->getValue();
194 if (
MI == MachineGadgetGraph::ArgNodeSentinel)
195 return "color = blue";
196 if (
MI->getOpcode() == X86::LFENCE)
197 return "color = green";
203 int EdgeVal = (*E.getCurrent()).getValue();
204 return EdgeVal >= 0 ?
"label = " + std::to_string(EdgeVal)
205 :
"color = red, style = \"dashed\"";
211char X86LoadValueInjectionLoadHardeningLegacy::ID = 0;
213void X86LoadValueInjectionLoadHardeningLegacy::getAnalysisUsage(
218 AU.
addRequired<MachineDominanceFrontierWrapperPass>();
223 MachineGadgetGraph *
G) {
225 "Speculative gadgets for \"" + MF.
getName() +
"\" function");
228bool X86LoadValueInjectionLoadHardeningImpl::run(
230 const MachineDominatorTree &MDT,
const MachineDominanceFrontier &MDF) {
234 const X86Options &CLOpts = STI->
getCLOpts();
240 ++NumFunctionsConsidered;
244 std::unique_ptr<MachineGadgetGraph> Graph = getGadgetGraph(MF, MLI, MDT, MDF);
246 if (Graph ==
nullptr)
249 if (CLOpts.lvi_load_dot_verify) {
254 if (CLOpts.lvi_load_dot || CLOpts.lvi_load_dot_only) {
256 std::error_code FileError;
257 std::string FileName =
"lvi.";
260 raw_fd_ostream FileOut(FileName, FileError);
262 errs() << FileError.message();
266 if (CLOpts.lvi_load_dot_only)
271 if (!CLOpts.lvi_load_opt_plugin.empty()) {
273 std::string ErrorMsg;
275 CLOpts.lvi_load_opt_plugin.str().c_str(), &ErrorMsg);
276 if (!ErrorMsg.empty())
283 FencesInserted = hardenLoadsWithPlugin(MF, std::move(Graph));
285 FencesInserted = hardenLoadsWithHeuristic(MF, std::move(Graph));
288 if (FencesInserted > 0)
289 ++NumFunctionsMitigated;
290 NumFences += FencesInserted;
291 return (FencesInserted > 0);
294std::unique_ptr<MachineGadgetGraph>
295X86LoadValueInjectionLoadHardeningImpl::getGadgetGraph(
297 const MachineDominatorTree &MDT,
298 const MachineDominanceFrontier &MDF)
const {
302 DataFlowGraph DFG{MF, *
TII, *
TRI, MDT, MDF};
307 GraphBuilder Builder;
308 using GraphIter = GraphBuilder::BuilderNodeRef;
309 DenseMap<MachineInstr *, GraphIter> NodeMap;
310 int FenceCount = 0, GadgetCount = 0;
311 auto MaybeAddNode = [&NodeMap, &Builder](MachineInstr *
MI) {
314 auto I = Builder.addVertex(
MI);
316 return std::pair<GraphIter, bool>{
I,
true};
318 return std::pair<GraphIter, bool>{
Ref->getSecond(),
false};
325 DenseMap<NodeId, std::vector<NodeId>> Transmitters;
329 auto AnalyzeDef = [&](NodeAddr<DefNode *> SourceDef) {
330 SmallSet<NodeId, 8> UsesVisited, DefsVisited;
331 std::function<void(NodeAddr<DefNode *>)> AnalyzeDefUseChain =
332 [&](NodeAddr<DefNode *>
Def) {
339 for (
auto UseID :
L.getAllReachedUses(DefReg, Def)) {
340 auto Use = DFG.addr<UseNode *>(UseID);
343 for (
const auto&
I :
L.getRealUses(
Phi.
Id)) {
344 if (DFG.getPRI().alias(RegisterRef(
I.first), DefReg)) {
345 for (
const auto &UA :
I.second)
346 Uses.emplace(UA.first);
357 for (
auto UseID :
Uses) {
358 if (!UsesVisited.
insert(UseID).second)
361 auto Use = DFG.addr<UseNode *>(UseID);
375 if (instrUsesRegToAccessMemory(
UseMI, UseMO.
getReg()) ||
376 (!STI->
getCLOpts().lvi_load_no_cbranch &&
387 for (
const auto &ChildDef :
388 Owner.Addr->members_if(DataFlowGraph::IsDef, DFG)) {
389 if (!DefsVisited.
insert(ChildDef.Id).second)
393 if (
Def.
Id == ChildDef.Id)
396 AnalyzeDefUseChain(ChildDef);
399 for (
auto TransmitterId : Transmitters[ChildDef.Id])
400 Transmitters[
Def.
Id].push_back(TransmitterId);
406 auto &DefTransmitters = Transmitters[
Def.
Id];
411 DefTransmitters.end());
415 AnalyzeDefUseChain(SourceDef);
416 auto &SourceDefTransmitters = Transmitters[SourceDef.Id];
417 if (SourceDefTransmitters.empty())
420 MachineInstr *
Source = SourceDef.Addr->getFlags() & NodeAttrs::PhiRef
421 ? MachineGadgetGraph::ArgNodeSentinel
422 : SourceDef.Addr->getOp().getParent();
423 auto GadgetSource = MaybeAddNode(Source);
425 for (
auto TransmitterId : SourceDefTransmitters) {
426 MachineInstr *Sink = DFG.addr<StmtNode *>(TransmitterId).Addr->getCode();
427 auto GadgetSink = MaybeAddNode(Sink);
429 Builder.addEdge(MachineGadgetGraph::GadgetEdgeSentinel,
430 GadgetSource.first, GadgetSink.first);
435 LLVM_DEBUG(
dbgs() <<
"Analyzing def-use chains to find gadgets\n");
437 NodeAddr<BlockNode *> EntryBlock = DFG.getFunc().Addr->getEntryBlock(DFG);
438 for (NodeAddr<PhiNode *> ArgPhi :
439 EntryBlock.Addr->members_if(DataFlowGraph::IsPhi, DFG)) {
440 NodeList Defs = ArgPhi.Addr->members_if(DataFlowGraph::IsDef, DFG);
444 for (NodeAddr<BlockNode *> BA : DFG.getFunc().Addr->members(DFG)) {
445 for (NodeAddr<StmtNode *> SA :
446 BA.Addr->members_if(DataFlowGraph::IsCode<NodeAttrs::Stmt>, DFG)) {
447 MachineInstr *
MI = SA.Addr->getCode();
451 }
else if (
MI->mayLoad()) {
452 NodeList Defs = SA.Addr->members_if(DataFlowGraph::IsDef, DFG);
459 if (GadgetCount == 0)
461 NumGadgets += GadgetCount;
464 SmallPtrSet<MachineBasicBlock *, 8> BlocksVisited;
465 std::function<void(MachineBasicBlock *, GraphIter,
unsigned)> TraverseCFG =
466 [&](MachineBasicBlock *
MBB, GraphIter GI,
unsigned ParentDepth) {
471 auto BeginBB = MaybeAddNode(&*NI);
472 Builder.addEdge(ParentDepth, GI, BeginBB.first);
478 while (++NI !=
MBB->
end()) {
480 if (
Ref != NodeMap.
end()) {
481 Builder.addEdge(LoopDepth, GI,
Ref->getSecond());
482 GI =
Ref->getSecond();
489 auto EndBB = MaybeAddNode(&*
T);
491 Builder.addEdge(LoopDepth, GI, EndBB.first);
496 TraverseCFG(Succ, GI, LoopDepth);
500 GraphIter ArgNode = MaybeAddNode(MachineGadgetGraph::ArgNodeSentinel).first;
501 TraverseCFG(&MF.
front(), ArgNode, 0);
502 std::unique_ptr<MachineGadgetGraph>
G{Builder.get(FenceCount, GadgetCount)};
508int X86LoadValueInjectionLoadHardeningImpl::elimMitigatedEdgesAndNodes(
509 MachineGadgetGraph &
G, EdgeSet &ElimEdges ,
510 NodeSet &ElimNodes )
const {
511 if (
G.NumFences > 0) {
514 for (
const Edge &
E :
G.edges()) {
515 const Node *Dest =
E.getDest();
516 if (isFence(Dest->getValue())) {
519 for (
const Edge &DE : Dest->edges())
520 ElimEdges.insert(DE);
526 int RemainingGadgets = 0;
527 NodeSet ReachableNodes{
G};
528 for (
const Node &
RootN :
G.nodes()) {
533 ReachableNodes.
clear();
534 std::function<void(
const Node *,
bool)> FindReachableNodes =
535 [&](
const Node *
N,
bool FirstNode) {
538 for (
const Edge &
E :
N->edges()) {
539 const Node *Dest =
E.getDest();
540 if (MachineGadgetGraph::isCFGEdge(
E) && !ElimEdges.contains(
E) &&
541 !ReachableNodes.contains(*Dest))
542 FindReachableNodes(Dest,
false);
545 FindReachableNodes(&
RootN,
true);
549 if (MachineGadgetGraph::isGadgetEdge(
E)) {
550 if (ReachableNodes.contains(*
E.getDest())) {
559 return RemainingGadgets;
562std::unique_ptr<MachineGadgetGraph>
563X86LoadValueInjectionLoadHardeningImpl::trimMitigatedEdges(
564 std::unique_ptr<MachineGadgetGraph> Graph)
const {
565 NodeSet ElimNodes{*Graph};
566 EdgeSet ElimEdges{*Graph};
567 int RemainingGadgets =
568 elimMitigatedEdgesAndNodes(*Graph, ElimEdges, ElimNodes);
569 if (ElimEdges.empty() && ElimNodes.
empty()) {
570 Graph->NumFences = 0;
571 Graph->NumGadgets = RemainingGadgets;
573 Graph = GraphBuilder::trim(*Graph, ElimNodes, ElimEdges, 0 ,
579int X86LoadValueInjectionLoadHardeningImpl::hardenLoadsWithPlugin(
580 MachineFunction &MF, std::unique_ptr<MachineGadgetGraph> Graph)
const {
581 int FencesInserted = 0;
585 Graph = trimMitigatedEdges(std::move(Graph));
587 if (Graph->NumGadgets == 0)
591 EdgeSet CutEdges{*Graph};
592 auto Nodes = std::make_unique<unsigned int[]>(Graph->nodes_size() +
594 auto Edges = std::make_unique<unsigned int[]>(Graph->edges_size());
595 auto EdgeCuts = std::make_unique<int[]>(Graph->edges_size());
596 auto EdgeValues = std::make_unique<int[]>(Graph->edges_size());
597 for (
const Node &
N : Graph->nodes()) {
598 Nodes[Graph->getNodeIndex(
N)] = Graph->getEdgeIndex(*
N.edges_begin());
600 Nodes[Graph->nodes_size()] = Graph->edges_size();
601 for (
const Edge &
E : Graph->edges()) {
602 Edges[Graph->getEdgeIndex(
E)] = Graph->getNodeIndex(*
E.getDest());
603 EdgeValues[Graph->getEdgeIndex(
E)] =
E.getValue();
605 OptimizeCut(Nodes.get(), Graph->nodes_size(), Edges.get(), EdgeValues.get(),
606 EdgeCuts.get(), Graph->edges_size());
607 for (
int I = 0;
I < Graph->edges_size(); ++
I)
614 FencesInserted += insertFences(MF, *Graph, CutEdges);
616 LLVM_DEBUG(
dbgs() <<
"Inserted " << FencesInserted <<
" fences\n");
618 Graph = GraphBuilder::trim(*Graph, NodeSet{*Graph}, CutEdges);
621 return FencesInserted;
624int X86LoadValueInjectionLoadHardeningImpl::hardenLoadsWithHeuristic(
625 MachineFunction &MF, std::unique_ptr<MachineGadgetGraph> Graph)
const {
628 if (Graph->NumFences > 0) {
630 Graph = trimMitigatedEdges(std::move(Graph));
634 if (Graph->NumGadgets == 0)
638 EdgeSet CutEdges{*Graph};
641 DenseMap<const Node *, SmallVector<const Edge *, 2>> IngressEdgeMap;
642 for (
const Edge &
E : Graph->edges())
643 if (MachineGadgetGraph::isCFGEdge(
E))
644 IngressEdgeMap[
E.getDest()].push_back(&
E);
654 for (
const Node &
N : Graph->nodes()) {
655 for (
const Edge &
E :
N.edges()) {
656 if (!MachineGadgetGraph::isGadgetEdge(
E))
661 for (
const Edge &EgressEdge :
N.edges())
662 if (MachineGadgetGraph::isCFGEdge(EgressEdge))
665 int EgressCutCost = 0, IngressCutCost = 0;
666 for (
const Edge *EgressEdge : EgressEdges)
667 if (!CutEdges.contains(*EgressEdge))
668 EgressCutCost += EgressEdge->getValue();
669 for (
const Edge *IngressEdge : IngressEdges)
670 if (!CutEdges.contains(*IngressEdge))
671 IngressCutCost += IngressEdge->getValue();
674 IngressCutCost < EgressCutCost ? IngressEdges : EgressEdges;
675 for (
const Edge *
E : EdgesToCut)
683 int FencesInserted = insertFences(MF, *Graph, CutEdges);
685 LLVM_DEBUG(
dbgs() <<
"Inserted " << FencesInserted <<
" fences\n");
687 return FencesInserted;
690int X86LoadValueInjectionLoadHardeningImpl::insertFences(
692 EdgeSet &CutEdges )
const {
693 int FencesInserted = 0;
694 for (
const Node &
N :
G.nodes()) {
695 for (
const Edge &
E :
N.edges()) {
696 if (CutEdges.contains(
E)) {
697 MachineInstr *
MI =
N.getValue(), *Prev;
698 MachineBasicBlock *
MBB;
700 if (
MI == MachineGadgetGraph::ArgNodeSentinel) {
705 }
else if (
MI->isBranch()) {
708 Prev =
MI->getPrevNode();
711 for (
const Edge &
E :
N.edges()) {
712 if (MachineGadgetGraph::isCFGEdge(
E))
717 InsertionPt =
MI->getNextNode() ?
MI->getNextNode() :
MBB->
end();
718 Prev = InsertionPt ==
MBB->
end()
720 : InsertionPt->getPrevNode();
723 if ((InsertionPt ==
MBB->
end() || !isFence(&*InsertionPt)) &&
724 (!Prev || !isFence(Prev))) {
731 return FencesInserted;
734bool X86LoadValueInjectionLoadHardeningImpl::instrUsesRegToAccessMemory(
736 if (!
MI.mayLoadOrStore() ||
MI.getOpcode() == X86::MFENCE ||
737 MI.getOpcode() == X86::SFENCE ||
MI.getOpcode() == X86::LFENCE)
741 if (MemRefBeginIdx < 0) {
742 LLVM_DEBUG(
dbgs() <<
"Warning: unable to obtain memory operand for loading "
748 const MachineOperand &BaseMO =
750 const MachineOperand &IndexMO =
758bool X86LoadValueInjectionLoadHardeningImpl::instrUsesRegToBranch(
760 if (!
MI.isConditionalBranch())
762 for (
const MachineOperand &Use :
MI.uses())
768bool X86LoadValueInjectionLoadHardeningLegacy::runOnMachineFunction(
773 if (!
F.hasOptNone() && skipFunction(
F))
777 if (!MF.
getSubtarget<X86Subtarget>().useLVILoadHardening()) {
781 const auto &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI();
782 const auto &MDT = getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
783 const auto &MDF = getAnalysis<MachineDominanceFrontierWrapperPass>().getMDF();
785 X86LoadValueInjectionLoadHardeningImpl Impl;
786 return Impl.run(MF, MLI, MDT, MDF);
800 X86LoadValueInjectionLoadHardeningImpl Impl;
801 const bool Modified = Impl.run(MF, MLI, MDT, MDF);
808 "X86 LVI load hardening",
false,
false)
816 return new X86LoadValueInjectionLoadHardeningLegacy();
MachineInstrBuilder & UseMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static ManagedStatic< DebugCounterOwner > Owner
This file defines the DenseMap class.
const HexagonInstrInfo * TII
Description: ImmutableGraph is a fast DAG implementation that cannot be modified, except by creating ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Remove Loads Into Fake Uses
std::pair< BasicBlock *, BasicBlock * > Edge
This file defines the SmallSet class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
int(* OptimizeCutT)(unsigned int *Nodes, unsigned int NodesSize, unsigned int *Edges, int *EdgeValues, int *CutEdges, unsigned int EdgesSize)
static void writeGadgetGraph(raw_ostream &OS, MachineFunction &MF, MachineGadgetGraph *G)
static llvm::sys::DynamicLibrary OptimizeDL
static OptimizeCutT OptimizeCut
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
LLVM_ABI void setPreservesCFG()
This function should be called by the pass, iff they do not:
Represents analyses that only rely on functions' control flow.
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
FunctionPass class - This class is used to implement most global optimizations.
unsigned getLoopDepth(const BlockT *BB) const
Return the loop nesting level of the specified block.
LLVM_ABI iterator getFirstNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the first non-debug instruction in the basic block, or end().
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
iterator_range< succ_iterator > successors()
MachineInstrBundleIterator< MachineInstr > iterator
Analysis pass which computes a MachineDominatorTree.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineBasicBlock & front() const
Representation of each machine instruction.
Analysis pass that exposes the MachineLoopInfo for a machine function.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
Register getReg() const
getReg - Returns the register number.
A NodeSet contains a set of SUnit DAG nodes with additional information that assigns a priority to th...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
void push_back(const T &Elt)
Represent a constant reference to a string, i.e.
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
const X86InstrInfo * getInstrInfo() const override
const X86RegisterInfo * getRegisterInfo() const override
const X86Options & getCLOpts() const
This class implements an extremely fast bulk output stream that can only output to a stream.
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
This class provides a portable interface to dynamic libraries which also might be known as shared lib...
static LLVM_ABI DynamicLibrary getPermanentLibrary(const char *filename, std::string *errMsg=nullptr)
This function permanently loads the dynamic library at the given path using the library load operatio...
LLVM_ABI void * getAddressOfSymbol(const char *symbolName)
Searches through the library for the symbol symbolName.
bool isValid() const
Returns true if the object refers to a valid library.
int getFirstAddrOperandIdx(const MachineInstr &MI)
Return the index of the instruction's first address operand, if it has a memory reference,...
NodeAddr< DefNode * > Def
NodeAddr< PhiNode * > Phi
NodeAddr< UseNode * > Use
std::set< NodeId > NodeSet
SmallVector< Node, 4 > NodeList
This is an optimization pass for GlobalISel generic memory operations.
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
LLVM_ABI raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
auto unique(Range &&R, Predicate P)
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
FunctionPass * createX86LoadValueInjectionLoadHardeningLegacyPass()
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Ref
The access may reference the value stored in memory.
static std::string getNodeAttributes(NodeRef Node, GraphType *)
Traits::ChildIteratorType ChildIteratorType
std::string getNodeLabel(NodeRef Node, GraphType *)
static std::string getEdgeAttributes(NodeRef, ChildIteratorType E, GraphType *)
MachineGadgetGraph GraphType
Traits::ChildEdgeIteratorType ChildEdgeIteratorType
llvm::GraphTraits< GraphType * > Traits
DOTGraphTraits(bool IsSimple=false)
DefaultDOTGraphTraits(bool simple=false)
typename GraphType::UnknownGraphTypeError NodeRef
uint16_t getAttrs() const
uint16_t getFlags() const
LLVM_ABI RegisterRef getRegRef(const DataFlowGraph &G) const
LLVM_ABI Node getOwner(const DataFlowGraph &G)