Moshon
Moshon

Reputation: 81

GCC variables alignment issues

I'm using GCC compiler for Microblaze processor. Recently I have encountered a problem with variable alignment. I've noticed that sometimes the compiler allocates static variable to an unaligned address (the address is not divisible by 4), so if I send a pointer of the unaligned variable to any function I can get an unaligned access hardware exception.

I have two questions regarding that subject:

Thanks.

Upvotes: 4

Views: 2199

Answers (1)

Istvan Balogh
Istvan Balogh

Reputation: 46

AFAIK there is no way to tell GCC that you want to enforce a certain alignment for the entire compilation unit. That is there is no compiler flag that goes something like "alignment_unit 4".

I'm no expert on the topic (and especially not on the Microblaze soft-core) but I did a little experimentation with GCC targeting the Intel x64 CPU of my PC and with IAR C targeting an ARM Cortex-M4 microcontroller.

SETUP 1 : global(file-level) variables

static uint64_t a = 0;
static uint8_t b = 0;
static uint16_t c = 0;
static uint16_t d = 0;
static uint8_t e = 0;

int main()
{   
    printf("&a = %u\n", &a);
    printf("&b = %u\n", &b);
    printf("&c = %u\n", &c);
    printf("&d = %u\n", &d);
    printf("&e = %u\n", &e);

    return 0;
}

SETUP 2 : local(function-level) variables

void some_func()
{    
    uint64_t a = 0;
    uint8_t b = 0;
    uint16_t c = 0;
    uint16_t d = 0;
    uint8_t e = 0;

    printf("&a = %u\n", &a);
    printf("&b = %u\n", &b);
    printf("&c = %u\n", &c);
    printf("&d = %u\n", &d);
    printf("&e = %u\n", &e);
}

int main()
{   
    some_func();    
    return 0;
}

I turned of all optimizations.

Neither setup resulted in 4 byte (or 8 byte for the PC) aligned variable addresses. That was the case for both compiler/platform combinations.

The only possible solution I can think of (as inelegant as it may be) is to create a header for custom types and put the following typedefs in there:

typedef __attribute__((aligned(4))) uint64_t ui64_aligned;
typedef __attribute__((aligned(4))) uint32_t ui32_aligned;
typedef __attribute__((aligned(4))) uint16_t ui16_aligned;
typedef __attribute__((aligned(4))) uint8_t ui8_aligned;

Then just use the "aligned types" whenever you need them. This way you'll have both "custom-aligned" and "auto-aligned" types and you won't compromise code readability either (too much..).

I know it's not exactly the solution you were looking for but this at least works (as far as my testing goes).

Upvotes: 1

Related Questions