1  /* Copyright (C) 2002  Free Software Foundation.
       2     by Hans-Peter Nilsson  <hp@axis.com>
       3  
       4     Making sure that asm clobbers conflicting with asm-declared input
       5     operands are detected: ``You may not write a clobber description in a
       6     way that overlaps with an input or output operand''.
       7  
       8     You must be this tall ---> fit two long longs in asm-declared registers
       9     to enter this amusement.  */
      10  
      11  /* { dg-do compile { target alpha*-*-* cris-*-* i?86-*-* mmix-*-* powerpc*-*-* rs6000-*-* x86_64-*-* } } */
      12  /* { dg-options "-O2" } */
      13  
      14  /* Constructed examples; input/output (same register), output, input, and
      15     input and output (different registers).  */
      16  
      17  /* The long longs are used to test overlap for multi-register
      18     registers.  REG2 and REG4 must be the second halves (defined as
      19     higher-numbered parts) of REG1 and REG3 respectively when two registers
      20     are needed.  */
      21  
      22  #if defined (__alpha__)
      23  # define REG1 "$1"
      24  # define REG2 "$2"
      25  #elif defined (__CRIS__)
      26  # define REG1 "r10"
      27  # define REG2 "r11"
      28  # define REG3 "r12"
      29  # define REG4 "r13"
      30  # define REG5 "r9"
      31  #elif defined (__i386__)
      32  # define REG1 "%eax"
      33  # define REG2 "%edx"
      34  /* On Darwin -fpic is on by default, so don't use %ebx. */
      35  # define REG3 "%esi"
      36  # define REG4 "%edi"
      37  #elif defined (__MMIX__)
      38  # define REG1 "$8"
      39  # define REG2 "$9"
      40  #elif defined (__powerpc__) || defined (__PPC__) || defined (__ppc__) \
      41  	|| defined (__POWERPC__) || defined (PPC) || defined (_IBMR2) \
      42  	|| defined (__ppc)
      43  # define REG1 "6"
      44  # define REG2 "7"
      45  # if !defined(_ARCH_PPC64)
      46  #  define REG3 "8"
      47  #  define REG4 "9"
      48  # endif
      49  #elif defined (__x86_64__)
      50  # define REG1 "rax"
      51  # define REG2 "rdx"
      52  #endif
      53  
      54  /* For readability of the tests.  */
      55  #ifdef REG3
      56  # define REG1a REG1
      57  # define REG1b REG2
      58  # define REG2a REG3
      59  # define REG2b REG4
      60  #else
      61  # define REG1a REG1
      62  # define REG1b REG1
      63  # define REG2a REG2
      64  # define REG2b REG2
      65  #endif
      66  
      67  /* REG5 is just another reg if there is one; the difference to REG4 is to
      68     keep the original set of registers for CRIS.  */
      69  #ifndef REG5
      70  #define REG5 REG2b
      71  #endif
      72  
      73  void *
      74  foo (void *p)
      75  {
      76    register void *q asm (REG1) = p;
      77    asm ("foo1 %0" : "=r" (q) : "0" (q) : REG1); /* { dg-error "conflict" } */
      78    return q;
      79  }
      80  
      81  void *
      82  nfoo (void *p)
      83  {
      84    register void *q asm (REG1) = p;
      85    asm ("foo1 %0" : "=r" (q) : "0" (q) : REG2);
      86    return q;
      87  }
      88  
      89  long long
      90  foolla (long long llp)
      91  {
      92    register long long ll asm (REG1a) = llp;
      93    asm ("foo1a %0" : "=r" (ll) : "0" (ll) : REG1a); /* { dg-error "conflict" } */
      94    return ll;
      95  }
      96  
      97  long long
      98  nfoolla (long long llp)
      99  {
     100    register long long ll asm (REG1a) = llp;
     101    asm ("foo1a %0" : "=r" (ll) : "0" (ll) : REG2a);
     102    return ll;
     103  }
     104  
     105  long long
     106  foollb (long long llp)
     107  {
     108    register long long ll asm (REG1a) = llp;
     109    asm ("foo1b %0" : "=r" (ll) : "0" (ll) : REG1b); /* { dg-error "conflict" } */
     110    return ll;
     111  }
     112  
     113  void *
     114  bar (void *p)
     115  {
     116    register void *q asm (REG1);
     117    register void *w asm (REG2) = p;
     118    asm ("bar1 %1,%0" : "=r" (q) : "r" (w) : REG1); /* { dg-error "conflict" } */
     119    return q;
     120  }
     121  
     122  long long
     123  barlla (long long llp)
     124  {
     125    register long long ll asm (REG1a);
     126    register long long mm asm (REG2a) = llp;
     127    asm ("bar1a %1,%0" : "=r" (ll) : "r" (mm) : REG1b); /* { dg-error "conflict" } */
     128    return ll;
     129  }
     130  
     131  long long
     132  barllb (long long llp)
     133  {
     134    register long long ll asm (REG1a);
     135    register long long mm asm (REG2a) = llp;
     136    asm ("bar1b %1,%0" : "=r" (ll) : "r" (mm) : REG2b); /* { dg-error "conflict" } */
     137    return ll;
     138  }
     139  
     140  void *
     141  foobar (void *p)
     142  {
     143    register void *q asm (REG1);
     144    register void *w asm (REG2) = p;
     145    asm ("foobar1 %1,%0" : "=r" (q) : "r" (w) : REG2); /* { dg-error "conflict" } */
     146    return q;
     147  }
     148  
     149  void *
     150  nfoobar (void *p)
     151  {
     152    register void *q asm (REG1);
     153    register void *w = p;
     154    asm ("foobar1 %1,%0" : "=r" (q) : "r" (w) : REG2);
     155    return q;
     156  }
     157  
     158  long long
     159  foobarlla (long long llp)
     160  {
     161    register long long ll asm (REG1a);
     162    register long long mm asm (REG2a) = llp;
     163    asm ("foobar1a %1,%0" : "=r" (ll) : "r" (mm) : REG1b); /* { dg-error "conflict" } */
     164    return ll;
     165  }
     166  
     167  long long
     168  nfoobarlla (long long llp)
     169  {
     170    register long long ll asm (REG1a);
     171    register long long mm = llp;
     172    asm ("foobar1a %1,%0" : "=r" (ll) : "r" (mm) : REG2a);
     173    return ll;
     174  }
     175  
     176  long long
     177  foobarllb (long long llp)
     178  {
     179    register long long ll asm (REG1a);
     180    register long long mm asm (REG2a) = llp;
     181    asm ("foobar1b %1,%0" : "=r" (ll) : "r" (mm) : REG2b); /* { dg-error "conflict" } */
     182    return ll;
     183  }
     184  
     185  long long
     186  nfoobarllb (long long llp)
     187  {
     188    register long long ll asm (REG1a);
     189    register long long mm = llp;
     190    asm ("foobar1b %1,%0" : "=r" (ll) : "r" (mm) : REG2b);
     191    return ll;
     192  }
     193  
     194  void *
     195  baz (void *p)
     196  {
     197    register void *q asm (REG1);
     198    register void *w asm (REG2) = p;
     199    asm ("baz1 %1,%0" : "=r" (q) : "r" (w) : REG1, REG2); /* { dg-error "conflict" } */
     200    return q;
     201  }
     202  
     203  void *
     204  nbaz (void *p)
     205  {
     206    register void *q;
     207    register void *w = p;
     208    asm ("baz1 %1,%0" : "=r" (q) : "r" (w) : REG1, REG2);
     209    return q;
     210  }
     211  
     212  void *
     213  nbaz2 (void *p)
     214  {
     215    register void *q asm (REG1);
     216    register void *w asm (REG2) = p;
     217    asm ("baz1 %1,%0" : "=r" (q) : "r" (w));
     218    return q;
     219  }
     220  
     221  long long
     222  bazlla (long long llp)
     223  {
     224    register long long ll asm (REG1a);
     225    register long long mm asm (REG2a) = llp;
     226    asm ("baz1a %1,%0" : "=r" (ll) : "r" (mm) : REG1a, REG2a); /* { dg-error "conflict" } */
     227    return ll;
     228  }
     229  
     230  long long
     231  bazllb (long long llp)
     232  {
     233    register long long ll asm (REG1a);
     234    register long long mm asm (REG2a) = llp;
     235    asm ("baz2a %1,%0" : "=r" (ll) : "r" (mm) : REG1b, REG2b); /* { dg-error "conflict" } */
     236    return ll;
     237  }
     238  
     239  /* Real-world example of bug.  */
     240  
     241  #ifdef _WIN64
     242  typedef unsigned int loc_size_t __attribute__ ((mode (DI)));
     243  #else
     244  typedef __SIZE_TYPE__ loc_size_t;
     245  #endif
     246  
     247  struct stat;
     248  int
     249  _dl_stat (const char *file_name, struct stat *buf)
     250  {
     251    register long a asm (REG1) = (long) (loc_size_t) file_name;
     252    register long b asm (REG2) = (long) (loc_size_t) buf;
     253  
     254    asm volatile ("movu.w %1,$r9\n\tbreak 13" : "=r" (a) : "g" (106), "0" (a), "r" (b) : REG1, REG5); /* { dg-error "conflict" } */
     255    if (a >= 0)
     256      return (int) a;
     257    return (int) -1;
     258  }