diff options
Diffstat (limited to 'llvm/lib/Target/X86')
-rw-r--r-- | llvm/lib/Target/X86/X86FrameLowering.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.h | 3 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86InstrCompiler.td | 3 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.td | 3 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86MCInstLower.cpp | 14 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86TargetMachine.cpp | 10 |
7 files changed, 37 insertions, 10 deletions
diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index e1ed5aa5abc..681a618e2d5 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -2558,7 +2558,7 @@ bool blockEndIsUnreachable(const MachineBasicBlock &MBB, MBB.succ_begin(), MBB.succ_end(), [](const MachineBasicBlock *Succ) { return Succ->isEHPad(); }) && std::all_of(MBBI, MBB.end(), [](const MachineInstr &MI) { - return MI.isMetaInstruction(); + return MI.isMetaInstruction() || MI.getOpcode() == X86::SEH_NoReturn; }); } diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 1130fcf9c36..80006c9f035 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -4129,6 +4129,17 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, InFlag = Chain.getValue(1); } + // Insert a pseudo instruction after noreturn calls that expands to int3 if + // this would be the last instruction in the funclet. If the return address of + // a call refers to the last PC of a function, the Windows SEH machinery can + // get confused about which function or scope the return address belongs to. + // MSVC inserts int3 after every noreturn function call, but LLVM only places + // them when it would cause a problem otherwise. + if (CLI.DoesNotReturn && Subtarget.isTargetWin64()) { + Chain = DAG.getNode(X86ISD::SEH_NORETURN, dl, NodeTys, Chain, InFlag); + InFlag = Chain.getValue(1); + } + // Handle result values, copying them out of physregs into vregs that we // return. return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, DAG, @@ -28711,6 +28722,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::VASTART_SAVE_XMM_REGS: return "X86ISD::VASTART_SAVE_XMM_REGS"; case X86ISD::VAARG_64: return "X86ISD::VAARG_64"; case X86ISD::WIN_ALLOCA: return "X86ISD::WIN_ALLOCA"; + case X86ISD::SEH_NORETURN: return "X86ISD::SEH_NORETURN"; case X86ISD::MEMBARRIER: return "X86ISD::MEMBARRIER"; case X86ISD::MFENCE: return "X86ISD::MFENCE"; case X86ISD::SEG_ALLOCA: return "X86ISD::SEG_ALLOCA"; diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h index 05e4f16fc49..e8255da2393 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/lib/Target/X86/X86ISelLowering.h @@ -531,6 +531,9 @@ namespace llvm { // Windows's _chkstk call to do stack probing. WIN_ALLOCA, + // Expands to int3 or nothing, depending on basic block layout. + SEH_NORETURN, + // For allocating variable amounts of stack space when using // segmented stacks. Check if the current stacklet has enough space, and // falls back to heap allocation if not. diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td index efaccdc9ee9..8462f42ffbe 100644 --- a/llvm/lib/Target/X86/X86InstrCompiler.td +++ b/llvm/lib/Target/X86/X86InstrCompiler.td @@ -239,6 +239,9 @@ let isPseudo = 1, SchedRW = [WriteSystem] in { "#SEH_EndPrologue", []>; def SEH_Epilogue : I<0, Pseudo, (outs), (ins), "#SEH_Epilogue", []>; + let hasSideEffects = 1 in + def SEH_NoReturn : I<0, Pseudo, (outs), (ins), + "#SEH_NoReturn", [(X86SehNoReturn)]>; } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td index 75958dd6c9e..9765ac7a8eb 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.td +++ b/llvm/lib/Target/X86/X86InstrInfo.td @@ -289,6 +289,9 @@ def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>; def X86WinAlloca : SDNode<"X86ISD::WIN_ALLOCA", SDT_X86WIN_ALLOCA, [SDNPHasChain, SDNPOutGlue]>; +def X86SehNoReturn : SDNode<"X86ISD::SEH_NORETURN", SDTX86Void, + [SDNPHasChain, SDNPOutGlue]>; + def X86SegAlloca : SDNode<"X86ISD::SEG_ALLOCA", SDT_X86SEG_ALLOCA, [SDNPHasChain]>; diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp index 55f0420a928..38d4b1aa647 100644 --- a/llvm/lib/Target/X86/X86MCInstLower.cpp +++ b/llvm/lib/Target/X86/X86MCInstLower.cpp @@ -1929,6 +1929,20 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) { return; } + case X86::SEH_NoReturn: { + // Materialize an int3 if this instruction is in the last basic block in the + // function. The int3 serves the same purpose as the noop emitted above for + // SEH_Epilogue, which is to make the Win64 unwinder happy. If the return + // address of the preceding call appears to precede an epilogue or a new + // function, then the unwinder may get lost. + const MachineBasicBlock *MBB = MI->getParent(); + const MachineBasicBlock *NextMBB = MBB->getNextNode(); + if (!NextMBB || NextMBB->isEHPad()) { + EmitAndCountInstruction(MCInstBuilder(X86::INT3)); + } + return; + } + // Lower PSHUFB and VPERMILP normally but add a comment if we can find // a constant shuffle mask. We won't be able to do this at the MC layer // because the mask isn't an immediate. diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp index d33a7a0b963..f9839f39ec9 100644 --- a/llvm/lib/Target/X86/X86TargetMachine.cpp +++ b/llvm/lib/Target/X86/X86TargetMachine.cpp @@ -219,17 +219,9 @@ X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT, getEffectiveX86CodeModel(CM, JIT, TT.getArch() == Triple::x86_64), OL), TLOF(createTLOF(getTargetTriple())) { - // Windows stack unwinder gets confused when execution flow "falls through" - // after a call to 'noreturn' function. - // To prevent that, we emit a trap for 'unreachable' IR instructions. - // (which on X86, happens to be the 'ud2' instruction) // On PS4, the "return address" of a 'noreturn' call must still be within // the calling function, and TrapUnreachable is an easy way to get that. - // The check here for 64-bit windows is a bit icky, but as we're unlikely - // to ever want to mix 32 and 64-bit windows code in a single module - // this should be fine. - if ((TT.isOSWindows() && TT.getArch() == Triple::x86_64) || TT.isPS4() || - TT.isOSBinFormatMachO()) { + if (TT.isPS4() || TT.isOSBinFormatMachO()) { this->Options.TrapUnreachable = true; this->Options.NoTrapAfterNoreturn = TT.isOSBinFormatMachO(); } |