Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu < %s | FileCheck %s
      2 
      3 %va_list = type {i8*, i8*, i8*, i32, i32}
      4 
      5 @var = global %va_list zeroinitializer
      6 
      7 declare void @llvm.va_start(i8*)
      8 
      9 define void @test_simple(i32 %n, ...) {
     10 ; CHECK-LABEL: test_simple:
     11 ; CHECK: sub sp, sp, #[[STACKSIZE:[0-9]+]]
     12 ; CHECK: mov x[[FPRBASE:[0-9]+]], sp
     13 ; CHECK: str q7, [x[[FPRBASE]], #112]
     14 ; CHECK: add x[[GPRBASE:[0-9]+]], sp, #[[GPRFROMSP:[0-9]+]]
     15 ; CHECK: str x7, [x[[GPRBASE]], #48]
     16 
     17 ; Omit the middle ones
     18 
     19 ; CHECK: str q0, [sp]
     20 ; CHECK: str x1, [sp, #[[GPRFROMSP]]]
     21 
     22   %addr = bitcast %va_list* @var to i8*
     23   call void @llvm.va_start(i8* %addr)
     24 ; CHECK: add x[[VA_LIST:[0-9]+]], {{x[0-9]+}}, #:lo12:var
     25 ; CHECK: movn [[VR_OFFS:w[0-9]+]], #127
     26 ; CHECK: str [[VR_OFFS]], [x[[VA_LIST]], #28]
     27 ; CHECK: movn [[GR_OFFS:w[0-9]+]], #55
     28 ; CHECK: str [[GR_OFFS]], [x[[VA_LIST]], #24]
     29 ; CHECK: add [[VR_TOP:x[0-9]+]], x[[FPRBASE]], #128
     30 ; CHECK: str [[VR_TOP]], [x[[VA_LIST]], #16]
     31 ; CHECK: add [[GR_TOP:x[0-9]+]], x[[GPRBASE]], #56
     32 ; CHECK: str [[GR_TOP]], [x[[VA_LIST]], #8]
     33 ; CHECK: add [[STACK:x[0-9]+]], sp, #[[STACKSIZE]]
     34 ; CHECK: str [[STACK]], [{{x[0-9]+}}, #:lo12:var]
     35 
     36   ret void
     37 }
     38 
     39 define void @test_fewargs(i32 %n, i32 %n1, i32 %n2, float %m, ...) {
     40 ; CHECK-LABEL: test_fewargs:
     41 ; CHECK: sub sp, sp, #[[STACKSIZE:[0-9]+]]
     42 ; CHECK: mov x[[FPRBASE:[0-9]+]], sp
     43 ; CHECK: str q7, [x[[FPRBASE]], #96]
     44 ; CHECK: add x[[GPRBASE:[0-9]+]], sp, #[[GPRFROMSP:[0-9]+]]
     45 ; CHECK: str x7, [x[[GPRBASE]], #32]
     46 
     47 ; Omit the middle ones
     48 
     49 ; CHECK: str q1, [sp]
     50 ; CHECK: str x3, [sp, #[[GPRFROMSP]]]
     51 
     52   %addr = bitcast %va_list* @var to i8*
     53   call void @llvm.va_start(i8* %addr)
     54 ; CHECK: add x[[VA_LIST:[0-9]+]], {{x[0-9]+}}, #:lo12:var
     55 ; CHECK: movn [[VR_OFFS:w[0-9]+]], #111
     56 ; CHECK: str [[VR_OFFS]], [x[[VA_LIST]], #28]
     57 ; CHECK: movn [[GR_OFFS:w[0-9]+]], #39
     58 ; CHECK: str [[GR_OFFS]], [x[[VA_LIST]], #24]
     59 ; CHECK: add [[VR_TOP:x[0-9]+]], x[[FPRBASE]], #112
     60 ; CHECK: str [[VR_TOP]], [x[[VA_LIST]], #16]
     61 ; CHECK: add [[GR_TOP:x[0-9]+]], x[[GPRBASE]], #40
     62 ; CHECK: str [[GR_TOP]], [x[[VA_LIST]], #8]
     63 ; CHECK: add [[STACK:x[0-9]+]], sp, #[[STACKSIZE]]
     64 ; CHECK: str [[STACK]], [{{x[0-9]+}}, #:lo12:var]
     65 
     66   ret void
     67 }
     68 
     69 define void @test_nospare([8 x i64], [8 x float], ...) {
     70 ; CHECK-LABEL: test_nospare:
     71 
     72   %addr = bitcast %va_list* @var to i8*
     73   call void @llvm.va_start(i8* %addr)
     74 ; CHECK-NOT: sub sp, sp
     75 ; CHECK: mov [[STACK:x[0-9]+]], sp
     76 ; CHECK: str [[STACK]], [{{x[0-9]+}}, #:lo12:var]
     77 
     78   ret void
     79 }
     80 
     81 ; If there are non-variadic arguments on the stack (here two i64s) then the
     82 ; __stack field should point just past them.
     83 define void @test_offsetstack([10 x i64], [3 x float], ...) {
     84 ; CHECK-LABEL: test_offsetstack:
     85 ; CHECK: sub sp, sp, #80
     86 ; CHECK: mov x[[FPRBASE:[0-9]+]], sp
     87 ; CHECK: str q7, [x[[FPRBASE]], #64]
     88 
     89 ; CHECK-NOT: str x{{[0-9]+}},
     90 ; Omit the middle ones
     91 
     92 ; CHECK: str q3, [sp]
     93 
     94   %addr = bitcast %va_list* @var to i8*
     95   call void @llvm.va_start(i8* %addr)
     96 ; CHECK: add x[[VA_LIST:[0-9]+]], {{x[0-9]+}}, #:lo12:var
     97 ; CHECK: movn [[VR_OFFS:w[0-9]+]], #79
     98 ; CHECK: str [[VR_OFFS]], [x[[VA_LIST]], #28]
     99 ; CHECK: str wzr, [x[[VA_LIST]], #24]
    100 ; CHECK: add [[VR_TOP:x[0-9]+]], x[[FPRBASE]], #80
    101 ; CHECK: str [[VR_TOP]], [x[[VA_LIST]], #16]
    102 ; CHECK: add [[STACK:x[0-9]+]], sp, #96
    103 ; CHECK: str [[STACK]], [{{x[0-9]+}}, #:lo12:var]
    104 
    105   ret void
    106 }
    107 
    108 declare void @llvm.va_end(i8*)
    109 
    110 define void @test_va_end() nounwind {
    111 ; CHECK-LABEL: test_va_end:
    112 ; CHECK-NEXT: BB#0
    113 
    114   %addr = bitcast %va_list* @var to i8*
    115   call void @llvm.va_end(i8* %addr)
    116 
    117   ret void
    118 ; CHECK-NEXT: ret
    119 }
    120 
    121 declare void @llvm.va_copy(i8* %dest, i8* %src)
    122 
    123 @second_list = global %va_list zeroinitializer
    124 
    125 define void @test_va_copy() {
    126 ; CHECK-LABEL: test_va_copy:
    127   %srcaddr = bitcast %va_list* @var to i8*
    128   %dstaddr = bitcast %va_list* @second_list to i8*
    129   call void @llvm.va_copy(i8* %dstaddr, i8* %srcaddr)
    130 
    131 ; Check beginning and end again:
    132 
    133 ; CHECK: ldr [[BLOCK:x[0-9]+]], [{{x[0-9]+}}, #:lo12:var]
    134 ; CHECK: str [[BLOCK]], [{{x[0-9]+}}, #:lo12:second_list]
    135 
    136 ; CHECK: add x[[DEST_LIST:[0-9]+]], {{x[0-9]+}}, #:lo12:second_list
    137 ; CHECK: add x[[SRC_LIST:[0-9]+]], {{x[0-9]+}}, #:lo12:var
    138 
    139 ; CHECK: ldr [[BLOCK:x[0-9]+]], [x[[SRC_LIST]], #24]
    140 ; CHECK: str [[BLOCK]], [x[[DEST_LIST]], #24]
    141 
    142   ret void
    143 ; CHECK: ret
    144 }
    145