How do I force const propagation through an inline function?

I'm trying to get the pre-processor to do some math for me, so the constant is propagated to inline assembly. Here's the cited case:

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;
}

      

The above code is based on processor specific features and I'm fine with it (its specializing by template on x86 / x64 Linux with GCC). The constraint says that the integral value must be between inclusive. "I"

[0,31]

The callers of the code look like this:

byte b1 = RotateRight(1, 1);
byte b2 = RotateRight(1, 31);

      

A RotateRight(1, 31)

comes from cryptographers (its undefined behavior in C / C ++ because a byte can only be rotated in a range [0,7]

). I can break free from the limitations of C / C ++ using ASM. And since the amount of the shift is known at compile time, I would like it to be reduced at compile time; and I would like the version to rorb

use the generated immediate code.

Without the COMPILE_ASSERT

code compiles, but I'm not sure if the constant is propagated. That is, it could be caused by an unexpected contraction ( % 32

). The COMPILE_ASSERT

code won't compile with.

$ 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)>

      

I know I shouldn't be using #define

, and C ++ built-in functions is the answer. But I feel like I am suffering from disconnection.

How do I force the compiler to propagate a value that includes values const

?

Or, if it COMPILE_ASSERT

is the wrong tool ( const

distributed), how do I set up the test so I can check that the rorb

immediate version is in use?


The linked one is a C ++ 03 project. It doesn't use Boost, it doesn't use Cmake, it doesn't use Autotools, etc.

+3


source to share


1 answer


When you supply a value as an argument to a function, you lose your compile-time constant.

Why don't you declare the sum as a template argument? In this case, the user of the function is also forced to pass a compile-time constant, which is fine too.



To ensure that the shift is used as a compile-time constant, you can create a local variable static const.

template<unsigned int amount> inline
unsigned int RotateRight(unsigned char value)
{
    static const unsigned char shift = (unsigned char)(amount%32);
    __asm__ ("rorb %1, %0" : "+mq" (value) : "I" (shift));
    return value;
}

      

+4


source







All Articles