aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.9/gcc/testsuite/gcc.dg/20020919-1.c
blob: dfb072109c15773b94839eb1eee565c000f3ec78 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/* Copyright (C) 2002  Free Software Foundation.
   by Hans-Peter Nilsson  <hp@axis.com>

   Making sure that asm clobbers conflicting with asm-declared input
   operands are detected: ``You may not write a clobber description in a
   way that overlaps with an input or output operand''.

   You must be this tall ---> fit two long longs in asm-declared registers
   to enter this amusement.  */

/* { dg-do compile { target alpha*-*-* cris-*-* crisv32-*-* i?86-*-* mmix-*-* powerpc*-*-* rs6000-*-* x86_64-*-* } } */
/* { dg-options "-O2" } */

/* Constructed examples; input/output (same register), output, input, and
   input and output (different registers).  */

/* The long longs are used to test overlap overlap for multi-register
   registers.  REG2 and REG4 must be the second halves (defined as
   higher-numbered parts) of REG1 and REG3 respectively when two registers
   are needed.  */

#if defined (__alpha__)
# define REG1 "$1"
# define REG2 "$2"
#elif defined (__CRIS__)
# define REG1 "r10"
# define REG2 "r11"
# define REG3 "r12"
# define REG4 "r13"
# define REG5 "r9"
#elif defined (__i386__)
# define REG1 "%eax"
# define REG2 "%edx"
/* On Darwin -fpic is on by default, so don't use %ebx. */
# define REG3 "%esi"
# define REG4 "%edi"
#elif defined (__MMIX__)
# define REG1 "$8"
# define REG2 "$9"
#elif defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) \
	|| defined (__POWERPC__) || defined (PPC) || defined (_IBMR2) \
	|| defined (__ppc)
# define REG1 "6"
# define REG2 "7"
# if !defined(__powerpc64__) && !defined(__LP64__)
#  define REG3 "8"
#  define REG4 "9"
# endif
#elif defined (__x86_64__)
# define REG1 "rax"
# define REG2 "rdx"
#endif

/* For readability of the tests.  */
#ifdef REG3
# define REG1a REG1
# define REG1b REG2
# define REG2a REG3
# define REG2b REG4
#else
# define REG1a REG1
# define REG1b REG1
# define REG2a REG2
# define REG2b REG2
#endif

/* REG5 is just another reg if there is one; the difference to REG4 is to
   keep the original set of registers for CRIS.  */
#ifndef REG5
#define REG5 REG2b
#endif

void *
foo (void *p)
{
  register void *q asm (REG1) = p;
  asm ("foo1 %0" : "=r" (q) : "0" (q) : REG1); /* { dg-error "conflict" } */
  return q;
}

void *
nfoo (void *p)
{
  register void *q asm (REG1) = p;
  asm ("foo1 %0" : "=r" (q) : "0" (q) : REG2);
  return q;
}

long long
foolla (long long llp)
{
  register long long ll asm (REG1a) = llp;
  asm ("foo1a %0" : "=r" (ll) : "0" (ll) : REG1a); /* { dg-error "conflict" } */
  return ll;
}

long long
nfoolla (long long llp)
{
  register long long ll asm (REG1a) = llp;
  asm ("foo1a %0" : "=r" (ll) : "0" (ll) : REG2a);
  return ll;
}

long long
foollb (long long llp)
{
  register long long ll asm (REG1a) = llp;
  asm ("foo1b %0" : "=r" (ll) : "0" (ll) : REG1b); /* { dg-error "conflict" } */
  return ll;
}

void *
bar (void *p)
{
  register void *q asm (REG1);
  register void *w asm (REG2) = p;
  asm ("bar1 %1,%0" : "=r" (q) : "r" (w) : REG1); /* { dg-error "conflict" } */
  return q;
}

