[llvm] [CodeGen] Inline stack guard check on Windows (PR #136290)
Omair Javaid via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 18 03:40:57 PDT 2025
https://github.com/omjavaid created https://github.com/llvm/llvm-project/pull/136290
This patch optimizes the Windows security cookie check mechanism by moving the comparison inline and only calling __security_check_cookie when the check fails. This reduces the overhead of making a DLL call for every function return.
Previously, we implemented this optimization through a dedicated pass (X86WinFixupBufferSecurityCheckPass) in PR #95904, but this solution appears generic and efficient. We have reverted that pass in favor of this new approach.
X86WinFixupBufferSecurityCheckPass is a machine-level pass that:
- Scanned through the generated code to find __security_check_cookie calls
- Modified these calls by splitting basic blocks
- Added comparison logic and conditional branching
- Required complex block management and live register computation
This new approach is simpler and more maintainable:
- Implements the optimization at instruction selection time when generating the security check sequence
- Directly emits the comparison and conditional branching
- No need for post-processing or basic block manipulation
- Generates more efficient code by design
We will abandon the AArch64 specific implementation of AArch64WinFixupBufferSecurityCheck pass in PR #121938 in favor of this more general solution.
Note: This solution is inspired from https://github.com/llvm/llvm-project/pull/121938#discussion_r1957778612 by @tamaspetz
>From 8e380d296c75a4eae6fca48b30af91069681c886 Mon Sep 17 00:00:00 2001
From: Muhammad Omair Javaid <omair.javaid at linaro.org>
Date: Tue, 15 Apr 2025 03:14:14 +0500
Subject: [PATCH 1/2] Revert "[X86][CodeGen] security check cookie execute only
when needed (#95904)"
This reverts commit 854bbc50fc99ddf71c4c65193e06eb79ce1ef69f.
---
llvm/lib/Target/X86/CMakeLists.txt | 1 -
llvm/lib/Target/X86/X86.h | 4 -
llvm/lib/Target/X86/X86TargetMachine.cpp | 1 -
.../X86/X86WinFixupBufferSecurityCheck.cpp | 245 ------------------
llvm/test/CodeGen/X86/opt-pipeline.ll | 1 -
llvm/test/CodeGen/X86/stack-protector-msvc.ll | 28 +-
llvm/test/CodeGen/X86/tailcc-ssp.ll | 20 +-
7 files changed, 10 insertions(+), 290 deletions(-)
delete mode 100644 llvm/lib/Target/X86/X86WinFixupBufferSecurityCheck.cpp
diff --git a/llvm/lib/Target/X86/CMakeLists.txt b/llvm/lib/Target/X86/CMakeLists.txt
index 9553a8619feb5..44a54c8ec62cb 100644
--- a/llvm/lib/Target/X86/CMakeLists.txt
+++ b/llvm/lib/Target/X86/CMakeLists.txt
@@ -83,7 +83,6 @@ set(sources
X86TargetTransformInfo.cpp
X86VZeroUpper.cpp
X86WinEHState.cpp
- X86WinFixupBufferSecurityCheck.cpp
X86InsertWait.cpp
GISel/X86CallLowering.cpp
GISel/X86InstructionSelector.cpp
diff --git a/llvm/lib/Target/X86/X86.h b/llvm/lib/Target/X86/X86.h
index 48a3fe1934a96..98faae9f14dbc 100644
--- a/llvm/lib/Target/X86/X86.h
+++ b/llvm/lib/Target/X86/X86.h
@@ -73,9 +73,6 @@ FunctionPass *createX86OptimizeLEAs();
/// Return a pass that transforms setcc + movzx pairs into xor + setcc.
FunctionPass *createX86FixupSetCC();
-/// Return a pass that transform inline buffer security check into seperate bb
-FunctionPass *createX86WinFixupBufferSecurityCheckPass();
-
/// Return a pass that avoids creating store forward block issues in the hardware.
FunctionPass *createX86AvoidStoreForwardingBlocks();
@@ -190,7 +187,6 @@ void initializeX86ExpandPseudoPass(PassRegistry &);
void initializeX86FastPreTileConfigPass(PassRegistry &);
void initializeX86FastTileConfigPass(PassRegistry &);
void initializeX86FixupSetCCPassPass(PassRegistry &);
-void initializeX86WinFixupBufferSecurityCheckPassPass(PassRegistry &);
void initializeX86FlagsCopyLoweringPassPass(PassRegistry &);
void initializeX86LoadValueInjectionLoadHardeningPassPass(PassRegistry &);
void initializeX86LoadValueInjectionRetHardeningPassPass(PassRegistry &);
diff --git a/llvm/lib/Target/X86/X86TargetMachine.cpp b/llvm/lib/Target/X86/X86TargetMachine.cpp
index 4cecbbf27aa30..c5e76b1c38d26 100644
--- a/llvm/lib/Target/X86/X86TargetMachine.cpp
+++ b/llvm/lib/Target/X86/X86TargetMachine.cpp
@@ -552,7 +552,6 @@ bool X86PassConfig::addPreISel() {
void X86PassConfig::addPreRegAlloc() {
if (getOptLevel() != CodeGenOptLevel::None) {
addPass(&LiveRangeShrinkID);
- addPass(createX86WinFixupBufferSecurityCheckPass());
addPass(createX86FixupSetCC());
addPass(createX86OptimizeLEAs());
addPass(createX86CallFrameOptimization());
diff --git a/llvm/lib/Target/X86/X86WinFixupBufferSecurityCheck.cpp b/llvm/lib/Target/X86/X86WinFixupBufferSecurityCheck.cpp
deleted file mode 100644
index 5c12af1fee637..0000000000000
--- a/llvm/lib/Target/X86/X86WinFixupBufferSecurityCheck.cpp
+++ /dev/null
@@ -1,245 +0,0 @@
-//===- X86WinFixupBufferSecurityCheck.cpp Fix Buffer Security Check Call -===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-// Buffer Security Check implementation inserts windows specific callback into
-// code. On windows, __security_check_cookie call gets call everytime function
-// is return without fixup. Since this function is defined in runtime library,
-// it incures cost of call in dll which simply does comparison and returns most
-// time. With Fixup, We selective move to call in DLL only if comparison fails.
-//===----------------------------------------------------------------------===//
-
-#include "X86.h"
-#include "X86FrameLowering.h"
-#include "X86InstrInfo.h"
-#include "X86Subtarget.h"
-#include "llvm/CodeGen/LivePhysRegs.h"
-#include "llvm/CodeGen/MachineFunctionPass.h"
-#include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/IR/Module.h"
-
-using namespace llvm;
-
-#define DEBUG_TYPE "x86-win-fixup-bscheck"
-
-namespace {
-
-class X86WinFixupBufferSecurityCheckPass : public MachineFunctionPass {
-public:
- static char ID;
-
- X86WinFixupBufferSecurityCheckPass() : MachineFunctionPass(ID) {}
-
- StringRef getPassName() const override {
- return "X86 Windows Fixup Buffer Security Check";
- }
-
- bool runOnMachineFunction(MachineFunction &MF) override;
-
- std::pair<MachineBasicBlock *, MachineInstr *>
- getSecurityCheckerBasicBlock(MachineFunction &MF);
-
- void getGuardCheckSequence(MachineBasicBlock *CurMBB, MachineInstr *CheckCall,
- MachineInstr *SeqMI[5]);
-
- void SplitBasicBlock(MachineBasicBlock *CurMBB, MachineBasicBlock *NewRetMBB,
- MachineBasicBlock::iterator SplitIt);
-
- void FinishBlock(MachineBasicBlock *MBB);
-
- void FinishFunction(MachineBasicBlock *FailMBB, MachineBasicBlock *NewRetMBB);
-
- std::pair<MachineInstr *, MachineInstr *>
- CreateFailCheckSequence(MachineBasicBlock *CurMBB, MachineBasicBlock *FailMBB,
- MachineInstr *SeqMI[5]);
-};
-} // end anonymous namespace
-
-char X86WinFixupBufferSecurityCheckPass::ID = 0;
-
-INITIALIZE_PASS(X86WinFixupBufferSecurityCheckPass, DEBUG_TYPE, DEBUG_TYPE,
- false, false)
-
-FunctionPass *llvm::createX86WinFixupBufferSecurityCheckPass() {
- return new X86WinFixupBufferSecurityCheckPass();
-}
-
-void X86WinFixupBufferSecurityCheckPass::SplitBasicBlock(
- MachineBasicBlock *CurMBB, MachineBasicBlock *NewRetMBB,
- MachineBasicBlock::iterator SplitIt) {
- NewRetMBB->splice(NewRetMBB->end(), CurMBB, SplitIt, CurMBB->end());
-}
-
-std::pair<MachineBasicBlock *, MachineInstr *>
-X86WinFixupBufferSecurityCheckPass::getSecurityCheckerBasicBlock(
- MachineFunction &MF) {
- MachineBasicBlock::reverse_iterator RBegin, REnd;
-
- for (auto &MBB : llvm::reverse(MF)) {
- for (RBegin = MBB.rbegin(), REnd = MBB.rend(); RBegin != REnd; ++RBegin) {
- auto &MI = *RBegin;
- if (MI.getOpcode() == X86::CALL64pcrel32 &&
- MI.getNumExplicitOperands() == 1) {
- auto MO = MI.getOperand(0);
- if (MO.isGlobal()) {
- auto Callee = dyn_cast<Function>(MO.getGlobal());
- if (Callee && Callee->getName() == "__security_check_cookie") {
- return std::make_pair(&MBB, &MI);
- break;
- }
- }
- }
- }
- }
- return std::make_pair(nullptr, nullptr);
-}
-
-void X86WinFixupBufferSecurityCheckPass::getGuardCheckSequence(
- MachineBasicBlock *CurMBB, MachineInstr *CheckCall,
- MachineInstr *SeqMI[5]) {
-
- MachineBasicBlock::iterator UIt(CheckCall);
- MachineBasicBlock::reverse_iterator DIt(CheckCall);
- // Seq From StackUp to Stack Down Is fixed.
- // ADJCALLSTACKUP64
- ++UIt;
- SeqMI[4] = &*UIt;
-
- // CALL __security_check_cookie
- SeqMI[3] = CheckCall;
-
- // COPY function slot cookie
- ++DIt;
- SeqMI[2] = &*DIt;
-
- // ADJCALLSTACKDOWN64
- ++DIt;
- SeqMI[1] = &*DIt;
-
- MachineBasicBlock::reverse_iterator XIt(SeqMI[1]);
- for (; XIt != CurMBB->rbegin(); ++XIt) {
- auto &CI = *XIt;
- if ((CI.getOpcode() == X86::XOR64_FP) || (CI.getOpcode() == X86::XOR32_FP))
- break;
- }
- SeqMI[0] = &*XIt;
-}
-
-std::pair<MachineInstr *, MachineInstr *>
-X86WinFixupBufferSecurityCheckPass::CreateFailCheckSequence(
- MachineBasicBlock *CurMBB, MachineBasicBlock *FailMBB,
- MachineInstr *SeqMI[5]) {
-
- auto MF = CurMBB->getParent();
-
- Module &M = *MF->getFunction().getParent();
- GlobalVariable *GV = M.getGlobalVariable("__security_cookie");
- assert(GV && " Security Cookie was not installed!");
-
- const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
-
- MachineInstr *GuardXor = SeqMI[0];
- MachineBasicBlock::iterator InsertPt(GuardXor);
- ++InsertPt;
-
- // Compare security_Cookie with XOR_Val, if not same, we have violation
- auto CMI = BuildMI(*CurMBB, InsertPt, DebugLoc(), TII->get(X86::CMP64rm))
- .addReg(GuardXor->getOperand(0).getReg())
- .addReg(X86::RIP)
- .addImm(1)
- .addReg(X86::NoRegister)
- .addGlobalAddress(GV)
- .addReg(X86::NoRegister);
-
- BuildMI(*CurMBB, InsertPt, DebugLoc(), TII->get(X86::JCC_1))
- .addMBB(FailMBB)
- .addImm(X86::COND_NE);
-
- auto JMI = BuildMI(*CurMBB, InsertPt, DebugLoc(), TII->get(X86::JMP_1));
-
- return std::make_pair(CMI.getInstr(), JMI.getInstr());
-}
-
-void X86WinFixupBufferSecurityCheckPass::FinishBlock(MachineBasicBlock *MBB) {
- LivePhysRegs LiveRegs;
- computeAndAddLiveIns(LiveRegs, *MBB);
-}
-
-void X86WinFixupBufferSecurityCheckPass::FinishFunction(
- MachineBasicBlock *FailMBB, MachineBasicBlock *NewRetMBB) {
- FailMBB->getParent()->RenumberBlocks();
- // FailMBB includes call to MSCV RT where is __security_check_cookie
- // function is called. This function uses regcall and it expects cookie
- // value from stack slot.( even if this is modified)
- // Before going further we compute back livein for this block to make sure
- // it is live and provided.
- FinishBlock(FailMBB);
- FinishBlock(NewRetMBB);
-}
-
-bool X86WinFixupBufferSecurityCheckPass::runOnMachineFunction(
- MachineFunction &MF) {
- bool Changed = false;
- const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();
-
- if (!(STI.isTargetWindowsItanium() || STI.isTargetWindowsMSVC()))
- return Changed;
-
- // Check if security cookie was installed or not
- Module &M = *MF.getFunction().getParent();
- GlobalVariable *GV = M.getGlobalVariable("__security_cookie");
- if (!GV)
- return Changed;
-
- const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
-
- // Check if security check cookie was installed or not
- auto [CurMBB, CheckCall] = getSecurityCheckerBasicBlock(MF);
-
- if (!CheckCall)
- return Changed;
-
- MachineBasicBlock *FailMBB = MF.CreateMachineBasicBlock();
- MachineBasicBlock *NewRetMBB = MF.CreateMachineBasicBlock();
-
- MF.insert(MF.end(), NewRetMBB);
- MF.insert(MF.end(), FailMBB);
-
- MachineInstr *SeqMI[5];
- getGuardCheckSequence(CurMBB, CheckCall, SeqMI);
- // MachineInstr * GuardXor = SeqMI[0];
-
- auto FailSeqRange = CreateFailCheckSequence(CurMBB, FailMBB, SeqMI);
- MachineInstrBuilder JMI(MF, FailSeqRange.second);
-
- // After Inserting JMP_1, we can not have two terminators
- // in same block, split CurrentMBB after JMP_1
- MachineBasicBlock::iterator SplitIt(SeqMI[4]);
- ++SplitIt;
- SplitBasicBlock(CurMBB, NewRetMBB, SplitIt);
-
- // Fill up Failure Routine, move Fail Check Squence from CurMBB to FailMBB
- MachineBasicBlock::iterator U1It(SeqMI[1]);
- MachineBasicBlock::iterator U2It(SeqMI[4]);
- ++U2It;
- FailMBB->splice(FailMBB->end(), CurMBB, U1It, U2It);
- BuildMI(*FailMBB, FailMBB->end(), DebugLoc(), TII->get(X86::INT3));
-
- // Move left over instruction after StackUp
- // from Current Basic BLocks into New Return Block
- JMI.addMBB(NewRetMBB);
- MachineBasicBlock::iterator SplicePt(JMI.getInstr());
- ++SplicePt;
- if (SplicePt != CurMBB->end())
- NewRetMBB->splice(NewRetMBB->end(), CurMBB, SplicePt);
-
- // Restructure Basic Blocks
- CurMBB->addSuccessor(NewRetMBB);
- CurMBB->addSuccessor(FailMBB);
-
- FinishFunction(FailMBB, NewRetMBB);
- return !Changed;
-}
diff --git a/llvm/test/CodeGen/X86/opt-pipeline.ll b/llvm/test/CodeGen/X86/opt-pipeline.ll
index d72f517cfb603..5dd368a9e1439 100644
--- a/llvm/test/CodeGen/X86/opt-pipeline.ll
+++ b/llvm/test/CodeGen/X86/opt-pipeline.ll
@@ -121,7 +121,6 @@
; CHECK-NEXT: Peephole Optimizations
; CHECK-NEXT: Remove dead machine instructions
; CHECK-NEXT: Live Range Shrink
-; CHECK-NEXT: X86 Windows Fixup Buffer Security Check
; CHECK-NEXT: X86 Fixup SetCC
; CHECK-NEXT: Lazy Machine Block Frequency Analysis
; CHECK-NEXT: X86 LEA Optimize
diff --git a/llvm/test/CodeGen/X86/stack-protector-msvc.ll b/llvm/test/CodeGen/X86/stack-protector-msvc.ll
index d718062d2c485..7cb36aa9db672 100644
--- a/llvm/test/CodeGen/X86/stack-protector-msvc.ll
+++ b/llvm/test/CodeGen/X86/stack-protector-msvc.ll
@@ -49,15 +49,10 @@ define void @test(ptr %a) nounwind ssp {
; MSVC-X64-NEXT: callq printf
; MSVC-X64-NEXT: movq {{[0-9]+}}(%rsp), %rcx
; MSVC-X64-NEXT: xorq %rsp, %rcx
-; MSVC-X64-NEXT: cmpq __security_cookie(%rip), %rcx
-; MSVC-X64-NEXT: jne .LBB0_2
-; MSVC-X64-NEXT: # %bb.1:
+; MSVC-X64-NEXT: callq __security_check_cookie
; MSVC-X64-NEXT: addq $64, %rsp
; MSVC-X64-NEXT: popq %rsi
; MSVC-X64-NEXT: retq
-; MSVC-X64-NEXT: .LBB0_2:
-; MSVC-X64-NEXT: callq __security_check_cookie
-; MSVC-X64-NEXT: int3
;
; MSVC-X86-O0-LABEL: test:
; MSVC-X86-O0: # %bb.0: # %entry
@@ -160,17 +155,11 @@ define void @test_vla(i32 %n) nounwind ssp {
; MSVC-X64-NEXT: addq $32, %rsp
; MSVC-X64-NEXT: movq -8(%rbp), %rcx
; MSVC-X64-NEXT: xorq %rbp, %rcx
-; MSVC-X64-NEXT: cmpq __security_cookie(%rip), %rcx
-; MSVC-X64-NEXT: jne .LBB1_2
-; MSVC-X64-NEXT: # %bb.1:
+; MSVC-X64-NEXT: subq $32, %rsp
+; MSVC-X64-NEXT: callq __security_check_cookie
; MSVC-X64-NEXT: movq %rbp, %rsp
; MSVC-X64-NEXT: popq %rbp
; MSVC-X64-NEXT: retq
-; MSVC-X64-NEXT: .LBB1_2:
-; MSVC-X64-NEXT: subq $32, %rsp
-; MSVC-X64-NEXT: callq __security_check_cookie
-; MSVC-X64-NEXT: addq $32, %rsp
-; MSVC-X64-NEXT: int3
;
; MSVC-X86-O0-LABEL: test_vla:
; MSVC-X86-O0: # %bb.0:
@@ -288,19 +277,13 @@ define void @test_vla_realign(i32 %n) nounwind ssp {
; MSVC-X64-NEXT: addq $32, %rsp
; MSVC-X64-NEXT: movq 24(%rbx), %rcx
; MSVC-X64-NEXT: xorq %rbp, %rcx
-; MSVC-X64-NEXT: cmpq __security_cookie(%rip), %rcx
-; MSVC-X64-NEXT: jne .LBB2_2
-; MSVC-X64-NEXT: # %bb.1:
+; MSVC-X64-NEXT: subq $32, %rsp
+; MSVC-X64-NEXT: callq __security_check_cookie
; MSVC-X64-NEXT: movq %rbp, %rsp
; MSVC-X64-NEXT: popq %rbx
; MSVC-X64-NEXT: popq %rsi
; MSVC-X64-NEXT: popq %rbp
; MSVC-X64-NEXT: retq
-; MSVC-X64-NEXT: .LBB2_2:
-; MSVC-X64-NEXT: subq $32, %rsp
-; MSVC-X64-NEXT: callq __security_check_cookie
-; MSVC-X64-NEXT: addq $32, %rsp
-; MSVC-X64-NEXT: int3
;
; MSVC-X86-O0-LABEL: test_vla_realign:
; MSVC-X86-O0: # %bb.0:
@@ -377,3 +360,4 @@ define void @test_vla_realign(i32 %n) nounwind ssp {
declare ptr @strcpy(ptr, ptr) nounwind
declare i32 @printf(ptr, ...) nounwind
+
diff --git a/llvm/test/CodeGen/X86/tailcc-ssp.ll b/llvm/test/CodeGen/X86/tailcc-ssp.ll
index 5211e4fe9eef9..672046a19e5ee 100644
--- a/llvm/test/CodeGen/X86/tailcc-ssp.ll
+++ b/llvm/test/CodeGen/X86/tailcc-ssp.ll
@@ -15,9 +15,7 @@ define tailcc void @tailcall_frame(ptr %0, i64 %1) sspreq {
; WINDOWS-NEXT: movq %rax, {{[0-9]+}}(%rsp)
; WINDOWS-NEXT: movq {{[0-9]+}}(%rsp), %rcx
; WINDOWS-NEXT: xorq %rsp, %rcx
-; WINDOWS-NEXT: cmpq __security_cookie(%rip), %rcx
-; WINDOWS-NEXT: jne .LBB0_1
-; WINDOWS-NEXT: # %bb.2:
+; WINDOWS-NEXT: callq __security_check_cookie
; WINDOWS-NEXT: xorl %ecx, %ecx
; WINDOWS-NEXT: xorl %edx, %edx
; WINDOWS-NEXT: xorl %r8d, %r8d
@@ -25,9 +23,6 @@ define tailcc void @tailcall_frame(ptr %0, i64 %1) sspreq {
; WINDOWS-NEXT: addq $56, %rsp
; WINDOWS-NEXT: .seh_endepilogue
; WINDOWS-NEXT: jmp h # TAILCALL
-; WINDOWS-NEXT: .LBB0_1:
-; WINDOWS-NEXT: callq __security_check_cookie
-; WINDOWS-NEXT: int3
; WINDOWS-NEXT: .seh_endproc
;
; LINUX-LABEL: tailcall_frame:
@@ -49,7 +44,6 @@ define tailcc void @tailcall_frame(ptr %0, i64 %1) sspreq {
; LINUX-NEXT: .LBB0_2: # %CallStackCheckFailBlk
; LINUX-NEXT: .cfi_def_cfa_offset 32
; LINUX-NEXT: callq __stack_chk_fail at PLT
-
tail call tailcc void @h(ptr null, i64 0, ptr null)
ret void
}
@@ -67,18 +61,13 @@ define void @tailcall_unrelated_frame() sspreq {
; WINDOWS-NEXT: callq bar
; WINDOWS-NEXT: movq {{[0-9]+}}(%rsp), %rcx
; WINDOWS-NEXT: xorq %rsp, %rcx
-; WINDOWS-NEXT: cmpq __security_cookie(%rip), %rcx
-; WINDOWS-NEXT: jne .LBB1_1
-; WINDOWS-NEXT: # %bb.2:
-; WINDOWS-NEXT: .seh_startepilogue
+; WINDOWS-NEXT: callq __security_check_cookie
+; WINDOWS-NEXT: nop
; WINDOWS-NEXT: addq $40, %rsp
; WINDOWS-NEXT: .seh_endepilogue
; WINDOWS-NEXT: jmp bar # TAILCALL
-; WINDOWS-NEXT: .LBB1_1:
-; WINDOWS-NEXT: callq __security_check_cookie
-; WINDOWS-NEXT: int3
; WINDOWS-NEXT: .seh_endproc
-
+;
; LINUX-LABEL: tailcall_unrelated_frame:
; LINUX: # %bb.0:
; LINUX-NEXT: pushq %rax
@@ -96,7 +85,6 @@ define void @tailcall_unrelated_frame() sspreq {
; LINUX-NEXT: .LBB1_2: # %CallStackCheckFailBlk
; LINUX-NEXT: .cfi_def_cfa_offset 16
; LINUX-NEXT: callq __stack_chk_fail at PLT
-
call void @bar()
tail call void @bar()
ret void
>From 32e051bb95e4e3f6a3c173b5b8354219e864319a Mon Sep 17 00:00:00 2001
From: Muhammad Omair Javaid <omair.javaid at linaro.org>
Date: Tue, 15 Apr 2025 02:41:05 +0500
Subject: [PATCH 2/2] Inline stack guard check on Windows
---
.../SelectionDAG/SelectionDAGBuilder.cpp | 93 +++++++-----
.../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 29 +---
.../irtranslator-stack-protector-windows.ll | 12 +-
llvm/test/CodeGen/X86/stack-protector-msvc.ll | 133 +++++++++++++++---
llvm/test/CodeGen/X86/tailcc-ssp.ll | 49 +++++--
llvm/test/DebugInfo/COFF/fpo-stack-protect.ll | 7 +-
6 files changed, 228 insertions(+), 95 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 8cae34d06c8ba..f2265c7f68e12 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3059,33 +3059,6 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD,
if (TLI.useStackGuardXorFP())
GuardVal = TLI.emitStackGuardXorFP(DAG, GuardVal, dl);
- // Retrieve guard check function, nullptr if instrumentation is inlined.
- if (const Function *GuardCheckFn = TLI.getSSPStackGuardCheck(M)) {
- // The target provides a guard check function to validate the guard value.
- // Generate a call to that function with the content of the guard slot as
- // argument.
- FunctionType *FnTy = GuardCheckFn->getFunctionType();
- assert(FnTy->getNumParams() == 1 && "Invalid function signature");
-
- TargetLowering::ArgListTy Args;
- TargetLowering::ArgListEntry Entry;
- Entry.Node = GuardVal;
- Entry.Ty = FnTy->getParamType(0);
- if (GuardCheckFn->hasParamAttribute(0, Attribute::AttrKind::InReg))
- Entry.IsInReg = true;
- Args.push_back(Entry);
-
- TargetLowering::CallLoweringInfo CLI(DAG);
- CLI.setDebugLoc(getCurSDLoc())
- .setChain(DAG.getEntryNode())
- .setCallee(GuardCheckFn->getCallingConv(), FnTy->getReturnType(),
- getValue(GuardCheckFn), std::move(Args));
-
- std::pair<SDValue, SDValue> Result = TLI.LowerCallTo(CLI);
- DAG.setRoot(Result.second);
- return;
- }
-
// If useLoadStackGuardNode returns true, generate LOAD_STACK_GUARD.
// Otherwise, emit a volatile load to retrieve the stack guard value.
SDValue Chain = DAG.getEntryNode();
@@ -3126,14 +3099,66 @@ void SelectionDAGBuilder::visitSPDescriptorParent(StackProtectorDescriptor &SPD,
/// For a high level explanation of how this fits into the stack protector
/// generation see the comment on the declaration of class
/// StackProtectorDescriptor.
-void
-SelectionDAGBuilder::visitSPDescriptorFailure(StackProtectorDescriptor &SPD) {
+void SelectionDAGBuilder::visitSPDescriptorFailure(
+ StackProtectorDescriptor &SPD) {
+
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
- TargetLowering::MakeLibCallOptions CallOptions;
- CallOptions.setDiscardResult(true);
- SDValue Chain = TLI.makeLibCall(DAG, RTLIB::STACKPROTECTOR_CHECK_FAIL,
- MVT::isVoid, {}, CallOptions, getCurSDLoc())
- .second;
+ MachineBasicBlock *ParentBB = SPD.getParentMBB();
+ const Module &M = *ParentBB->getParent()->getFunction().getParent();
+ SDValue Chain;
+
+ // Retrieve guard check function, nullptr if instrumentation is inlined.
+ if (const Function *GuardCheckFn = TLI.getSSPStackGuardCheck(M)) {
+
+ // First create the loads to the guard/stack slot for the comparison.
+ EVT PtrTy = TLI.getPointerTy(DAG.getDataLayout());
+ EVT PtrMemTy = TLI.getPointerMemTy(DAG.getDataLayout());
+
+ MachineFrameInfo &MFI = ParentBB->getParent()->getFrameInfo();
+ int FI = MFI.getStackProtectorIndex();
+
+ SDLoc dl = getCurSDLoc();
+ SDValue StackSlotPtr = DAG.getFrameIndex(FI, PtrTy);
+ Align Align = DAG.getDataLayout().getPrefTypeAlign(
+ PointerType::get(M.getContext(), 0));
+
+ // Generate code to load the content of the guard slot.
+ SDValue GuardVal = DAG.getLoad(
+ PtrMemTy, dl, DAG.getEntryNode(), StackSlotPtr,
+ MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), Align,
+ MachineMemOperand::MOVolatile);
+
+ if (TLI.useStackGuardXorFP())
+ GuardVal = TLI.emitStackGuardXorFP(DAG, GuardVal, dl);
+
+ // The target provides a guard check function to validate the guard value.
+ // Generate a call to that function with the content of the guard slot as
+ // argument.
+ FunctionType *FnTy = GuardCheckFn->getFunctionType();
+ assert(FnTy->getNumParams() == 1 && "Invalid function signature");
+
+ TargetLowering::ArgListTy Args;
+ TargetLowering::ArgListEntry Entry;
+ Entry.Node = GuardVal;
+ Entry.Ty = FnTy->getParamType(0);
+ if (GuardCheckFn->hasParamAttribute(0, Attribute::AttrKind::InReg))
+ Entry.IsInReg = true;
+ Args.push_back(Entry);
+
+ TargetLowering::CallLoweringInfo CLI(DAG);
+ CLI.setDebugLoc(getCurSDLoc())
+ .setChain(DAG.getEntryNode())
+ .setCallee(GuardCheckFn->getCallingConv(), FnTy->getReturnType(),
+ getValue(GuardCheckFn), std::move(Args));
+
+ Chain = TLI.LowerCallTo(CLI).second;
+ } else {
+ TargetLowering::MakeLibCallOptions CallOptions;
+ CallOptions.setDiscardResult(true);
+ Chain = TLI.makeLibCall(DAG, RTLIB::STACKPROTECTOR_CHECK_FAIL, MVT::isVoid,
+ {}, CallOptions, getCurSDLoc())
+ .second;
+ }
// Emit a trap instruction if we are required to do so.
const TargetOptions &TargetOpts = DAG.getTarget().Options;
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 598de6b207754..2a75dd7d8419b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -1881,12 +1881,9 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
FastIS->recomputeInsertPt();
}
- if (SP->shouldEmitSDCheck(*LLVMBB)) {
- bool FunctionBasedInstrumentation =
- TLI->getSSPStackGuardCheck(*Fn.getParent());
+ if (SP->shouldEmitSDCheck(*LLVMBB))
SDB->SPDescriptor.initialize(LLVMBB, FuncInfo->getMBB(LLVMBB),
- FunctionBasedInstrumentation);
- }
+ false);
if (Begin != BI)
++NumDAGBlocks;
@@ -1948,24 +1945,7 @@ SelectionDAGISel::FinishBasicBlock() {
PHI.addReg(FuncInfo->PHINodesToUpdate[i].second).addMBB(FuncInfo->MBB);
}
- // Handle stack protector.
- if (SDB->SPDescriptor.shouldEmitFunctionBasedCheckStackProtector()) {
- // The target provides a guard check function. There is no need to
- // generate error handling code or to split current basic block.
- MachineBasicBlock *ParentMBB = SDB->SPDescriptor.getParentMBB();
-
- // Add load and check to the basicblock.
- FuncInfo->MBB = ParentMBB;
- FuncInfo->InsertPt =
- findSplitPointForStackProtector(ParentMBB, *TII);
- SDB->visitSPDescriptorParent(SDB->SPDescriptor, ParentMBB);
- CurDAG->setRoot(SDB->getRoot());
- SDB->clear();
- CodeGenAndEmitDAG();
-
- // Clear the Per-BB State.
- SDB->SPDescriptor.resetPerBBState();
- } else if (SDB->SPDescriptor.shouldEmitStackProtector()) {
+ if (SDB->SPDescriptor.shouldEmitStackProtector()) {
MachineBasicBlock *ParentMBB = SDB->SPDescriptor.getParentMBB();
MachineBasicBlock *SuccessMBB = SDB->SPDescriptor.getSuccessMBB();
@@ -1979,8 +1959,7 @@ SelectionDAGISel::FinishBasicBlock() {
findSplitPointForStackProtector(ParentMBB, *TII);
// Splice the terminator of ParentMBB into SuccessMBB.
- SuccessMBB->splice(SuccessMBB->end(), ParentMBB,
- SplitPoint,
+ SuccessMBB->splice(SuccessMBB->end(), ParentMBB, SplitPoint,
ParentMBB->end());
// Add compare/jump on neq/jump to the parent BB.
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
index 6aefc5341da07..83b964a89d44d 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-windows.ll
@@ -17,8 +17,12 @@ define void @caller() sspreq {
; CHECK-NEXT: ldr x8, [x8, :lo12:__security_cookie]
; CHECK-NEXT: str x8, [sp, #8]
; CHECK-NEXT: bl callee
-; CHECK-NEXT: ldr x0, [sp, #8]
-; CHECK-NEXT: bl __security_check_cookie
+; CHECK-NEXT: adrp x8, __security_cookie
+; CHECK-NEXT: ldr x9, [sp, #8]
+; CHECK-NEXT: ldr x8, [x8, :lo12:__security_cookie]
+; CHECK-NEXT: cmp x8, x9
+; CHECK-NEXT: b.ne .LBB0_2
+; CHECK-NEXT: // %bb.1: // %entry
; CHECK-NEXT: .seh_startepilogue
; CHECK-NEXT: ldr x30, [sp, #16] // 8-byte Folded Reload
; CHECK-NEXT: .seh_save_reg x30, 16
@@ -26,6 +30,10 @@ define void @caller() sspreq {
; CHECK-NEXT: .seh_stackalloc 32
; CHECK-NEXT: .seh_endepilogue
; CHECK-NEXT: ret
+; CHECK-NEXT: .LBB0_2: // %entry
+; CHECK-NEXT: ldr x0, [sp, #8]
+; CHECK-NEXT: bl __security_check_cookie
+; CHECK-NEXT: brk #0x1
; CHECK-NEXT: .seh_endfunclet
; CHECK-NEXT: .seh_endproc
entry:
diff --git a/llvm/test/CodeGen/X86/stack-protector-msvc.ll b/llvm/test/CodeGen/X86/stack-protector-msvc.ll
index 7cb36aa9db672..142c7d7b57b4b 100644
--- a/llvm/test/CodeGen/X86/stack-protector-msvc.ll
+++ b/llvm/test/CodeGen/X86/stack-protector-msvc.ll
@@ -25,12 +25,20 @@ define void @test(ptr %a) nounwind ssp {
; MSVC-X86-NEXT: pushl $LC
; MSVC-X86-NEXT: calll _printf
; MSVC-X86-NEXT: addl $8, %esp
-; MSVC-X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
-; MSVC-X86-NEXT: xorl %esp, %ecx
-; MSVC-X86-NEXT: calll @__security_check_cookie at 4
+; MSVC-X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; MSVC-X86-NEXT: xorl %esp, %eax
+; MSVC-X86-NEXT: movl ___security_cookie, %ecx
+; MSVC-X86-NEXT: cmpl %eax, %ecx
+; MSVC-X86-NEXT: jne LBB0_2
+; MSVC-X86: # %bb.1: # %return
; MSVC-X86-NEXT: addl $12, %esp
; MSVC-X86-NEXT: popl %esi
; MSVC-X86-NEXT: retl
+; MSVC-X86: LBB0_2: # %return
+; MSVC-X86-NEXT: movl 8(%esp), %ecx
+; MSVC-X86-NEXT: xorl %esp, %ecx
+; MSVC-X86-NEXT: calll @__security_check_cookie at 4
+
;
; MSVC-X64-LABEL: test:
; MSVC-X64: # %bb.0: # %entry
@@ -47,12 +55,19 @@ define void @test(ptr %a) nounwind ssp {
; MSVC-X64-NEXT: leaq LC(%rip), %rcx
; MSVC-X64-NEXT: movq %rsi, %rdx
; MSVC-X64-NEXT: callq printf
-; MSVC-X64-NEXT: movq {{[0-9]+}}(%rsp), %rcx
-; MSVC-X64-NEXT: xorq %rsp, %rcx
-; MSVC-X64-NEXT: callq __security_check_cookie
+; MSVC-X64-NEXT: movq 56(%rsp), %rax
+; MSVC-X64-NEXT: xorq %rsp, %rax
+; MSVC-X64-NEXT: movq __security_cookie(%rip), %rcx
+; MSVC-X64-NEXT: cmpq %rax, %rcx
+; MSVC-X64-NEXT: jne .LBB0_2
+; MSVC-X64-NEXT: # %bb.1: # %return
; MSVC-X64-NEXT: addq $64, %rsp
; MSVC-X64-NEXT: popq %rsi
; MSVC-X64-NEXT: retq
+; MSVC-X64-NEXT: .LBB0_2: # %return
+; MSVC-X64-NEXT: movq 56(%rsp), %rcx
+; MSVC-X64-NEXT: xorq %rsp, %rcx
+; MSVC-X64-NEXT: callq __security_check_cookie
;
; MSVC-X86-O0-LABEL: test:
; MSVC-X86-O0: # %bb.0: # %entry
@@ -75,7 +90,15 @@ define void @test(ptr %a) nounwind ssp {
; MSVC-X86-O0-NEXT: # %bb.1: # %return
; MSVC-X86-O0-NEXT: movl {{[0-9]+}}(%esp), %ecx
; MSVC-X86-O0-NEXT: xorl %esp, %ecx
+; MSVC-X86-O0-NEXT: movl ___security_cookie, %eax
+; MSVC-X86-O0-NEXT: subl %ecx, %eax
+; MSVC-X86-O0-NEXT: jne LBB0_3
+; MSVC-X86-O0-NEXT: jmp LBB0_2
+; MSVC-X86-O0-NEXT: LBB0_3: # %return
+; MSVC-X86-O0-NEXT: movl 16(%esp), %ecx
+; MSVC-X86-O0-NEXT: xorl %esp, %ecx
; MSVC-X86-O0-NEXT: calll @__security_check_cookie at 4
+; MSVC-X86-O0-NEXT: LBB0_2: # %return
; MSVC-X86-O0-NEXT: addl $20, %esp
; MSVC-X86-O0-NEXT: retl
;
@@ -95,7 +118,15 @@ define void @test(ptr %a) nounwind ssp {
; MSVC-X64-O0-NEXT: # %bb.1: # %return
; MSVC-X64-O0-NEXT: movq {{[0-9]+}}(%rsp), %rcx
; MSVC-X64-O0-NEXT: xorq %rsp, %rcx
+; MSVC-X64-O0-NEXT: movq __security_cookie(%rip), %rax
+; MSVC-X64-O0-NEXT: subq %rcx, %rax
+; MSVC-X64-O0-NEXT: jne .LBB0_3
+; MSVC-X64-O0-NEXT: jmp .LBB0_2
+; MSVC-X64-O0-NEXT: .LBB0_3: # %return
+; MSVC-X64-O0-NEXT: movq 48(%rsp), %rcx
+; MSVC-X64-O0-NEXT: xorq %rsp, %rcx
; MSVC-X64-O0-NEXT: callq __security_check_cookie
+; MSVC-X64-O0-NEXT: .LBB0_2: # %return
; MSVC-X64-O0-NEXT: addq $56, %rsp
; MSVC-X64-O0-NEXT: retq
entry:
@@ -129,12 +160,19 @@ define void @test_vla(i32 %n) nounwind ssp {
; MSVC-X86-NEXT: pushl %eax
; MSVC-X86-NEXT: calll _escape
; MSVC-X86-NEXT: addl $4, %esp
-; MSVC-X86-NEXT: movl -4(%ebp), %ecx
-; MSVC-X86-NEXT: xorl %ebp, %ecx
-; MSVC-X86-NEXT: calll @__security_check_cookie at 4
-; MSVC-X86-NEXT: movl %ebp, %esp
-; MSVC-X86-NEXT: popl %ebp
+; MSVC-X86-NEXT: movl -4(%ebp), %eax
+; MSVC-X86-NEXT: xorl %ebp, %eax
+; MSVC-X86-NEXT: movl ___security_cookie, %ecx
+; MSVC-X86-NEXT: cmpl %eax, %ecx
+; MSVC-X86-NEXT: jne LBB1_2
+; MSVC-X86-NEXT: # %bb.1:
+; MSVC-X86-NEXT: movl %ebp, %esp
+; MSVC-X86-NEXT: popl %ebp
; MSVC-X86-NEXT: retl
+; MSVC-X86-NEXT: LBB1_2:
+; MSVC-X86-NEXT: movl -4(%ebp), %ecx
+; MSVC-X86-NEXT: xorl %ebp, %ecx
+; MSVC-X86-NEXT: calll @__security_check_cookie at 4
;
; MSVC-X64-LABEL: test_vla:
; MSVC-X64: # %bb.0:
@@ -153,13 +191,20 @@ define void @test_vla(i32 %n) nounwind ssp {
; MSVC-X64-NEXT: subq $32, %rsp
; MSVC-X64-NEXT: callq escape
; MSVC-X64-NEXT: addq $32, %rsp
+; MSVC-X64-NEXT: movq -8(%rbp), %rax
+; MSVC-X64-NEXT: xorq %rbp, %rax
+; MSVC-X64-NEXT: movq __security_cookie(%rip), %rcx
+; MSVC-X64-NEXT: cmpq %rax, %rcx
+; MSVC-X64-NEXT: jne .LBB1_2
+; MSVC-X64-NEXT: # %bb.1:
+; MSVC-X64-NEXT: movq %rbp, %rsp
+; MSVC-X64-NEXT: popq %rbp
+; MSVC-X64-NEXT: retq
+; MSVC-X64-NEXT: .LBB1_2:
; MSVC-X64-NEXT: movq -8(%rbp), %rcx
; MSVC-X64-NEXT: xorq %rbp, %rcx
; MSVC-X64-NEXT: subq $32, %rsp
; MSVC-X64-NEXT: callq __security_check_cookie
-; MSVC-X64-NEXT: movq %rbp, %rsp
-; MSVC-X64-NEXT: popq %rbp
-; MSVC-X64-NEXT: retq
;
; MSVC-X86-O0-LABEL: test_vla:
; MSVC-X86-O0: # %bb.0:
@@ -179,7 +224,15 @@ define void @test_vla(i32 %n) nounwind ssp {
; MSVC-X86-O0-NEXT: addl $4, %esp
; MSVC-X86-O0-NEXT: movl -4(%ebp), %ecx
; MSVC-X86-O0-NEXT: xorl %ebp, %ecx
+; MSVC-X86-O0-NEXT: movl ___security_cookie, %eax
+; MSVC-X86-O0-NEXT: subl %ecx, %eax
+; MSVC-X86-O0-NEXT: jne LBB1_2
+; MSVC-X86-O0-NEXT: jmp LBB1_1
+; MSVC-X86-O0-NEXT: LBB1_2:
+; MSVC-X86-O0-NEXT: movl -4(%ebp), %ecx
+; MSVC-X86-O0-NEXT: xorl %ebp, %ecx
; MSVC-X86-O0-NEXT: calll @__security_check_cookie at 4
+; MSVC-X86-O0-NEXT: LBB1_1:
; MSVC-X86-O0-NEXT: movl %ebp, %esp
; MSVC-X86-O0-NEXT: popl %ebp
; MSVC-X86-O0-NEXT: retl
@@ -204,8 +257,16 @@ define void @test_vla(i32 %n) nounwind ssp {
; MSVC-X64-O0-NEXT: addq $32, %rsp
; MSVC-X64-O0-NEXT: movq -8(%rbp), %rcx
; MSVC-X64-O0-NEXT: xorq %rbp, %rcx
+; MSVC-X64-O0-NEXT: movq __security_cookie(%rip), %rax
+; MSVC-X64-O0-NEXT: subq %rcx, %rax
+; MSVC-X64-O0-NEXT: jne .LBB1_2
+; MSVC-X64-O0-NEXT: jmp .LBB1_1
+; MSVC-X64-O0-NEXT: .LBB1_2:
+; MSVC-X64-O0-NEXT: movq -8(%rbp), %rcx
+; MSVC-X64-O0-NEXT: xorq %rbp, %rcx
; MSVC-X64-O0-NEXT: subq $32, %rsp
; MSVC-X64-O0-NEXT: callq __security_check_cookie
+; MSVC-X64-O0-NEXT: .LBB1_1:
; MSVC-X64-O0-NEXT: movq %rbp, %rsp
; MSVC-X64-O0-NEXT: popq %rbp
; MSVC-X64-O0-NEXT: retq
@@ -242,14 +303,21 @@ define void @test_vla_realign(i32 %n) nounwind ssp {
; MSVC-X86-NEXT: pushl %edi
; MSVC-X86-NEXT: calll _escape
; MSVC-X86-NEXT: addl $4, %esp
-; MSVC-X86-NEXT: movl 12(%esi), %ecx
-; MSVC-X86-NEXT: xorl %ebp, %ecx
-; MSVC-X86-NEXT: calll @__security_check_cookie at 4
+; MSVC-X86-NEXT: movl 12(%esi), %eax
+; MSVC-X86-NEXT: xorl %ebp, %eax
+; MSVC-X86-NEXT: movl ___security_cookie, %ecx
+; MSVC-X86-NEXT: cmpl %eax, %ecx
+; MSVC-X86-NEXT: jne LBB2_2
+; MSVC-X86-NEXT: # %bb.1:
; MSVC-X86-NEXT: leal -8(%ebp), %esp
; MSVC-X86-NEXT: popl %esi
; MSVC-X86-NEXT: popl %edi
; MSVC-X86-NEXT: popl %ebp
; MSVC-X86-NEXT: retl
+; MSVC-X86-NEXT: LBB2_2:
+; MSVC-X86-NEXT: movl 12(%esi), %ecx
+; MSVC-X86-NEXT: xorl %ebp, %ecx
+; MSVC-X86-NEXT: calll @__security_check_cookie at 4
;
; MSVC-X64-LABEL: test_vla_realign:
; MSVC-X64: # %bb.0:
@@ -275,15 +343,22 @@ define void @test_vla_realign(i32 %n) nounwind ssp {
; MSVC-X64-NEXT: movq %rsi, %rcx
; MSVC-X64-NEXT: callq escape
; MSVC-X64-NEXT: addq $32, %rsp
-; MSVC-X64-NEXT: movq 24(%rbx), %rcx
-; MSVC-X64-NEXT: xorq %rbp, %rcx
-; MSVC-X64-NEXT: subq $32, %rsp
-; MSVC-X64-NEXT: callq __security_check_cookie
+; MSVC-X64-NEXT: movq 24(%rbx), %rax
+; MSVC-X64-NEXT: xorq %rbp, %rax
+; MSVC-X64-NEXT: movq __security_cookie(%rip), %rcx
+; MSVC-X64-NEXT: cmpq %rax, %rcx
+; MSVC-X64-NEXT: jne .LBB2_2
+; MSVC-X64-NEXT: # %bb.1:
; MSVC-X64-NEXT: movq %rbp, %rsp
; MSVC-X64-NEXT: popq %rbx
; MSVC-X64-NEXT: popq %rsi
; MSVC-X64-NEXT: popq %rbp
; MSVC-X64-NEXT: retq
+; MSVC-X64-NEXT: .LBB2_2:
+; MSVC-X64-NEXT: movq 24(%rbx), %rcx
+; MSVC-X64-NEXT: xorq %rbp, %rcx
+; MSVC-X64-NEXT: subq $32, %rsp
+; MSVC-X64-NEXT: callq __security_check_cookie
;
; MSVC-X86-O0-LABEL: test_vla_realign:
; MSVC-X86-O0: # %bb.0:
@@ -311,7 +386,15 @@ define void @test_vla_realign(i32 %n) nounwind ssp {
; MSVC-X86-O0-NEXT: addl $4, %esp
; MSVC-X86-O0-NEXT: movl 48(%esi), %ecx
; MSVC-X86-O0-NEXT: xorl %ebp, %ecx
+; MSVC-X86-O0-NEXT: movl ___security_cookie, %eax
+; MSVC-X86-O0-NEXT: subl %ecx, %eax
+; MSVC-X86-O0-NEXT: jne LBB2_2
+; MSVC-X86-O0-NEXT: jmp LBB2_1
+; MSVC-X86-O0-NEXT: LBB2_2:
+; MSVC-X86-O0-NEXT: movl 48(%esi), %ecx
+; MSVC-X86-O0-NEXT: xorl %ebp, %ecx
; MSVC-X86-O0-NEXT: calll @__security_check_cookie at 4
+; MSVC-X86-O0-NEXT: LBB2_1:
; MSVC-X86-O0-NEXT: leal -4(%ebp), %esp
; MSVC-X86-O0-NEXT: popl %esi
; MSVC-X86-O0-NEXT: popl %ebp
@@ -344,8 +427,16 @@ define void @test_vla_realign(i32 %n) nounwind ssp {
; MSVC-X64-O0-NEXT: addq $32, %rsp
; MSVC-X64-O0-NEXT: movq 64(%rbx), %rcx
; MSVC-X64-O0-NEXT: xorq %rbp, %rcx
+; MSVC-X64-O0-NEXT: movq __security_cookie(%rip), %rax
+; MSVC-X64-O0-NEXT: subq %rcx, %rax
+; MSVC-X64-O0-NEXT: jne .LBB2_2
+; MSVC-X64-O0-NEXT: jmp .LBB2_1
+; MSVC-X64-O0-NEXT: .LBB2_2:
+; MSVC-X64-O0-NEXT: movq 64(%rbx), %rcx
+; MSVC-X64-O0-NEXT: xorq %rbp, %rcx
; MSVC-X64-O0-NEXT: subq $32, %rsp
; MSVC-X64-O0-NEXT: callq __security_check_cookie
+; MSVC-X64-O0-NEXT: .LBB2_1:
; MSVC-X64-O0-NEXT: leaq 8(%rbp), %rsp
; MSVC-X64-O0-NEXT: popq %rbx
; MSVC-X64-O0-NEXT: popq %rbp
diff --git a/llvm/test/CodeGen/X86/tailcc-ssp.ll b/llvm/test/CodeGen/X86/tailcc-ssp.ll
index 672046a19e5ee..bc2d5baaa948a 100644
--- a/llvm/test/CodeGen/X86/tailcc-ssp.ll
+++ b/llvm/test/CodeGen/X86/tailcc-ssp.ll
@@ -6,16 +6,20 @@ declare void @h(ptr, i64, ptr)
define tailcc void @tailcall_frame(ptr %0, i64 %1) sspreq {
; WINDOWS-LABEL: tailcall_frame:
-; WINDOWS: # %bb.0:
+; WINDOWS-NEXT: .seh_proc tailcall_frame
+; WINDOWS-NEXT: # %bb.0:
; WINDOWS-NEXT: subq $56, %rsp
; WINDOWS-NEXT: .seh_stackalloc 56
; WINDOWS-NEXT: .seh_endprologue
; WINDOWS-NEXT: movq __security_cookie(%rip), %rax
; WINDOWS-NEXT: xorq %rsp, %rax
; WINDOWS-NEXT: movq %rax, {{[0-9]+}}(%rsp)
-; WINDOWS-NEXT: movq {{[0-9]+}}(%rsp), %rcx
-; WINDOWS-NEXT: xorq %rsp, %rcx
-; WINDOWS-NEXT: callq __security_check_cookie
+; WINDOWS-NEXT: movq {{[0-9]+}}(%rsp), %rax
+; WINDOWS-NEXT: xorq %rsp, %rax
+; WINDOWS-NEXT: movq __security_cookie(%rip), %rcx
+; WINDOWS-NEXT: cmpq %rax, %rcx
+; WINDOWS-NEXT: jne .LBB0_1
+; WINDOWS-NEXT: # %bb.2:
; WINDOWS-NEXT: xorl %ecx, %ecx
; WINDOWS-NEXT: xorl %edx, %edx
; WINDOWS-NEXT: xorl %r8d, %r8d
@@ -23,6 +27,11 @@ define tailcc void @tailcall_frame(ptr %0, i64 %1) sspreq {
; WINDOWS-NEXT: addq $56, %rsp
; WINDOWS-NEXT: .seh_endepilogue
; WINDOWS-NEXT: jmp h # TAILCALL
+; WINDOWS-NEXT: .LBB0_1:
+; WINDOWS-NEXT: movq {{[0-9]+}}(%rsp), %rcx
+; WINDOWS-NEXT: xorq %rsp, %rcx
+; WINDOWS-NEXT: callq __security_check_cookie
+; WINDOWS-NEXT: int3
; WINDOWS-NEXT: .seh_endproc
;
; LINUX-LABEL: tailcall_frame:
@@ -59,13 +68,21 @@ define void @tailcall_unrelated_frame() sspreq {
; WINDOWS-NEXT: xorq %rsp, %rax
; WINDOWS-NEXT: movq %rax, {{[0-9]+}}(%rsp)
; WINDOWS-NEXT: callq bar
-; WINDOWS-NEXT: movq {{[0-9]+}}(%rsp), %rcx
-; WINDOWS-NEXT: xorq %rsp, %rcx
-; WINDOWS-NEXT: callq __security_check_cookie
-; WINDOWS-NEXT: nop
+; WINDOWS-NEXT: movq 32(%rsp), %rax
+; WINDOWS-NEXT: xorq %rsp, %rax
+; WINDOWS-NEXT: movq __security_cookie(%rip), %rcx
+; WINDOWS-NEXT: cmpq %rax, %rcx
+; WINDOWS-NEXT: jne .LBB1_1
+; WINDOWS-NEXT: # %bb.2:
+; WINDOWS-NEXT: .seh_startepilogue
; WINDOWS-NEXT: addq $40, %rsp
; WINDOWS-NEXT: .seh_endepilogue
; WINDOWS-NEXT: jmp bar # TAILCALL
+; WINDOWS-NEXT: .LBB1_1:
+; WINDOWS-NEXT: movq 32(%rsp), %rcx
+; WINDOWS-NEXT: xorq %rsp, %rcx
+; WINDOWS-NEXT: callq __security_check_cookie
+; WINDOWS-NEXT: int3
; WINDOWS-NEXT: .seh_endproc
;
; LINUX-LABEL: tailcall_unrelated_frame:
@@ -95,9 +112,19 @@ define void @caller() sspreq {
; WINDOWS-LABEL: caller:
; WINDOWS: callq callee
; WINDOWS: callq callee
-; WINDOWS: cmpq __security_cookie(%rip), %rcx
-; WINDOWS: jne
-; WINDOWS: callq __security_check_cookie
+; WINDOWS: cmpq %rax, %rcx
+; WINDOWS-NEXT: jne .LBB2_2
+; WINDOWS-NEXT: # %bb.1:
+; WINDOWS-NEXT: .seh_startepilogue
+; WINDOWS-NEXT: addq $40, %rsp
+; WINDOWS-NEXT: .seh_endepilogue
+; WINDOWS-NEXT: retq
+; WINDOWS-NEXT: .LBB2_2:
+; WINDOWS-NEXT: movq 32(%rsp), %rcx
+; WINDOWS-NEXT: xorq %rsp, %rcx
+; WINDOWS-NEXT: callq __security_check_cookie
+; WINDOWS-NEXT: int3
+; WINDOWS-NEXT: .seh_endproc
; LINUX-LABEL: caller:
; LINUX: callq callee at PLT
diff --git a/llvm/test/DebugInfo/COFF/fpo-stack-protect.ll b/llvm/test/DebugInfo/COFF/fpo-stack-protect.ll
index 566d36e87d2b6..d0d724910faf1 100644
--- a/llvm/test/DebugInfo/COFF/fpo-stack-protect.ll
+++ b/llvm/test/DebugInfo/COFF/fpo-stack-protect.ll
@@ -15,7 +15,7 @@
; CHECK: subl $20, %esp
; CHECK: .cv_fpo_stackalloc 20
; CHECK: .cv_fpo_endprologue
-; CHECK: ___security_cookie
+; CHECK: movl ___security_cookie, %ea
; CHECK: movl 28(%esp), %esi
; CHECK: movl %esi, {{[0-9]*}}(%esp)
@@ -24,13 +24,16 @@
; CHECK: movl %esi, {{[0-9]*}}(%esp)
; CHECK: calll _escape
-; CHECK: calll @__security_check_cookie at 4
+
+; CHECK: movl ___security_cookie, %ecx
+; CHECK: cmpl %eax, %ecx
; CHECK: movl %esi, %eax
; CHECK: addl $20, %esp
; CHECK: popl %esi
; CHECK: retl
; CHECK: Ltmp4:
+; CHECK: calll @__security_check_cookie at 4
; CHECK: .cv_fpo_endproc
; ModuleID = 't.c'
More information about the llvm-commits
mailing list