4
votes

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:

  • How can I make sure all my static variables are aligned? is there a flag that forces that? Currently I'm using the variable attribute:

    __attribute__((aligned(4)))
    

    But this is very uncomfortable, because I need to define it for every static variable I have, which does not make sense.

  • Is there a way to make sure my functions local variables (which are allocated in the stack) will be aligned? I mean is there a way to make sure my stack head is aligned, every function uses an aligned portion of the stack and any variable that is allocated in the stack is aligned.

Thanks.

1
This sounds like a compiler bug. The compiler should take care of the alignement depending on the target architecture.Jabberwocky
Note: Don't use compiler extensions where a standard alternative exists. Use the _Alignas specifier (resp. stdalign.h names). You can check the alignment your compiler should expect with _Alignof. I'd test the issue very thoroughly this before filing a bug report.too honest for this site
I have tested the alignment. for types of size 1 the alignment is 1, so It could be possible to get unaligned variables. But my question is if there is a flag that makes the default alignment at least 4, or something of that nature.Moshon
What flags are you passing to gcc?Tim

1 Answers

1
votes

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