//===----- X86AvoidTrailingCall.cpp - Insert int3 after trailing calls ----===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // The Windows x64 unwinder decodes the instruction stream during unwinding. // The unwinder decodes forward from the current PC to detect epilogue code // patterns. // // First, this means that there must be an instruction after every // call instruction for the unwinder to decode. LLVM must maintain the invariant // that the last instruction of a function or funclet is not a call, or the // unwinder may decode into the next function. Similarly, a call may not // immediately precede an epilogue code pattern. As of this writing, the // SEH_Epilogue pseudo instruction takes care of that. // // Second, all non-tail call jump targets must be within the *half-open* // interval of the bounds of the function. The unwinder distinguishes between // internal jump instructions and tail calls in an epilogue sequence by checking // the jump target against the function bounds from the .pdata section. This // means that the last regular MBB of an LLVM function must not be empty if // there are regular jumps targeting it. // // This pass upholds these invariants by ensuring that blocks at the end of a // function or funclet are a) not empty and b) do not end in a CALL instruction. // // Unwinder implementation for reference: // https://github.com/dotnet/coreclr/blob/a9f3fc16483eecfc47fb79c362811d870be02249/src/unwinder/amd64/unwinder_amd64.cpp#L1015 // //===----------------------------------------------------------------------===// #include "X86.h" #include "X86InstrInfo.h" #include "X86Subtarget.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #define AVOIDCALL_DESC … #define AVOIDCALL_NAME … #define DEBUG_TYPE … usingnamespacellvm; namespace { class X86AvoidTrailingCallPass : public MachineFunctionPass { … }; } // end anonymous namespace char X86AvoidTrailingCallPass::ID = …; FunctionPass *llvm::createX86AvoidTrailingCallPass() { … } INITIALIZE_PASS(…) // A real instruction is a non-meta, non-pseudo instruction. Some pseudos // expand to nothing, and some expand to code. This logic conservatively assumes // they might expand to nothing. static bool isCallOrRealInstruction(MachineInstr &MI) { … } // Return true if this is a call instruction, but not a tail call. static bool isCallInstruction(const MachineInstr &MI) { … } bool X86AvoidTrailingCallPass::runOnMachineFunction(MachineFunction &MF) { … }