Fixture 94

alignment

C · 4 functions · 4 lanes · 16 of 16 function-lanes behave identically

All 4 lanes recompile and return the same results as the original.

C11 alignment: _Alignas raises a member's alignment, which inserts padding that offsetof exposes. sizeof and offsetof are compile-time constants, so the emitted code contains the resolved numbers and nothing else.

tests/decompiler_fixtures/src/94_alignment.c source
#include <stdint.h>
#include <stddef.h>

/* C11 alignment: _Alignas raises a member's alignment, which inserts padding
 * that offsetof exposes. sizeof and offsetof are compile-time constants, so the
 * emitted code contains the resolved numbers and nothing else. */

struct Padded {
    uint8_t tag;
    _Alignas(16) int32_t payload;
    uint8_t trailer;
};

struct Packed {
    uint8_t tag;
    int32_t payload;
    uint8_t trailer;
};

__attribute__((noinline)) int32_t alignment_of_padded(void) {
    return (int32_t)_Alignof(struct Padded);
}

__attribute__((noinline)) int32_t offset_of_payload(int32_t which) {
    return which ? (int32_t)offsetof(struct Padded, payload)
                 : (int32_t)offsetof(struct Packed, payload);
}

__attribute__((noinline)) int32_t size_difference(void) {
    return (int32_t)(sizeof(struct Padded) - sizeof(struct Packed));
}

__attribute__((noinline)) int32_t
padded_roundtrip(int32_t tag, int32_t payload) {
    struct Padded object;
    object.tag = (uint8_t)tag;
    object.payload = payload;
    object.trailer = (uint8_t)(tag + 1);
    return object.payload + (int32_t)object.tag + (int32_t)object.trailer;
}

Recovered C

Generated by glaurung decompile --style decbench at b47f6b43. baseline.json records the result after recompiling the C and calling it beside the original with seeded inputs.

clang -O0

4/4
alignment_of_padded pass 6 lines
// glaurung: alignment_of_padded @ 0x1100
int32_t alignment_of_padded(void) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return 16;
}
offset_of_payload pass 6 lines
// glaurung: offset_of_payload @ 0x1110
int32_t offset_of_payload(int32_t arg0) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return (((unsigned long)((unsigned int)(arg0)) != 0) ? 16 : 4);
}
padded_roundtrip pass 10 lines
// glaurung: padded_roundtrip @ 0x1140
__attribute__((no_stack_protector)) int32_t padded_roundtrip(int32_t arg0, int32_t arg1) {
    unsigned char local_30[32];
    // x86-64 prologue: save rbp
    *(signed char *)(&local_30[0]) = arg0;
    *(int *)((&local_30[0] + 16)) = arg1;
    *(signed char *)((&local_30[0] + 20)) = ((unsigned long)((unsigned int)(arg0)) + 1);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)((&local_30[0] + 16)))) + (unsigned int)((unsigned char)(*(char *)(&local_30[0])))))) + (unsigned int)((unsigned char)(*(char *)((&local_30[0] + 20))))));
}
size_difference pass 6 lines
// glaurung: size_difference @ 0x1130
int32_t size_difference(void) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return 20;
}

clang -O2

4/4
alignment_of_padded pass 4 lines
// glaurung: alignment_of_padded @ 0x1100
int32_t alignment_of_padded(void) {
    return 16;
}
offset_of_payload pass 4 lines
// glaurung: offset_of_payload @ 0x1110
int32_t offset_of_payload(int32_t arg0) {
    return (((unsigned long)((unsigned int)(arg0)) == 0) ? 4 : 16);
}
padded_roundtrip pass 4 lines
// glaurung: padded_roundtrip @ 0x1130
int32_t padded_roundtrip(int32_t arg0, int32_t arg1) {
    return (unsigned int)(((unsigned int)((unsigned char)(((unsigned long)((unsigned int)((arg0 + 1))) & 255))) + (unsigned long)((unsigned int)(((unsigned int)((unsigned char)((arg0 & 255))) + arg1)))));
}
size_difference pass 4 lines
// glaurung: size_difference @ 0x1120
int32_t size_difference(void) {
    return 20;
}

gcc -O0

4/4
alignment_of_padded pass 6 lines
// glaurung: alignment_of_padded @ 0x10f9
int32_t alignment_of_padded(void) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return 16;
}
offset_of_payload pass 9 lines
// glaurung: offset_of_payload @ 0x1108
int32_t offset_of_payload(int32_t arg0) {
    // x86-64 prologue: save rbp
    if (((unsigned long)((unsigned int)(arg0)) == 0)) {
        return 4;
    } else {
        return 16;
    }
}
padded_roundtrip pass 10 lines
// glaurung: padded_roundtrip @ 0x1136
__attribute__((no_stack_protector)) int32_t padded_roundtrip(int32_t arg0, int32_t arg1) {
    unsigned char local_20[32];
    // x86-64 prologue: save rbp
    *(signed char *)(&local_20[0]) = arg0;
    *(int *)((&local_20[0] + 16)) = arg1;
    *(signed char *)((&local_20[0] + 20)) = ((unsigned long)((unsigned int)(arg0)) + 1);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned int)((unsigned char)(((unsigned int)((unsigned char)(*(char *)((&local_20[0] + 20)))) & 255))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(*(int *)((&local_20[0] + 16)))) + (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(*(char *)(&local_20[0]))) & 255))))))));
}
size_difference pass 6 lines
// glaurung: size_difference @ 0x1127
int32_t size_difference(void) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return 20;
}

gcc -O2

4/4
alignment_of_padded pass 4 lines
// glaurung: alignment_of_padded @ 0x1100
int32_t alignment_of_padded(void) {
    return 16;
}
offset_of_payload pass 4 lines
// glaurung: offset_of_payload @ 0x1110
int32_t offset_of_payload(int32_t arg0) {
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned int)((0 - ((unsigned long)((unsigned long)((unsigned int)(arg0))) < (unsigned long)(1)))) & -12))) + 16));
}
padded_roundtrip pass 4 lines
// glaurung: padded_roundtrip @ 0x1130
int32_t padded_roundtrip(int32_t arg0, int32_t arg1) {
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned int)((unsigned char)((arg0 & 255))) + arg1))) + (unsigned int)((unsigned char)(((unsigned long)((unsigned int)((arg0 + 1))) & 255)))));
}
size_difference pass 4 lines
// glaurung: size_difference @ 0x1120
int32_t size_difference(void) {
    return 20;
}

← 213 fixtures