Проблема с оптимизацией времени соединения, приводящая к неопределенным символам с константами ASM

Я собираю mplayer с llvm-gcc-4.2.1.

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

Неопределенные символы для архитектуры x86_64:
  "_MM_FIX_0_707106781", на который ссылаются:
      _filter в vf_fspp.o
  "_MM_FIX_0_541196100", на который ссылаются:
      _filter в vf_fspp.o
ld: символы не найдены для архитектуры x86_64
collect2: ld вернул 1 статус выхода

К вашему сведению, моя версия 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 ответа

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

Проблема заключалась в том, что скрипты 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), однако вы должны рассмотреть этот вопрос как полурешенный, так как два других компилятора правильно работают с этим кодом.

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

./configure --cc=i686-apple-darwin10-gcc-4.2.1 --enable-gpl --enable-nonfree

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

РЕДАКТИРОВАТЬ: я не заметил static, что означает, что как встроенный asm, так и символ находятся в одном модуле, и это другая ошибка.

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

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

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

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

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

Другие вопросы по тегам