Search code examples
attributesclangpragmapackinglwip

clang compiler struct packing - always padded to 2bytes


clang compiler struct packing - always padded to 2bytes

Short: I'm unable to get my clang compiler to pack the packed_struct_test test struct in lwip to 5 bytes. It always shows 6bytes.

Details: Here's my test code (start section of lwip/src/core/init.c), i commented out the original lwip definition in order to be sure that it is compiled, what i need.

#ifndef LWIP_SKIP_PACKING_CHECK

#ifdef PACK_STRUCT_USE_INCLUDES
//#  include "arch/bpstruct.h"
#endif
// PACK_STRUCT_BEGIN
// struct packed_struct_test {
//   PACK_STRUCT_FLD_8(u8_t  dummy1);
//   PACK_STRUCT_FIELD(u32_t dummy2);
// } PACK_STRUCT_STRUCT;
// PACK_STRUCT_END

struct __attribute__((packed)) packed_struct_test
{
  uint8_t dummy1;
  uint32_t dummy2;
};


#ifdef PACK_STRUCT_USE_INCLUDES
//#  include "arch/epstruct.h"
#endif
#define PACKED_STRUCT_TEST_EXPECTED_SIZE 5

#endif

The packing check is done here:

#ifndef LWIP_SKIP_PACKING_CHECK
  volatile int temp = sizeof(struct packed_struct_test);
  LWIP_ASSERT("Struct packing not implemented correctly. Check your lwIP port.", temp == PACKED_STRUCT_TEST_EXPECTED_SIZE);
#endif

With the debugger i see that temp is 6 bytes long. If i remove the __attribute__((packed)), it is 8.

I tried following:

  • move the packed attribute to different places in the definition (e.g. here)
  • using the #pragma pack(1) (e.g. here)
  • using the attribute with typedef
  • using the aligned attribute (e.g. here)
  • use the compiler arg -fpack-struct=1
  • tried to compile with -O0

My compiler args look like this (removed the secret stuff):

C:/.conan/3535fc1/1/toolchains/tricore/v9.0.0/bin/clang.exe
-g
-Og
-march=tc162
-fno-common
-ffunction-sections
-fdata-sections
-Wall
-save-temps=obj
-MP
-Wno-parentheses-equality

-I...

-std=c99
-MMD

../....../init.c

-c
-o build-debug/....../init.o

Versions:

  • lwip 2.1.2
  • compiler hightec tricore compiler 9.0.0 (clang compiler)

Here is a minimal reproducible example:

test.c

struct __attribute__((packed)) packed_struct_test
{
  unsigned int dummy2;
  unsigned char dummy1;
};

int main() {
    volatile int temp = sizeof(struct packed_struct_test);
    return 0;
}

To build it

clang.exe -g -O1 -march=tc162 -Wall -fpack-struct=1 -save-temps=obj -MP -std=c99 -MMD test.c -c -o test.o

Then in the tests.s in the line mov %d15, 6 it's visible, that the struct size is 6:

.Ltmp0:
    .loc    1 9 5 prologue_end              # test.c:9:5
    mov %d2, 0
    .loc    1 8 18                          # test.c:8:18
    mov %d15, 6
    st.w    [%a10], 4, %d15
    .loc    1 9 5                           # test.c:9:5
    ret
.Ltmp1:

Solution

  • Got a reply from Hightec support:

    You can use attribute packed or pragma pack (1) and the struct internal fields wont be aligned. There is only one limitation with packed structs, that the overall struct size will be aligned to 2.

    Seems like the compiler intentionally does that.