// REQUIRES: asserts
//
// RUN: %clang %cflags -march=armv8.3-a %s -o %t.exe
// RUN: llvm-bolt-binary-analysis --scanners=pacret -no-threads \
// RUN:    -debug-only bolt-pauth-scanner %t.exe 2>&1 | FileCheck %s

// Check the debug output generated by PAuth gadget scanner to make sure the
// that output is kept meaningful and to provide an overview of what happens
// inside the scanner.

        .globl  simple
        .type   simple,@function
simple:
        paciasp
        b       1f
1:
        autiasp
        ret
        .size simple, .-simple

// CHECK-LABEL:Analyzing in function simple, AllocatorId 1
// CHECK-NEXT: Binary Function "simple"  {
// CHECK-NEXT:   Number      : 1
// CHECK-NEXT:   State       : CFG constructed
// ...
// CHECK:        BB Layout   : [[BB0:[0-9a-zA-Z.]+]], [[BB1:[0-9a-zA-Z.]+]]
// CHECK-NEXT: }
// CHECK-NEXT: [[BB0]] (2 instructions, align : 1)
// CHECK-NEXT:   Entry Point
// CHECK-NEXT:     00000000:   paciasp
// CHECK-NEXT:     00000004:   b       [[BB1]]
// CHECK-NEXT:   Successors: [[BB1]]
// CHECK-EMPTY:
// CHECK-NEXT: [[BB1]] (2 instructions, align : 1)
// CHECK-NEXT:   Predecessors: [[BB0]]
// CHECK-NEXT:     00000008:   autiasp
// CHECK-NEXT:     0000000c:   ret
// CHECK-EMPTY:
// CHECK-NEXT: DWARF CFI Instructions:
// CHECK-NEXT:     <empty>
// CHECK-NEXT: End of Function "simple"
// CHECK-EMPTY:
// CHECK-NEXT:  PacRetAnalysis::ComputeNext(   hint    #25, pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT:   .. result: (pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT:  PacRetAnalysis::ComputeNext(   b       [[BB1]], pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT:   .. result: (pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT:  PacRetAnalysis::Confluence(
// CHECK-NEXT:    State 1: pacret-state<empty>
// CHECK-NEXT:    State 2: pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT:    merged state: pacret-state<SafeToDerefRegs: , Insts: >
// CHECK-NEXT:  PacRetAnalysis::ComputeNext(   hint    #29, pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT:   .. result: (pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT:  PacRetAnalysis::ComputeNext(   ret     x30, pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT:   .. result: (pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT:  PacRetAnalysis::Confluence(
// CHECK-NEXT:    State 1: pacret-state<SafeToDerefRegs: , Insts: >
// CHECK-NEXT:    State 2: pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT:    merged state: pacret-state<SafeToDerefRegs: , Insts: >
// CHECK-NEXT:  PacRetAnalysis::ComputeNext(   hint    #29, pacret-state<SafeToDerefRegs: , Insts: >)
// CHECK-NEXT:   .. result: (pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT:  PacRetAnalysis::ComputeNext(   ret     x30, pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT:   .. result: (pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT:  After PacRetAnalysis:
// CHECK-NEXT: Binary Function "simple"  {
// CHECK-NEXT:   Number      : 1
// CHECK-NEXT:   State       : CFG constructed
// ...
// CHECK:        BB Layout   : [[BB0]], [[BB1]]
// CHECK-NEXT: }
// CHECK-NEXT: [[BB0]] (2 instructions, align : 1)
// CHECK-NEXT:   Entry Point
// CHECK-NEXT:     00000000:   paciasp # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT:     00000004:   b       [[BB1]] # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT:   Successors: [[BB1]]
// CHECK-EMPTY:
// CHECK-NEXT: [[BB1]] (2 instructions, align : 1)
// CHECK-NEXT:   Predecessors: [[BB0]]
// CHECK-NEXT:     00000008:   autiasp # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT:     0000000c:   ret # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-EMPTY:
// CHECK-NEXT: DWARF CFI Instructions:
// CHECK-NEXT:     <empty>
// CHECK-NEXT: End of Function "simple"
// CHECK-EMPTY:
// CHECK-NEXT:   Found RET inst:     00000000:         ret # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT:     RetReg: LR
// CHECK-NEXT:     Authenticated reg: (none)
// CHECK-NEXT:     SafeToDerefRegs: LR W30 W30_HI{{[ \t]*$}}

        .globl  clobber
        .type   clobber,@function
clobber:
        mov     w30, #0
        ret
        .size clobber, .-clobber

// CHECK-LABEL:Analyzing in function clobber, AllocatorId 1
// ...
// CHECK:       PacRetAnalysis::ComputeNext(   mov     w30, #0x0, pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: >)
// CHECK-NEXT:   .. result: (pacret-state<SafeToDerefRegs: W30_HI , Insts: >)
// CHECK-NEXT:  PacRetAnalysis::ComputeNext(   ret     x30, pacret-state<SafeToDerefRegs: W30_HI , Insts: >)
// CHECK-NEXT:   .. result: (pacret-state<SafeToDerefRegs: W30_HI , Insts: >)
// CHECK-NEXT:  After PacRetAnalysis:
// CHECK-NEXT: Binary Function "clobber"  {
// ...
// CHECK:      End of Function "clobber"

// The above output was printed after first run of analysis

// CHECK-EMPTY:
// CHECK-NEXT:   Found RET inst:     00000000:         ret # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: >
// CHECK-NEXT:     RetReg: LR
// CHECK-NEXT:     Authenticated reg: (none)
// CHECK-NEXT:     SafeToDerefRegs: W30_HI{{[ \t]*$}}
// CHECK-NEXT:  PacRetAnalysis::ComputeNext(   mov     w30, #0x0, pacret-state<SafeToDerefRegs: LR W30 W30_HI , Insts: [0]()>)
// CHECK-NEXT:   .. result: (pacret-state<SafeToDerefRegs: W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
// CHECK-NEXT:  PacRetAnalysis::ComputeNext(   ret     x30, pacret-state<SafeToDerefRegs: W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
// CHECK-NEXT:   .. result: (pacret-state<SafeToDerefRegs: W30_HI , Insts: [0](0x{{[0-9a-f]+}} )>)
// CHECK-NEXT:  After detailed PacRetAnalysis:
// CHECK-NEXT: Binary Function "clobber"  {
// ...
// CHECK:      End of Function "clobber"

// The analysis was re-computed with register tracking, as an issue was found in this function.
// Iterating over the reports and attaching clobbering info:

// CHECK-EMPTY:
// CHECK-NEXT:   Attaching clobbering info to:     00000000:         ret # PacRetAnalysis: pacret-state<SafeToDerefRegs: BitVector, Insts: [0](0x{{[0-9a-f]+}} )>


// CHECK-LABEL:Analyzing in function main, AllocatorId 1
        .globl  main
        .type   main,@function
main:
        ret
        .size main, .-main
