218 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			218 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C
		
	
	
	
| // 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++;
 | |
| }
 |