Fixture 85

designated initializers

C · 3 functions · 4 lanes · 10 of 12 function-lanes behave identically

2 of 4 lanes have a function that returns a different result after decompilation: clang-O0 (2/3), gcc-O0 (2/3).

C99 designated initializers. Unnamed members are zero-initialized and array designators may appear out of order, so the initialized image does not follow the textual order. (A duplicate designator would also be legal C, but both compilers reject it under -Werror and this corpus does not suppress warnings.)

tests/decompiler_fixtures/src/85_designated_initializers.c source
#include <stdint.h>

/* C99 designated initializers. Unnamed members are zero-initialized and array
 * designators may appear out of order, so the initialized image does not follow
 * the textual order. (A duplicate designator would also be legal C, but both
 * compilers reject it under -Werror and this corpus does not suppress
 * warnings.) */

struct Config {
    int32_t alpha;
    int32_t beta;
    int32_t gamma;
    int32_t delta;
};

__attribute__((noinline)) int32_t
designated_struct(int32_t selector) {
    struct Config config = {.gamma = 3, .alpha = 1};
    /* beta and delta are zero. */
    switch (selector & 3) {
    case 0:
        return config.alpha;
    case 1:
        return config.beta;
    case 2:
        return config.gamma;
    default:
        return config.delta;
    }
}

__attribute__((noinline)) int32_t
designated_array_out_of_order(int32_t index) {
    /* Written [4], [1], [2]; the object is still laid out in index order, and
     * the three unnamed slots are zero. */
    static const int32_t table[6] = {[4] = 50, [1] = 10, [2] = 30};
    if (index < 0 || index > 5) {
        return -1;
    }
    return table[index];
}

__attribute__((noinline)) int32_t
designated_sum(void) {
    const int32_t sparse[8] = {[0] = 1, [3] = 4, [7] = 8};
    int32_t total = 0;
    int32_t index;
    for (index = 0; index < 8; ++index) {
        total += sparse[index];
    }
    return total;
}

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

