2015-07-19 3 views
3

Я пытаюсь принудить препроцессор к выполнению какой-то математики для меня, поэтому константа распространяется на встроенную сборку. Вот уменьшенный случай:Как заставить const-распространение через встроенную функцию?

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

Код выше зависит от процессора конкретной функциональности, и я в порядке с ним (его собственно шаблоном специализацией на x86/x64 Linux, когда GCC доступен). "I" ограничение говорит, что интегральное значение должно быть между [0,31] включительно.

Вызывающие кода будет выглядеть следующим образом:

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

RotateRight(1, 31) происходит от криптографов (его поведение не определенно в C/C++, потому что байты могут вращаться только в диапазоне [0,7]). Я могу освободиться от ограничений C/C++, используя ASM. И так как сумма сдвига известна во время компиляции, я бы хотел, чтобы она сокращалась во время компиляции; и я хотел бы получить версию rorb с использованием сгенерированного моментально-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?

Или, если используется неправильный инструмент COMPILE_ASSERT (const), как мне настроить тест, чтобы я мог проверить, что используется версия немедленной версии rorb?


Связанный, это проект C++ 03. Он не использует Boost, не использует Cmake, не использует Autotools и т. Д.

+0

Сумма сдвига ограничена на C и C++, поскольку аппаратное обеспечение маскирует счетчик сдвига. Использование сборки не меняет этого. –

+0

@Bo - согласен, но я не связан неопределенным поведением C/C++. Если я уменьшу константу во время компиляции или поместим величину сдвига в CX, я получаю сокращение до 5-ти младших разрядов бесплатно. И его хорошо определены в ASM, и не подлежат удалению, как в C/C++. – jww

+0

Мой компилятор MinGW говорит, что * x * не определено (при возврате оператора). Это нормально? – stgatilov

ответ

4

Когда вы укажете сумму как аргумент функции, вы теряете свою константу времени компиляции.

Почему вы не заявляете количество является аргументом шаблона? В этом случае пользователь функции также вынужден передать константу времени компиляции, что тоже хорошо.

Чтобы гарантировать, что сдвиг используется как константа времени компиляции, вы можете создать статическую константную локальную переменную.

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

О, это хорошая идея. Позвольте мне попробовать. На данный момент я работаю над другой проблемой, поэтому мне нужно некоторое время, чтобы изменить исходный код. – jww

+0

Итак, я посмотрел на влияние изменений, добавив дополнительный аргумент шаблона. (В настоящее время 'RotateLeft' и' RotateRight' - это шаблон, основанный на размере слова). Я не думаю, что смогу внести изменения. Я уберу это для будущих изменений, например, для обновления версии библиотеки. – jww

+0

@jww Любая конкретная причина? В C++ 03 нет constexpr, поэтому, если вы передаете * amount * в качестве аргумента функции, язык всегда будет рассматривать его как не константу времени компиляции, и вы останетесь на милость оптимизатора (что никогда гарантировано). – stgatilov

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