LLVM  10.0.0svn
X86AvoidTrailingCall.cpp
Go to the documentation of this file.
1 //===----- X86AvoidTrailingCall.cpp - Insert int3 after trailing calls ----===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // The Windows x64 unwinder has trouble unwinding the stack when a return
10 // address points to the end of the function. This pass maintains the invariant
11 // that every return address is inside the bounds of its parent function or
12 // funclet by inserting int3 if the last instruction would otherwise be a call.
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #include "X86.h"
17 #include "X86InstrInfo.h"
18 #include "X86Subtarget.h"
20 
21 #define DEBUG_TYPE "x86-avoid-trailing-call"
22 
23 using namespace llvm;
24 
25 namespace {
26 
27 class X86AvoidTrailingCallPass : public MachineFunctionPass {
28 public:
29  X86AvoidTrailingCallPass() : MachineFunctionPass(ID) {}
30 
31  bool runOnMachineFunction(MachineFunction &MF) override;
32 
33 private:
34  StringRef getPassName() const override {
35  return "X86 avoid trailing call pass";
36  }
37  static char ID;
38 };
39 
41 
42 } // end anonymous namespace
43 
45  return new X86AvoidTrailingCallPass();
46 }
47 
48 // A real instruction is a non-meta, non-pseudo instruction. Some pseudos
49 // expand to nothing, and some expand to code. This logic conservatively assumes
50 // they might expand to nothing.
52  return !MI.isPseudo() && !MI.isMetaInstruction();
53 }
54 
55 // Return true if this is a call instruction, but not a tail call.
56 static bool isCallInstruction(const MachineInstr &MI) {
57  return MI.isCall() && !MI.isReturn();
58 }
59 
60 bool X86AvoidTrailingCallPass::runOnMachineFunction(MachineFunction &MF) {
61  const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();
62  const X86InstrInfo &TII = *STI.getInstrInfo();
63  assert(STI.isTargetWin64() && "pass only runs on Win64");
64 
65  // FIXME: Perhaps this pass should also replace SEH_Epilogue by inserting nops
66  // before epilogues.
67 
68  bool Changed = false;
69  for (MachineBasicBlock &MBB : MF) {
70  // Look for basic blocks that precede funclet entries or are at the end of
71  // the function.
72  MachineBasicBlock *NextMBB = MBB.getNextNode();
73  if (NextMBB && !NextMBB->isEHFuncletEntry())
74  continue;
75 
76  // Find the last real instruction in this block, or previous blocks if this
77  // block is empty.
79  for (MachineBasicBlock &RMBB :
80  make_range(MBB.getReverseIterator(), MF.rend())) {
81  LastRealInstr = llvm::find_if(reverse(RMBB), isRealInstruction);
82  if (LastRealInstr != RMBB.rend())
83  break;
84  }
85 
86  // Do nothing if this function or funclet has no instructions.
87  if (LastRealInstr == MF.begin()->rend())
88  continue;
89 
90  // If this is a call instruction, insert int3 right after it with the same
91  // DebugLoc. Convert back to a forward iterator and advance the insertion
92  // position once.
93  if (isCallInstruction(*LastRealInstr)) {
94  LLVM_DEBUG({
95  dbgs() << "inserting int3 after trailing call instruction:\n";
96  LastRealInstr->dump();
97  dbgs() << '\n';
98  });
99 
100  MachineBasicBlock::iterator MBBI = std::next(LastRealInstr.getReverse());
101  BuildMI(*LastRealInstr->getParent(), MBBI, LastRealInstr->getDebugLoc(),
102  TII.get(X86::INT3));
103  Changed = true;
104  }
105  }
106 
107  return Changed;
108 }
bool isCall(QueryType Type=AnyInBundle) const
Definition: MachineInstr.h:656
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
Definition: ilist_node.h:288
This class represents lattice values for constants.
Definition: AllocatorList.h:23
const X86InstrInfo * getInstrInfo() const override
Definition: X86Subtarget.h:507
bool isMetaInstruction() const
Return true if this instruction doesn&#39;t produce any output in the form of executable instructions...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const HexagonInstrInfo * TII
MachineBasicBlock iterator that automatically skips over MIs that are inside bundles (i...
static bool isRealInstruction(MachineInstr &MI)
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
Definition: STLExtras.h:261
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
bool isReturn(QueryType Type=AnyInBundle) const
Definition: MachineInstr.h:646
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
bool isPseudo(QueryType Type=IgnoreBundle) const
Return true if this is a pseudo instruction that doesn&#39;t correspond to a real machine instruction...
Definition: MachineInstr.h:642
static bool isCallInstruction(const MachineInstr &MI)
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1193
bool isTargetWin64() const
Definition: X86Subtarget.h:800
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
Representation of each machine instruction.
Definition: MachineInstr.h:63
bool isEHFuncletEntry() const
Returns true if this is the entry block of an EH funclet.
FunctionPass * createX86AvoidTrailingCallPass()
Return a pass that inserts int3 at the end of the function if it ends with a CALL instruction...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
#define LLVM_DEBUG(X)
Definition: Debug.h:122