1 //===----- X86AvoidTrailingCall.cpp - Insert int3 after trailing calls ----===//
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
7 //===----------------------------------------------------------------------===//
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.
14 //===----------------------------------------------------------------------===//
17 #include "X86InstrInfo.h"
18 #include "X86Subtarget.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
21 #define DEBUG_TYPE "x86-avoid-trailing-call"
27 class X86AvoidTrailingCallPass
: public MachineFunctionPass
{
29 X86AvoidTrailingCallPass() : MachineFunctionPass(ID
) {}
31 bool runOnMachineFunction(MachineFunction
&MF
) override
;
34 StringRef
getPassName() const override
{
35 return "X86 avoid trailing call pass";
40 char X86AvoidTrailingCallPass::ID
= 0;
42 } // end anonymous namespace
44 FunctionPass
*llvm::createX86AvoidTrailingCallPass() {
45 return new X86AvoidTrailingCallPass();
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.
51 static bool isRealInstruction(MachineInstr
&MI
) {
52 return !MI
.isPseudo() && !MI
.isMetaInstruction();
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();
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");
65 // FIXME: Perhaps this pass should also replace SEH_Epilogue by inserting nops
69 for (MachineBasicBlock
&MBB
: MF
) {
70 // Look for basic blocks that precede funclet entries or are at the end of
72 MachineBasicBlock
*NextMBB
= MBB
.getNextNode();
73 if (NextMBB
&& !NextMBB
->isEHFuncletEntry())
76 // Find the last real instruction in this block, or previous blocks if this
78 MachineBasicBlock::reverse_iterator LastRealInstr
;
79 for (MachineBasicBlock
&RMBB
:
80 make_range(MBB
.getReverseIterator(), MF
.rend())) {
81 LastRealInstr
= llvm::find_if(reverse(RMBB
), isRealInstruction
);
82 if (LastRealInstr
!= RMBB
.rend())
86 // Do nothing if this function or funclet has no instructions.
87 if (LastRealInstr
== MF
.begin()->rend())
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
93 if (isCallInstruction(*LastRealInstr
)) {
95 dbgs() << "inserting int3 after trailing call instruction:\n";
96 LastRealInstr
->dump();
100 MachineBasicBlock::iterator MBBI
= std::next(LastRealInstr
.getReverse());
101 BuildMI(*LastRealInstr
->getParent(), MBBI
, LastRealInstr
->getDebugLoc(),