1631248dcShstk30-hw // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 2631248dcShstk30-hw // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s 3631248dcShstk30-hw 4631248dcShstk30-hw typedef struct { struct {} a; } empty; 5631248dcShstk30-hw 69c8dd5e6SLongsheng Mou // CHECK-LABEL: @_Z17empty_record_testiz( 7631248dcShstk30-hw // CHECK-NEXT: entry: 8631248dcShstk30-hw // CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 9631248dcShstk30-hw // CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 10631248dcShstk30-hw // CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 11631248dcShstk30-hw // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 12ab7dba23SAlex Voicu // CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) 13631248dcShstk30-hw // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 14631248dcShstk30-hw // CHECK-NEXT: ret void 159c8dd5e6SLongsheng Mou // 16631248dcShstk30-hw empty empty_record_test(int z, ...) { 17631248dcShstk30-hw __builtin_va_list list; 18631248dcShstk30-hw __builtin_va_start(list, z); 19631248dcShstk30-hw return __builtin_va_arg(list, empty); 20631248dcShstk30-hw } 219c8dd5e6SLongsheng Mou 229c8dd5e6SLongsheng Mou typedef struct { 239c8dd5e6SLongsheng Mou struct{} a; 249c8dd5e6SLongsheng Mou double b; 259c8dd5e6SLongsheng Mou } s1; 269c8dd5e6SLongsheng Mou 279c8dd5e6SLongsheng Mou // CHECK-LABEL: @_Z1fiz( 289c8dd5e6SLongsheng Mou // CHECK-NEXT: entry: 299c8dd5e6SLongsheng Mou // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_S1:%.*]], align 8 309c8dd5e6SLongsheng Mou // CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 319c8dd5e6SLongsheng Mou // CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 32*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_S1]], align 8 339c8dd5e6SLongsheng Mou // CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 349c8dd5e6SLongsheng Mou // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 35ab7dba23SAlex Voicu // CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) 369c8dd5e6SLongsheng Mou // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 3794473f4dSHari Limaye // CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 1 389c8dd5e6SLongsheng Mou // CHECK-NEXT: [[FP_OFFSET:%.*]] = load i32, ptr [[FP_OFFSET_P]], align 4 399c8dd5e6SLongsheng Mou // CHECK-NEXT: [[FITS_IN_FP:%.*]] = icmp ule i32 [[FP_OFFSET]], 160 409c8dd5e6SLongsheng Mou // CHECK-NEXT: br i1 [[FITS_IN_FP]], label [[VAARG_IN_REG:%.*]], label [[VAARG_IN_MEM:%.*]] 419c8dd5e6SLongsheng Mou // CHECK: vaarg.in_reg: 4294473f4dSHari Limaye // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 439c8dd5e6SLongsheng Mou // CHECK-NEXT: [[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 449c8dd5e6SLongsheng Mou // CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] 45*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP2:%.*]] = load double, ptr [[TMP1]], align 8 46*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 47*a27f40e5SLongsheng Mou // CHECK-NEXT: store double [[TMP2]], ptr [[TMP3]], align 8 48*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 49*a27f40e5SLongsheng Mou // CHECK-NEXT: store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 509c8dd5e6SLongsheng Mou // CHECK-NEXT: br label [[VAARG_END:%.*]] 519c8dd5e6SLongsheng Mou // CHECK: vaarg.in_mem: 5294473f4dSHari Limaye // CHECK-NEXT: [[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 539c8dd5e6SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA:%.*]] = load ptr, ptr [[OVERFLOW_ARG_AREA_P]], align 8 549c8dd5e6SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA_NEXT:%.*]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i32 16 559c8dd5e6SLongsheng Mou // CHECK-NEXT: store ptr [[OVERFLOW_ARG_AREA_NEXT]], ptr [[OVERFLOW_ARG_AREA_P]], align 8 569c8dd5e6SLongsheng Mou // CHECK-NEXT: br label [[VAARG_END]] 579c8dd5e6SLongsheng Mou // CHECK: vaarg.end: 58*a27f40e5SLongsheng Mou // CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] 599c8dd5e6SLongsheng Mou // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[VAARG_ADDR]], i64 16, i1 false) 60*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[RETVAL]], i64 8 61*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP6:%.*]] = load double, ptr [[TMP5]], align 8 62*a27f40e5SLongsheng Mou // CHECK-NEXT: ret double [[TMP6]] 639c8dd5e6SLongsheng Mou // 649c8dd5e6SLongsheng Mou s1 f(int z, ...) { 659c8dd5e6SLongsheng Mou __builtin_va_list list; 669c8dd5e6SLongsheng Mou __builtin_va_start(list, z); 679c8dd5e6SLongsheng Mou return __builtin_va_arg(list, s1); 689c8dd5e6SLongsheng Mou } 69*a27f40e5SLongsheng Mou 70*a27f40e5SLongsheng Mou typedef struct { 71*a27f40e5SLongsheng Mou struct{} a[5]; 72*a27f40e5SLongsheng Mou float b; 73*a27f40e5SLongsheng Mou float c; 74*a27f40e5SLongsheng Mou } s2; 75*a27f40e5SLongsheng Mou 76*a27f40e5SLongsheng Mou // CHECK-LABEL: @_Z2f2iz( 77*a27f40e5SLongsheng Mou // CHECK-NEXT: entry: 78*a27f40e5SLongsheng Mou // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_S2:%.*]], align 4 79*a27f40e5SLongsheng Mou // CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 80*a27f40e5SLongsheng Mou // CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 81*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_S2]], align 4 82*a27f40e5SLongsheng Mou // CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 83*a27f40e5SLongsheng Mou // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 84*a27f40e5SLongsheng Mou // CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) 85*a27f40e5SLongsheng Mou // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 86*a27f40e5SLongsheng Mou // CHECK-NEXT: [[FP_OFFSET_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 1 87*a27f40e5SLongsheng Mou // CHECK-NEXT: [[FP_OFFSET:%.*]] = load i32, ptr [[FP_OFFSET_P]], align 4 88*a27f40e5SLongsheng Mou // CHECK-NEXT: [[FITS_IN_FP:%.*]] = icmp ule i32 [[FP_OFFSET]], 160 89*a27f40e5SLongsheng Mou // CHECK-NEXT: br i1 [[FITS_IN_FP]], label [[VAARG_IN_REG:%.*]], label [[VAARG_IN_MEM:%.*]] 90*a27f40e5SLongsheng Mou // CHECK: vaarg.in_reg: 91*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 92*a27f40e5SLongsheng Mou // CHECK-NEXT: [[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 93*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[FP_OFFSET]] 94*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP2:%.*]] = load <2 x float>, ptr [[TMP1]], align 4 95*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 96*a27f40e5SLongsheng Mou // CHECK-NEXT: store <2 x float> [[TMP2]], ptr [[TMP3]], align 4 97*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP4:%.*]] = add i32 [[FP_OFFSET]], 16 98*a27f40e5SLongsheng Mou // CHECK-NEXT: store i32 [[TMP4]], ptr [[FP_OFFSET_P]], align 4 99*a27f40e5SLongsheng Mou // CHECK-NEXT: br label [[VAARG_END:%.*]] 100*a27f40e5SLongsheng Mou // CHECK: vaarg.in_mem: 101*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 102*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA:%.*]] = load ptr, ptr [[OVERFLOW_ARG_AREA_P]], align 8 103*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA_NEXT:%.*]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i32 16 104*a27f40e5SLongsheng Mou // CHECK-NEXT: store ptr [[OVERFLOW_ARG_AREA_NEXT]], ptr [[OVERFLOW_ARG_AREA_P]], align 8 105*a27f40e5SLongsheng Mou // CHECK-NEXT: br label [[VAARG_END]] 106*a27f40e5SLongsheng Mou // CHECK: vaarg.end: 107*a27f40e5SLongsheng Mou // CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] 108*a27f40e5SLongsheng Mou // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[RETVAL]], ptr align 4 [[VAARG_ADDR]], i64 16, i1 false) 109*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[RETVAL]], i64 8 110*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP6:%.*]] = load <2 x float>, ptr [[TMP5]], align 4 111*a27f40e5SLongsheng Mou // CHECK-NEXT: ret <2 x float> [[TMP6]] 112*a27f40e5SLongsheng Mou // 113*a27f40e5SLongsheng Mou s2 f2(int z, ...) { 114*a27f40e5SLongsheng Mou __builtin_va_list list; 115*a27f40e5SLongsheng Mou __builtin_va_start(list, z); 116*a27f40e5SLongsheng Mou return __builtin_va_arg(list, s2); 117*a27f40e5SLongsheng Mou } 118*a27f40e5SLongsheng Mou 119*a27f40e5SLongsheng Mou typedef struct { 120*a27f40e5SLongsheng Mou struct{} a; 121*a27f40e5SLongsheng Mou long long b; 122*a27f40e5SLongsheng Mou } s3; 123*a27f40e5SLongsheng Mou 124*a27f40e5SLongsheng Mou // CHECK-LABEL: @_Z2f3iz( 125*a27f40e5SLongsheng Mou // CHECK-NEXT: entry: 126*a27f40e5SLongsheng Mou // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_S3:%.*]], align 8 127*a27f40e5SLongsheng Mou // CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 128*a27f40e5SLongsheng Mou // CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 129*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_S3]], align 8 130*a27f40e5SLongsheng Mou // CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 131*a27f40e5SLongsheng Mou // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 132*a27f40e5SLongsheng Mou // CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) 133*a27f40e5SLongsheng Mou // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 134*a27f40e5SLongsheng Mou // CHECK-NEXT: [[GP_OFFSET_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 0 135*a27f40e5SLongsheng Mou // CHECK-NEXT: [[GP_OFFSET:%.*]] = load i32, ptr [[GP_OFFSET_P]], align 16 136*a27f40e5SLongsheng Mou // CHECK-NEXT: [[FITS_IN_GP:%.*]] = icmp ule i32 [[GP_OFFSET]], 40 137*a27f40e5SLongsheng Mou // CHECK-NEXT: br i1 [[FITS_IN_GP]], label [[VAARG_IN_REG:%.*]], label [[VAARG_IN_MEM:%.*]] 138*a27f40e5SLongsheng Mou // CHECK: vaarg.in_reg: 139*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 140*a27f40e5SLongsheng Mou // CHECK-NEXT: [[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 141*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[GP_OFFSET]] 142*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 143*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 144*a27f40e5SLongsheng Mou // CHECK-NEXT: store i64 [[TMP2]], ptr [[TMP3]], align 8 145*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP4:%.*]] = add i32 [[GP_OFFSET]], 8 146*a27f40e5SLongsheng Mou // CHECK-NEXT: store i32 [[TMP4]], ptr [[GP_OFFSET_P]], align 16 147*a27f40e5SLongsheng Mou // CHECK-NEXT: br label [[VAARG_END:%.*]] 148*a27f40e5SLongsheng Mou // CHECK: vaarg.in_mem: 149*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 150*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA:%.*]] = load ptr, ptr [[OVERFLOW_ARG_AREA_P]], align 8 151*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA_NEXT:%.*]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i32 16 152*a27f40e5SLongsheng Mou // CHECK-NEXT: store ptr [[OVERFLOW_ARG_AREA_NEXT]], ptr [[OVERFLOW_ARG_AREA_P]], align 8 153*a27f40e5SLongsheng Mou // CHECK-NEXT: br label [[VAARG_END]] 154*a27f40e5SLongsheng Mou // CHECK: vaarg.end: 155*a27f40e5SLongsheng Mou // CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] 156*a27f40e5SLongsheng Mou // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[VAARG_ADDR]], i64 16, i1 false) 157*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[RETVAL]], i64 8 158*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr [[TMP5]], align 8 159*a27f40e5SLongsheng Mou // CHECK-NEXT: ret i64 [[TMP6]] 160*a27f40e5SLongsheng Mou // 161*a27f40e5SLongsheng Mou s3 f3(int z, ...) { 162*a27f40e5SLongsheng Mou __builtin_va_list list; 163*a27f40e5SLongsheng Mou __builtin_va_start(list, z); 164*a27f40e5SLongsheng Mou return __builtin_va_arg(list, s3); 165*a27f40e5SLongsheng Mou } 166*a27f40e5SLongsheng Mou 167*a27f40e5SLongsheng Mou typedef struct { 168*a27f40e5SLongsheng Mou struct{} a[7]; 169*a27f40e5SLongsheng Mou short b; 170*a27f40e5SLongsheng Mou int c; 171*a27f40e5SLongsheng Mou } s4; 172*a27f40e5SLongsheng Mou 173*a27f40e5SLongsheng Mou // CHECK-LABEL: @_Z2f4iz( 174*a27f40e5SLongsheng Mou // CHECK-NEXT: entry: 175*a27f40e5SLongsheng Mou // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_S4:%.*]], align 4 176*a27f40e5SLongsheng Mou // CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 177*a27f40e5SLongsheng Mou // CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 178*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_S4]], align 4 179*a27f40e5SLongsheng Mou // CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 180*a27f40e5SLongsheng Mou // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 181*a27f40e5SLongsheng Mou // CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) 182*a27f40e5SLongsheng Mou // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 183*a27f40e5SLongsheng Mou // CHECK-NEXT: [[GP_OFFSET_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 0 184*a27f40e5SLongsheng Mou // CHECK-NEXT: [[GP_OFFSET:%.*]] = load i32, ptr [[GP_OFFSET_P]], align 16 185*a27f40e5SLongsheng Mou // CHECK-NEXT: [[FITS_IN_GP:%.*]] = icmp ule i32 [[GP_OFFSET]], 40 186*a27f40e5SLongsheng Mou // CHECK-NEXT: br i1 [[FITS_IN_GP]], label [[VAARG_IN_REG:%.*]], label [[VAARG_IN_MEM:%.*]] 187*a27f40e5SLongsheng Mou // CHECK: vaarg.in_reg: 188*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 189*a27f40e5SLongsheng Mou // CHECK-NEXT: [[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 190*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[GP_OFFSET]] 191*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4 192*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 193*a27f40e5SLongsheng Mou // CHECK-NEXT: store i64 [[TMP2]], ptr [[TMP3]], align 4 194*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP4:%.*]] = add i32 [[GP_OFFSET]], 8 195*a27f40e5SLongsheng Mou // CHECK-NEXT: store i32 [[TMP4]], ptr [[GP_OFFSET_P]], align 16 196*a27f40e5SLongsheng Mou // CHECK-NEXT: br label [[VAARG_END:%.*]] 197*a27f40e5SLongsheng Mou // CHECK: vaarg.in_mem: 198*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 199*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA:%.*]] = load ptr, ptr [[OVERFLOW_ARG_AREA_P]], align 8 200*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA_NEXT:%.*]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i32 16 201*a27f40e5SLongsheng Mou // CHECK-NEXT: store ptr [[OVERFLOW_ARG_AREA_NEXT]], ptr [[OVERFLOW_ARG_AREA_P]], align 8 202*a27f40e5SLongsheng Mou // CHECK-NEXT: br label [[VAARG_END]] 203*a27f40e5SLongsheng Mou // CHECK: vaarg.end: 204*a27f40e5SLongsheng Mou // CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] 205*a27f40e5SLongsheng Mou // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[RETVAL]], ptr align 4 [[VAARG_ADDR]], i64 16, i1 false) 206*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[RETVAL]], i64 8 207*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr [[TMP5]], align 4 208*a27f40e5SLongsheng Mou // CHECK-NEXT: ret i64 [[TMP6]] 209*a27f40e5SLongsheng Mou // 210*a27f40e5SLongsheng Mou s4 f4(int z, ...) { 211*a27f40e5SLongsheng Mou __builtin_va_list list; 212*a27f40e5SLongsheng Mou __builtin_va_start(list, z); 213*a27f40e5SLongsheng Mou return __builtin_va_arg(list, s4); 214*a27f40e5SLongsheng Mou } 215*a27f40e5SLongsheng Mou 216*a27f40e5SLongsheng Mou typedef struct { 217*a27f40e5SLongsheng Mou struct{} a[5]; 218*a27f40e5SLongsheng Mou float b; 219*a27f40e5SLongsheng Mou int c; 220*a27f40e5SLongsheng Mou } s5; 221*a27f40e5SLongsheng Mou 222*a27f40e5SLongsheng Mou // CHECK-LABEL: @_Z2f5iz( 223*a27f40e5SLongsheng Mou // CHECK-NEXT: entry: 224*a27f40e5SLongsheng Mou // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_S5:%.*]], align 4 225*a27f40e5SLongsheng Mou // CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 226*a27f40e5SLongsheng Mou // CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 227*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_S5]], align 4 228*a27f40e5SLongsheng Mou // CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 229*a27f40e5SLongsheng Mou // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 230*a27f40e5SLongsheng Mou // CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) 231*a27f40e5SLongsheng Mou // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 232*a27f40e5SLongsheng Mou // CHECK-NEXT: [[GP_OFFSET_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 0 233*a27f40e5SLongsheng Mou // CHECK-NEXT: [[GP_OFFSET:%.*]] = load i32, ptr [[GP_OFFSET_P]], align 16 234*a27f40e5SLongsheng Mou // CHECK-NEXT: [[FITS_IN_GP:%.*]] = icmp ule i32 [[GP_OFFSET]], 40 235*a27f40e5SLongsheng Mou // CHECK-NEXT: br i1 [[FITS_IN_GP]], label [[VAARG_IN_REG:%.*]], label [[VAARG_IN_MEM:%.*]] 236*a27f40e5SLongsheng Mou // CHECK: vaarg.in_reg: 237*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 238*a27f40e5SLongsheng Mou // CHECK-NEXT: [[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 239*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[GP_OFFSET]] 240*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 4 241*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 8 242*a27f40e5SLongsheng Mou // CHECK-NEXT: store i64 [[TMP2]], ptr [[TMP3]], align 4 243*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP4:%.*]] = add i32 [[GP_OFFSET]], 8 244*a27f40e5SLongsheng Mou // CHECK-NEXT: store i32 [[TMP4]], ptr [[GP_OFFSET_P]], align 16 245*a27f40e5SLongsheng Mou // CHECK-NEXT: br label [[VAARG_END:%.*]] 246*a27f40e5SLongsheng Mou // CHECK: vaarg.in_mem: 247*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 248*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA:%.*]] = load ptr, ptr [[OVERFLOW_ARG_AREA_P]], align 8 249*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA_NEXT:%.*]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i32 16 250*a27f40e5SLongsheng Mou // CHECK-NEXT: store ptr [[OVERFLOW_ARG_AREA_NEXT]], ptr [[OVERFLOW_ARG_AREA_P]], align 8 251*a27f40e5SLongsheng Mou // CHECK-NEXT: br label [[VAARG_END]] 252*a27f40e5SLongsheng Mou // CHECK: vaarg.end: 253*a27f40e5SLongsheng Mou // CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] 254*a27f40e5SLongsheng Mou // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 [[RETVAL]], ptr align 4 [[VAARG_ADDR]], i64 16, i1 false) 255*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds i8, ptr [[RETVAL]], i64 8 256*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP6:%.*]] = load i64, ptr [[TMP5]], align 4 257*a27f40e5SLongsheng Mou // CHECK-NEXT: ret i64 [[TMP6]] 258*a27f40e5SLongsheng Mou // 259*a27f40e5SLongsheng Mou s5 f5(int z, ...) { 260*a27f40e5SLongsheng Mou __builtin_va_list list; 261*a27f40e5SLongsheng Mou __builtin_va_start(list, z); 262*a27f40e5SLongsheng Mou return __builtin_va_arg(list, s5); 263*a27f40e5SLongsheng Mou } 264*a27f40e5SLongsheng Mou 265*a27f40e5SLongsheng Mou typedef struct { 266*a27f40e5SLongsheng Mou long long a; 267*a27f40e5SLongsheng Mou struct{} b; 268*a27f40e5SLongsheng Mou } s6; 269*a27f40e5SLongsheng Mou 270*a27f40e5SLongsheng Mou // CHECK-LABEL: @_Z2f6iz( 271*a27f40e5SLongsheng Mou // CHECK-NEXT: entry: 272*a27f40e5SLongsheng Mou // CHECK-NEXT: [[RETVAL:%.*]] = alloca [[STRUCT_S6:%.*]], align 8 273*a27f40e5SLongsheng Mou // CHECK-NEXT: [[Z_ADDR:%.*]] = alloca i32, align 4 274*a27f40e5SLongsheng Mou // CHECK-NEXT: [[LIST:%.*]] = alloca [1 x %struct.__va_list_tag], align 16 275*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP:%.*]] = alloca [[STRUCT_S6]], align 8 276*a27f40e5SLongsheng Mou // CHECK-NEXT: store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4 277*a27f40e5SLongsheng Mou // CHECK-NEXT: [[ARRAYDECAY:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 278*a27f40e5SLongsheng Mou // CHECK-NEXT: call void @llvm.va_start.p0(ptr [[ARRAYDECAY]]) 279*a27f40e5SLongsheng Mou // CHECK-NEXT: [[ARRAYDECAY1:%.*]] = getelementptr inbounds [1 x %struct.__va_list_tag], ptr [[LIST]], i64 0, i64 0 280*a27f40e5SLongsheng Mou // CHECK-NEXT: [[GP_OFFSET_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG:%.*]], ptr [[ARRAYDECAY1]], i32 0, i32 0 281*a27f40e5SLongsheng Mou // CHECK-NEXT: [[GP_OFFSET:%.*]] = load i32, ptr [[GP_OFFSET_P]], align 16 282*a27f40e5SLongsheng Mou // CHECK-NEXT: [[FITS_IN_GP:%.*]] = icmp ule i32 [[GP_OFFSET]], 40 283*a27f40e5SLongsheng Mou // CHECK-NEXT: br i1 [[FITS_IN_GP]], label [[VAARG_IN_REG:%.*]], label [[VAARG_IN_MEM:%.*]] 284*a27f40e5SLongsheng Mou // CHECK: vaarg.in_reg: 285*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 3 286*a27f40e5SLongsheng Mou // CHECK-NEXT: [[REG_SAVE_AREA:%.*]] = load ptr, ptr [[TMP0]], align 16 287*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[REG_SAVE_AREA]], i32 [[GP_OFFSET]] 288*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP2:%.*]] = load i64, ptr [[TMP1]], align 8 289*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, ptr [[TMP]], i32 0 290*a27f40e5SLongsheng Mou // CHECK-NEXT: store i64 [[TMP2]], ptr [[TMP3]], align 8 291*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP4:%.*]] = add i32 [[GP_OFFSET]], 8 292*a27f40e5SLongsheng Mou // CHECK-NEXT: store i32 [[TMP4]], ptr [[GP_OFFSET_P]], align 16 293*a27f40e5SLongsheng Mou // CHECK-NEXT: br label [[VAARG_END:%.*]] 294*a27f40e5SLongsheng Mou // CHECK: vaarg.in_mem: 295*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA_P:%.*]] = getelementptr inbounds nuw [[STRUCT___VA_LIST_TAG]], ptr [[ARRAYDECAY1]], i32 0, i32 2 296*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA:%.*]] = load ptr, ptr [[OVERFLOW_ARG_AREA_P]], align 8 297*a27f40e5SLongsheng Mou // CHECK-NEXT: [[OVERFLOW_ARG_AREA_NEXT:%.*]] = getelementptr i8, ptr [[OVERFLOW_ARG_AREA]], i32 16 298*a27f40e5SLongsheng Mou // CHECK-NEXT: store ptr [[OVERFLOW_ARG_AREA_NEXT]], ptr [[OVERFLOW_ARG_AREA_P]], align 8 299*a27f40e5SLongsheng Mou // CHECK-NEXT: br label [[VAARG_END]] 300*a27f40e5SLongsheng Mou // CHECK: vaarg.end: 301*a27f40e5SLongsheng Mou // CHECK-NEXT: [[VAARG_ADDR:%.*]] = phi ptr [ [[TMP]], [[VAARG_IN_REG]] ], [ [[OVERFLOW_ARG_AREA]], [[VAARG_IN_MEM]] ] 302*a27f40e5SLongsheng Mou // CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[RETVAL]], ptr align 8 [[VAARG_ADDR]], i64 16, i1 false) 303*a27f40e5SLongsheng Mou // CHECK-NEXT: [[COERCE_DIVE:%.*]] = getelementptr inbounds nuw [[STRUCT_S6]], ptr [[RETVAL]], i32 0, i32 0 304*a27f40e5SLongsheng Mou // CHECK-NEXT: [[TMP5:%.*]] = load i64, ptr [[COERCE_DIVE]], align 8 305*a27f40e5SLongsheng Mou // CHECK-NEXT: ret i64 [[TMP5]] 306*a27f40e5SLongsheng Mou // 307*a27f40e5SLongsheng Mou s6 f6(int z, ...) { 308*a27f40e5SLongsheng Mou __builtin_va_list list; 309*a27f40e5SLongsheng Mou __builtin_va_start(list, z); 310*a27f40e5SLongsheng Mou return __builtin_va_arg(list, s6); 311*a27f40e5SLongsheng Mou } 312