2016-05-06 92 views
1

我一直在研究這個問題一段時間了,我希望有人能指出我的錯誤。我想我無法再通過樹木看到森林了。爲什麼編譯器沒有定義__ARM_FEATURE_CRC32?

我有一個用於測試的LeMaker HiKey開發板。它AArch64,所以其具有NEON和其他CPU的功能,如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本質,當定義__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 - ARM的gcc定義了__ARM_FEATURE_SIMD32,但確實提供了SIMD32(ARMv6)內部函數](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57989) 。從錯誤:*「實現ACLE正在進行中。不幸的是,這個定義是在內部函數被添加之前添加的。」*。看起來他們抽出了所有與ARM相關的定義。 – jww

相關問題