Проблема с оптимизацией времени соединения, приводящая к неопределенным символам с константами ASM - PullRequest
3 голосов
/ 17 марта 2011

Я компилирую mplayer с помощью llvm-gcc-4.2.1.

С '-O1' (который отключает оптимизацию времени ссылки), программа успешно компилирует и связывает.С '-O2' или '-O1 -flto' ld жалуется на неопределенные символы:

Undefined symbols for architecture x86_64:
  "_MM_FIX_0_707106781", referenced from:
      _filter in vf_fspp.o
  "_MM_FIX_0_541196100", referenced from:
      _filter in vf_fspp.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

fyi, моя версия ld:

@(#)PROGRAM:ld  PROJECT:ld64-123.2
llvm version 2.9svn, from Apple Clang 2.0 (build 137)

Я сосредоточусь только наMM_FIX_0_707106781, поскольку все остальные константы следуют той же процедуре.

MM_FIX_0_707106781 инициализируется с помощью макроса:

DECLARE_ASM_CONST(8, uint64_t, MM_FIX_0_707106781)=FIX64(0.707106781, 14);

, который оценивается как:

static const uint64_t __attribute__((used, aligned (8))) MM_FIX_0_707106781=0x2d412d412d412d41;

Эти константыиспользуется в коде asm:

#define MANGLE(a) "_" #a "(%%rip)"

__asm__ volatile(
...
  "pmulhw "MANGLE(MM_FIX_0_707106781)", %%mm7 \n\t"
...
);

У меня была похожая (та же?) проблема с функциями asm, которую я смог решить, добавив:
".globl "LABLE_MANGLE(functionnamehere)"\n\t"
перед каждой меткой, ноэти знания не помогли мне с этими константами ASM.

Боюсь, это столько информации, сколько я могу предоставить.Еще раз, с -O1 код компилируется, связывается и запускается.С -O2 компоновщик не может найти эти константы asm.

Может кто-нибудь предложить решение этой проблемы?Спасибо.

Ответы [ 4 ]

1 голос
/ 18 марта 2011

Спасибо всем, кто нашел время, чтобы рассмотреть мой вопрос, однако я только что понял, что испортил свои инструменты компиляции и теперь могу компилировать нормально.

Проблема заключалась в том, что скрипты mplayer make вызывают для компиляции 'cc', ожидая, что cc == gcc.Это было не так в моей системе;cc был связан с другой версией gcc.Как только я сделал символическую ссылку cc на gcc, я получил проект для компиляции с -O4 (как установлено в скрипте настройки mplayer по умолчанию).

В заключение: неправильно настроенные инструменты компилятора вызывали конфликты во время соединения.Решено с помощью одного и того же компилятора на всех этапах сборки.

Редактировать: На самом деле llvm-gcc по-прежнему не работает с -O4, но другие компиляторы (gcc-4.5.2 и gcc42, которыеэто версия Apple GCC) успешно.Оба других компилятора не принимают флаг -flto, поэтому оптимизация во время соединения все еще не выполняется.По крайней мере, я счастлив, что могу скомпилировать с -O2, -O3 и т. Д., И это главная причина, по которой я был мотивирован поставить этот вопрос.

Естественно, я хотел бы иметь возможность использовать компилятор llvm-gcc, если захочу (на уровне выше -O1), однако вы должны рассмотреть этот вопрос как полурешенный, так как два других компилятора работают правильнос этим кодом.

0 голосов
/ 25 июля 2011

Следующие команды позволили скомпилировать ffmpeg-0.8 в моей системе:

./configure --cc=i686-apple-darwin10-gcc-4.2.1 --enable-gpl --enable-nonfree
0 голосов
/ 17 марта 2011

Ну, это определенно ошибка. Если вы думаете, что это ошибка компилятора, у вас есть несколько вариантов:

  1. Сообщите об ошибке в Apple, так как кажется, что вы используете llvm-gcc, поставляемый с XCode
  2. Попробуйте захватить top-of-tree llvm & llvm-gcc (что уже устарело, кстати) и попытаться воспроизвести проблему (или, наоборот, захватить лязг) Если воспроизводит - тогда заполните LLVM PR.

Так обычно поступают с ошибками компилятора:)

Однако, как мне кажется, ошибка в исходном коде. Здесь вы предполагаете, что имя символа, соответствующего этой статической константе в конечном объекте, будет иметь некоторую форму. Обычно это вещи, определяемые реализацией, и компилятор может изменить имя произвольным образом (поскольку он статичен и, следовательно, внешне не виден).

Попробуйте удалить «статический» и проверить, существует ли проблема до сих пор. В качестве альтернативы (и это правильный путь) вы должны исправить свой встроенный ассемблер и предоставить свою константу через операнд встроенного ассемблера.

0 голосов
/ 17 марта 2011

В llvm-ссылке есть ошибка - она ​​не учитывает символы из внедренного asm.Я не знаю ни одного достойного обходного пути, кроме ссылки на тот же символ где-нибудь из того же модуля в C. Если вы выполняете отдельную компиляцию, это не проблема, поскольку используется нативный компоновщик.Для LTO будет использоваться компоновщик LLVM, и он имеет недостатки.

EDIT : я не заметил static, что означает, что как встроенный asm, так и символ находятся в одном и том жемодуль, и это другая ошибка.

...