2/3
designated_array_out_of_order fail 18 lines
// glaurung: designated_array_out_of_order @ 0x1180
int32_t designated_array_out_of_order(int32_t arg0) {
    int local_4;
    // x86-64 prologue: save rbp
    if (((long)(arg0) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg0)) == 5) | ((long)(arg0) < 5)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_4 = *(int *)((0x2010 + ((long)(arg0) * 4)));
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
designated_struct pass 26 lines
// glaurung: designated_struct @ 0x1100
__attribute__((no_stack_protector)) int32_t designated_struct(int32_t arg0) {
    unsigned char local_20[16];
    int local_24;
    int var5;
    // x86-64 prologue: save rbp
    *(int *)(&local_20[0]) = 1;
    *(int *)((&local_20[0] + 4)) = 0;
    *(int *)((&local_20[0] + 8)) = 3;
    *(int *)((&local_20[0] + 12)) = 0;
    var5 = ((unsigned int)(arg0) & 3);
    local_24 = var5;
    if (((unsigned long)((unsigned int)(var5)) == 0)) {
        return (unsigned int)(*(int *)(&local_20[0]));
    } else {
        if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_24)) - 1))) == 0)) {
            return (unsigned int)(*(int *)((&local_20[0] + 4)));
        } else {
            if (((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(local_24)) - 2))) == 0)) {
                return (unsigned int)(*(int *)((&local_20[0] + 8)));
            } else {
                return (unsigned int)(*(int *)((&local_20[0] + 12)));
            }
        }
    }
}
designated_sum pass 17 lines
// glaurung: designated_sum @ 0x11c0
__attribute__((no_stack_protector)) int32_t designated_sum(void) {
    int total;
    int index;
    unsigned char local_20[32];
    // x86-64 prologue: save rbp
    *(long *)(&local_20[0]) = 1;
    *(long *)((&local_20[0] + 8)) = 0x400000000;
    *(long *)((&local_20[0] + 16)) = 0;
    *(long *)((&local_20[0] + 24)) = 0x800000000;
    total = 0;
    for (index = 0; ((long)(index) < 8); index++) {
        total = ((unsigned int)(*(int *)((&local_20[0] + ((long)(index) * 4)))) + total);
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(total);
}

gcc -O0

2/3
designated_array_out_of_order fail 14 lines
// glaurung: designated_array_out_of_order @ 0x1171
int32_t designated_array_out_of_order(int32_t arg0) {
    // x86-64 prologue: save rbp
    if (((long)(arg0) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg0)) == 5) | ((long)(arg0) < 5)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(*(int *)((((long)(arg0) * 4) + 0x2000)));
}
designated_struct pass 28 lines
// glaurung: designated_struct @ 0x1119
__attribute__((no_stack_protector)) int32_t designated_struct(int32_t arg0) {
    unsigned char local_10[16];
    long var2;
    // x86-64 prologue: save rbp
    *(long *)(&local_10[0]) = 0;
    *(long *)((&local_10[0] + 8)) = 0;
    *(int *)(&local_10[0]) = 1;
    *(int *)((&local_10[0] + 8)) = 3;
    var2 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) & 3)));
    if (((unsigned long)((unsigned int)(var2)) == 2)) {
        return (unsigned int)(*(int *)((&local_10[0] + 8)));
    } else {
        if (((((unsigned long)((unsigned int)(var2)) == 2) | ((long)((int)(var2)) < 2)) == 0)) {
            // x86-64 epilogue: restore rbp
            return (unsigned int)(*(int *)((&local_10[0] + 12)));
        }
        if (((unsigned long)((unsigned int)(var2)) == 0)) {
            return (unsigned int)(*(int *)(&local_10[0]));
        } else {
            if (((unsigned long)((unsigned int)(var2)) == 1)) {
                return (unsigned int)(*(int *)((&local_10[0] + 4)));
            } else {
                return (unsigned int)(*(int *)((&local_10[0] + 12)));
            }
        }
    }
}
designated_sum pass 28 lines
// glaurung: designated_sum @ 0x11a8
int32_t designated_sum(void) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    int total;
    int index;
    unsigned char local_30[32];
    long local_8;
    long ret;
    // x86-64 prologue: save rbp, frame 64 bytes
    local_8 = (long)(0x28);
    *(long *)(&local_30[0]) = 0;
    *(long *)((&local_30[0] + 8)) = 0;
    *(long *)((&local_30[0] + 16)) = 0;
    *(long *)((&local_30[0] + 24)) = 0;
    *(int *)(&local_30[0]) = 1;
    *(int *)((&local_30[0] + 12)) = 4;
    *(int *)((&local_30[0] + 28)) = 8;
    total = 0;
    for (index = 0; ((((unsigned long)((unsigned int)(index)) == 7) | ((long)(index) < 7)) != 0); index++) {
        total = (total + (unsigned int)(*(int *)((&local_30[0] + ((long)(index) * 4)))));
    }
    ret = (unsigned long)((unsigned int)(total));
    if ((local_8 != 0x28)) {
        __stack_chk_fail();
    }
    // x86-64 epilogue: restore rbp
    return ret;
}

clang -O2

