| // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fms-extensions -emit-llvm < %s | FileCheck %s |
| |
| // ------------- |
| // Scalar integer |
| // ------------- |
| __unaligned int x; |
| void test1(void) { |
| // CHECK: {{%.*}} = load i32, i32* @x, align 1 |
| // CHECK: store i32 {{%.*}}, i32* @x, align 1 |
| x++; |
| } |
| |
| void test2(void) { |
| // CHECK: %y = alloca i32, align 1 |
| // CHECK: {{%.*}} = load i32, i32* %y, align 1 |
| // CHECK: store i32 {{%.*}}, i32* %y, align 1 |
| __unaligned int y; |
| y++; |
| } |
| |
| void test2_1(void) { |
| // CHECK: %y = alloca i32, align 1 |
| // CHECK: store i32 1, i32* %y, align 1 |
| __unaligned int y = 1; |
| } |
| |
| // ------------- |
| // Global pointer |
| // ------------- |
| int *__unaligned p1; |
| void test3(void) { |
| |
| // CHECK: {{%.*}} = load i32*, i32** @p1, align 1 |
| // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 4 |
| // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 4 |
| (*p1)++; |
| } |
| |
| int __unaligned *p2; |
| void test4(void) { |
| // CHECK: {{%.*}} = load i32*, i32** @p2, align 8 |
| // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 |
| // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 |
| (*p2)++; |
| } |
| |
| int __unaligned *__unaligned p3; |
| void test5(void) { |
| // CHECK: {{%.*}} = load i32*, i32** @p3, align 1 |
| // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 |
| // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 |
| (*p3)++; |
| } |
| |
| // ------------- |
| // Local pointer |
| // ------------- |
| void test6(void) { |
| // CHECK: %lp1 = alloca i32*, align 1 |
| // CHECK: {{%.*}} = load i32*, i32** %lp1, align 1 |
| // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 4 |
| // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 4 |
| int *__unaligned lp1; |
| (*lp1)++; |
| } |
| |
| void test7(void) { |
| // CHECK: %lp2 = alloca i32*, align 8 |
| // CHECK: {{%.*}} = load i32*, i32** %lp2, align 8 |
| // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 |
| // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 |
| int __unaligned *lp2; |
| (*lp2)++; |
| } |
| |
| void test8(void) { |
| // CHECK: %lp3 = alloca i32*, align 1 |
| // CHECK: {{%.*}} = load i32*, i32** %lp3, align 1 |
| // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 |
| // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 |
| int __unaligned *__unaligned lp3; |
| (*lp3)++; |
| } |
| |
| // ------------- |
| // Global array |
| // ------------- |
| __unaligned int a[10]; |
| void test9(void) { |
| // CHECK: {{%.*}} = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @a, i64 0, i64 3), align 1 |
| // CHECK: store i32 {{%.*}}, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @a, i64 0, i64 3), align 1 |
| (a[3])++; |
| } |
| |
| // ------------- |
| // Local array |
| // ------------- |
| void test10(void) { |
| // CHECK: %la = alloca [10 x i32], align 1 |
| // CHECK: {{%.*}} = getelementptr inbounds [10 x i32], [10 x i32]* %la, i64 0, i64 3 |
| // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 |
| // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 |
| __unaligned int la[10]; |
| (la[3])++; |
| } |
| |
| // -------- |
| // Typedefs |
| // -------- |
| |
| typedef __unaligned int UnalignedInt; |
| void test13() { |
| // CHECK: %i = alloca i32, align 1 |
| // CHECK: {{%.*}} = load i32, i32* %i, align 1 |
| // CHECK: store i32 {{%.*}}, i32* %i, align 1 |
| UnalignedInt i; |
| i++; |
| } |
| |
| typedef int Aligned; |
| typedef __unaligned Aligned UnalignedInt2; |
| void test14() { |
| // CHECK: %i = alloca i32, align 1 |
| // CHECK: {{%.*}} = load i32, i32* %i, align 1 |
| // CHECK: store i32 {{%.*}}, i32* %i, align 1 |
| UnalignedInt2 i; |
| i++; |
| } |
| |
| typedef UnalignedInt UnalignedInt3; |
| void test15() { |
| // CHECK: %i = alloca i32, align 1 |
| // CHECK: {{%.*}} = load i32, i32* %i, align 1 |
| // CHECK: store i32 {{%.*}}, i32* %i, align 1 |
| UnalignedInt3 i; |
| i++; |
| } |
| |
| // ------------- |
| // Decayed types |
| // ------------- |
| void test16(__unaligned int c[10]) { |
| // CHECK: {{%.*}} = alloca i32*, align 8 |
| // CHECK: store i32* %c, i32** {{%.*}}, align 8 |
| // CHECK: {{%.*}} = load i32*, i32** {{%.*}}, align 8 |
| // CHECK: {{%.*}} = getelementptr inbounds i32, i32* {{%.*}}, i64 3 |
| // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 |
| // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 |
| c[3]++; |
| } |
| |
| // ----------- |
| // __alignof__ |
| // ----------- |
| int test17(void) { |
| // CHECK: ret i32 1 |
| return __alignof__(__unaligned int); |
| } |
| |
| int test18(void) { |
| // CHECK: ret i32 1 |
| __unaligned int a; |
| return __alignof__(a); |
| } |
| |
| int test19(void) { |
| // CHECK: ret i32 1 |
| __unaligned int a[10]; |
| return __alignof__(a); |
| } |
| |
| // ----------- |
| // structs |
| // ----------- |
| typedef |
| struct S1 { |
| char c; |
| int x; |
| } S1; |
| |
| __unaligned S1 s1; |
| void test20(void) { |
| // CHECK: {{%.*}} = load i32, i32* getelementptr inbounds (%struct.S1, %struct.S1* @s1, i32 0, i32 1), align 1 |
| // CHECK: store i32 {{%.*}}, i32* getelementptr inbounds (%struct.S1, %struct.S1* @s1, i32 0, i32 1), align 1 |
| s1.x++; |
| } |
| |
| void test21(void) { |
| // CHECK: {{%.*}} = alloca %struct.S1, align 1 |
| // CHECK: {{%.*}} = getelementptr inbounds %struct.S1, %struct.S1* {{%.*}}, i32 0, i32 1 |
| // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 |
| // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 |
| __unaligned S1 s1_2; |
| s1_2.x++; |
| } |
| |
| typedef |
| struct __attribute__((packed)) S2 { |
| char c; |
| int x; |
| } S2; |
| |
| __unaligned S2 s2; |
| void test22(void) { |
| // CHECK: {{%.*}} = load i32, i32* getelementptr inbounds (%struct.S2, %struct.S2* @s2, i32 0, i32 1), align 1 |
| // CHECK: store i32 {{%.*}}, i32* getelementptr inbounds (%struct.S2, %struct.S2* @s2, i32 0, i32 1), align 1 |
| s2.x++; |
| } |
| |
| void test23(void) { |
| // CHECK: {{%.*}} = alloca %struct.S2, align 1 |
| // CHECK: {{%.*}} = getelementptr inbounds %struct.S2, %struct.S2* {{%.*}}, i32 0, i32 1 |
| // CHECK: {{%.*}} = load i32, i32* {{%.*}}, align 1 |
| // CHECK: store i32 {{%.*}}, i32* {{%.*}}, align 1 |
| __unaligned S2 s2_2; |
| s2_2.x++; |
| } |