В Clang отсутствует CRC32 для ARMv8/Aarch64?

Я пытаюсь настроить CI для кросс-компиляции Xcode. Кросс-компиляции тестируют как ARMv7, так и ARMv8. Все выглядит хорошо, за исключением случаев, когда приходит время компоновки для ARMv8:

clang++ -DNDEBUG -g2 -O3 -fPIC -pipe -Wall -miphoneos-version-min=7 -arch arm64 \
  -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.2.sdk \
  -stdlib=libc++ -c cryptlib.cpp
clang++ -DNDEBUG -g2 -O3 -fPIC -pipe -Wall -miphoneos-version-min=7 -arch arm64 \
  -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.2.sdk \
  -stdlib=libc++ -c cpu.cpp
...

clang++ -o cryptest.exe -DNDEBUG -g2 -O3 -fPIC -pipe -Wall -miphoneos-version-min=7 -arch arm64 \
  -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.2.sdk \
  -stdlib=libc++ test.o bench1.o bench2.o ... ./libcryptopp.a  

Undefined symbols for architecture arm64:

  "CryptoPP::CRC32_Update_ARMV8(unsigned char const*, unsigned long, unsigned int&)", referenced from:

      CryptoPP::CRC32::Update(unsigned char const*, unsigned long) in libcryptopp.a(crc.o)

  "CryptoPP::CRC32C_Update_ARMV8(unsigned char const*, unsigned long, unsigned int&)", referenced from:

      CryptoPP::CRC32C::Update(unsigned char const*, unsigned long) in libcryptopp.a(crc.o)

ld: symbol(s) not found for architecture arm64

clang: error: linker command failed with exit code 1 (use -v to see invocation)

make: *** [cryptest.exe] Error 1

Очевидно, мы не запускаем выходной артефакт cryptest.exe. Мы просто компилируем и связываем для тестирования.

Код отлично тестировался в LLVM Clang.

Все машины ARMv8/Aarch64 имеют CRC-32 и CRC-32C; но расширения Crypto являются необязательными. Ошибка не имеет особого смысла.

В Clang отсутствует CRC32 для ARMv8/Aarch64?


Ниже приведен код, вызывающий ошибки.

#if defined(__ARM_FEATURE_CRC32)

void CRC32_Update_ARMV8(const uint8_t *s, size_t n, uint32_t& c)
{
    for(; !IsAligned<uint32_t>(s) && n > 0; s++, n--)
        c = __crc32b(c, *s);

    for(; n > 4; s+=4, n-=4)
        c = __crc32w(c, *s);

    for(; n > 0; s++, n--)
        c = __crc32b(c, *s);
}

#endif

person jww    schedule 11.08.2017    source источник


Ответы (1)


В Xcode 8.3.3 я столкнулся с ошибкой компиляции в __crc32*(). Затем я добавил переключатель командной строки

-march=armv8-a+crc

как указано в этой ссылке, то код компилируется хорошо. Я тестировал с iphone7+/iOS10.3.1, и он работает.

Примечание согласно документ ARM («Справочное руководство по архитектуре ARM® ARMv8, для профиля архитектуры ARMv8-A» DDI0487B_a_armv8_arm.pdf: страница A1-58), инструкции crc32 являются необязательными для версии 8 и обязательными для версии 8.1. Когда я запускал ту же программу на iphone6+/iOS9.3.3, она вылетала на __crc32*(). Я также проверил это с помощью встроенного ассемблера. Следовательно, чтобы избежать сбоя, необходима какая-то проверка во время выполнения. Я не совсем понимаю, как, но в крайнем случае мы могли бы использовать названия моделей.

person beshio    schedule 16.09.2017
comment
Спасибо @beshio. Поэтому, чтобы избежать сбоя, необходима какая-то проверка во время выполнения... - см. Как определять функции ARMv8 во время выполнения на iOS? - person jww; 16.09.2017
comment
@jww, спасибо за информацию. Я проверю ссылку и изучу ее. - person beshio; 16.09.2017
comment
Пришлось вернуться к этому. Это проблема Clang в целом, а не проблема Apple в частности. Clang не работает на универсальной плате Aarch под управлением Linux. Ошибка связана с -march=armv8-a+crc. - person jww; 20.10.2019