// RUN: %clang %cflags -march=armv9.5-a+pauth-lr -mbranch-protection=pac-ret %s %p/../../Inputs/asm_main.c -o %t.exe
// RUN: llvm-bolt-binary-analysis --scanners=pacret %t.exe 2>&1 | FileCheck %s

        .text

        .globl  f1
        .type   f1,@function
f1:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        // autiasp
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f1, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f1, .-f1


        .globl  f_intermediate_overwrite1
        .type   f_intermediate_overwrite1,@function
f_intermediate_overwrite1:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        autiasp
        ldp     x29, x30, [sp], #16
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_intermediate_overwrite1, basic block {{[0-9a-zA-Z.]+}}
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   autiasp
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_intermediate_overwrite1, .-f_intermediate_overwrite1

        .globl  f_intermediate_overwrite2
        .type   f_intermediate_overwrite2,@function
f_intermediate_overwrite2:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autiasp
        mov     x30, x0
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_intermediate_overwrite2, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: mov     x30, x0
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autiasp
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x30, x0
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_intermediate_overwrite2, .-f_intermediate_overwrite2

        .globl  f_intermediate_read
        .type   f_intermediate_read,@function
f_intermediate_read:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autiasp
        mov     x0, x30
// CHECK-NOT: function f_intermediate_read
        ret
        .size f_intermediate_read, .-f_intermediate_read

        .globl  f_intermediate_overwrite3
        .type   f_intermediate_overwrite3,@function
f_intermediate_overwrite3:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autiasp
        mov     w30, w0
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_intermediate_overwrite3, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: mov     w30, w0
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autiasp
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     w30, w0
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_intermediate_overwrite3, .-f_intermediate_overwrite3

        .globl  f_nonx30_ret
        .type   f_nonx30_ret,@function
f_nonx30_ret:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        mov     x16, x30
        autiasp
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_nonx30_ret, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret     x16
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: mov     x16, x30
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x16, x30
// CHECK-NEXT: {{[0-9a-f]+}}:   autiasp
// CHECK-NEXT: {{[0-9a-f]+}}:   ret     x16
        ret     x16
        .size f_nonx30_ret, .-f_nonx30_ret

        .globl  f_nonx30_ret_ok
        .type   f_nonx30_ret_ok,@function
f_nonx30_ret_ok:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        ldp     x29, x30, [sp], #16
        autiasp
        mov     x16, x30
// CHECK-NOT: function f_nonx30_ret_ok
        ret     x16
        .size f_nonx30_ret_ok, .-f_nonx30_ret_ok

        .globl  f_detect_clobbered_x30_passed_to_other
        .type   f_detect_clobbered_x30_passed_to_other,@function
f_detect_clobbered_x30_passed_to_other:
        str x30, [sp]
        ldr x30, [sp]
// FIXME: Ideally, the pac-ret scanner would report on the following instruction, which
// performs a tail call, that x30 might be attacker-controlled.
// CHECK-NOT: function f_detect_clobbered_x30_passed_to_other
        b   f_tail_called
        .size f_detect_clobbered_x30_passed_to_other, .-f_detect_clobbered_x30_passed_to_other

        .globl  f_tail_called
        .type   f_tail_called,@function
f_tail_called:
        ret
        .size f_tail_called, .-f_tail_called

        .globl  f_nonx30_ret_non_auted
        .type   f_nonx30_ret_non_auted,@function
f_nonx30_ret_non_auted:
// x1 is neither authenticated nor implicitly considered safe at function entry.
// Note that we assume it's fine for x30 to not be authenticated before
// returning to, as assuming that x30 is not attacker controlled at function
// entry is part (implicitly) of the pac-ret hardening scheme.
//
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_nonx30_ret_non_auted, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 0 instructions that write to the affected registers after any authentication are:
        ret     x1
        .size f_nonx30_ret_non_auted, .-f_nonx30_ret_non_auted


        .globl  f_callclobbered_x30
        .type   f_callclobbered_x30,@function
f_callclobbered_x30:
        bl      g
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_callclobbered_x30, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: bl
        ret
        .size f_callclobbered_x30, .-f_callclobbered_x30

        .globl  f_callclobbered_calleesaved
        .type   f_callclobbered_calleesaved,@function