long long
barlla (long long llp)
{
  register long long ll asm (REG1a);
  register long long mm asm (REG2a) = llp;
  asm ("bar1a %1,%0" : "=r" (ll) : "r" (mm) : REG1b); /* { dg-error "conflict" } */
  return ll;
}

long long
barllb (long long llp)
{
  register long long ll asm (REG1a);
  register long long mm asm (REG2a) = llp;
  asm ("bar1b %1,%0" : "=r" (ll) : "r" (mm) : REG2b); /* { dg-error "conflict" } */
  return ll;
}

void *
foobar (void *p)
{
  register void *q asm (REG1);
  register void *w asm (REG2) = p;
  asm ("foobar1 %1,%0" : "=r" (q) : "r" (w) : REG2); /* { dg-error "conflict" } */
  return q;
}

void *
nfoobar (void *p)
{
  register void *q asm (REG1);
  register void *w = p;
  asm ("foobar1 %1,%0" : "=r" (q) : "r" (w) : REG2);
  return q;
}

long long
foobarlla (long long llp)
{
  register long long ll asm (REG1a);
  register long long mm asm (REG2a) = llp;
  asm ("foobar1a %1,%0" : "=r" (ll) : "r" (mm) : REG1b); /* { dg-error "conflict" } */
  return ll;
}

long long
nfoobarlla (long long llp)
{
  register long long ll asm (REG1a);
  register long long mm = llp;
  asm ("foobar1a %1,%0" : "=r" (ll) : "r" (mm) : REG2a);
  return ll;
}

long long
foobarllb (long long llp)
{
  register long long ll asm (REG1a);
  register long long mm asm (REG2a) = llp;
  asm ("foobar1b %1,%0" : "=r" (ll) : "r" (mm) : REG2b); /* { dg-error "conflict" } */
  return ll;
}

long long
nfoobarllb (long long llp)
{
  register long long ll asm (REG1a);
  register long long mm = llp;
  asm ("foobar1b %1,%0" : "=r" (ll) : "r" (mm) : REG2b);
  return ll;
}

void *
baz (void *p)
{
  register void *q asm (REG1);
  register void *w asm (REG2) = p;
  asm ("baz1 %1,%0" : "=r" (q) : "r" (w) : REG1, REG2); /* { dg-error "conflict" } */
  return q;
}

void *
nbaz (void *p)
{
  register void *q;
  register void *w = p;
  asm ("baz1 %1,%0" : "=r" (q) : "r" (w) : REG1, REG2);
  return q;
}

void *
nbaz2 (void *p)
{
  register void *q asm (REG1);
  register void *w asm (REG2) = p;
  asm ("baz1 %1,%0" : "=r" (q) : "r" (w));
  return q;
}

long long
bazlla (long long llp)
{
  register long long ll asm (REG1a);
  register long long mm asm (REG2a) = llp;
  asm ("baz1a %1,%0" : "=r" (ll) : "r" (mm) : REG1a, REG2a); /* { dg-error "conflict" } */
  return ll;
}

long long
bazllb (long long llp)
{
  register long long ll asm (REG1a);
  register long long mm asm (REG2a) = llp;
  asm ("baz2a %1,%0" : "=r" (ll) : "r" (mm) : REG1b, REG2b); /* { dg-error "conflict" } */
  return ll;
}

/* Real-world example of bug.  */

#ifdef _WIN64
typedef unsigned int loc_size_t __attribute__ ((mode (DI)));
#else
typedef __SIZE_TYPE__ loc_size_t;
#endif

struct stat;
int
_dl_stat (const char *file_name, struct stat *buf)
{
  register long a asm (REG1) = (long) (loc_size_t) file_name;
  register long b asm (REG2) = (long) (loc_size_t) buf;

  asm volatile ("movu.w %1,$r9\n\tbreak 13" : "=r" (a) : "g" (106), "0" (a), "r" (b) : REG1, REG5); /* { dg-error "conflict" } */
  if (a >= 0)
    return (int) a;
  return (int) -1;
}