1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -triple aarch64 -emit-llvm -o - %s | FileCheck %s 2*f4a2713aSLionel Sambuc #include <stdarg.h> 3*f4a2713aSLionel Sambuc 4*f4a2713aSLionel Sambuc // Obviously there's more than one way to implement va_arg. This test should at 5*f4a2713aSLionel Sambuc // least prevent unintentional regressions caused by refactoring. 6*f4a2713aSLionel Sambuc 7*f4a2713aSLionel Sambuc va_list the_list; 8*f4a2713aSLionel Sambuc 9*f4a2713aSLionel Sambuc int simple_int(void) { 10*f4a2713aSLionel Sambuc // CHECK-LABEL: define i32 @simple_int 11*f4a2713aSLionel Sambuc return va_arg(the_list, int); 12*f4a2713aSLionel Sambuc // CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) 13*f4a2713aSLionel Sambuc // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0 14*f4a2713aSLionel Sambuc // CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]] 15*f4a2713aSLionel Sambuc 16*f4a2713aSLionel Sambuc // CHECK: [[VAARG_MAYBE_REG]] 17*f4a2713aSLionel Sambuc // CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8 18*f4a2713aSLionel Sambuc // CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) 19*f4a2713aSLionel Sambuc // CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0 20*f4a2713aSLionel Sambuc // CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]] 21*f4a2713aSLionel Sambuc 22*f4a2713aSLionel Sambuc // CHECK: [[VAARG_IN_REG]] 23*f4a2713aSLionel Sambuc // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 1) 24*f4a2713aSLionel Sambuc // CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[GR_OFFS]] 25*f4a2713aSLionel Sambuc // CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to i32* 26*f4a2713aSLionel Sambuc // CHECK: br label %[[VAARG_END:[a-z._0-9]+]] 27*f4a2713aSLionel Sambuc 28*f4a2713aSLionel Sambuc // CHECK: [[VAARG_ON_STACK]] 29*f4a2713aSLionel Sambuc // CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) 30*f4a2713aSLionel Sambuc // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[STACK]], i32 8 31*f4a2713aSLionel Sambuc // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) 32*f4a2713aSLionel Sambuc // CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to i32* 33*f4a2713aSLionel Sambuc // CHECK: br label %[[VAARG_END]] 34*f4a2713aSLionel Sambuc 35*f4a2713aSLionel Sambuc // CHECK: [[VAARG_END]] 36*f4a2713aSLionel Sambuc // CHECK: [[ADDR:%[a-z._0-9]+]] = phi i32* [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ] 37*f4a2713aSLionel Sambuc // CHECK: [[RESULT:%[a-z_0-9]+]] = load i32* [[ADDR]] 38*f4a2713aSLionel Sambuc // CHECK: ret i32 [[RESULT]] 39*f4a2713aSLionel Sambuc } 40*f4a2713aSLionel Sambuc 41*f4a2713aSLionel Sambuc __int128 aligned_int(void) { 42*f4a2713aSLionel Sambuc // CHECK-LABEL: define i128 @aligned_int 43*f4a2713aSLionel Sambuc return va_arg(the_list, __int128); 44*f4a2713aSLionel Sambuc // CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) 45*f4a2713aSLionel Sambuc // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0 46*f4a2713aSLionel Sambuc // CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]] 47*f4a2713aSLionel Sambuc 48*f4a2713aSLionel Sambuc // CHECK: [[VAARG_MAYBE_REG]] 49*f4a2713aSLionel Sambuc // CHECK: [[ALIGN_REGOFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 15 50*f4a2713aSLionel Sambuc // CHECK: [[ALIGNED_REGOFFS:%[a-z_0-9]+]] = and i32 [[ALIGN_REGOFFS]], -16 51*f4a2713aSLionel Sambuc // CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[ALIGNED_REGOFFS]], 16 52*f4a2713aSLionel Sambuc // CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) 53*f4a2713aSLionel Sambuc // CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0 54*f4a2713aSLionel Sambuc // CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]] 55*f4a2713aSLionel Sambuc 56*f4a2713aSLionel Sambuc // CHECK: [[VAARG_IN_REG]] 57*f4a2713aSLionel Sambuc // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 1) 58*f4a2713aSLionel Sambuc // CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[ALIGNED_REGOFFS]] 59*f4a2713aSLionel Sambuc // CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to i128* 60*f4a2713aSLionel Sambuc // CHECK: br label %[[VAARG_END:[a-z._0-9]+]] 61*f4a2713aSLionel Sambuc 62*f4a2713aSLionel Sambuc // CHECK: [[VAARG_ON_STACK]] 63*f4a2713aSLionel Sambuc // CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) 64*f4a2713aSLionel Sambuc // CHECK: [[STACKINT:%[a-z_0-9]+]] = ptrtoint i8* [[STACK]] to i64 65*f4a2713aSLionel Sambuc // CHECK: [[ALIGN_STACK:%[a-z_0-9]+]] = add i64 [[STACKINT]], 15 66*f4a2713aSLionel Sambuc // CHECK: [[ALIGNED_STACK_INT:%[a-z_0-9]+]] = and i64 [[ALIGN_STACK]], -16 67*f4a2713aSLionel Sambuc // CHECK: [[ALIGNED_STACK_PTR:%[a-z_0-9]+]] = inttoptr i64 [[ALIGNED_STACK_INT]] to i8* 68*f4a2713aSLionel Sambuc // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[ALIGNED_STACK_PTR]], i32 16 69*f4a2713aSLionel Sambuc // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) 70*f4a2713aSLionel Sambuc // CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[ALIGNED_STACK_PTR]] to i128* 71*f4a2713aSLionel Sambuc // CHECK: br label %[[VAARG_END]] 72*f4a2713aSLionel Sambuc 73*f4a2713aSLionel Sambuc // CHECK: [[VAARG_END]] 74*f4a2713aSLionel Sambuc // CHECK: [[ADDR:%[a-z._0-9]+]] = phi i128* [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ] 75*f4a2713aSLionel Sambuc // CHECK: [[RESULT:%[a-z_0-9]+]] = load i128* [[ADDR]] 76*f4a2713aSLionel Sambuc // CHECK: ret i128 [[RESULT]] 77*f4a2713aSLionel Sambuc } 78*f4a2713aSLionel Sambuc 79*f4a2713aSLionel Sambuc struct bigstruct { 80*f4a2713aSLionel Sambuc int a[10]; 81*f4a2713aSLionel Sambuc }; 82*f4a2713aSLionel Sambuc 83*f4a2713aSLionel Sambuc struct bigstruct simple_indirect(void) { 84*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @simple_indirect 85*f4a2713aSLionel Sambuc return va_arg(the_list, struct bigstruct); 86*f4a2713aSLionel Sambuc // CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) 87*f4a2713aSLionel Sambuc // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0 88*f4a2713aSLionel Sambuc // CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]] 89*f4a2713aSLionel Sambuc 90*f4a2713aSLionel Sambuc // CHECK: [[VAARG_MAYBE_REG]] 91*f4a2713aSLionel Sambuc // CHECK-NOT: and i32 92*f4a2713aSLionel Sambuc // CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8 93*f4a2713aSLionel Sambuc // CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) 94*f4a2713aSLionel Sambuc // CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0 95*f4a2713aSLionel Sambuc // CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]] 96*f4a2713aSLionel Sambuc 97*f4a2713aSLionel Sambuc // CHECK: [[VAARG_IN_REG]] 98*f4a2713aSLionel Sambuc // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 1) 99*f4a2713aSLionel Sambuc // CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[GR_OFFS]] 100*f4a2713aSLionel Sambuc // CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to %struct.bigstruct** 101*f4a2713aSLionel Sambuc // CHECK: br label %[[VAARG_END:[a-z._0-9]+]] 102*f4a2713aSLionel Sambuc 103*f4a2713aSLionel Sambuc // CHECK: [[VAARG_ON_STACK]] 104*f4a2713aSLionel Sambuc // CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) 105*f4a2713aSLionel Sambuc // CHECK-NOT: and i64 106*f4a2713aSLionel Sambuc // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[STACK]], i32 8 107*f4a2713aSLionel Sambuc // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) 108*f4a2713aSLionel Sambuc // CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to %struct.bigstruct** 109*f4a2713aSLionel Sambuc // CHECK: br label %[[VAARG_END]] 110*f4a2713aSLionel Sambuc 111*f4a2713aSLionel Sambuc // CHECK: [[VAARG_END]] 112*f4a2713aSLionel Sambuc // CHECK: [[ADDR:%[a-z._0-9]+]] = phi %struct.bigstruct** [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ] 113*f4a2713aSLionel Sambuc // CHECK: load %struct.bigstruct** [[ADDR]] 114*f4a2713aSLionel Sambuc } 115*f4a2713aSLionel Sambuc 116*f4a2713aSLionel Sambuc struct aligned_bigstruct { 117*f4a2713aSLionel Sambuc float a; 118*f4a2713aSLionel Sambuc long double b; 119*f4a2713aSLionel Sambuc }; 120*f4a2713aSLionel Sambuc 121*f4a2713aSLionel Sambuc struct aligned_bigstruct simple_aligned_indirect(void) { 122*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @simple_aligned_indirect 123*f4a2713aSLionel Sambuc return va_arg(the_list, struct aligned_bigstruct); 124*f4a2713aSLionel Sambuc // CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) 125*f4a2713aSLionel Sambuc // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0 126*f4a2713aSLionel Sambuc // CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]] 127*f4a2713aSLionel Sambuc 128*f4a2713aSLionel Sambuc // CHECK: [[VAARG_MAYBE_REG]] 129*f4a2713aSLionel Sambuc // CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[GR_OFFS]], 8 130*f4a2713aSLionel Sambuc // CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 3) 131*f4a2713aSLionel Sambuc // CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0 132*f4a2713aSLionel Sambuc // CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]] 133*f4a2713aSLionel Sambuc 134*f4a2713aSLionel Sambuc // CHECK: [[VAARG_IN_REG]] 135*f4a2713aSLionel Sambuc // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 1) 136*f4a2713aSLionel Sambuc // CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[GR_OFFS]] 137*f4a2713aSLionel Sambuc // CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to %struct.aligned_bigstruct** 138*f4a2713aSLionel Sambuc // CHECK: br label %[[VAARG_END:[a-z._0-9]+]] 139*f4a2713aSLionel Sambuc 140*f4a2713aSLionel Sambuc // CHECK: [[VAARG_ON_STACK]] 141*f4a2713aSLionel Sambuc // CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) 142*f4a2713aSLionel Sambuc // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[STACK]], i32 8 143*f4a2713aSLionel Sambuc // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) 144*f4a2713aSLionel Sambuc // CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to %struct.aligned_bigstruct** 145*f4a2713aSLionel Sambuc // CHECK: br label %[[VAARG_END]] 146*f4a2713aSLionel Sambuc 147*f4a2713aSLionel Sambuc // CHECK: [[VAARG_END]] 148*f4a2713aSLionel Sambuc // CHECK: [[ADDR:%[a-z._0-9]+]] = phi %struct.aligned_bigstruct** [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ] 149*f4a2713aSLionel Sambuc // CHECK: load %struct.aligned_bigstruct** [[ADDR]] 150*f4a2713aSLionel Sambuc } 151*f4a2713aSLionel Sambuc 152*f4a2713aSLionel Sambuc double simple_double(void) { 153*f4a2713aSLionel Sambuc // CHECK-LABEL: define double @simple_double 154*f4a2713aSLionel Sambuc return va_arg(the_list, double); 155*f4a2713aSLionel Sambuc // CHECK: [[VR_OFFS:%[a-z_0-9]+]] = load i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 4) 156*f4a2713aSLionel Sambuc // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[VR_OFFS]], 0 157*f4a2713aSLionel Sambuc // CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK]], label %[[VAARG_MAYBE_REG]] 158*f4a2713aSLionel Sambuc 159*f4a2713aSLionel Sambuc // CHECK: [[VAARG_MAYBE_REG]] 160*f4a2713aSLionel Sambuc // CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[VR_OFFS]], 16 161*f4a2713aSLionel Sambuc // CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 4) 162*f4a2713aSLionel Sambuc // CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0 163*f4a2713aSLionel Sambuc // CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]] 164*f4a2713aSLionel Sambuc 165*f4a2713aSLionel Sambuc // CHECK: [[VAARG_IN_REG]] 166*f4a2713aSLionel Sambuc // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 2) 167*f4a2713aSLionel Sambuc // CHECK: [[REG_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[VR_OFFS]] 168*f4a2713aSLionel Sambuc // CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast i8* [[REG_ADDR]] to double* 169*f4a2713aSLionel Sambuc // CHECK: br label %[[VAARG_END]] 170*f4a2713aSLionel Sambuc 171*f4a2713aSLionel Sambuc // CHECK: [[VAARG_ON_STACK]] 172*f4a2713aSLionel Sambuc // CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) 173*f4a2713aSLionel Sambuc // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[STACK]], i32 8 174*f4a2713aSLionel Sambuc // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) 175*f4a2713aSLionel Sambuc // CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to double* 176*f4a2713aSLionel Sambuc // CHECK: br label %[[VAARG_END]] 177*f4a2713aSLionel Sambuc 178*f4a2713aSLionel Sambuc // CHECK: [[VAARG_END]] 179*f4a2713aSLionel Sambuc // CHECK: [[ADDR:%[a-z._0-9]+]] = phi double* [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ] 180*f4a2713aSLionel Sambuc // CHECK: [[RESULT:%[a-z_0-9]+]] = load double* [[ADDR]] 181*f4a2713aSLionel Sambuc // CHECK: ret double [[RESULT]] 182*f4a2713aSLionel Sambuc } 183*f4a2713aSLionel Sambuc 184*f4a2713aSLionel Sambuc struct hfa { 185*f4a2713aSLionel Sambuc float a, b; 186*f4a2713aSLionel Sambuc }; 187*f4a2713aSLionel Sambuc 188*f4a2713aSLionel Sambuc struct hfa simple_hfa(void) { 189*f4a2713aSLionel Sambuc // CHECK-LABEL: define %struct.hfa @simple_hfa 190*f4a2713aSLionel Sambuc return va_arg(the_list, struct hfa); 191*f4a2713aSLionel Sambuc // CHECK: [[VR_OFFS:%[a-z_0-9]+]] = load i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 4) 192*f4a2713aSLionel Sambuc // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[VR_OFFS]], 0 193*f4a2713aSLionel Sambuc // CHECK: br i1 [[EARLY_ONSTACK]], label %[[VAARG_ON_STACK:[a-z_.0-9]+]], label %[[VAARG_MAYBE_REG:[a-z_.0-9]+]] 194*f4a2713aSLionel Sambuc 195*f4a2713aSLionel Sambuc // CHECK: [[VAARG_MAYBE_REG]] 196*f4a2713aSLionel Sambuc // CHECK: [[NEW_REG_OFFS:%[a-z_0-9]+]] = add i32 [[VR_OFFS]], 32 197*f4a2713aSLionel Sambuc // CHECK: store i32 [[NEW_REG_OFFS]], i32* getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 4) 198*f4a2713aSLionel Sambuc // CHECK: [[INREG:%[a-z_0-9]+]] = icmp sle i32 [[NEW_REG_OFFS]], 0 199*f4a2713aSLionel Sambuc // CHECK: br i1 [[INREG]], label %[[VAARG_IN_REG:[a-z_.0-9]+]], label %[[VAARG_ON_STACK]] 200*f4a2713aSLionel Sambuc 201*f4a2713aSLionel Sambuc // CHECK: [[VAARG_IN_REG]] 202*f4a2713aSLionel Sambuc // CHECK: [[REG_TOP:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 2) 203*f4a2713aSLionel Sambuc // CHECK: [[FIRST_REG:%[a-z_0-9]+]] = getelementptr i8* [[REG_TOP]], i32 [[VR_OFFS]] 204*f4a2713aSLionel Sambuc // CHECK: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[FIRST_REG]], i32 0 205*f4a2713aSLionel Sambuc // CHECK: [[EL_TYPED:%[a-z_0-9]+]] = bitcast i8* [[EL_ADDR]] to float* 206*f4a2713aSLionel Sambuc // CHECK: [[EL_TMPADDR:%[a-z_0-9]+]] = getelementptr inbounds [2 x float]* %[[TMP_HFA:[a-z_.0-9]+]], i32 0, i32 0 207*f4a2713aSLionel Sambuc // CHECK: [[EL:%[a-z_0-9]+]] = load float* [[EL_TYPED]] 208*f4a2713aSLionel Sambuc // CHECK: store float [[EL]], float* [[EL_TMPADDR]] 209*f4a2713aSLionel Sambuc // CHECK: [[EL_ADDR:%[a-z_0-9]+]] = getelementptr i8* [[FIRST_REG]], i32 16 210*f4a2713aSLionel Sambuc // CHECK: [[EL_TYPED:%[a-z_0-9]+]] = bitcast i8* [[EL_ADDR]] to float* 211*f4a2713aSLionel Sambuc // CHECK: [[EL_TMPADDR:%[a-z_0-9]+]] = getelementptr inbounds [2 x float]* %[[TMP_HFA]], i32 0, i32 1 212*f4a2713aSLionel Sambuc // CHECK: [[EL:%[a-z_0-9]+]] = load float* [[EL_TYPED]] 213*f4a2713aSLionel Sambuc // CHECK: store float [[EL]], float* [[EL_TMPADDR]] 214*f4a2713aSLionel Sambuc // CHECK: [[FROMREG_ADDR:%[a-z_0-9]+]] = bitcast [2 x float]* %[[TMP_HFA]] to %struct.hfa* 215*f4a2713aSLionel Sambuc // CHECK: br label %[[VAARG_END:[a-z_.0-9]+]] 216*f4a2713aSLionel Sambuc 217*f4a2713aSLionel Sambuc // CHECK: [[VAARG_ON_STACK]] 218*f4a2713aSLionel Sambuc // CHECK: [[STACK:%[a-z_0-9]+]] = load i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) 219*f4a2713aSLionel Sambuc // CHECK: [[NEW_STACK:%[a-z_0-9]+]] = getelementptr i8* [[STACK]], i32 8 220*f4a2713aSLionel Sambuc // CHECK: store i8* [[NEW_STACK]], i8** getelementptr inbounds (%struct.__va_list* @the_list, i32 0, i32 0) 221*f4a2713aSLionel Sambuc // CHECK: [[FROMSTACK_ADDR:%[a-z_0-9]+]] = bitcast i8* [[STACK]] to %struct.hfa* 222*f4a2713aSLionel Sambuc // CHECK: br label %[[VAARG_END]] 223*f4a2713aSLionel Sambuc 224*f4a2713aSLionel Sambuc // CHECK: [[VAARG_END]] 225*f4a2713aSLionel Sambuc // CHECK: [[ADDR:%[a-z._0-9]+]] = phi %struct.hfa* [ [[FROMREG_ADDR]], %[[VAARG_IN_REG]] ], [ [[FROMSTACK_ADDR]], %[[VAARG_ON_STACK]] ] 226*f4a2713aSLionel Sambuc } 227*f4a2713aSLionel Sambuc 228*f4a2713aSLionel Sambuc void check_start(int n, ...) { 229*f4a2713aSLionel Sambuc // CHECK-LABEL: define void @check_start(i32 %n, ...) 230*f4a2713aSLionel Sambuc 231*f4a2713aSLionel Sambuc va_list the_list; 232*f4a2713aSLionel Sambuc va_start(the_list, n); 233*f4a2713aSLionel Sambuc // CHECK: [[THE_LIST:%[a-z_0-9]+]] = alloca %struct.__va_list 234*f4a2713aSLionel Sambuc // CHECK: [[VOIDP_THE_LIST:%[a-z_0-9]+]] = bitcast %struct.__va_list* [[THE_LIST]] to i8* 235*f4a2713aSLionel Sambuc // CHECK: call void @llvm.va_start(i8* [[VOIDP_THE_LIST]]) 236*f4a2713aSLionel Sambuc } 237*f4a2713aSLionel Sambuc 238*f4a2713aSLionel Sambuc 239