3

I'm attempting to set-up CI for our Xcode cross-compiles. The cross-compiles test both ARMv7 and ARMv8. Things look good except when it comes time to link for 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

We obviously don't run the output artifact cryptest.exe. We just compile and link to test things.

The code has been testing fine under LLVM Clang.

All ARMv8/Aarch64 machines have CRC-32 and CRC-32C; but the Crypto extensions are optional. The error does not make much sense.

Does Clang lack CRC32 for ARMv8/Aarch64?


Below is the code that's causing the errors.

#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
jww
  • 97,681
  • 90
  • 411
  • 885

1 Answers1

1

Under Xcode 8.3.3, I came across the compile error at __crc32*(). Then I added the command line switch

-march=armv8-a+crc

as found at this link, then the code compiles well. I tested with iphone7+/iOS10.3.1 and it's working.

Note according to ARM's document ("ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture profile" DDI0487B_a_armv8_arm.pdf: page A1-58), crc32 instructions are optional for v8 and mandatory for v8.1. When I ran the same program on iphone6+/iOS9.3.3, it crashed at __crc32*(). I also verified it with inline assembler. To avoid the crash, therefore, some kind of run-time check is necessary. I don't fully understand how, but as a last resort, we could use the model names.

beshio
  • 794
  • 2
  • 7
  • 17
  • Thanks @beshio. *"To avoid the crash, therefore, some kind of run-time check is necessary..."* - see [How to determine ARMv8 features at runtime on iOS?](https://stackoverflow.com/q/45637888/608639) – jww Sep 16 '17 at 08:32
  • @jww, thanks for the info. I will check the link and study it. – beshio Sep 16 '17 at 08:40
  • I had to circle back to this. This is a Clang problem in general, not a Apple problem in particular. Clang is failing on a generic Aarch board running Linux. The failure is with `-march=armv8-a+crc`. – jww Oct 20 '19 at 15:45