我试图强制预处理器为我执行一些数学运算,以便将常量传播到内联汇编中。这是简化的情况:
inline
unsigned int RotateRight(unsigned char value, unsigned int amount)
{
COMPILE_ASSERT(((unsigned char)(amount%32)) < 32);
__asm__ ("rorb %1, %0" : "+mq" (value) : "I" ((unsigned char)(amount%32)));
return value;
}
上面的代码依赖于 CPU 特定的功能,我对此很满意(实际上,当 GCC 可用时,它是 x86/x64 Linux 上的模板专门化)。这"I"
约束表示积分值必须介于[0,31]
包括的。
代码的调用者看起来像:
byte b1 = RotateRight(1, 1);
byte b2 = RotateRight(1, 31);
A RotateRight(1, 31)
来自密码学家(它在 C/C++ 中的未定义行为,因为字节只能在范围内旋转[0,7]
)。我可以使用 ASM 摆脱 C/C++ 的限制。由于移位量在编译时已知,因此我希望在编译时减少它;我想要rorb
使用immediate-8生成的版本。
如果没有COMPILE_ASSERT
,代码可以编译,但我不确定该常量是否正在传播。也就是说,它可能会以意外减少的方式生成(% 32
)。随着COMPILE_ASSERT
,代码无法编译。
$ make validat1.o
g++ -DNDEBUG -g2 -O3 -march=native -pipe -c validat1.cpp
In file included from simple.h:10:0,
from filters.h:6,
from files.h:5,
from validat1.cpp:6:
misc.h: In function ‘T CryptoPP::rotlFixed(T, unsigned int) [with T = unsigned char]’:
misc.h:940:43: error: ‘y’ cannot appear in a constant-expression
CRYPTOPP_COMPILE_ASSERT(((unsigned char)(y%32)) < 32);
^
misc.h:72:85: note: in definition of macro ‘CRYPTOPP_COMPILE_ASSERT_INSTANCE’
_COMPILE_ASSERT_INSTANCE(assertion, instance) static CompileAssert<(assertion)>
我知道我不应该使用#define
,而 C++ 内联函数就是答案。但我觉得我正在遭受脱节。
如何强制编译器传播涉及的值const
values?
或者,如果COMPILE_ASSERT
是错误的工具(const
正在传播),我如何设置一个测试,以便我可以验证即时 8 版本rorb
用来?
相关的是,这是一个C++03项目。它不使用Boost,不使用Cmake,不使用Autotools等。