2016-05-06 3 views
1

Я уже давно занимаюсь этой проблемой, и я надеюсь, что кто-то может указать на мою ошибку. Наверное, я больше не могу видеть лес через деревья.Почему __ARM_FEATURE_CRC32 не определяется компилятором?

У меня есть плата LeMaker HiKey, которую я использую для тестирования. Его AArch64, поэтому его имеет неон и другие функции центрального процессора, как AES, SHA и CRC32:

$ cat /proc/cpuinfo 
Processor : AArch64 Processor rev 3 (aarch64) 
... 
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 
... 

При попытке скомпилировать программу:

$ cat test.cxx 
#if (defined(__ARM_NEON__) || defined(__ARM_NEON)) 
# define NEON_INTRINSICS_AVAILABLE 1 
#else 
# define NEON_INTRINSICS_AVAILABLE 0 
#endif 

#if BOOL_NEON_INTRINSICS_AVAILABLE 
# include <arm_neon.h> 
# if defined(__ARM_FEATURE_CRC32) || (__ARM_ACLE >= 200) 
# include <arm_acle.h> 
# endif 
#endif 

#include <stdint.h> 

int main(int argc, char* argv[]) 
{ 
    uint32_t crc = 0; 

    crc = __crc32b(crc, (uint8_t)0); 
    return 0 
} 

Это приводит к следующему:

$ g++ test.cxx -o test.exe 
test.cxx: In function ‘int main(int, char**)’: 
test.cxx:20:33: error: ‘__crc32b’ was not declared in this scope 
    crc = __crc32b(crc, (uint8_t)0); 
           ^
test.cxx:22:1: error: expected ‘;’ before ‘}’ token 
} 
^ 

$ clang++ test.cxx -o test.exe 
test.cxx:20:9: error: use of undeclared identifier '__crc32b' 
    crc = __crc32b(crc, (uint8_t)0); 
     ^
test.cxx:21:11: error: expected ';' after return statement 
    return 0 
     ^
      ; 
2 errors generated. 

Grep файловой системы показывает arm_acle.h фактически заголовок:

$ grep -IR '__crc32' /usr/lib 
/usr/lib/gcc/.../include/arm_acle.h:__crc32b (uint32_t __a, uint8_t __b) 
... 

И согласно ARM® C Language Extensions, раздел 9.7 CRC32 Intrinsics, недостающие символы предположим, присутствовать при __ARM_FEATURE_CRC32 определяется. Проверяет его arm_acle.h.

Для полноты, я попытался скомпилировать с -march=native, но компилятор отклонил его.

Почему __ARM_FEATURE_CRC32 не определяется компилятором?

Что я могу сделать, чтобы программа могла компилироваться с помощью встроенных функций, доступных на плате?


$ gcc --version 
gcc (Debian/Linaro 4.9.2-10) 4.9.2 
Copyright (C) 2014 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

$ clang --version 
Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0) 
Target: aarch64-unknown-linux-gnu 
Thread model: posix 

$ g++ -dM -E - </dev/null | egrep -i '(arm|neon|acle)' 
#define __ARM_NEON 1 

$ clang++ -dM -E - </dev/null | egrep -i '(arm|neon|acle)' 
#define __ARM_64BIT_STATE 1 
#define __ARM_ACLE 200 
#define __ARM_ALIGN_MAX_STACK_PWR 4 
#define __ARM_ARCH 8 
#define __ARM_ARCH_ISA_A64 1 
#define __ARM_ARCH_PROFILE 'A' 
#define __ARM_FEATURE_CLZ 1 
#define __ARM_FEATURE_DIV 1 
#define __ARM_FEATURE_FMA 1 
#define __ARM_FEATURE_UNALIGNED 1 
#define __ARM_FP 0xe 
#define __ARM_FP16_FORMAT_IEEE 1 
#define __ARM_FP_FENV_ROUNDING 1 
#define __ARM_NEON 1 
#define __ARM_NEON_FP 0xe 
#define __ARM_PCS_AAPCS64 1 
#define __ARM_SIZEOF_MINIMAL_ENUM 4 
#define __ARM_SIZEOF_WCHAR_T 4 

ответ

2

А почему эта функция не включена по умолчанию; это необязательная функция, отсутствующая в базовом ABI, что ваши цели компилятора, то есть бинарные файлы, которые ваш компилятор производит, как ожидается, смогут работать на устройствах, не имеющих функции CRC.

По крайней мере для GCC, вы можете включить эту функцию с помощью -march модификатора crc, как это:

$ gcc -dM -E - -march=armv8-a+crc < /dev/null | egrep -i '(arm|neon|acle|crc)' 
#define __ARM_FEATURE_CRC32 1 
#define __ARM_NEON 1 

См https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/AArch64-Options.html (или ту же страницу для старых GCC версии) для более документы о том, как установить это ,

Я думаю, можно было бы ожидать, что -march=native сделает то же самое, но этот вариант в настоящее время только реализуется для архитектур x86.

+0

Спасибо @mstorsjo. Это объясняет многое для меня; еще раз спасибо. Как я могу получить другие определения, которые должны присутствовать, как и другие отсутствующие функции, '__ARM_ARCH' и' __ARM_ACLE'? '__ARM_ACLE' очень важен, потому что Linaro предоставляет компилятор 4.9, поэтому' has_include (x) 'недоступен. – jww

+0

Wrt '__ARM_ARCH', очевидно, gcc решил не включать его для aarch64; если '__AARCH64__' определен, он должен быть в значительной степени эквивалентен' __ARM_ARCH> = 8'. Что касается '__ARM_ACLE', очевидно, что gcc также не устанавливает это. Думаю, вы можете просто предположить, что если '__ARM_FEATURE_CRC32' установлен, вы можете включить' arm_acle.h' (по крайней мере, если вы находитесь в gcc/clang и для версий выше того, где был добавлен '__ARM_FEATURE_CRC32', в зависимости от того, что было - я не знаю, что делать). – mstorsjo

+0

О, вот мы идем ... [GCC Bug 57989 - gcc для ARM определяет __ARM_FEATURE_SIMD32, но обеспечивает встроенные свойства SIMD32 (ARMv6)] (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57989) , Из ошибки: * «Внедрение ACLE - это незавершенное производство. К сожалению, этот параметр был добавлен до того, как были встроены функции ...» *. Похоже, что они дергали все связанные с ARM определения. – jww

Смежные вопросы