f_callclobbered_calleesaved:
        bl      g
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_callclobbered_calleesaved, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret x19
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: bl
        // x19, according to the Arm ABI (AAPCS) is a callee-saved register.
        // Therefore, if function g respects the AAPCS, it should not write
        // anything to x19. However, we can't know whether function g actually
        // does respect the AAPCS rules, so the scanner should assume x19 can
        // get overwritten, and report a gadget if the code does not properly
        // deal with that.
        // Furthermore, there's a good chance that callee-saved registers have
        // been saved on the stack at some point during execution of the callee,
        // and so should be considered as potentially modified by an
        // attacker/written to.
        ret x19
        .size f_callclobbered_calleesaved, .-f_callclobbered_calleesaved

        .globl  f_unreachable_instruction
        .type   f_unreachable_instruction,@function
f_unreachable_instruction:
// CHECK-LABEL: GS-PAUTH: Warning: possibly imprecise CFG, the analysis quality may be degraded in this function. According to BOLT, unreachable code is found in function f_unreachable_instruction, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       add     x0, x1, x2
// CHECK-NOT:   instructions that write to the affected registers after any authentication are:
        b       1f
        add     x0, x1, x2
1:
        ret
        .size f_unreachable_instruction, .-f_unreachable_instruction

// Without CFG, the state is reset at labels, assuming every register that can
// be clobbered in the function was actually clobbered.

        .globl  lr_untouched_nocfg
        .type   lr_untouched_nocfg,@function
lr_untouched_nocfg:
// CHECK-NOT: lr_untouched_nocfg
        adr     x2, 1f
        br      x2
1:
        ret
        .size lr_untouched_nocfg, .-lr_untouched_nocfg

        .globl  lr_clobbered_nocfg
        .type   lr_clobbered_nocfg,@function
lr_clobbered_nocfg:
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function lr_clobbered_nocfg, at address
// CHECK-NEXT:  The instruction is     {{[0-9a-f]+}}:      ret
// CHECK-NEXT:  The 0 instructions that write to the affected registers after any authentication are:
        adr     x2, 1f
        br      x2
1:
        b       2f
        bl      g   // never executed, but affects the expected worst-case scenario
2:
        ret
        .size lr_clobbered_nocfg, .-lr_clobbered_nocfg

/// Now do a basic sanity check on every different Authentication instruction:

        .globl  f_autiasp
        .type   f_autiasp,@function
f_autiasp:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autiasp
// CHECK-NOT: function f_autiasp
        ret
        .size f_autiasp, .-f_autiasp

        .globl  f_autibsp
        .type   f_autibsp,@function
f_autibsp:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autibsp
// CHECK-NOT: function f_autibsp
        ret
        .size f_autibsp, .-f_autibsp

        .globl  f_autiaz
        .type   f_autiaz,@function
f_autiaz:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autiaz
// CHECK-NOT: function f_autiaz
        ret
        .size f_autiaz, .-f_autiaz

        .globl  f_autibz
        .type   f_autibz,@function
f_autibz:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autibz
// CHECK-NOT: function f_autibz
        ret
        .size f_autibz, .-f_autibz

        .globl  f_autia1716
        .type   f_autia1716,@function
f_autia1716:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autia1716
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autia1716, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autia1716
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_autia1716, .-f_autia1716

        .globl  f_autib1716
        .type   f_autib1716,@function
f_autib1716:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autib1716
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autib1716, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autib1716
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_autib1716, .-f_autib1716

        .globl  f_autiax12
        .type   f_autiax12,@function
f_autiax12:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autia   x12, sp
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autiax12, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autia   x12, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_autiax12, .-f_autiax12

        .globl  f_autibx12
        .type   f_autibx12,@function
f_autibx12:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autib   x12, sp
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autibx12, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autib   x12, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_autibx12, .-f_autibx12

        .globl  f_autiax30
        .type   f_autiax30,@function
f_autiax30:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autia   x30, sp
// CHECK-NOT: function f_autiax30
        ret
        .size f_autiax30, .-f_autiax30

        .globl  f_autibx30
        .type   f_autibx30,@function
