【问题标题】:Why is __ARM_FEATURE_CRC32 not being defined by the compiler?为什么编译器没有定义 __ARM_FEATURE_CRC32?
【发布时间】:2016-09-01 03:58:59
【问题描述】:

我已经研究这个问题一段时间了,我希望有人能指出我的错误。我想我再也看不到森林了。

我有一个用于测试的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

【问题讨论】:

    标签: c++ arm c-preprocessor neon intrinsics


    【解决方案1】:

    至于为什么默认不启用此功能;这是您的编译器所针对的基线 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 架构。

    【讨论】:

    • 谢谢@mstorsjo。这对我来说解释了很多;再次感谢。我怎样才能获得应该存在的其他定义,例如其他缺少的功能,__ARM_ARCH__ARM_ACLE__ARM_ACLE 有点重要,因为 Linaro 提供 4.9 编译器,所以 has_include(x) 不可用。
    • Wrt __ARM_ARCH,显然 gcc 已选择不将其包含在 aarch64 中;如果定义了__AARCH64__,它应该几乎等同于__ARM_ARCH &gt;= 8。至于__ARM_ACLE,显然 gcc 也没有设置。我想您可以假设如果设置了__ARM_FEATURE_CRC32,则可以包含arm_acle.h(至少如果您使用gcc/clang,并且对于添加__ARM_FEATURE_CRC32的版本以上的版本,无论是哪一个-我不知道'不知道副手)。
    • 哦,我们开始...GCC Bug 57989 - gcc for ARM defines __ARM_FEATURE_SIMD32, but does provide SIMD32 (ARMv6) intrinsics。来自错误:“实施 ACLE 正在进行中。不幸的是,这个定义是在内部函数之前添加的......”。看起来他们取消了所有与 ARM 相关的定义。
    • 不,这不是您缺少与 arm 相关的原因的原因(但可能解释了为什么缺少__ARM_ACLE)。如果您针对 32 位 arm 执行相同的 g++ -dM -E - &lt;/dev/null | egrep -i '(arm|neon|acle)',您将获得很多(与 clang 在 64 位上提供的几乎相同)。在 64 位 arm/aarch64 上的 gcc 上,其中一些是隐含的(如果不确定,您可以检查 __AARCH64__ 并暗示您正在寻找的任何其他功能,这在 aarch64 中是强制性的或不相关的),但是有些似乎也不见了。
    • 是的,这些只是 AArch64 GCC 端口中缺少的功能。 __ARM_ACLE 未定义,因为 ACLE 支持远未完成,因此声称通过此宏支持任何特定版本会产生误导。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-09
    • 2020-09-20
    相关资源
    最近更新 更多