2009-05-18 2 views
2

Недавно мы обновили код до gcc4.3.3 от gcc4.2.4.Ошибка сборки сборки (gcc4.2.4 = win, gcc4.3.3 = fail)

void testAndSet( volatile int* s, int* val) 
{ 
    __asm__ __volatile__ ("btsl $0, %0\n " 
      "jc bitSet\n " 
      "movl $0, %1\n " 
      "jmp returnVector\n" 
      "bitSet:\n " 
      "movl $1, %1\n" 
      "returnVector: " : "=m"(*s), "=m"(*val)); 
} 

Наш код в настоящее время не удается со следующими ошибками,

lock.cxx: Assembler messages: 
lock.cxx:59: Error: symbol `bitSet' is already defined 
lock.cxx:61: Error: symbol `returnVector' is already defined 
lock.cxx:59: Error: symbol `bitSet' is already defined 
lock.cxx:61: Error: symbol `returnVector' is already defined 

Эти символы не были нигде. (Переименование их вызывает ту же ошибку с новым именем).

Что случилось с этим? почему я получаю ошибки дважды?

ответ

9

Возможно, оптимизатор изменился и теперь вставляет вашу функцию testAndSet() в 2 места. Поскольку вы используете глобальные имена для своих ярлыков, это не работает. Вместо этого вы должны использовать локальные имена. Например:

__asm__ __volatile__ ("btsl $0, %0\n " 
      "jc 0f\n " 
      "movl $0, %1\n " 
      "jmp 1f\n" 
      "0:\n " 
      "movl $1, %1\n" 
      "1: " : "=m"(*s), "=m"(*val)); 

Местные этикетки - это всего лишь цифры; для устранения неоднозначности случаев, когда есть много ярлыков под названием «0», вам нужно использовать «jmp 0f» для передовых переходов и «jmp 0b» для переходов назад.

+0

Отлично. Вот и все. Интересно, что неудача с опцией gcc -02, но не с -O – user48956

+0

Чем выше значение параметра -O, тем выше вероятность того, что он будет встроен в строки; по существу, -O2 и -O3 будут использовать оптимизацию, основанную на все более агрессивной инкрустации и разворачивании циклов и т. д. Возможно, стоит попробовать «-O» (оптимизировать без увеличения размера кода), что часто обеспечивает хорошую оптимизацию на средних площадках. –

5

Это не имеет никакого отношения к вашей ошибке, но вы могли бы улучшить свой код и избежать ветвей просто используя setCC instruction:

__asm__ __volatile__ ("btsl $0, %0\n " 
     "mov $0, %1\n" 
     "setc %1\n" : "=m"(*s), "=m"(*val)); 

setCC инструкция (где CC является одним из состояния кодовых флагов, аналогично jCC инструкция) устанавливает байт в 0 или 1 в зависимости от того, выполнено ли данное условие. Поскольку адресат является значением 4 байта, вам необходимо либо предварительно загрузить его с 0 или использовать MOVZX instruction сделать верхний 3 байта 0.

1

Также вы можете использовать локальные имена меток, добавляя % = после каждой локальной ярлык:

"loop% =:" "\ n \ t"

Смежные вопросы