https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102279
Bug ID: 102279 Summary: Bad codegen with ILP32, packed struct field pointer, static variable Product: gcc Version: 10.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: nyphbl8d at gmail dot com Target Milestone: --- Created attachment 51435 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=51435&action=edit preprocessed source When using a packed struct with AArch64 ILP32, -O2, and packed struct field manipulation by pointer, gcc can produce bad assembly output. The preprocessed Linux-native test case source is attached. The original test case was compiled with: aarch64-rtems6-gcc (GCC) 10.3.1 20210409 (RTEMS 6, RSB d162b7de619779d29a27b95bfd10a2441c2e5dca-modified, Newlib 4f81149) aarch64-rtems6-gcc -c -o align_test.o -D__rtems__ -D_GNU_SOURCE -O2 -g -Wall -I../new-install/aarch64-rtems6/xilinx_zynqmp_ilp32_zu3eg/lib/include -mcpu=cortex-a53 -mabi=ilp32 -ffunction-sections -fdata-sections align_test.c The Linux-native test case was compiled with: https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-a/downloads aarch64-none-linux-gnu-gcc (GNU Toolchain for the A-profile Architecture 10.3-2021.07 (arm-10.29)) 10.3.1 20210621 ./gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-gcc align_test.linux.c -o align_test.linux.o -c -mabi=ilp32 -O2 -mcpu=cortex-a53 -Wall -ffunction-sections -fdata-sections --save-temps This code should produce 0x12341234, but instead produces 0x1234abcd under RTEMS running under QEMU and on hardware. I was not able to run the code under Linux on an ARM64 machine, but the assembly looks equally broken based on my reading and understanding. Linux-native source align_test.linux.c: #include <stdio.h> #include <stdint.h> #pragma pack(1) struct S { uint32_t field1; uint16_t field2; }; #pragma pack() int main() { static int static_int = 0; uint16_t *word_ptr; struct S m; m.field1 = 0x1234ABCD + static_int; word_ptr = (uint16_t *) &(m.field1); word_ptr[0] = word_ptr[1]; printf("0x%x\n", m.field1); static_int++; return 0; } I'm happy to provide any other information required and I have source, object files, and disassembly ready to share if necessary. These resolve the problem: * Removing the pack pragmas * Changing -O2 to -O0 (-Os still displays bad codegen) * Switching the data manipulation to bitshifting * Removing "static_int++" * Removing field2 * Adding "uint16_t field3;" after field2