ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Воскресенье
19 мая
37315
VAI (15.08.2005 13:52, просмотров: 713)
ИАР МСП еволюшн в.3.30а: Ошибка оптимизатора при установленой оптимизации "Function inlining" 
Ошибка оптимизатора при установленой оптимизации "Function inlining"
==========================================================================================
Код:
inline int is_circle_full( CIRCULAR_BUFFER *buf )   // "буфер полон" == 1
{
  return( buf->tail == NULL );
}
......
int uart1_tx( int c )
{
  while ( is_circle_full( &tx1buf ))    // ждем пустого места

    ;
  put_circle( c, &tx1buf );             // положим байт в буффер передачи
  return( c );
}
-----------------------------------------------------------------------------
Результат компиляции
НЕ ПРАВИЛЬНО!!!
     78            while ( is_circle_full( &tx1buf ))    // ждем пустого места
   \   000004   8293....     CMP.W   #0x0, &tx1buf + 4
   \   000008   0120         JNE     ??uart1_tx_1
   \                     ??uart1_tx_0:                    // ********************
   \   00000A   FF3F         JMP     ??uart1_tx_0         // ********************
     79              ;
     80          //   while ( ( &tx1buf )->tail == NULL )    // ждем пустого места
     81          //     ;


Правильно!!! (ручками вписали...)

     78          //   while ( is_circle_full( &tx1buf ))    // ждем пустого места
     79          //     ;
     80            while ( ( &tx1buf )->tail == NULL )    // ждем пустого места
   \                     ??uart1_tx_0:
   \   000004   8293....     CMP.W   #0x0, &tx1buf + 4
   \   000008   FD27         JEQ     ??uart1_tx_0
     81              ;

или так - оптимизатор сам делает инлайн-подстановку
Код:
int is_circle_full( CIRCULAR_BUFFER *buf )   // "буфер полон" == 1
{
  return( buf->tail == NULL );
}
......
int uart1_tx( int c )
{
  while ( is_circle_full( &tx1buf ))    // ждем пустого места

    ;
  put_circle( c, &tx1buf );             // положим байт в буффер передачи
  return( c );
}
-----------------------------------------------------------------------------



     76          int is_circle_full( CIRCULAR_BUFFER *buf )   // "буфер полон" == 1
   \                     is_circle_full:
     77          {
     78            return( buf->tail == NULL );
   \   000000   8C930400     CMP.W   #0x0, 0x4(R12)
   \   000004   0224         JEQ     ??is_circle_full_0
   \   000006   4C43         MOV.B   #0x0, R12
   \   000008   3041         RET
   \                     ??is_circle_full_0:
   \   00000A   5C43         MOV.B   #0x1, R12
   \   00000C   3041         RET
     79          }
     80          

   \                                 In segment CODE, align 2
     81          int uart1_tx( int c )
   \                     uart1_tx:
     82          {
   \   000000   0A12         PUSH.W  R10
   \   000002   0A4C         MOV.W   R12, R10
     83            while ( is_circle_full( (&tx1buf) ))    // ждем пустого места
   \   000004   8293....     CMP.W   #0x0, &tx1buf + 4
   \   000008   0120         JNE     ??uart1_tx_1
   \                     ??uart1_tx_0:                    // *******************
   \   00000A   FF3F         JMP     ??uart1_tx_0         // *******************
     84              ;
     85          //   while ( ( &tx1buf )->tail == NULL )    // ждем пустого места
     86          //     ;
     87            put_circle( c, &tx1buf );             // положим байт в буффер передачи
   \                     ??uart1_tx_1:
   \   00000C   3E40....     MOV.W   #tx1buf, R14
   \   000010   B012....     CALL    #put_circle
     88            return( c );
   \   000014   0C4A         MOV.W   R10, R12
   \   000016   3A41         POP.W   R10
   \   000018   3041         RET
     89          }
     90          
-------------------------------------------------------------------
Обходится использованием макроса (в данном случае) и наблюдением за листингом - если компилятор сам вставляет функцию inline-ом.

#define is_circle_full_p( buf_ptr )   ( ( buf_ptr )->tail == NULL )   // Для указателя
+++++++++++++++++++++++++++++++++
     76          int uart1_tx( int c )
   \                     uart1_tx:
     77          {
   \   000000   0A12         PUSH.W  R10
   \   000002   0A4C         MOV.W   R12, R10
     78            while ( is_circle_full_p( &tx1buf ))    // ждем пустого места
   \                     ??uart1_tx_0:
   \   000004   8293....     CMP.W   #0x0, &tx1buf + 4
   \   000008   FD27         JEQ     ??uart1_tx_0
     79              ;
     80          //   while ( ( &tx1buf )->tail == NULL )    // ждем пустого места
     81          //     ;
     82            put_circle( c, &tx1buf );             // положим байт в буффер передачи
   \   00000A   3E40....     MOV.W   #tx1buf, R14
   \   00000E   B012....     CALL    #put_circle
     83            return( c );
   \   000012   0C4A         MOV.W   R10, R12
   \   000014   3A41         POP.W   R10
   \   000016   3041         RET
     84          }
=========================================
#define is_circle_full( buf )         ( ( buf ).tail == NULL )
+++++++++++++++++++++++++++++++++

     76          int uart1_tx( int c )
   \                     uart1_tx:
     77          {
   \   000000   0A12         PUSH.W  R10
   \   000002   0A4C         MOV.W   R12, R10
     78            while ( is_circle_full( tx1buf ))    // ждем пустого места
   \                     ??uart1_tx_0:
   \   000004   8293....     CMP.W   #0x0, &tx1buf + 4
   \   000008   FD27         JEQ     ??uart1_tx_0
     79              ;
     80          //   while ( ( &tx1buf )->tail == NULL )    // ждем пустого места
     81          //     ;
     82            put_circle( c, &tx1buf );             // положим байт в буффер передачи
   \   00000A   3E40....     MOV.W   #tx1buf, R14
   \   00000E   B012....     CALL    #put_circle
     83            return( c );
   \   000012   0C4A         MOV.W   R10, R12
   \   000014   3A41         POP.W   R10
   \   000016   3041         RET
     84          }
====================================================