Compiler projects using llvm
; RUN: llc -mtriple=arm64-apple-ios15 %s -o - | FileCheck %s --check-prefixes=CHECK-NOAUTH,CHECK
; RUN: llc -mtriple=arm64-apple-ios15 -mcpu=apple-a13 %s -o - | FileCheck %s --check-prefixes=CHECK-NOAUTH,CHECK
; RUN: llc -mtriple=arm64e-apple-ios15 %s -o - | FileCheck %s --check-prefixes=CHECK-AUTH,CHECK

; Important details in prologue:
;   * x22 is stored just below x29
;   * Enough stack space is allocated for everything
define swifttailcc void @simple(i8* swiftasync %ctx) "frame-pointer"="all" {
; CHECK-LABEL: simple:
; CHECK: orr x29, x29, #0x100000000000000
; CHECK: sub sp, sp, #32
; CHECK: stp x29, x30, [sp, #16]

; CHECK-NOAUTH-DAG: str x22, [sp, #8]
; CHECK-AUTH: add x16, sp, #8
; CHECK-AUTH: movk x16, #49946, lsl #48
; CHECK-AUTH: mov x17, x22
; CHECK-AUTH: pacdb x17, x16
; CHECK-AUTH: str x17, [sp, #8]

; CHECK-DAG: add x29, sp, #16
; CHECK: .cfi_def_cfa w29, 16
; CHECK: .cfi_offset w30, -8
; CHECK: .cfi_offset w29, -16

;[...]

; CHECK: ldp x29, x30, [sp, #16]
; CHECK: and x29, x29, #0xefffffffffffffff
; CHECK: add sp, sp, #32

  ret void
}

define swifttailcc void @more_csrs(i8* swiftasync %ctx) "frame-pointer"="all" {
; CHECK-LABEL: more_csrs:
; CHECK: orr x29, x29, #0x100000000000000
; CHECK: str x23, [sp, #-32]!
; CHECK: stp x29, x30, [sp, #16]

; CHECK-NOAUTH-DAG: str x22, [sp, #8]
; CHECK-AUTH: add x16, sp, #8
; CHECK-AUTH: movk x16, #49946, lsl #48
; CHECK-AUTH: mov x17, x22
; CHECK-AUTH: pacdb x17, x16
; CHECK-AUTH: str x17, [sp, #8]

; CHECK-DAG: add x29, sp, #16
; CHECK: .cfi_def_cfa w29, 16
; CHECK: .cfi_offset w30, -8
; CHECK: .cfi_offset w29, -16
; CHECK: .cfi_offset w23, -32

; [...]

; CHECK: ldp x29, x30, [sp, #16]
; CHECK: ldr x23, [sp], #32
; CHECK: and x29, x29, #0xefffffffffffffff
  call void asm sideeffect "", "~{x23}"()
  ret void
}

define swifttailcc void @locals(i8* swiftasync %ctx) "frame-pointer"="all" {
; CHECK-LABEL: locals:
; CHECK: orr x29, x29, #0x100000000000000
; CHECK: sub sp, sp, #64
; CHECK: stp x29, x30, [sp, #48]

; CHECK-NOAUTH-DAG: str x22, [sp, #40]
; CHECK-AUTH: add x16, sp, #40
; CHECK-AUTH: movk x16, #49946, lsl #48
; CHECK-AUTH: mov x17, x22
; CHECK-AUTH: pacdb x17, x16
; CHECK-AUTH: str x17, [sp, #40]

; CHECK-DAG: add x29, sp, #48
; CHECK: .cfi_def_cfa w29, 16
; CHECK: .cfi_offset w30, -8
; CHECK: .cfi_offset w29, -16

; CHECK: mov x0, sp
; CHECK: bl _bar

; [...]

; CHECK: ldp x29, x30, [sp, #48]
; CHECK: and x29, x29, #0xefffffffffffffff
; CHECK: add sp, sp, #64
  %var = alloca i32, i32 10
  call void @bar(i32* %var)
  ret void
}

define swifttailcc void @use_input_context(i8* swiftasync %ctx, i8** %ptr) "frame-pointer"="all" {
; CHECK-LABEL: use_input_context:

; CHECK-NOAUTH: str x22, [sp
; CHECK-AUTH: mov x17, x22

; CHECK-NOT: x22
; CHECK: str x22, [x0]

  store i8* %ctx, i8** %ptr
  ret void
}

define swifttailcc i8** @context_in_func() "frame-pointer"="non-leaf" {
; CHECK-LABEL: context_in_func:

; CHECK-NOAUTH: str xzr, [sp, #8]
; CHECK-AUTH: add x16, sp, #8
; CHECK-AUTH: movk x16, #49946, lsl #48
; CHECK-AUTH: mov x17, xzr
; CHECK-AUTH: pacdb x17, x16
; CHECK-AUTH: str x17, [sp, #8]

  %ptr = call i8** @llvm.swift.async.context.addr()
  ret i8** %ptr
}

define swifttailcc void @write_frame_context(i8* swiftasync %ctx, i8* %newctx) "frame-pointer"="non-leaf" {
; CHECK-LABEL: write_frame_context:
; CHECK: sub x[[ADDR:[0-9]+]], x29, #8
; CHECK: str x0, [x[[ADDR]]]
  %ptr = call i8** @llvm.swift.async.context.addr()
  store i8* %newctx, i8** %ptr
  ret void
}

define swifttailcc void @simple_fp_elim(i8* swiftasync %ctx) "frame-pointer"="non-leaf" {
; CHECK-LABEL: simple_fp_elim:
; CHECK-NOT: orr x29, x29, #0x100000000000000

  ret void
}

define swifttailcc void @large_frame(i8* swiftasync %ctx) "frame-pointer"="all" {
; CHECK-LABEL: large_frame:
; CHECK: str x28, [sp, #-32]!
; CHECK: stp x29, x30, [sp, #16]
; CHECK-NOAUTH-DAG: str x22, [sp, #8]
; CHECK-DAG: add x29, sp, #16
; CHECK: sub sp, sp, #1024
; [...]
; CHECK: add sp, sp, #1024
; CHECK: ldp x29, x30, [sp, #16]
; CHECK: ldr x28, [sp], #32
; CHECK: ret
  %var = alloca i8, i32 1024
  ret void
}

; Important point is that there is just one 8-byte gap in the CSR region (right
; now just above d8) to realign the stack.
define swifttailcc void @two_unpaired_csrs(i8* swiftasync) "frame-pointer"="all" {
; CHECK-LABEL: two_unpaired_csrs:
; CHECK: str d8, [sp, #-48]!
; CHECK: str x19, [sp, #16]
; CHECK: stp x29, x30, [sp, #32]
; CHECK-NOAUTH-DAG: str x22, [sp, #24]
; CHECK-DAG: add x29, sp, #32

; CHECK: .cfi_def_cfa w29, 16
; CHECK: .cfi_offset w30, -8
; CHECK: .cfi_offset w29, -16
; CHECK: .cfi_offset w19, -32
; CHECK: .cfi_offset b8, -48

  call void asm "","~{x19},~{d8}"()
  call swifttailcc void @bar(i32* undef)
  ret void
}
declare swifttailcc void @bar(i32*)
declare i8** @llvm.swift.async.context.addr()