xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/X86/X86AvoidTrailingCall.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
18bcb0991SDimitry Andric //===----- X86AvoidTrailingCall.cpp - Insert int3 after trailing calls ----===//
28bcb0991SDimitry Andric //
38bcb0991SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48bcb0991SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
58bcb0991SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68bcb0991SDimitry Andric //
78bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
88bcb0991SDimitry Andric //
9*5ffd83dbSDimitry Andric // The Windows x64 unwinder decodes the instruction stream during unwinding.
10*5ffd83dbSDimitry Andric // The unwinder decodes forward from the current PC to detect epilogue code
11*5ffd83dbSDimitry Andric // patterns.
12*5ffd83dbSDimitry Andric //
13*5ffd83dbSDimitry Andric // First, this means that there must be an instruction after every
14*5ffd83dbSDimitry Andric // call instruction for the unwinder to decode. LLVM must maintain the invariant
15*5ffd83dbSDimitry Andric // that the last instruction of a function or funclet is not a call, or the
16*5ffd83dbSDimitry Andric // unwinder may decode into the next function. Similarly, a call may not
17*5ffd83dbSDimitry Andric // immediately precede an epilogue code pattern. As of this writing, the
18*5ffd83dbSDimitry Andric // SEH_Epilogue pseudo instruction takes care of that.
19*5ffd83dbSDimitry Andric //
20*5ffd83dbSDimitry Andric // Second, all non-tail call jump targets must be within the *half-open*
21*5ffd83dbSDimitry Andric // interval of the bounds of the function. The unwinder distinguishes between
22*5ffd83dbSDimitry Andric // internal jump instructions and tail calls in an epilogue sequence by checking
23*5ffd83dbSDimitry Andric // the jump target against the function bounds from the .pdata section. This
24*5ffd83dbSDimitry Andric // means that the last regular MBB of an LLVM function must not be empty if
25*5ffd83dbSDimitry Andric // there are regular jumps targeting it.
26*5ffd83dbSDimitry Andric //
27*5ffd83dbSDimitry Andric // This pass upholds these invariants by ensuring that blocks at the end of a
28*5ffd83dbSDimitry Andric // function or funclet are a) not empty and b) do not end in a CALL instruction.
29*5ffd83dbSDimitry Andric //
30*5ffd83dbSDimitry Andric // Unwinder implementation for reference:
31*5ffd83dbSDimitry Andric // https://github.com/dotnet/coreclr/blob/a9f3fc16483eecfc47fb79c362811d870be02249/src/unwinder/amd64/unwinder_amd64.cpp#L1015
328bcb0991SDimitry Andric //
338bcb0991SDimitry Andric //===----------------------------------------------------------------------===//
348bcb0991SDimitry Andric 
358bcb0991SDimitry Andric #include "X86.h"
368bcb0991SDimitry Andric #include "X86InstrInfo.h"
378bcb0991SDimitry Andric #include "X86Subtarget.h"
388bcb0991SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
398bcb0991SDimitry Andric 
40*5ffd83dbSDimitry Andric #define AVOIDCALL_DESC "X86 avoid trailing call pass"
41*5ffd83dbSDimitry Andric #define AVOIDCALL_NAME "x86-avoid-trailing-call"
42*5ffd83dbSDimitry Andric 
43*5ffd83dbSDimitry Andric #define DEBUG_TYPE AVOIDCALL_NAME
448bcb0991SDimitry Andric 
458bcb0991SDimitry Andric using namespace llvm;
468bcb0991SDimitry Andric 
478bcb0991SDimitry Andric namespace {
488bcb0991SDimitry Andric class X86AvoidTrailingCallPass : public MachineFunctionPass {
498bcb0991SDimitry Andric public:
508bcb0991SDimitry Andric   X86AvoidTrailingCallPass() : MachineFunctionPass(ID) {}
518bcb0991SDimitry Andric 
528bcb0991SDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
538bcb0991SDimitry Andric 
548bcb0991SDimitry Andric   static char ID;
55*5ffd83dbSDimitry Andric 
56*5ffd83dbSDimitry Andric private:
57*5ffd83dbSDimitry Andric   StringRef getPassName() const override { return AVOIDCALL_DESC; }
588bcb0991SDimitry Andric };
59*5ffd83dbSDimitry Andric } // end anonymous namespace
608bcb0991SDimitry Andric 
618bcb0991SDimitry Andric char X86AvoidTrailingCallPass::ID = 0;
628bcb0991SDimitry Andric 
638bcb0991SDimitry Andric FunctionPass *llvm::createX86AvoidTrailingCallPass() {
648bcb0991SDimitry Andric   return new X86AvoidTrailingCallPass();
658bcb0991SDimitry Andric }
668bcb0991SDimitry Andric 
67*5ffd83dbSDimitry Andric INITIALIZE_PASS(X86AvoidTrailingCallPass, AVOIDCALL_NAME, AVOIDCALL_DESC, false, false)
68*5ffd83dbSDimitry Andric 
698bcb0991SDimitry Andric // A real instruction is a non-meta, non-pseudo instruction.  Some pseudos
708bcb0991SDimitry Andric // expand to nothing, and some expand to code. This logic conservatively assumes
718bcb0991SDimitry Andric // they might expand to nothing.
728bcb0991SDimitry Andric static bool isRealInstruction(MachineInstr &MI) {
738bcb0991SDimitry Andric   return !MI.isPseudo() && !MI.isMetaInstruction();
748bcb0991SDimitry Andric }
758bcb0991SDimitry Andric 
768bcb0991SDimitry Andric // Return true if this is a call instruction, but not a tail call.
778bcb0991SDimitry Andric static bool isCallInstruction(const MachineInstr &MI) {
788bcb0991SDimitry Andric   return MI.isCall() && !MI.isReturn();
798bcb0991SDimitry Andric }
808bcb0991SDimitry Andric 
818bcb0991SDimitry Andric bool X86AvoidTrailingCallPass::runOnMachineFunction(MachineFunction &MF) {
828bcb0991SDimitry Andric   const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();
838bcb0991SDimitry Andric   const X86InstrInfo &TII = *STI.getInstrInfo();
848bcb0991SDimitry Andric   assert(STI.isTargetWin64() && "pass only runs on Win64");
858bcb0991SDimitry Andric 
86*5ffd83dbSDimitry Andric   // We don't need to worry about any of the invariants described above if there
87*5ffd83dbSDimitry Andric   // is no unwind info (CFI).
88*5ffd83dbSDimitry Andric   if (!MF.hasWinCFI())
89*5ffd83dbSDimitry Andric     return false;
90*5ffd83dbSDimitry Andric 
918bcb0991SDimitry Andric   // FIXME: Perhaps this pass should also replace SEH_Epilogue by inserting nops
928bcb0991SDimitry Andric   // before epilogues.
938bcb0991SDimitry Andric 
948bcb0991SDimitry Andric   bool Changed = false;
958bcb0991SDimitry Andric   for (MachineBasicBlock &MBB : MF) {
968bcb0991SDimitry Andric     // Look for basic blocks that precede funclet entries or are at the end of
978bcb0991SDimitry Andric     // the function.
988bcb0991SDimitry Andric     MachineBasicBlock *NextMBB = MBB.getNextNode();
998bcb0991SDimitry Andric     if (NextMBB && !NextMBB->isEHFuncletEntry())
1008bcb0991SDimitry Andric       continue;
1018bcb0991SDimitry Andric 
102*5ffd83dbSDimitry Andric     // Find the last real instruction in this block.
103*5ffd83dbSDimitry Andric     auto LastRealInstr = llvm::find_if(reverse(MBB), isRealInstruction);
1048bcb0991SDimitry Andric 
105*5ffd83dbSDimitry Andric     // If the block is empty or the last real instruction is a call instruction,
106*5ffd83dbSDimitry Andric     // insert an int3. If there is a call instruction, insert the int3 between
107*5ffd83dbSDimitry Andric     // the call and any labels or other meta instructions. If the block is
108*5ffd83dbSDimitry Andric     // empty, insert at block end.
109*5ffd83dbSDimitry Andric     bool IsEmpty = LastRealInstr == MBB.rend();
110*5ffd83dbSDimitry Andric     bool IsCall = !IsEmpty && isCallInstruction(*LastRealInstr);
111*5ffd83dbSDimitry Andric     if (IsEmpty || IsCall) {
1128bcb0991SDimitry Andric       LLVM_DEBUG({
113*5ffd83dbSDimitry Andric         if (IsCall) {
1148bcb0991SDimitry Andric           dbgs() << "inserting int3 after trailing call instruction:\n";
1158bcb0991SDimitry Andric           LastRealInstr->dump();
1168bcb0991SDimitry Andric           dbgs() << '\n';
117*5ffd83dbSDimitry Andric         } else {
118*5ffd83dbSDimitry Andric           dbgs() << "inserting int3 in trailing empty MBB:\n";
119*5ffd83dbSDimitry Andric           MBB.dump();
120*5ffd83dbSDimitry Andric         }
1218bcb0991SDimitry Andric       });
1228bcb0991SDimitry Andric 
123*5ffd83dbSDimitry Andric       MachineBasicBlock::iterator MBBI = MBB.end();
124*5ffd83dbSDimitry Andric       DebugLoc DL;
125*5ffd83dbSDimitry Andric       if (IsCall) {
126*5ffd83dbSDimitry Andric         MBBI = std::next(LastRealInstr.getReverse());
127*5ffd83dbSDimitry Andric         DL = LastRealInstr->getDebugLoc();
128*5ffd83dbSDimitry Andric       }
129*5ffd83dbSDimitry Andric       BuildMI(MBB, MBBI, DL, TII.get(X86::INT3));
1308bcb0991SDimitry Andric       Changed = true;
1318bcb0991SDimitry Andric     }
1328bcb0991SDimitry Andric   }
1338bcb0991SDimitry Andric 
1348bcb0991SDimitry Andric   return Changed;
1358bcb0991SDimitry Andric }
136