1 // RUN: %clang_cc1 -triple x86_64 -emit-llvm -o - %s | opt -S -strip -o %t 2 // RUN: FileCheck --check-prefix=CHECK-GLOBAL < %t %s 3 // RUN: FileCheck --check-prefix=CHECK-FUNCTIONS < %t %s 4 5 struct s0 { 6 int x; 7 int y __attribute__((packed)); 8 }; 9 10 // CHECK-GLOBAL: @s0_align_x = global i32 4 11 12 // CHECK-GLOBAL: @s0_align_y = global i32 1 13 14 // CHECK-GLOBAL: @s0_align = global i32 4 15 int s0_align_x = __alignof(((struct s0*)0)->x); 16 int s0_align_y = __alignof(((struct s0*)0)->y); 17 int s0_align = __alignof(struct s0); 18 19 // CHECK-FUNCTIONS: define i32 @s0_load_x 20 // CHECK-FUNCTIONS: [[s0_load_x:%.*]] = load i32* {{.*}}, align 4 21 // CHECK-FUNCTIONS: ret i32 [[s0_load_x]] 22 int s0_load_x(struct s0 *a) { return a->x; } 23 // FIXME: This seems like it should be align 1. This is actually something which 24 // has changed in llvm-gcc recently, previously both x and y would be loaded 25 // with align 1 (in 2363.1 at least). 26 // 27 // CHECK-FUNCTIONS: define i32 @s0_load_y 28 // CHECK-FUNCTIONS: [[s0_load_y:%.*]] = load i32* {{.*}}, align 1 29 // CHECK-FUNCTIONS: ret i32 [[s0_load_y]] 30 int s0_load_y(struct s0 *a) { return a->y; } 31 // CHECK-FUNCTIONS: define void @s0_copy 32 // CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 4, i1 false) 33 void s0_copy(struct s0 *a, struct s0 *b) { *b = *a; } 34 35 // 36 37 struct s1 { 38 int x; 39 int y; 40 } __attribute__((packed)); 41 42 // CHECK-GLOBAL: @s1_align_x = global i32 1 43 // CHECK-GLOBAL: @s1_align_y = global i32 1 44 // CHECK-GLOBAL: @s1_align = global i32 1 45 int s1_align_x = __alignof(((struct s1*)0)->x); 46 int s1_align_y = __alignof(((struct s1*)0)->y); 47 int s1_align = __alignof(struct s1); 48 49 // CHECK-FUNCTIONS: define i32 @s1_load_x 50 // CHECK-FUNCTIONS: [[s1_load_x:%.*]] = load i32* {{.*}}, align 1 51 // CHECK-FUNCTIONS: ret i32 [[s1_load_x]] 52 int s1_load_x(struct s1 *a) { return a->x; } 53 // CHECK-FUNCTIONS: define i32 @s1_load_y 54 // CHECK-FUNCTIONS: [[s1_load_y:%.*]] = load i32* {{.*}}, align 1 55 // CHECK-FUNCTIONS: ret i32 [[s1_load_y]] 56 int s1_load_y(struct s1 *a) { return a->y; } 57 // CHECK-FUNCTIONS: define void @s1_copy 58 // CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 1, i1 false) 59 void s1_copy(struct s1 *a, struct s1 *b) { *b = *a; } 60 61 // 62 63 #pragma pack(push,2) 64 struct s2 { 65 int x; 66 int y; 67 }; 68 #pragma pack(pop) 69 70 // CHECK-GLOBAL: @s2_align_x = global i32 2 71 // CHECK-GLOBAL: @s2_align_y = global i32 2 72 // CHECK-GLOBAL: @s2_align = global i32 2 73 int s2_align_x = __alignof(((struct s2*)0)->x); 74 int s2_align_y = __alignof(((struct s2*)0)->y); 75 int s2_align = __alignof(struct s2); 76 77 // CHECK-FUNCTIONS: define i32 @s2_load_x 78 // CHECK-FUNCTIONS: [[s2_load_y:%.*]] = load i32* {{.*}}, align 2 79 // CHECK-FUNCTIONS: ret i32 [[s2_load_y]] 80 int s2_load_x(struct s2 *a) { return a->x; } 81 // CHECK-FUNCTIONS: define i32 @s2_load_y 82 // CHECK-FUNCTIONS: [[s2_load_y:%.*]] = load i32* {{.*}}, align 2 83 // CHECK-FUNCTIONS: ret i32 [[s2_load_y]] 84 int s2_load_y(struct s2 *a) { return a->y; } 85 // CHECK-FUNCTIONS: define void @s2_copy 86 // CHECK-FUNCTIONS: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* {{.*}}, i64 8, i32 2, i1 false) 87 void s2_copy(struct s2 *a, struct s2 *b) { *b = *a; } 88 89 struct __attribute__((packed, aligned)) s3 { 90 short aShort; 91 int anInt; 92 }; 93 // CHECK-GLOBAL: @s3_1 = global i32 1 94 int s3_1 = __alignof(((struct s3*) 0)->anInt); 95 // CHECK-FUNCTIONS: define i32 @test3( 96 int test3(struct s3 *ptr) { 97 // CHECK-FUNCTIONS: [[PTR:%.*]] = getelementptr inbounds {{%.*}}* {{%.*}}, i32 0, i32 1 98 // CHECK-FUNCTIONS-NEXT: load i32* [[PTR]], align 1 99 return ptr->anInt; 100 } 101