3/3
designated_array_out_of_order pass 9 lines
// glaurung: designated_array_out_of_order @ 0x1120
int32_t designated_array_out_of_order(int32_t arg0) {
    long ret;
    ret = 0xffffffff;
    if (((unsigned long)((unsigned long)((unsigned int)(arg0))) <= (unsigned long)(5))) {
        ret = (unsigned long)((unsigned int)((((unsigned long)((unsigned int)(arg0)) == 0) ? 0 : (((unsigned long)((unsigned int)(arg0)) == 1) ? 10 : (((unsigned long)((unsigned int)(arg0)) == 2) ? 30 : (((unsigned long)((unsigned int)(arg0)) == 3) ? 0 : (((unsigned long)((unsigned int)(arg0)) == 4) ? 50 : (((unsigned long)((unsigned int)(arg0)) == 5) ? 0 : *(int *)((0x2000 + ((unsigned long)((unsigned int)(arg0)) * 4)))))))))));
    }
    return ret;
}
designated_struct pass 11 lines
// glaurung: designated_struct @ 0x1100
int32_t designated_struct(int32_t arg0) {
    long ret;
    long var1;
    var1 = (unsigned long)((unsigned int)((arg0 & 3)));
    ret = 0;
    if (((unsigned long)((unsigned int)(var1)) != 3)) {
        ret = (unsigned long)((unsigned int)((((unsigned long)((unsigned int)(var1)) == 0) ? 1 : (((unsigned long)((unsigned int)(var1)) == 1) ? 0 : (((unsigned long)((unsigned int)(var1)) == 2) ? 3 : *(int *)((0x2018 + ((unsigned long)((unsigned int)(var1)) * 4))))))));
    }
    return ret;
}
designated_sum pass 4 lines
// glaurung: designated_sum @ 0x1140
int32_t designated_sum(void) {
    return 13;
}

gcc -O2

3/3
designated_array_out_of_order pass 7 lines
// glaurung: designated_array_out_of_order @ 0x1140
int32_t designated_array_out_of_order(int32_t arg0) {
    if (((unsigned long)(5) < (unsigned long)((unsigned long)((unsigned int)(arg0))))) {
        return 0xffffffff;
    }
    return (unsigned int)(((long)(arg0) == 0) ? 0 : (((long)(arg0) == 1) ? 10 : (((long)(arg0) == 2) ? 30 : (((long)(arg0) == 3) ? 0 : (((long)(arg0) == 4) ? 50 : (((long)(arg0) == 5) ? 0 : *(int *)((0x2010 + ((long)(arg0) * 4)))))))));
}
designated_struct pass 11 lines
// glaurung: designated_struct @ 0x1120
int32_t designated_struct(int32_t arg0) {
    long ret;
    long var1;
    var1 = (unsigned long)((unsigned int)((arg0 & 3)));
    ret = 0;
    if (((unsigned long)((unsigned int)(var1)) != 3)) {
        ret = (unsigned long)((unsigned int)(((var1 == 0) ? 1 : ((var1 == 1) ? 0 : ((var1 == 2) ? 3 : *(int *)((0x2000 + (var1 * 4))))))));
    }
    return ret;
}
designated_sum pass 39 lines
// glaurung: designated_sum @ 0x1170
int32_t designated_sum(void) {
    extern __attribute__((noreturn)) void __stack_chk_fail(void);
    int index;
    int total;
    long local_10;
    unsigned char local_38[32];
    long var11;
    long var12;
    long var13;
    long var15;
    long var5;
    var5 = 1;
    local_10 = (long)(0x28);
    var11 = (long)((&local_38[0] + 32));
    *(int *)(&local_38[0]) = 0;
    *(int *)((&local_38[0] + 4)) = 0;
    *(int *)((&local_38[0] + 8)) = 0;
    *(int *)((&local_38[0] + 12)) = 0;
    var12 = (long)((&local_38[0] + 4));
    *(long *)((&local_38[0] + 16)) = 0;
    *(int *)((&local_38[0] + 24)) = 0;
    *(int *)((&local_38[0] + 12)) = 4;
    *(int *)((&local_38[0] + 28)) = 8;
    var13 = 0;
    while (1) {
        var15 = (unsigned long)((unsigned int)((var13 + var5)));
        if ((var12 == var11)) {
            break;
        }
        var5 = (unsigned long)((unsigned int)(*(int *)((var12))));
        var12 = (var12 + 4);
        var13 = var15;
    }
    if ((local_10 != 0x28)) {
        __stack_chk_fail();
    }
    return (unsigned int)(var15);
}

← 213 fixtures