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 //
95ffd83dbSDimitry Andric // The Windows x64 unwinder decodes the instruction stream during unwinding.
105ffd83dbSDimitry Andric // The unwinder decodes forward from the current PC to detect epilogue code
115ffd83dbSDimitry Andric // patterns.
125ffd83dbSDimitry Andric //
135ffd83dbSDimitry Andric // First, this means that there must be an instruction after every
145ffd83dbSDimitry Andric // call instruction for the unwinder to decode. LLVM must maintain the invariant
155ffd83dbSDimitry Andric // that the last instruction of a function or funclet is not a call, or the
165ffd83dbSDimitry Andric // unwinder may decode into the next function. Similarly, a call may not
175ffd83dbSDimitry Andric // immediately precede an epilogue code pattern. As of this writing, the
185ffd83dbSDimitry Andric // SEH_Epilogue pseudo instruction takes care of that.
195ffd83dbSDimitry Andric //
205ffd83dbSDimitry Andric // Second, all non-tail call jump targets must be within the *half-open*
215ffd83dbSDimitry Andric // interval of the bounds of the function. The unwinder distinguishes between
225ffd83dbSDimitry Andric // internal jump instructions and tail calls in an epilogue sequence by checking
235ffd83dbSDimitry Andric // the jump target against the function bounds from the .pdata section. This
245ffd83dbSDimitry Andric // means that the last regular MBB of an LLVM function must not be empty if
255ffd83dbSDimitry Andric // there are regular jumps targeting it.
265ffd83dbSDimitry Andric //
275ffd83dbSDimitry Andric // This pass upholds these invariants by ensuring that blocks at the end of a
285ffd83dbSDimitry Andric // function or funclet are a) not empty and b) do not end in a CALL instruction.
295ffd83dbSDimitry Andric //
305ffd83dbSDimitry Andric // Unwinder implementation for reference:
315ffd83dbSDimitry 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"
38*81ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
398bcb0991SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
408bcb0991SDimitry Andric
415ffd83dbSDimitry Andric #define AVOIDCALL_DESC "X86 avoid trailing call pass"
425ffd83dbSDimitry Andric #define AVOIDCALL_NAME "x86-avoid-trailing-call"
435ffd83dbSDimitry Andric
445ffd83dbSDimitry Andric #define DEBUG_TYPE AVOIDCALL_NAME
458bcb0991SDimitry Andric
468bcb0991SDimitry Andric using namespace llvm;
478bcb0991SDimitry Andric
488bcb0991SDimitry Andric namespace {
498bcb0991SDimitry Andric class X86AvoidTrailingCallPass : public MachineFunctionPass {
508bcb0991SDimitry Andric public:
X86AvoidTrailingCallPass()518bcb0991SDimitry Andric X86AvoidTrailingCallPass() : MachineFunctionPass(ID) {}
528bcb0991SDimitry Andric
538bcb0991SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
548bcb0991SDimitry Andric
558bcb0991SDimitry Andric static char ID;
565ffd83dbSDimitry Andric
575ffd83dbSDimitry Andric private:
getPassName() const585ffd83dbSDimitry Andric StringRef getPassName() const override { return AVOIDCALL_DESC; }
598bcb0991SDimitry Andric };
605ffd83dbSDimitry Andric } // end anonymous namespace
618bcb0991SDimitry Andric
628bcb0991SDimitry Andric char X86AvoidTrailingCallPass::ID = 0;
638bcb0991SDimitry Andric
createX86AvoidTrailingCallPass()648bcb0991SDimitry Andric FunctionPass *llvm::createX86AvoidTrailingCallPass() {
658bcb0991SDimitry Andric return new X86AvoidTrailingCallPass();
668bcb0991SDimitry Andric }
678bcb0991SDimitry Andric
INITIALIZE_PASS(X86AvoidTrailingCallPass,AVOIDCALL_NAME,AVOIDCALL_DESC,false,false)685ffd83dbSDimitry Andric INITIALIZE_PASS(X86AvoidTrailingCallPass, AVOIDCALL_NAME, AVOIDCALL_DESC, false, false)
695ffd83dbSDimitry Andric
708bcb0991SDimitry Andric // A real instruction is a non-meta, non-pseudo instruction. Some pseudos
718bcb0991SDimitry Andric // expand to nothing, and some expand to code. This logic conservatively assumes
728bcb0991SDimitry Andric // they might expand to nothing.
73*81ad6265SDimitry Andric static bool isCallOrRealInstruction(MachineInstr &MI) {
74*81ad6265SDimitry Andric return MI.isCall() || (!MI.isPseudo() && !MI.isMetaInstruction());
758bcb0991SDimitry Andric }
768bcb0991SDimitry Andric
778bcb0991SDimitry Andric // Return true if this is a call instruction, but not a tail call.
isCallInstruction(const MachineInstr & MI)788bcb0991SDimitry Andric static bool isCallInstruction(const MachineInstr &MI) {
798bcb0991SDimitry Andric return MI.isCall() && !MI.isReturn();
808bcb0991SDimitry Andric }
818bcb0991SDimitry Andric
runOnMachineFunction(MachineFunction & MF)828bcb0991SDimitry Andric bool X86AvoidTrailingCallPass::runOnMachineFunction(MachineFunction &MF) {
838bcb0991SDimitry Andric const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();
848bcb0991SDimitry Andric const X86InstrInfo &TII = *STI.getInstrInfo();
858bcb0991SDimitry Andric assert(STI.isTargetWin64() && "pass only runs on Win64");
868bcb0991SDimitry Andric
875ffd83dbSDimitry Andric // We don't need to worry about any of the invariants described above if there
885ffd83dbSDimitry Andric // is no unwind info (CFI).
895ffd83dbSDimitry Andric if (!MF.hasWinCFI())
905ffd83dbSDimitry Andric return false;
915ffd83dbSDimitry Andric
928bcb0991SDimitry Andric // FIXME: Perhaps this pass should also replace SEH_Epilogue by inserting nops
938bcb0991SDimitry Andric // before epilogues.
948bcb0991SDimitry Andric
958bcb0991SDimitry Andric bool Changed = false;
968bcb0991SDimitry Andric for (MachineBasicBlock &MBB : MF) {
978bcb0991SDimitry Andric // Look for basic blocks that precede funclet entries or are at the end of
988bcb0991SDimitry Andric // the function.
998bcb0991SDimitry Andric MachineBasicBlock *NextMBB = MBB.getNextNode();
1008bcb0991SDimitry Andric if (NextMBB && !NextMBB->isEHFuncletEntry())
1018bcb0991SDimitry Andric continue;
1028bcb0991SDimitry Andric
1035ffd83dbSDimitry Andric // Find the last real instruction in this block.
104*81ad6265SDimitry Andric auto LastRealInstr = llvm::find_if(reverse(MBB), isCallOrRealInstruction);
1058bcb0991SDimitry Andric
1065ffd83dbSDimitry Andric // If the block is empty or the last real instruction is a call instruction,
1075ffd83dbSDimitry Andric // insert an int3. If there is a call instruction, insert the int3 between
1085ffd83dbSDimitry Andric // the call and any labels or other meta instructions. If the block is
1095ffd83dbSDimitry Andric // empty, insert at block end.
1105ffd83dbSDimitry Andric bool IsEmpty = LastRealInstr == MBB.rend();
1115ffd83dbSDimitry Andric bool IsCall = !IsEmpty && isCallInstruction(*LastRealInstr);
1125ffd83dbSDimitry Andric if (IsEmpty || IsCall) {
1138bcb0991SDimitry Andric LLVM_DEBUG({
1145ffd83dbSDimitry Andric if (IsCall) {
1158bcb0991SDimitry Andric dbgs() << "inserting int3 after trailing call instruction:\n";
1168bcb0991SDimitry Andric LastRealInstr->dump();
1178bcb0991SDimitry Andric dbgs() << '\n';
1185ffd83dbSDimitry Andric } else {
1195ffd83dbSDimitry Andric dbgs() << "inserting int3 in trailing empty MBB:\n";
1205ffd83dbSDimitry Andric MBB.dump();
1215ffd83dbSDimitry Andric }
1228bcb0991SDimitry Andric });
1238bcb0991SDimitry Andric
1245ffd83dbSDimitry Andric MachineBasicBlock::iterator MBBI = MBB.end();
1255ffd83dbSDimitry Andric DebugLoc DL;
1265ffd83dbSDimitry Andric if (IsCall) {
1275ffd83dbSDimitry Andric MBBI = std::next(LastRealInstr.getReverse());
1285ffd83dbSDimitry Andric DL = LastRealInstr->getDebugLoc();
1295ffd83dbSDimitry Andric }
1305ffd83dbSDimitry Andric BuildMI(MBB, MBBI, DL, TII.get(X86::INT3));
1318bcb0991SDimitry Andric Changed = true;
1328bcb0991SDimitry Andric }
1338bcb0991SDimitry Andric }
1348bcb0991SDimitry Andric
1358bcb0991SDimitry Andric return Changed;
1368bcb0991SDimitry Andric }
137