From: Victor Huang Date: Thu, 12 Aug 2021 13:03:21 +0000 (-0500) Subject: [PowerPC] Fix return address computation for "__builtin_return_address" X-Git-Tag: upstream/15.0.7~34075 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=99e00663d4cd13b0c296380147ef3f53a2172fbf;p=platform%2Fupstream%2Fllvm.git [PowerPC] Fix return address computation for "__builtin_return_address" When depth > 0, callee frame address is used to compute the return address of callee producing improper return address. This patch adds the fix to use caller frame address to compute the return address of callee. Reviewed By: nemanjai, #powerpc Differential revision: https://reviews.llvm.org/D107646 --- diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp index 3735817..6d38b39f 100644 --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -15960,7 +15960,12 @@ SDValue PPCTargetLowering::LowerRETURNADDR(SDValue Op, auto PtrVT = getPointerTy(MF.getDataLayout()); if (Depth > 0) { - SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); + // The link register (return address) is saved in the caller's frame + // not the callee's stack frame. So we must get the caller's frame + // address and load the return address at the LR offset from there. + SDValue FrameAddr = + DAG.getLoad(Op.getValueType(), dl, DAG.getEntryNode(), + LowerFRAMEADDR(Op, DAG), MachinePointerInfo()); SDValue Offset = DAG.getConstant(Subtarget.getFrameLowering()->getReturnSaveOffset(), dl, isPPC64 ? MVT::i64 : MVT::i32); diff --git a/llvm/test/CodeGen/PowerPC/2010-05-03-retaddr1.ll b/llvm/test/CodeGen/PowerPC/2010-05-03-retaddr1.ll index 170a82a..055cd44 100644 --- a/llvm/test/CodeGen/PowerPC/2010-05-03-retaddr1.ll +++ b/llvm/test/CodeGen/PowerPC/2010-05-03-retaddr1.ll @@ -23,6 +23,7 @@ define i8* @g() nounwind readnone { ; CHECK-NEXT: stw 0, 4(1) ; CHECK-NEXT: stwu 1, -16(1) ; CHECK-NEXT: lwz 3, 0(1) +; CHECK-NEXT: lwz 3, 0(3) ; CHECK-NEXT: lwz 3, 4(3) ; CHECK-NEXT: lwz 0, 20(1) ; CHECK-NEXT: addi 1, 1, 16 diff --git a/llvm/test/CodeGen/PowerPC/retaddr_multi_levels.ll b/llvm/test/CodeGen/PowerPC/retaddr_multi_levels.ll new file mode 100644 index 0000000..7e55f05 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/retaddr_multi_levels.ll @@ -0,0 +1,140 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64le-unknown-linux \ +; RUN: -mcpu=pwr8 | FileCheck %s -check-prefix=CHECK-64B-LE +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux \ +; RUN: -mcpu=pwr7 | FileCheck %s -check-prefix=CHECK-64B-BE +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-aix \ +; RUN: -mcpu=pwr7 | FileCheck %s -check-prefix=CHECK-64B-BE +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-aix \ +; RUN: -mcpu=pwr7 | FileCheck %s -check-prefix=CHECK-32B-BE + +declare i8* @llvm.returnaddress(i32) nounwind readnone + +define i8* @test0() nounwind readnone { +; CHECK-64B-LE-LABEL: test0: +; CHECK-64B-LE: # %bb.0: # %entry +; CHECK-64B-LE-NEXT: mflr 0 +; CHECK-64B-LE-NEXT: std 0, 16(1) +; CHECK-64B-LE-NEXT: stdu 1, -32(1) +; CHECK-64B-LE-NEXT: ld 3, 48(1) +; CHECK-64B-LE-NEXT: addi 1, 1, 32 +; CHECK-64B-LE-NEXT: ld 0, 16(1) +; CHECK-64B-LE-NEXT: mtlr 0 +; CHECK-64B-LE-NEXT: blr +; +; CHECK-64B-BE-LABEL: test0: +; CHECK-64B-BE: # %bb.0: # %entry +; CHECK-64B-BE-NEXT: mflr 0 +; CHECK-64B-BE-NEXT: std 0, 16(1) +; CHECK-64B-BE-NEXT: stdu 1, -48(1) +; CHECK-64B-BE-NEXT: ld 3, 64(1) +; CHECK-64B-BE-NEXT: addi 1, 1, 48 +; CHECK-64B-BE-NEXT: ld 0, 16(1) +; CHECK-64B-BE-NEXT: mtlr 0 +; CHECK-64B-BE-NEXT: blr +; +; CHECK-32B-BE-LABEL: test0: +; CHECK-32B-BE: # %bb.0: # %entry +; CHECK-32B-BE-NEXT: mflr 0 +; CHECK-32B-BE-NEXT: stw 0, 8(1) +; CHECK-32B-BE-NEXT: stwu 1, -32(1) +; CHECK-32B-BE-NEXT: lwz 3, 40(1) +; CHECK-32B-BE-NEXT: addi 1, 1, 32 +; CHECK-32B-BE-NEXT: lwz 0, 8(1) +; CHECK-32B-BE-NEXT: mtlr 0 +; CHECK-32B-BE-NEXT: blr +entry: + %0 = tail call i8* @llvm.returnaddress(i32 0); + ret i8* %0 +} + +define i8* @test1() nounwind readnone { +; CHECK-64B-LE-LABEL: test1: +; CHECK-64B-LE: # %bb.0: # %entry +; CHECK-64B-LE-NEXT: mflr 0 +; CHECK-64B-LE-NEXT: std 0, 16(1) +; CHECK-64B-LE-NEXT: stdu 1, -32(1) +; CHECK-64B-LE-NEXT: ld 3, 0(1) +; CHECK-64B-LE-NEXT: ld 3, 0(3) +; CHECK-64B-LE-NEXT: ld 3, 16(3) +; CHECK-64B-LE-NEXT: addi 1, 1, 32 +; CHECK-64B-LE-NEXT: ld 0, 16(1) +; CHECK-64B-LE-NEXT: mtlr 0 +; CHECK-64B-LE-NEXT: blr +; +; CHECK-64B-BE-LABEL: test1: +; CHECK-64B-BE: # %bb.0: # %entry +; CHECK-64B-BE-NEXT: mflr 0 +; CHECK-64B-BE-NEXT: std 0, 16(1) +; CHECK-64B-BE-NEXT: stdu 1, -48(1) +; CHECK-64B-BE-NEXT: ld 3, 0(1) +; CHECK-64B-BE-NEXT: ld 3, 0(3) +; CHECK-64B-BE-NEXT: ld 3, 16(3) +; CHECK-64B-BE-NEXT: addi 1, 1, 48 +; CHECK-64B-BE-NEXT: ld 0, 16(1) +; CHECK-64B-BE-NEXT: mtlr 0 +; CHECK-64B-BE-NEXT: blr +; +; CHECK-32B-BE-LABEL: test1: +; CHECK-32B-BE: # %bb.0: # %entry +; CHECK-32B-BE-NEXT: mflr 0 +; CHECK-32B-BE-NEXT: stw 0, 8(1) +; CHECK-32B-BE-NEXT: stwu 1, -32(1) +; CHECK-32B-BE-NEXT: lwz 3, 0(1) +; CHECK-32B-BE-NEXT: lwz 3, 0(3) +; CHECK-32B-BE-NEXT: lwz 3, 8(3) +; CHECK-32B-BE-NEXT: addi 1, 1, 32 +; CHECK-32B-BE-NEXT: lwz 0, 8(1) +; CHECK-32B-BE-NEXT: mtlr 0 +; CHECK-32B-BE-NEXT: blr +entry: + %0 = tail call i8* @llvm.returnaddress(i32 1); + ret i8* %0 +} + +define i8* @test2() nounwind readnone { +; CHECK-64B-LE-LABEL: test2: +; CHECK-64B-LE: # %bb.0: # %entry +; CHECK-64B-LE-NEXT: mflr 0 +; CHECK-64B-LE-NEXT: std 0, 16(1) +; CHECK-64B-LE-NEXT: stdu 1, -32(1) +; CHECK-64B-LE-NEXT: ld 3, 0(1) +; CHECK-64B-LE-NEXT: ld 3, 0(3) +; CHECK-64B-LE-NEXT: ld 3, 0(3) +; CHECK-64B-LE-NEXT: ld 3, 16(3) +; CHECK-64B-LE-NEXT: addi 1, 1, 32 +; CHECK-64B-LE-NEXT: ld 0, 16(1) +; CHECK-64B-LE-NEXT: mtlr 0 +; CHECK-64B-LE-NEXT: blr +; +; CHECK-64B-BE-LABEL: test2: +; CHECK-64B-BE: # %bb.0: # %entry +; CHECK-64B-BE-NEXT: mflr 0 +; CHECK-64B-BE-NEXT: std 0, 16(1) +; CHECK-64B-BE-NEXT: stdu 1, -48(1) +; CHECK-64B-BE-NEXT: ld 3, 0(1) +; CHECK-64B-BE-NEXT: ld 3, 0(3) +; CHECK-64B-BE-NEXT: ld 3, 0(3) +; CHECK-64B-BE-NEXT: ld 3, 16(3) +; CHECK-64B-BE-NEXT: addi 1, 1, 48 +; CHECK-64B-BE-NEXT: ld 0, 16(1) +; CHECK-64B-BE-NEXT: mtlr 0 +; CHECK-64B-BE-NEXT: blr +; +; CHECK-32B-BE-LABEL: test2: +; CHECK-32B-BE: # %bb.0: # %entry +; CHECK-32B-BE-NEXT: mflr 0 +; CHECK-32B-BE-NEXT: stw 0, 8(1) +; CHECK-32B-BE-NEXT: stwu 1, -32(1) +; CHECK-32B-BE-NEXT: lwz 3, 0(1) +; CHECK-32B-BE-NEXT: lwz 3, 0(3) +; CHECK-32B-BE-NEXT: lwz 3, 0(3) +; CHECK-32B-BE-NEXT: lwz 3, 8(3) +; CHECK-32B-BE-NEXT: addi 1, 1, 32 +; CHECK-32B-BE-NEXT: lwz 0, 8(1) +; CHECK-32B-BE-NEXT: mtlr 0 +; CHECK-32B-BE-NEXT: blr +entry: + %0 = tail call i8* @llvm.returnaddress(i32 2); + ret i8* %0 +}