f_autibx30:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autib   x30, sp
// CHECK-NOT: function f_autibx30
        ret
        .size f_autibx30, .-f_autibx30


        .globl  f_autdax12
        .type   f_autdax12,@function
f_autdax12:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autda   x12, sp
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autdax12, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autda   x12, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_autdax12, .-f_autdax12

        .globl  f_autdbx12
        .type   f_autdbx12,@function
f_autdbx12:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autdb   x12, sp
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autdbx12, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autdb   x12, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_autdbx12, .-f_autdbx12

        .globl  f_autdax30
        .type   f_autdax30,@function
f_autdax30:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autda   x30, sp
// CHECK-NOT: function f_autdax30
        ret
        .size f_autdax30, .-f_autdax30

        .globl  f_autdbx30
        .type   f_autdbx30,@function
f_autdbx30:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autdb   x30, sp
// CHECK-NOT: function f_autdbx30
        ret
        .size f_autdbx30, .-f_autdbx30


        .globl  f_autizax12
        .type   f_autizax12,@function
f_autizax12:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autiza  x12
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autizax12, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autiza  x12
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_autizax12, .-f_autizax12

        .globl  f_autizbx12
        .type   f_autizbx12,@function
f_autizbx12:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autizb  x12
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autizbx12, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autizb  x12
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_autizbx12, .-f_autizbx12

        .globl  f_autizax30
        .type   f_autizax30,@function
f_autizax30:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autiza  x30
// CHECK-NOT: function f_autizax30
        ret
        .size f_autizax30, .-f_autizax30

        .globl  f_autizbx30
        .type   f_autizbx30,@function
f_autizbx30:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autizb  x30
// CHECK-NOT: function f_autizbx30
        ret
        .size f_autizbx30, .-f_autizbx30


        .globl  f_autdzax12
        .type   f_autdzax12,@function
f_autdzax12:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autdza  x12
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autdzax12, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autdza  x12
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_autdzax12, .-f_autdzax12

        .globl  f_autdzbx12
        .type   f_autdzbx12,@function
f_autdzbx12:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autdzb  x12
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autdzbx12, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autdzb  x12
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_autdzbx12, .-f_autdzbx12

        .globl  f_autdzax30
        .type   f_autdzax30,@function
f_autdzax30:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autdza  x30
// CHECK-NOT: function f_autdzax30
        ret
        .size f_autdzax30, .-f_autdzax30

        .globl  f_autdzbx30
        .type   f_autdzbx30,@function
f_autdzbx30:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autdzb  x30
// CHECK-NOT: function f_autdzbx30
        ret
        .size f_autdzbx30, .-f_autdzbx30

        .globl  f_retaa
        .type   f_retaa,@function
f_retaa:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
// CHECK-NOT: function f_retaa
        retaa
        .size f_retaa, .-f_retaa

        .globl  f_retab
        .type   f_retab,@function
f_retab:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
// CHECK-NOT: function f_retab
        retab
        .size f_retab, .-f_retab

        .globl  f_eretaa
        .type   f_eretaa,@function
f_eretaa:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
// CHECK-LABEL: GS-PAUTH: Warning: pac-ret analysis could not analyze this return instruction in function f_eretaa, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:   The instruction is     {{[0-9a-f]+}}:       eretaa
        eretaa
        .size f_eretaa, .-f_eretaa

        .globl  f_eretab
        .type   f_eretab,@function
f_eretab:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
// CHECK-LABEL: GS-PAUTH: Warning: pac-ret analysis could not analyze this return instruction in function f_eretab, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:   The instruction is     {{[0-9a-f]+}}:       eretab
        eretab
        .size f_eretab, .-f_eretab

        .globl  f_eret
        .type   f_eret,@function
f_eret:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
// CHECK-LABEL: GS-PAUTH: Warning: pac-ret analysis could not analyze this return instruction in function f_eret, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:   The instruction is     {{[0-9a-f]+}}:       eret
        eret
        .size f_eret, .-f_eret

        .globl f_movx30reg
        .type   f_movx30reg,@function
