Должны ли встроенные команды gcc всегда разрешаться на этапе компиляции или на этапе компоновщика?

При запуске gcc 3.4.3 в окне Solaris 5.11 я вижу, что встроенные функции остаются неопределенными во время компиляции, но разрешаются в libgcc.a, когда компоновщик Solaris ссылается на libgcc.a.

На gcc 4.5.2 на другом компьютере Solaris те же встроенные функции разрешаются во время компиляции.o, и компоновщик их не беспокоит.

Файл примера скомпилированного компилятора на gcc 3.4.3:

# cat ctzll.c
int func(unsigned long long x)
{
        return __builtin_ctzll(x);
}

# cat main.c
int main(void)
{
        return func(0xc0ffee);
}

Сначала скомпилируйте ctzll.c и проверьте символы:

# nm ctzll.o
                 U __ctzdi2
0000000000000000 T func

Теперь скомпилируйте main.c и свяжите объекты:

# gcc -m64 main.c -c
# gcc -m64 ctzll.o main.o -v
Reading specs from /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/specs
Configured with: /build/i386/components/gcc3/gcc-3.4.3/configure --prefix=/usr/sfw --mandir=/usr/sfw/share/man --infodir=/usr/sfw/share/info --without-gnu-ld --with-ld=/usr/bin/ld --enable-languages=c,c++,f77,objc --enable-shared --with-gnu-as --with-as=/usr/gnu/bin/as
Thread model: posix
gcc version 3.4.3 (csl-sol210-3_4-20050802)
 /usr/sfw/libexec/gcc/i386-pc-solaris2.11/3.4.3/collect2 -V -Y P,/lib/64:/usr/lib/64:/usr/sfw/lib/64 -R /lib/64:/usr/lib/64:/usr/sfw/lib/64 -Qy /usr/lib/amd64/crt1.o /usr/lib/amd64/crti.o /usr/lib/amd64/values-Xa.o /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/crtbegin.o -L/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64 -L/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/../../../amd64 -L/lib/amd64 -L/usr/lib/amd64 ctzll.o main.o -lgcc -lgcc_eh -lc -lgcc -lgcc_eh /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/crtend.o /usr/lib/amd64/crtn.o
ld: Software Generation Utilities - Solaris Link Editors: 5.11-1.2276
# nm a.out | grep ctz
0000000000400fd0 T __ctzdi2

Итак, если я правильно понимаю, компоновщик Solaris разрешил __ctzdi2 (внутреннее представление __builtin_ctzll).

Теперь скомпилируйте gcc 4.5.2 на другом компьютере Solaris:

#gcc -m64 ctzll.c -c
# nm ctzll.o
0000000000000000 T func

Символ был точно разрешен в объектном файле, и он был встроен в сборку.o следующим образом:

   8:   48 0f bc 45 f8          bsf    -0x8(%rbp),%rax

Правильно ли работает компилятор 3.4.3? Я ожидал, что фактическая компиляция будет обрабатывать встроенные функции, такие как 4.5.2, ссылаясь на 64-битную версию libgcc.a. Отсутствие единообразия между компиляторами вызывает проблемы с исходным кодом в моем проекте, так как встроенный модуль остается неопределенным, а компоновщик не разрешает символы, так как я не связываюсь с конкретными 64-битными библиотеками ОС (libgcc.a). Я не уверен, что компилятор 3.4.3 неправильно настроен, что приводит к тому, что в файлах.o есть неопределенные встроенные функции, перехваченные связыванием, или если более новые компиляторы просто умнее, и мне нужно добавить 64-битные библиотеки в компоновщик для обработки старый компилятор

3.4.3, кажется, показывает действительный libgcc.a, который содержит определение _ctzdi2:

# gcc -m64 -print-libgcc-file-name
/usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/libgcc.a
# nm /usr/sfw/lib/gcc/i386-pc-solaris2.11/3.4.3/amd64/libgcc.a | grep ctzdi2
0000000000000000 T __ctzdi2
_ctzdi2.o:

1 ответ

Весь смысл libgcc.a заключается в реализации встроенных операций, для которых gcc не может генерировать код (который включает в себя не только функции __builtin_, но и такие вещи, как математические операции long long на некоторых 32-битных платформах).

Очевидно, что более новый gcc стал более умным в отношении выдачи кода.

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