Fixture 120

const and literals

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

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

const on the object versus const through the pointer. A const object with a constant initializer can be folded entirely; a pointer-to-const only promises this access path will not write.

tests/decompiler_fixtures/src/120_const_and_literals.c source
#include <stdint.h>

/* const on the object versus const through the pointer. A `const` object with
 * a constant initializer can be folded entirely; a pointer-to-const only
 * promises this access path will not write. */

static const int32_t FOLDABLE = 41;

__attribute__((noinline)) int32_t reads_foldable_constant(void) {
    return FOLDABLE + 1;
}

__attribute__((noinline)) int32_t
pointer_to_const_still_loads(const int32_t *values, int32_t index) {
    if (values == 0 || index < 0 || index > 15) {
        return -1;
    }
    /* The pointee may change between these two loads through another path, so
     * neither load may be reused for the other. */
    return values[index] * 2;
}

__attribute__((noinline)) int32_t
const_array_of_pointers(int32_t which, int32_t fallback) {
    static const int32_t first = 7;
    static const int32_t second = 8;
    static const int32_t third = 9;
    static const int32_t *const table[3] = {&first, &second, &third};
    if (which < 0 || which > 2) {
        return fallback;
    }
    return *table[which];
}

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
const_array_of_pointers fail 18 lines
// glaurung: const_array_of_pointers @ 0x1160
int32_t const_array_of_pointers(int32_t arg0, int32_t arg1) {
    int local_4;
    // x86-64 prologue: save rbp
    if (((long)(arg0) < 0)) {
        local_4 = arg1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg0)) == 2) | ((long)(arg0) < 2)) == 0)) {
        local_4 = arg1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_4 = *(int *)(*(long *)((0x3e30 + ((long)(arg0) * 8))));
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
pointer_to_const_still_loads pass 23 lines
// glaurung: pointer_to_const_still_loads @ 0x1110
int32_t pointer_to_const_still_loads(const int32_t * arg0, int32_t arg1) {
    int local_4;
    // x86-64 prologue: save rbp
    if ((arg0 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((long)(arg1) < 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 15) | ((long)(arg1) < 15)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_4 = ((unsigned long)((unsigned int)(arg0[(long)(arg1)])) << 1);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
reads_foldable_constant pass 6 lines
// glaurung: reads_foldable_constant @ 0x1100
int32_t reads_foldable_constant(void) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return 42;
}

clang -O2

2/3
const_array_of_pointers fail 9 lines
// glaurung: const_array_of_pointers @ 0x1130
int32_t const_array_of_pointers(int32_t arg0, int32_t arg1) {
    long ret;
    ret = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)((unsigned long)((unsigned int)(arg0))) <= (unsigned long)(2))) {
        ret = (unsigned long)((unsigned int)(*(int *)(((long)((int)((((unsigned long)((unsigned int)(arg0)) == 0) ? 0xfffffff4 : (((unsigned long)((unsigned int)(arg0)) == 1) ? 0xfffffff8 : (((unsigned long)((unsigned int)(arg0)) == 2) ? 0xfffffffc : *(int *)((0x200c + ((unsigned long)((unsigned int)(arg0)) * 4)))))))) + 0x200c))));
    }
    return ret;
}
pointer_to_const_still_loads pass 13 lines
// glaurung: pointer_to_const_still_loads @ 0x1110
int32_t pointer_to_const_still_loads(const int32_t * arg0, int32_t arg1) {
    long ret;
    long var1;
    ret = 0xffffffff;
    if ((arg0 != 0)) {
        if (((unsigned long)((unsigned long)((unsigned int)(arg1))) <= (unsigned long)(15))) {
            var1 = (unsigned long)((unsigned int)(arg0[(unsigned long)((unsigned int)(arg1))]));
            ret = (unsigned long)((unsigned int)((var1 + var1)));
        }
    }
    return ret;
}
reads_foldable_constant pass 4 lines
// glaurung: reads_foldable_constant @ 0x1100
int32_t reads_foldable_constant(void) {
    return 42;
}

gcc -O0

2/3
const_array_of_pointers fail 14 lines
// glaurung: const_array_of_pointers @ 0x114e
int32_t const_array_of_pointers(int32_t arg0, int32_t arg1) {
    // x86-64 prologue: save rbp
    if (((long)(arg0) < 0)) {
        // x86-64 epilogue: restore rbp
        return (unsigned int)(arg1);
    }
    if (((((unsigned long)((unsigned int)(arg0)) == 2) | ((long)(arg0) < 2)) == 0)) {
        // x86-64 epilogue: restore rbp
        return (unsigned int)(arg1);
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(*(int *)(*(long *)((((long)(arg0) * 8) + 0x3e70))));
}
pointer_to_const_still_loads pass 20 lines
// glaurung: pointer_to_const_still_loads @ 0x110b
int32_t pointer_to_const_still_loads(const int32_t * arg0, int32_t arg1) {
    long var5;
    // x86-64 prologue: save rbp
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 15) | ((long)(arg1) < 15)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    var5 = (unsigned long)((unsigned int)(arg0[(long)(arg1)]));
    // x86-64 epilogue: restore rbp
    return (unsigned int)((var5 + var5));
}
reads_foldable_constant pass 6 lines
// glaurung: reads_foldable_constant @ 0x10f9
int32_t reads_foldable_constant(void) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return 42;
}

gcc -O2

2/3
const_array_of_pointers fail 9 lines
// glaurung: const_array_of_pointers @ 0x1140
int32_t const_array_of_pointers(int32_t arg0, int32_t arg1) {
    long ret;
    ret = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)((unsigned long)((unsigned int)(arg0))) <= (unsigned long)(2))) {
        ret = (unsigned long)((unsigned int)(*(int *)(*(long *)((0x3e70 + ((long)(arg0) * 8))))));
    }
    return ret;
}
pointer_to_const_still_loads pass 11 lines
// glaurung: pointer_to_const_still_loads @ 0x1110
int32_t pointer_to_const_still_loads(const int32_t * arg0, int32_t arg1) {
    long var1;
    if ((arg0 != 0)) {
        if (((unsigned long)((unsigned long)((unsigned int)(arg1))) <= (unsigned long)(15))) {
            var1 = (unsigned long)((unsigned int)(arg0[(long)(arg1)]));
            return (unsigned int)((var1 + var1));
        }
    }
    return 0xffffffff;
}
reads_foldable_constant pass 4 lines
// glaurung: reads_foldable_constant @ 0x1100
int32_t reads_foldable_constant(void) {
    return 42;
}

← 213 fixtures