f_movx30reg:
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_movx30reg, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: mov x30, x22
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x30, x22
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        mov     x30, x22
        ret
        .size f_movx30reg, .-f_movx30reg

        .globl  f_autiasppci
        .type   f_autiasppci,@function
f_autiasppci:
0:
        pacnbiasppc
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autiasppc 0b
// CHECK-NOT: function f_autiasppci
        ret
        .size f_autiasppci, .-f_autiasppci

        .globl  f_autibsppci
        .type   f_autibsppci,@function
f_autibsppci:
0:
        pacnbibsppc
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autibsppc 0b
// CHECK-NOT: function f_autibsppci
        ret
        .size f_autibsppci, .-f_autibsppci

        .globl  f_autiasppcr
        .type   f_autiasppcr,@function

f_autiasppcr:
0:
        pacnbiasppc
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        adr     x28, 0b
        autiasppcr x28
// CHECK-NOT: function f_autiasppcr
        ret
        .size f_autiasppcr, .-f_autiasppcr

f_autibsppcr:
0:
        pacnbibsppc
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        adr     x28, 0b
        autibsppcr x28
// CHECK-NOT: function f_autibsppcr
        ret
        .size f_autibsppcr, .-f_autibsppcr

        .globl  f_retaasppci
        .type   f_retaasppci,@function
f_retaasppci:
0:
        pacnbiasppc
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
// CHECK-NOT: function f_retaasppci
        retaasppc 0b
        .size f_retaasppci, .-f_retaasppci

        .globl  f_retabsppci
        .type   f_retabsppci,@function
f_retabsppci:
0:
        pacnbibsppc
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
// CHECK-NOT: function f_retabsppci
        retabsppc 0b
        .size f_retabsppci, .-f_retabsppci

        .globl  f_retaasppcr
        .type   f_retaasppcr,@function

f_retaasppcr:
0:
        pacnbiasppc
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        adr     x28, 0b
// CHECK-NOT: function f_retaasppcr
        retaasppcr x28
        .size f_retaasppcr, .-f_retaasppcr

f_retabsppcr:
0:
        pacnbibsppc
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        adr     x28, 0b
// CHECK-NOT: function f_retabsppcr
        retabsppcr x28
        .size f_retabsppcr, .-f_retabsppcr

        .globl  f_autia171615
        .type   f_autia171615,@function
f_autia171615:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autia171615
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autia171615, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autia171615
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_autia171615, .-f_autia171615

        .globl  f_autib171615
        .type   f_autib171615,@function
f_autib171615:
        paciasp
        stp     x29, x30, [sp, #-16]!
        mov     x29, sp
        bl      g
        add     x0, x0, #3
        ldp     x29, x30, [sp], #16
        autib171615
// CHECK-LABEL: GS-PAUTH: non-protected ret found in function f_autib171615, basic block {{[0-9a-zA-Z.]+}}, at address
// CHECK-NEXT:    The instruction is     {{[0-9a-f]+}}:       ret
// CHECK-NEXT:    The 1 instructions that write to the affected registers after any authentication are:
// CHECK-NEXT:    1. {{[0-9a-f]+}}: ldp     x29, x30, [sp], #0x10
// CHECK-NEXT:  This happens in the following basic block:
// CHECK-NEXT: {{[0-9a-f]+}}:   paciasp
// CHECK-NEXT: {{[0-9a-f]+}}:   stp     x29, x30, [sp, #-0x10]!
// CHECK-NEXT: {{[0-9a-f]+}}:   mov     x29, sp
// CHECK-NEXT: {{[0-9a-f]+}}:   bl      g
// CHECK-NEXT: {{[0-9a-f]+}}:   add     x0, x0, #0x3
// CHECK-NEXT: {{[0-9a-f]+}}:   ldp     x29, x30, [sp], #0x10
// CHECK-NEXT: {{[0-9a-f]+}}:   autib171615
// CHECK-NEXT: {{[0-9a-f]+}}:   ret
        ret
        .size f_autib171615, .-f_autib171615

        .globl  g
        .type   g,@function
g:
        nop
        ret
        .size g, .-g
