diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -2271,6 +2271,13 @@ } bool AArch64FrameLowering::enableCFIFixup(MachineFunction &MF) const { + const auto &MFI = *MF.getInfo(); + + // Return-address signing requires CFIFixup to toggle the value of + // RA_SIGN_STATE around early-return tail calls + if (MFI.shouldSignReturnAddress(MF)) + return true; + return TargetFrameLowering::enableCFIFixup(MF) && MF.getInfo()->needsAsyncDwarfUnwindInfo(MF); } diff --git a/llvm/test/CodeGen/AArch64/sign-return-address-cfi-negate-ra-state.ll b/llvm/test/CodeGen/AArch64/sign-return-address-cfi-negate-ra-state.ll --- a/llvm/test/CodeGen/AArch64/sign-return-address-cfi-negate-ra-state.ll +++ b/llvm/test/CodeGen/AArch64/sign-return-address-cfi-negate-ra-state.ll @@ -5,7 +5,7 @@ @.str = private unnamed_addr constant [15 x i8] c"some exception\00", align 1 @_ZTIPKc = external dso_local constant ptr -; CHECK: @_Z3fooi +; CHECK-LABEL: @_Z3fooi ; CHECK-V8A: hint #25 ; CHECK-V83A: paciasp ; CHECK-NEXT: .cfi_negate_ra_state @@ -25,10 +25,59 @@ ret i32 %0 } +; CHECK-LABEL: @_Z3bazi +; In the prologue, sign the return address, toggle RA_SIGN_STATE to 1, and save +; the unwind state. +; CHECK-V8A: hint #25 +; CHECK-V83A: paciasp +; CHECK-NEXT: .cfi_negate_ra_state +; CHECK: .cfi_remember_state +; To tail-call bar, authenticate the return address, and toggle RA_SIGN_STATE to 0. +; CHECK-V8A: hint #29 +; CHECK-V83A: autiasp +; CHECK-NEXT: .cfi_negate_ra_state +; CHECK-NEXT: b _Z3bari +; To call quux, restore the unwind state, which sets RA_SIGN_STATE back to 1. +; CHECK: .cfi_restore_state +; CHECK: bl _Z4quuxi +; To return, authenticate the return address. v8.3-A can do this in one +; instruction, so doesn't need any unwind opcodes. +; CHECK-V83A: retaa +; CHECK-V8A: hint #29 +; CHECK-V8A-NEXT: .cfi_negate_ra_state +; CHECK-V8A-NEXT: ret +define hidden noundef i32 @_Z3bazi(i32 noundef %a) #0 { +entry: + %tobool.not = icmp eq i32 %a, 0 + br i1 %tobool.not, label %if.else, label %if.then + +if.then: ; preds = %entry + %call = tail call noundef i32 @_Z3bari(i32 noundef 0) + %call1 = tail call noundef i32 @_Z3bari(i32 noundef %call) + br label %return + +if.else: ; preds = %entry + %call2 = tail call noundef i32 @_Z4quuxi(i32 noundef 0) + %add = add nsw i32 %call2, 1 + br label %return + +return: ; preds = %if.else, %if.then + %retval.0 = phi i32 [ %call1, %if.then ], [ %add, %if.else ] + ret i32 %retval.0 +} + declare dso_local ptr @__cxa_allocate_exception(i64) declare dso_local void @__cxa_throw(ptr, ptr, ptr) +declare dso_local noundef i32 @_Z3bari(i32 noundef) local_unnamed_addr +declare dso_local noundef i32 @_Z4quuxi(i32 noundef) local_unnamed_addr + attributes #0 = { "sign-return-address"="all" } ;CHECK-DUMP: DW_CFA_AARCH64_negate_ra_state +;CHECK-DUMP: DW_CFA_AARCH64_negate_ra_state +;CHECK-DUMP: DW_CFA_remember_state +;CHECK-DUMP: DW_CFA_AARCH64_negate_ra_state +;CHECK-DUMP: DW_CFA_restore_state +;CHECK-DUMP: DW_CFA_AARCH64_negate_ra_state