Skip to content

Commit

Permalink
[Sparc] Flush register windows for @llvm.returnaddress(1)
Browse files Browse the repository at this point in the history
Summary: When @llvm.returnaddress is called with a value higher than 0
it needs to read from the call stack to get the return address. This
means that the register windows needs to be flushed to the stack to
guarantee that the data read is valid. For values higher than 1 this
is done indirectly by the call to getFRAMEADDR(), but not for the value 1.

Reviewers: jyknight, venkatra

Reviewed By: jyknight

Subscribers: fedor.sergeev, jrtc27, llvm-commits

Differential Revision: https://reviews.llvm.org/D48636

llvm-svn: 340003
  • Loading branch information
doac committed Aug 17, 2018
1 parent 4c0c37d commit 7d3e08f
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 11 deletions.
17 changes: 6 additions & 11 deletions llvm/lib/Target/Sparc/SparcISelLowering.cpp
Expand Up @@ -2666,7 +2666,8 @@ static SDValue getFLUSHW(SDValue Op, SelectionDAG &DAG) {
}

static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG,
const SparcSubtarget *Subtarget) {
const SparcSubtarget *Subtarget,
bool AlwaysFlush = false) {
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
MFI.setFrameAddressIsTaken(true);

Expand All @@ -2676,17 +2677,11 @@ static SDValue getFRAMEADDR(uint64_t depth, SDValue Op, SelectionDAG &DAG,
unsigned stackBias = Subtarget->getStackPointerBias();

SDValue FrameAddr;

if (depth == 0) {
FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
if (Subtarget->is64Bit())
FrameAddr = DAG.getNode(ISD::ADD, dl, VT, FrameAddr,
DAG.getIntPtrConstant(stackBias, dl));
return FrameAddr;
}
SDValue Chain;

// flush first to make sure the windowed registers' values are in stack
SDValue Chain = getFLUSHW(Op, DAG);
Chain = (depth || AlwaysFlush) ? getFLUSHW(Op, DAG) : DAG.getEntryNode();

FrameAddr = DAG.getCopyFromReg(Chain, dl, FrameReg, VT);

unsigned Offset = (Subtarget->is64Bit()) ? (stackBias + 112) : 56;
Expand Down Expand Up @@ -2735,7 +2730,7 @@ static SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG,
}

// Need frame address to find return address of the caller.
SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget);
SDValue FrameAddr = getFRAMEADDR(depth - 1, Op, DAG, Subtarget, true);

unsigned Offset = (Subtarget->is64Bit()) ? 120 : 60;
SDValue Ptr = DAG.getNode(ISD::ADD,
Expand Down
18 changes: 18 additions & 0 deletions llvm/test/CodeGen/SPARC/2011-01-11-FrameAddr.ll
Expand Up @@ -96,4 +96,22 @@ entry:
ret i8* %0
}

define i8* @retaddr3() nounwind readnone {
entry:
;V8-LABEL: retaddr3:
;V8: ta 3
;V8: ld [%fp+60], {{.+}}

;V9-LABEL: retaddr3:
;V9: flushw
;V9: ld [%fp+60], {{.+}}

;SPARC64-LABEL: retaddr3
;SPARC64: flushw
;SPARC64: ldx [%fp+2167], %[[R0:[goli][0-7]]]

%0 = tail call i8* @llvm.returnaddress(i32 1)
ret i8* %0
}

declare i8* @llvm.returnaddress(i32) nounwind readnone

0 comments on commit 7d3e08f

Please sign in to comment.