Skip to content

Commit 0c7dc30

Browse files
Merge pull request #2704 from TNorthover/tailcc-ssp
StackProtector: ensure protection does not interfere with tail call frame
2 parents eb716e3 + da878f7 commit 0c7dc30

File tree

2 files changed

+49
-4
lines changed

2 files changed

+49
-4
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,16 +1691,35 @@ static bool MIIsInTerminatorSequence(const MachineInstr &MI) {
16911691
/// terminator, but additionally the copies that move the vregs into the
16921692
/// physical registers.
16931693
static MachineBasicBlock::iterator
1694-
FindSplitPointForStackProtector(MachineBasicBlock *BB) {
1694+
FindSplitPointForStackProtector(MachineBasicBlock *BB,
1695+
const TargetInstrInfo &TII) {
16951696
MachineBasicBlock::iterator SplitPoint = BB->getFirstTerminator();
1696-
//
16971697
if (SplitPoint == BB->begin())
16981698
return SplitPoint;
16991699

17001700
MachineBasicBlock::iterator Start = BB->begin();
17011701
MachineBasicBlock::iterator Previous = SplitPoint;
17021702
--Previous;
17031703

1704+
if (TII.isTailCall(*SplitPoint) &&
1705+
Previous->getOpcode() == TII.getCallFrameDestroyOpcode()) {
1706+
// Call frames cannot be nested, so if this frame is describing the tail
1707+
// call itself then we must insert before the sequence even starts. On the
1708+
// other hand, it could be an unrelated call in which case this tail call
1709+
// has to register moves of its own and should be the split point.
1710+
bool DifferentCall = false;
1711+
MachineBasicBlock::iterator I = Previous;
1712+
do {
1713+
--I;
1714+
if (I->isCall()) {
1715+
DifferentCall = true;
1716+
break;
1717+
}
1718+
} while(I->getOpcode() != TII.getCallFrameSetupOpcode());
1719+
1720+
return DifferentCall ? SplitPoint : I;
1721+
}
1722+
17041723
while (MIIsInTerminatorSequence(*Previous)) {
17051724
SplitPoint = Previous;
17061725
if (Previous == Start)
@@ -1740,7 +1759,7 @@ SelectionDAGISel::FinishBasicBlock() {
17401759
// Add load and check to the basicblock.
17411760
FuncInfo->MBB = ParentMBB;
17421761
FuncInfo->InsertPt =
1743-
FindSplitPointForStackProtector(ParentMBB);
1762+
FindSplitPointForStackProtector(ParentMBB, *TII);
17441763
SDB->visitSPDescriptorParent(SDB->SPDescriptor, ParentMBB);
17451764
CurDAG->setRoot(SDB->getRoot());
17461765
SDB->clear();
@@ -1759,7 +1778,7 @@ SelectionDAGISel::FinishBasicBlock() {
17591778
// register allocation issues caused by us splitting the parent mbb. The
17601779
// register allocator will clean up said virtual copies later on.
17611780
MachineBasicBlock::iterator SplitPoint =
1762-
FindSplitPointForStackProtector(ParentMBB);
1781+
FindSplitPointForStackProtector(ParentMBB, *TII);
17631782

17641783
// Splice the terminator of ParentMBB into SuccessMBB.
17651784
SuccessMBB->splice(SuccessMBB->end(), ParentMBB,

llvm/test/CodeGen/X86/tailcc-ssp.ll

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
; RUN: llc -mtriple=x86_64-windows-msvc %s -o - -verify-machineinstrs | FileCheck %s
2+
3+
declare void @h(i8*, i64, i8*)
4+
5+
define tailcc void @tailcall_frame(i8* %0, i64 %1) sspreq {
6+
; CHECK-LABEL: tailcall_frame:
7+
; CHECK: callq __security_check_cookie
8+
; CHECK: xorl %ecx, %ecx
9+
; CHECK: jmp h
10+
11+
tail call tailcc void @h(i8* null, i64 0, i8* null)
12+
ret void
13+
}
14+
15+
declare void @bar()
16+
define void @tailcall_unrelated_frame() sspreq {
17+
; CHECK-LABEL: tailcall_unrelated_frame:
18+
; CHECK: subq [[STACK:\$.*]], %rsp
19+
; CHECK: callq bar
20+
; CHECK: callq __security_check_cookie
21+
; CHECK: addq [[STACK]], %rsp
22+
; CHECK: jmp bar
23+
call void @bar()
24+
tail call void @bar()
25+
ret void
26+
}

0 commit comments

Comments
 (0)