// 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++; }