1 // RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -DSTRUCT -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-STRUCT
2 // RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -USTRUCT -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-NOSTRUCT
3 // RUN: not %clang_cc1 -triple=x86_64-unknown-linux-gnu -DIMPOSSIBLE_ODD -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-IMPOSSIBLE_ODD
4 // RUN: not %clang_cc1 -triple=x86_64-unknown-linux-gnu -DIMPOSSIBLE_BIG -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-IMPOSSIBLE_BIG
5 // RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -DPOSSIBLE_X -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-X
6 // RUN: not %clang_cc1 -triple=x86_64-unknown-linux-gnu -DIMPOSSIBLE_X -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-IMPOSSIBLE_X
7 // RUN: not %clang_cc1 -triple=x86_64-unknown-linux-gnu -DIMPOSSIBLE_9BYTES -emit-llvm %s -o - 2>&1 | FileCheck %s --check-prefix=CHECK-IMPOSSIBLE_9BYTES
8 
9 // Make sure Clang doesn't treat |lockval| as asm input.
_raw_spin_lock(void)10 void _raw_spin_lock(void) {
11 #ifdef STRUCT
12   struct {
13     unsigned short owner, next;
14   } lockval;
15   lockval.owner = 1;
16   lockval.next = 2;
17 #else
18   int lockval;
19   lockval = 3;
20 #endif
21   asm("nop"
22       : "=r"(lockval));
23 }
24 // CHECK-LABEL: _raw_spin_lock
25 // CHECK-LABEL: entry:
26 
27 // CHECK-STRUCT:  %lockval = alloca %struct.anon, align 2
28 // CHECK-STRUCT:  store i16 1
29 // CHECK-STRUCT:  store i16 2
30 // CHECK-STRUCT: [[RES:%[0-9]+]] = call i32 asm "nop", "=r,~{dirflag},~{fpsr},~{flags}"()
31 // CHECK-STRUCT: [[CAST:%[0-9]+]] = bitcast %struct.anon* %lockval to i32*
32 // CHECK-STRUCT: store i32 [[RES]], i32* [[CAST]], align 2
33 
34 // CHECK-NOSTRUCT: %lockval = alloca i32, align 4
35 // CHECK-NOSTRUCT: store i32 3
36 // CHECK-NOSTRUCT:  [[RES:%[0-9]+]] = call i32 asm "nop", "=r,~{dirflag},~{fpsr},~{flags}"()
37 // CHECK-NOSTRUCT: store i32 [[RES]], i32* %lockval, align 4
38 
39 // Check Clang correctly handles a structure with padding.
unusual_struct(void)40 void unusual_struct(void) {
41   struct {
42     unsigned short first;
43     unsigned char second;
44   } str;
45   asm("nop"
46       : "=r"(str));
47 }
48 
49 // Check Clang reports an error if attempting to return a structure for which
50 // no direct conversion to a register is possible.
odd_struct(void)51 void odd_struct(void) {
52 #ifdef IMPOSSIBLE_ODD
53   struct __attribute__((__packed__)) {
54     unsigned short first;
55     unsigned char second;
56   } str;
57   asm("nop"
58       : "=r"(str));
59 #endif
60 }
61 // CHECK-IMPOSSIBLE_ODD: impossible constraint in asm: can't store value into a register
62 
63 // Check Clang reports an error if attempting to return a big structure via a register.
big_struct(void)64 void big_struct(void) {
65 #ifdef IMPOSSIBLE_BIG
66   struct {
67     long long int v1, v2, v3, v4;
68   } str;
69   asm("nop"
70       : "=r"(str));
71 #endif
72 }
73 // CHECK-IMPOSSIBLE_BIG: impossible constraint in asm: can't store value into a register
74 
75 // Clang is able to emit LLVM IR for an 16-byte structure.
x_constraint_fit()76 void x_constraint_fit() {
77 #ifdef POSSIBLE_X
78   struct S {
79     unsigned x[4];
80   } z;
81   asm volatile("nop"
82                : "=x"(z));
83 #endif
84 }
85 // CHECK-LABEL: x_constraint_fit
86 // CHECK-X: %z = alloca %struct.S, align 4
87 // CHECK-X: [[RES:%[0-9]+]] = call i128 asm sideeffect "nop", "=x,~{dirflag},~{fpsr},~{flags}"()
88 // CHECK-X: [[CAST:%[0-9]+]] = bitcast %struct.S* %z to i128*
89 // CHECK-X: store i128 [[RES]], i128* [[CAST]], align 4
90 // CHECK-X: ret
91 
92 // Clang is unable to emit LLVM IR for a 32-byte structure.
x_constraint_nofit()93 void x_constraint_nofit() {
94 #ifdef IMPOSSIBLE_X
95   struct S {
96     unsigned x[8];
97   } z;
98   asm volatile("nop"
99                : "=x"(z));
100 #endif
101 }
102 
103 // CHECK-IMPOSSIBLE_X: invalid output size for constraint
104 
105 // http://crbug.com/999160
106 // Clang used to report the following message:
107 //   "impossible constraint in asm: can't store struct into a register"
108 // for the assembly directive below, although there's no struct.
crbug_999160_regtest()109 void crbug_999160_regtest() {
110 #ifdef IMPOSSIBLE_9BYTES
111   char buf[9];
112   asm(""
113       : "=r"(buf));
114 #endif
115 }
116 
117 // CHECK-IMPOSSIBLE_9BYTES: impossible constraint in asm: can't store value into a register
118