Выравнивание, переданное как макрос в #pragma pack (pu sh, ALIGNMENT), приводит к возникновению кода аппаратной ошибки - PullRequest
0 голосов
/ 09 июля 2020

Я получаю жесткий сбой со следующим кодом, используя как 9-2020-q2-update, так и 8-2019-q3-update arm-none-eabi toolchains: in #pragma pack g cc генерирует следующий код с -O0:

217         ((a_t *) s)->u64 = (uint64_t)-1;
08043654:   ldr     r1, [r7, #16]
08043656:   mov.w   r2, #4294967295
0804365a:   mov.w   r3, #4294967295
0804365e:   strd    r2, r3, [r1, #8]
218         ((a_t *) s)->i16 = 0;
08043662:   ldr     r3, [r7, #16]
08043664:   movs    r2, #0
08043666:   strh    r2, [r3, #0]

r7 содержит значение s, которое не выровнено по 4-байтовой границе. strd генерирует аппаратный сбой.

Правильная сборка создается, когда я использую #pragma pack(push, 1):

217         ((a_t *) s)->u64 = (uint64_t)-1;
08043918:   ldr     r3, [r7, #16]
0804391a:   adds    r3, #2
0804391c:   mov.w   r2, #4294967295
08043920:   strb    r2, [r3, #0]
08043922:   mov.w   r2, #4294967295
08043926:   strb    r2, [r3, #1]
08043928:   mov.w   r2, #4294967295
0804392c:   strb    r2, [r3, #2]
0804392e:   mov.w   r2, #4294967295
08043932:   strb    r2, [r3, #3]
08043934:   mov.w   r2, #4294967295
08043938:   strb    r2, [r3, #4]
0804393a:   mov.w   r2, #4294967295
0804393e:   strb    r2, [r3, #5]
08043940:   mov.w   r2, #4294967295
08043944:   strb    r2, [r3, #6]
08043946:   mov.w   r2, #4294967295
0804394a:   strb    r2, [r3, #7]
218         ((a_t *) s)->i16 = 0;
0804394c:   ldr     r3, [r7, #16]
0804394e:   movs    r2, #0
08043950:   strb    r2, [r3, #0]
08043952:   movs    r2, #0
08043954:   strb    r2, [r3, #1]

Есть ли способ правильно передать выравнивание, определенное как макрос, в #pragma pack? У меня есть упакованные определения структур, разбросанные по всей кодовой базе. Есть некоторые платформы с ограничением памяти, где я хочу выровнять их по однобайтовой границе, и некоторые платформы, где это не так важно, и прирост производительности был бы неплохим. Было бы удобно, если бы выравнивание было определено один раз и использовалось во всех прагмах.

1 Ответ

1 голос
/ 09 июля 2020

Просто используйте правильный g cc extension attribute:

#define ALIGNMENT 1
typedef struct a {
    int16_t i16;
    uint64_t u64;
} a_t __attribute__((__aligned__(ALIGNMENT)));

#pragma pack(push - это синтаксис, который g cc сохраняет для совместимости с msv c. Не используйте его с g cc.

В новейшем стандарте C синтаксис атрибутов стандартизируется. С arm-none-eabi-gcc10.1 с -std=c2x вы можете использовать атрибут [[gnu::aligned(ALIGNMENT)]].

...