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 7declare void @llvm.va_start(i8*) 8 9define 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 39define 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 69define 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. 83define 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 108declare void @llvm.va_end(i8*) 109 110define 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 121declare void @llvm.va_copy(i8* %dest, i8* %src) 122 123@second_list = global %va_list zeroinitializer 124 125define 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