1*7475156dSBill Wendling // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 2*7475156dSBill Wendling // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=X86_64 3*7475156dSBill Wendling // RUN: %clang_cc1 -triple i386-unknown-unknown -emit-llvm -o - %s | FileCheck %s --check-prefix=I386 4*7475156dSBill Wendling 5*7475156dSBill Wendling struct a { 6*7475156dSBill Wendling char x; 7*7475156dSBill Wendling short count; 8*7475156dSBill Wendling int array[] __attribute__((counted_by(count))); 9*7475156dSBill Wendling }; 10*7475156dSBill Wendling 11*7475156dSBill Wendling // X86_64-LABEL: define dso_local ptr @test1( 12*7475156dSBill Wendling // X86_64-SAME: i32 noundef [[SIZE:%.*]]) #[[ATTR0:[0-9]+]] { 13*7475156dSBill Wendling // X86_64-NEXT: [[ENTRY:.*:]] 14*7475156dSBill Wendling // X86_64-NEXT: [[SIZE_ADDR:%.*]] = alloca i32, align 4 15*7475156dSBill Wendling // X86_64-NEXT: [[P:%.*]] = alloca ptr, align 8 16*7475156dSBill Wendling // X86_64-NEXT: store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4 17*7475156dSBill Wendling // X86_64-NEXT: [[TMP0:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 18*7475156dSBill Wendling // X86_64-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 19*7475156dSBill Wendling // X86_64-NEXT: [[MUL:%.*]] = mul i64 4, [[CONV]] 20*7475156dSBill Wendling // X86_64-NEXT: [[ADD:%.*]] = add i64 4, [[MUL]] 21*7475156dSBill Wendling // X86_64-NEXT: [[CALL:%.*]] = call ptr @malloc(i64 noundef [[ADD]]) #[[ATTR2:[0-9]+]] 22*7475156dSBill Wendling // X86_64-NEXT: store ptr [[CALL]], ptr [[P]], align 8 23*7475156dSBill Wendling // X86_64-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 24*7475156dSBill Wendling // X86_64-NEXT: [[CONV1:%.*]] = trunc i32 [[TMP1]] to i16 25*7475156dSBill Wendling // X86_64-NEXT: [[TMP2:%.*]] = load ptr, ptr [[P]], align 8 26*7475156dSBill Wendling // X86_64-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[TMP2]], i32 0, i32 1 27*7475156dSBill Wendling // X86_64-NEXT: store i16 [[CONV1]], ptr [[DOT_COUNTED_BY_GEP]], align 2 28*7475156dSBill Wendling // X86_64-NEXT: [[TMP3:%.*]] = load ptr, ptr [[P]], align 8 29*7475156dSBill Wendling // X86_64-NEXT: ret ptr [[TMP3]] 30*7475156dSBill Wendling // 31*7475156dSBill Wendling // I386-LABEL: define dso_local ptr @test1( 32*7475156dSBill Wendling // I386-SAME: i32 noundef [[SIZE:%.*]]) #[[ATTR0:[0-9]+]] { 33*7475156dSBill Wendling // I386-NEXT: [[ENTRY:.*:]] 34*7475156dSBill Wendling // I386-NEXT: [[SIZE_ADDR:%.*]] = alloca i32, align 4 35*7475156dSBill Wendling // I386-NEXT: [[P:%.*]] = alloca ptr, align 4 36*7475156dSBill Wendling // I386-NEXT: store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4 37*7475156dSBill Wendling // I386-NEXT: [[TMP0:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 38*7475156dSBill Wendling // I386-NEXT: [[MUL:%.*]] = mul i32 4, [[TMP0]] 39*7475156dSBill Wendling // I386-NEXT: [[ADD:%.*]] = add i32 4, [[MUL]] 40*7475156dSBill Wendling // I386-NEXT: [[CALL:%.*]] = call ptr @malloc(i32 noundef [[ADD]]) #[[ATTR2:[0-9]+]] 41*7475156dSBill Wendling // I386-NEXT: store ptr [[CALL]], ptr [[P]], align 4 42*7475156dSBill Wendling // I386-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 43*7475156dSBill Wendling // I386-NEXT: [[CONV:%.*]] = trunc i32 [[TMP1]] to i16 44*7475156dSBill Wendling // I386-NEXT: [[TMP2:%.*]] = load ptr, ptr [[P]], align 4 45*7475156dSBill Wendling // I386-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_A:%.*]], ptr [[TMP2]], i32 0, i32 1 46*7475156dSBill Wendling // I386-NEXT: store i16 [[CONV]], ptr [[DOT_COUNTED_BY_GEP]], align 2 47*7475156dSBill Wendling // I386-NEXT: [[TMP3:%.*]] = load ptr, ptr [[P]], align 4 48*7475156dSBill Wendling // I386-NEXT: ret ptr [[TMP3]] 49*7475156dSBill Wendling // 50*7475156dSBill Wendling struct a *test1(int size) { 51*7475156dSBill Wendling struct a *p = __builtin_malloc(sizeof(struct a) + sizeof(int) * size); 52*7475156dSBill Wendling 53*7475156dSBill Wendling *__builtin_counted_by_ref(p->array) = size; 54*7475156dSBill Wendling return p; 55*7475156dSBill Wendling } 56*7475156dSBill Wendling 57*7475156dSBill Wendling struct b { 58*7475156dSBill Wendling int _filler; 59*7475156dSBill Wendling struct { 60*7475156dSBill Wendling int __filler; 61*7475156dSBill Wendling struct { 62*7475156dSBill Wendling int ___filler; 63*7475156dSBill Wendling struct { 64*7475156dSBill Wendling char count; 65*7475156dSBill Wendling }; 66*7475156dSBill Wendling }; 67*7475156dSBill Wendling }; 68*7475156dSBill Wendling struct { 69*7475156dSBill Wendling int filler_; 70*7475156dSBill Wendling struct { 71*7475156dSBill Wendling int filler__; 72*7475156dSBill Wendling struct { 73*7475156dSBill Wendling long array[] __attribute__((counted_by(count))); 74*7475156dSBill Wendling }; 75*7475156dSBill Wendling }; 76*7475156dSBill Wendling }; 77*7475156dSBill Wendling }; 78*7475156dSBill Wendling 79*7475156dSBill Wendling // X86_64-LABEL: define dso_local ptr @test2( 80*7475156dSBill Wendling // X86_64-SAME: i32 noundef [[SIZE:%.*]]) #[[ATTR0]] { 81*7475156dSBill Wendling // X86_64-NEXT: [[ENTRY:.*:]] 82*7475156dSBill Wendling // X86_64-NEXT: [[SIZE_ADDR:%.*]] = alloca i32, align 4 83*7475156dSBill Wendling // X86_64-NEXT: [[P:%.*]] = alloca ptr, align 8 84*7475156dSBill Wendling // X86_64-NEXT: store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4 85*7475156dSBill Wendling // X86_64-NEXT: [[TMP0:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 86*7475156dSBill Wendling // X86_64-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 87*7475156dSBill Wendling // X86_64-NEXT: [[MUL:%.*]] = mul i64 4, [[CONV]] 88*7475156dSBill Wendling // X86_64-NEXT: [[ADD:%.*]] = add i64 4, [[MUL]] 89*7475156dSBill Wendling // X86_64-NEXT: [[CALL:%.*]] = call ptr @malloc(i64 noundef [[ADD]]) #[[ATTR2]] 90*7475156dSBill Wendling // X86_64-NEXT: store ptr [[CALL]], ptr [[P]], align 8 91*7475156dSBill Wendling // X86_64-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 92*7475156dSBill Wendling // X86_64-NEXT: [[CONV1:%.*]] = trunc i32 [[TMP1]] to i8 93*7475156dSBill Wendling // X86_64-NEXT: [[TMP2:%.*]] = load ptr, ptr [[P]], align 8 94*7475156dSBill Wendling // X86_64-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_B:%.*]], ptr [[TMP2]], i32 0, i32 1, i32 1, i32 1, i32 0 95*7475156dSBill Wendling // X86_64-NEXT: store i8 [[CONV1]], ptr [[DOT_COUNTED_BY_GEP]], align 1 96*7475156dSBill Wendling // X86_64-NEXT: [[TMP3:%.*]] = load ptr, ptr [[P]], align 8 97*7475156dSBill Wendling // X86_64-NEXT: ret ptr [[TMP3]] 98*7475156dSBill Wendling // 99*7475156dSBill Wendling // I386-LABEL: define dso_local ptr @test2( 100*7475156dSBill Wendling // I386-SAME: i32 noundef [[SIZE:%.*]]) #[[ATTR0]] { 101*7475156dSBill Wendling // I386-NEXT: [[ENTRY:.*:]] 102*7475156dSBill Wendling // I386-NEXT: [[SIZE_ADDR:%.*]] = alloca i32, align 4 103*7475156dSBill Wendling // I386-NEXT: [[P:%.*]] = alloca ptr, align 4 104*7475156dSBill Wendling // I386-NEXT: store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4 105*7475156dSBill Wendling // I386-NEXT: [[TMP0:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 106*7475156dSBill Wendling // I386-NEXT: [[MUL:%.*]] = mul i32 4, [[TMP0]] 107*7475156dSBill Wendling // I386-NEXT: [[ADD:%.*]] = add i32 4, [[MUL]] 108*7475156dSBill Wendling // I386-NEXT: [[CALL:%.*]] = call ptr @malloc(i32 noundef [[ADD]]) #[[ATTR2]] 109*7475156dSBill Wendling // I386-NEXT: store ptr [[CALL]], ptr [[P]], align 4 110*7475156dSBill Wendling // I386-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 111*7475156dSBill Wendling // I386-NEXT: [[CONV:%.*]] = trunc i32 [[TMP1]] to i8 112*7475156dSBill Wendling // I386-NEXT: [[TMP2:%.*]] = load ptr, ptr [[P]], align 4 113*7475156dSBill Wendling // I386-NEXT: [[DOT_COUNTED_BY_GEP:%.*]] = getelementptr inbounds [[STRUCT_B:%.*]], ptr [[TMP2]], i32 0, i32 1, i32 1, i32 1, i32 0 114*7475156dSBill Wendling // I386-NEXT: store i8 [[CONV]], ptr [[DOT_COUNTED_BY_GEP]], align 1 115*7475156dSBill Wendling // I386-NEXT: [[TMP3:%.*]] = load ptr, ptr [[P]], align 4 116*7475156dSBill Wendling // I386-NEXT: ret ptr [[TMP3]] 117*7475156dSBill Wendling // 118*7475156dSBill Wendling struct b *test2(int size) { 119*7475156dSBill Wendling struct b *p = __builtin_malloc(sizeof(struct a) + sizeof(int) * size); 120*7475156dSBill Wendling 121*7475156dSBill Wendling *__builtin_counted_by_ref(p->array) = size; 122*7475156dSBill Wendling return p; 123*7475156dSBill Wendling } 124*7475156dSBill Wendling 125*7475156dSBill Wendling struct c { 126*7475156dSBill Wendling char x; 127*7475156dSBill Wendling short count; 128*7475156dSBill Wendling int array[]; 129*7475156dSBill Wendling }; 130*7475156dSBill Wendling 131*7475156dSBill Wendling // X86_64-LABEL: define dso_local ptr @test3( 132*7475156dSBill Wendling // X86_64-SAME: i32 noundef [[SIZE:%.*]]) #[[ATTR0]] { 133*7475156dSBill Wendling // X86_64-NEXT: [[ENTRY:.*:]] 134*7475156dSBill Wendling // X86_64-NEXT: [[SIZE_ADDR:%.*]] = alloca i32, align 4 135*7475156dSBill Wendling // X86_64-NEXT: [[P:%.*]] = alloca ptr, align 8 136*7475156dSBill Wendling // X86_64-NEXT: [[__IGNORED:%.*]] = alloca i64, align 8 137*7475156dSBill Wendling // X86_64-NEXT: store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4 138*7475156dSBill Wendling // X86_64-NEXT: [[TMP0:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 139*7475156dSBill Wendling // X86_64-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 140*7475156dSBill Wendling // X86_64-NEXT: [[MUL:%.*]] = mul i64 4, [[CONV]] 141*7475156dSBill Wendling // X86_64-NEXT: [[ADD:%.*]] = add i64 4, [[MUL]] 142*7475156dSBill Wendling // X86_64-NEXT: [[CALL:%.*]] = call ptr @malloc(i64 noundef [[ADD]]) #[[ATTR2]] 143*7475156dSBill Wendling // X86_64-NEXT: store ptr [[CALL]], ptr [[P]], align 8 144*7475156dSBill Wendling // X86_64-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 145*7475156dSBill Wendling // X86_64-NEXT: [[CONV1:%.*]] = sext i32 [[TMP1]] to i64 146*7475156dSBill Wendling // X86_64-NEXT: store i64 [[CONV1]], ptr [[__IGNORED]], align 8 147*7475156dSBill Wendling // X86_64-NEXT: [[TMP2:%.*]] = load ptr, ptr [[P]], align 8 148*7475156dSBill Wendling // X86_64-NEXT: ret ptr [[TMP2]] 149*7475156dSBill Wendling // 150*7475156dSBill Wendling // I386-LABEL: define dso_local ptr @test3( 151*7475156dSBill Wendling // I386-SAME: i32 noundef [[SIZE:%.*]]) #[[ATTR0]] { 152*7475156dSBill Wendling // I386-NEXT: [[ENTRY:.*:]] 153*7475156dSBill Wendling // I386-NEXT: [[SIZE_ADDR:%.*]] = alloca i32, align 4 154*7475156dSBill Wendling // I386-NEXT: [[P:%.*]] = alloca ptr, align 4 155*7475156dSBill Wendling // I386-NEXT: [[__IGNORED:%.*]] = alloca i32, align 4 156*7475156dSBill Wendling // I386-NEXT: store i32 [[SIZE]], ptr [[SIZE_ADDR]], align 4 157*7475156dSBill Wendling // I386-NEXT: [[TMP0:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 158*7475156dSBill Wendling // I386-NEXT: [[MUL:%.*]] = mul i32 4, [[TMP0]] 159*7475156dSBill Wendling // I386-NEXT: [[ADD:%.*]] = add i32 4, [[MUL]] 160*7475156dSBill Wendling // I386-NEXT: [[CALL:%.*]] = call ptr @malloc(i32 noundef [[ADD]]) #[[ATTR2]] 161*7475156dSBill Wendling // I386-NEXT: store ptr [[CALL]], ptr [[P]], align 4 162*7475156dSBill Wendling // I386-NEXT: [[TMP1:%.*]] = load i32, ptr [[SIZE_ADDR]], align 4 163*7475156dSBill Wendling // I386-NEXT: store i32 [[TMP1]], ptr [[__IGNORED]], align 4 164*7475156dSBill Wendling // I386-NEXT: [[TMP2:%.*]] = load ptr, ptr [[P]], align 4 165*7475156dSBill Wendling // I386-NEXT: ret ptr [[TMP2]] 166*7475156dSBill Wendling // 167*7475156dSBill Wendling struct c *test3(int size) { 168*7475156dSBill Wendling struct c *p = __builtin_malloc(sizeof(struct c) + sizeof(int) * size); 169*7475156dSBill Wendling unsigned long int __ignored; 170*7475156dSBill Wendling 171*7475156dSBill Wendling *_Generic( 172*7475156dSBill Wendling __builtin_counted_by_ref(p->array), 173*7475156dSBill Wendling void *: &__ignored, 174*7475156dSBill Wendling default: __builtin_counted_by_ref(p->array)) = size; 175*7475156dSBill Wendling 176*7475156dSBill Wendling return p; 177*7475156dSBill Wendling } 178