|
@@ -0,0 +1,217 @@
|
|
|
+// 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++;
|
|
|
+}
|