Fixture 01

conditional polarity

C · 12 functions · 4 lanes · 48 of 48 function-lanes behave identically

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

Branch-polarity fixture. Every function is a pure integer function whose each reachable branch returns a UNIQUE constant, so an execution-differential test (original vs. recompiled decompilation) detects a swapped taken/fallthrough edge or an inverted condition the moment any input reaches the wrong arm.

Targets review P0 #1 (conditional-edge polarity). Keep every function pure (no globals, no memory) and deterministic in its integer arguments.

tests/decompiler_fixtures/src/01_conditional_polarity.c source
/* 01_conditional_polarity.c
 *
 * Branch-polarity fixture. Every function is a pure integer function whose each
 * reachable branch returns a UNIQUE constant, so an execution-differential test
 * (original vs. recompiled decompilation) detects a swapped taken/fallthrough
 * edge or an inverted condition the moment any input reaches the wrong arm.
 *
 * Targets review P0 #1 (conditional-edge polarity). Keep every function pure
 * (no globals, no memory) and deterministic in its integer arguments.
 */
#include <stdint.h>

/* Signed comparison ladder. a<b, a>b, a==b each return a distinct value. */
int cmp_signed(int a, int b) {
    if (a < b) return 11;
    if (a > b) return 22;
    return 33;
}

/* Unsigned comparison — polarity AND signedness must be preserved. For
 * a=-1 (0xFFFFFFFF) and b=1, unsigned makes a>b, so this must NOT match the
 * signed version. */
int cmp_unsigned(unsigned a, unsigned b) {
    if (a < b) return 44;
    if (a > b) return 55;
    return 66;
}

/* Early return: the `then` arm exits, the fallthrough continues. */
int early_return(int x) {
    if (x < 0) return 77;
    return 88;
}

/* Inverted early return via `>=`. */
int early_return_ge(int x) {
    if (x >= 100) return 111;
    return 222;
}

/* Nested if with distinct returns in every leaf. */
int nested(int x, int y) {
    if (x != 0) {
        if (y != 0)
            return 1;
        else
            return 2;
    }
    return 3;
}

/* if / else if / else — a comparison tree. */
int elseif(int x) {
    if (x < 0)
        return -1;
    else if (x == 0)
        return 0;
    else if (x < 10)
        return 5;
    else
        return 100;
}

/* Ternary. */
int ternary(int x) {
    return x > 5 ? 1000 : 2000;
}

/* Nested ternary. */
int ternary_nested(int x) {
    return x < 0 ? 10 : (x == 0 ? 20 : 30);
}

/* Short-circuit AND: body runs only when BOTH hold. Distinct return catches a
 * mis-structured `&&` (e.g. treating it as `&`, or the wrong join). */
int sc_and(int x, int y) {
    if (x > 0 && y > 0)
        return 1234;
    return 4321;
}

/* Short-circuit OR. */
int sc_or(int x, int y) {
    if (x > 0 || y > 0)
        return 5678;
    return 8765;
}

/* Combined: (a && b) || c — three-way short circuit with a unique constant. */
int sc_mixed(int a, int b, int c) {
    if ((a > 0 && b > 0) || c > 0)
        return 9;
    return 90;
}

/* A guard that returns early on the *taken* branch of a forward conditional
 * (jl/jle) — the exact shape that inverts if arm order is chosen by block
 * index rather than the taken edge. */
int classify(int a, int b) {
    if (a > b) return a - b;
    if (a < b) return b - a;
    return 0;
}

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

12/12
classify pass 13 lines
// glaurung: classify @ 0x13e0
int classify(int arg0, int arg1) {
    // x86-64 prologue: save rbp
    if ((((unsigned int)(arg0) == (unsigned int)(arg1)) | (arg0 < arg1))) {
        if ((arg1 <= arg0)) {
            return 0;
        } else {
            return (unsigned int)(((unsigned long)((unsigned int)(arg1)) - arg0));
        }
    } else {
        return (unsigned int)(((unsigned long)((unsigned int)(arg0)) - arg1));
    }
}
cmp_signed pass 13 lines
// glaurung: cmp_signed @ 0x1100
int cmp_signed(int arg0, int arg1) {
    // x86-64 prologue: save rbp
    if ((arg1 <= arg0)) {
        if ((((unsigned int)(arg0) == (unsigned int)(arg1)) | (arg0 < arg1))) {
            return 33;
        } else {
            return 22;
        }
    } else {
        return 11;
    }
}
cmp_unsigned pass 13 lines
// glaurung: cmp_unsigned @ 0x1150
int cmp_unsigned(unsigned int arg0, unsigned int arg1) {
    // x86-64 prologue: save rbp
    if (((unsigned long)(arg1) <= (unsigned long)(arg0))) {
        if (((unsigned long)(arg0) <= (unsigned long)(arg1))) {
            return 66;
        } else {
            return 55;
        }
    } else {
        return 44;
    }
}
early_return pass 9 lines
// glaurung: early_return @ 0x11a0
int early_return(int arg0) {
    // x86-64 prologue: save rbp
    if ((0 <= (long)(arg0))) {
        return 88;
    } else {
        return 77;
    }
}
early_return_ge pass 9 lines
// glaurung: early_return_ge @ 0x11d0
int early_return_ge(int arg0) {
    // x86-64 prologue: save rbp
    if (((long)(arg0) < 100)) {
        return 222;
    } else {
        return 111;
    }
}
elseif pass 17 lines
// glaurung: elseif @ 0x1250
int elseif(int arg0) {
    // x86-64 prologue: save rbp
    if ((0 <= (long)(arg0))) {
        if (((unsigned long)((unsigned int)(arg0)) != 0)) {
            if ((10 <= (long)(arg0))) {
                return 100;
            } else {
                return 5;
            }
        } else {
            return 0;
        }
    } else {
        return (unsigned int)(-1);
    }
}
nested pass 13 lines
// glaurung: nested @ 0x1200
int nested(int arg0, int arg1) {
    // x86-64 prologue: save rbp
    if (((unsigned long)((unsigned int)(arg0)) == 0)) {
        return 3;
    } else {
        if (((unsigned long)((unsigned int)(arg1)) == 0)) {
            return 2;
        } else {
            return 1;
        }
    }
}
sc_and pass 18 lines
// glaurung: sc_and @ 0x1310
int sc_and(int arg0, int arg1) {
    int local_4;
    // x86-64 prologue: save rbp
    if ((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0))) {
        local_4 = 0x10e1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        local_4 = 0x10e1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_4 = 1234;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
sc_mixed pass 17 lines
// glaurung: sc_mixed @ 0x1390
int sc_mixed(int arg0, int arg1, int arg2) {
    if (((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0)) == 0)) {
        if (((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) == 0)) {
            goto L_13bb;
        }
    }
    if ((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0))) {
        goto L_13c7;
    }
    L_13bb: ;
    // x86-64 epilogue: restore rbp
    return 9;
    L_13c7: ;
    // x86-64 epilogue: restore rbp
    return 90;
}
sc_or pass 18 lines
// glaurung: sc_or @ 0x1350
int sc_or(int arg0, int arg1) {
    int local_4;
    // x86-64 prologue: save rbp
    if (((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0)) == 0)) {
        local_4 = 0x162e;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) == 0)) {
        local_4 = 0x162e;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_4 = 0x223d;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
ternary pass 6 lines
// glaurung: ternary @ 0x12b0
int ternary(int arg0) {
    // x86-64 prologue: save rbp
    // x86-64 epilogue: restore rbp
    return (((((unsigned long)((unsigned int)(arg0)) == 5) | ((long)(arg0) < 5)) == 0) ? 1000 : 2000);
}
ternary_nested pass 9 lines
// glaurung: ternary_nested @ 0x12d0
int ternary_nested(int arg0) {
    // x86-64 prologue: save rbp
    if ((0 <= (long)(arg0))) {
        return (unsigned int)(((unsigned long)((unsigned int)(arg0)) == 0) ? 20 : 30);
    } else {
        return 10;
    }
}

clang -O2

12/12
classify pass 6 lines
// glaurung: classify @ 0x1250
int classify(int arg0, int arg1) {
    int var6;
    var6 = (arg0 - arg1);
    return (((((unsigned long)((unsigned int)(var6)) == 0) | (arg0 < arg1)) == 0) ? (unsigned long)((unsigned int)(var6)) : ((arg0 < arg1) ? (-(unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) - arg1)))) : 0));
}
cmp_signed pass 4 lines
// glaurung: cmp_signed @ 0x1100
int cmp_signed(int arg0, int arg1) {
    return ((arg1 <= arg0) ? (((((unsigned int)(arg0) == (unsigned int)(arg1)) | (arg0 < arg1)) == 0) ? 22 : 33) : 11);
}
cmp_unsigned pass 4 lines
// glaurung: cmp_unsigned @ 0x1120
int cmp_unsigned(unsigned int arg0, unsigned int arg1) {
    return (((unsigned long)(arg1) <= (unsigned long)(arg0)) ? (((unsigned long)(arg1) < (unsigned long)(arg0)) ? 55 : 66) : 44);
}
early_return pass 4 lines
// glaurung: early_return @ 0x1140
int early_return(int arg0) {
    return (((long)(arg0) < 0) ? 77 : 88);
}
early_return_ge pass 4 lines
// glaurung: early_return_ge @ 0x1150
int early_return_ge(int arg0) {
    return ((100 <= (long)(arg0)) ? 111 : 222);
}
elseif pass 10 lines
// glaurung: elseif @ 0x1190
int elseif(int arg0) {
    if (((long)(arg0) < 0)) {
        return 0xffffffff;
    }
    if (((unsigned long)((unsigned int)(arg0)) == 0)) {
        return 0;
    }
    return (((unsigned long)((unsigned long)((unsigned int)(arg0))) < (unsigned long)(10)) ? 5 : 100);
}
nested pass 4 lines
// glaurung: nested @ 0x1170
int nested(int arg0, int arg1) {
    return (((unsigned long)((unsigned int)(arg0)) != 0) ? (unsigned int)((1 + ((unsigned long)((unsigned long)((unsigned int)(arg1))) < (unsigned long)(1)))) : 3);
}
sc_and pass 4 lines
// glaurung: sc_and @ 0x11f0
int sc_and(int arg0, int arg1) {
    return ((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0)) ? 0x10e1 : ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) ? 0x10e1 : 1234));
}
sc_mixed pass 6 lines
// glaurung: sc_mixed @ 0x1230
int sc_mixed(int arg0, int arg1, int arg2) {
    int var2;
    var2 = (((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0)) == 0) ? 9 : 90);
    return ((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0)) ? var2 : ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) ? var2 : 9));
}
sc_or pass 4 lines
// glaurung: sc_or @ 0x1210
int sc_or(int arg0, int arg1) {
    return (((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0)) == 0) ? 0x162e : (((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) == 0) ? 0x162e : 0x223d));
}
ternary pass 4 lines
// glaurung: ternary @ 0x11b0
int ternary(int arg0) {
    return ((6 <= (long)(arg0)) ? 1000 : 2000);
}
ternary_nested pass 4 lines
// glaurung: ternary_nested @ 0x11d0
int ternary_nested(int arg0) {
    return ((0 <= (long)(arg0)) ? (((unsigned long)((unsigned int)(arg0)) == 0) ? 20 : 30) : 10);
}

gcc -O0

12/12
classify pass 13 lines
// glaurung: classify @ 0x12d1
int classify(int arg0, int arg1) {
    // x86-64 prologue: save rbp
    if ((((unsigned int)(arg0) == (unsigned int)(arg1)) | (arg0 < arg1))) {
        if ((arg1 <= arg0)) {
            return 0;
        } else {
            return (unsigned int)(((unsigned long)((unsigned int)(arg1)) - arg0));
        }
    } else {
        return (unsigned int)(((unsigned long)((unsigned int)(arg0)) - arg1));
    }
}
cmp_signed pass 13 lines
// glaurung: cmp_signed @ 0x10f9
int cmp_signed(int arg0, int arg1) {
    // x86-64 prologue: save rbp
    if ((arg1 <= arg0)) {
        if ((((unsigned int)(arg0) == (unsigned int)(arg1)) | (arg0 < arg1))) {
            return 33;
        } else {
            return 22;
        }
    } else {
        return 11;
    }
}
cmp_unsigned pass 13 lines
// glaurung: cmp_unsigned @ 0x112c
int cmp_unsigned(unsigned int arg0, unsigned int arg1) {
    // x86-64 prologue: save rbp
    if (((unsigned long)(arg1) <= (unsigned long)(arg0))) {
        if (((unsigned long)(arg0) <= (unsigned long)(arg1))) {
            return 66;
        } else {
            return 55;
        }
    } else {
        return 44;
    }
}
early_return pass 9 lines
// glaurung: early_return @ 0x115f
int early_return(int arg0) {
    // x86-64 prologue: save rbp
    if ((0 <= (long)(arg0))) {
        return 88;
    } else {
        return 77;
    }
}
early_return_ge pass 9 lines
// glaurung: early_return_ge @ 0x117e
int early_return_ge(int arg0) {
    // x86-64 prologue: save rbp
    if ((((unsigned long)((unsigned int)(arg0)) == 99) | ((long)(arg0) < 99))) {
        return 222;
    } else {
        return 111;
    }
}
elseif pass 17 lines
// glaurung: elseif @ 0x11cc
int elseif(int arg0) {
    // x86-64 prologue: save rbp
    if ((0 <= (long)(arg0))) {
        if (((unsigned long)((unsigned int)(arg0)) != 0)) {
            if (((((unsigned long)((unsigned int)(arg0)) == 9) | ((long)(arg0) < 9)) == 0)) {
                return 100;
            } else {
                return 5;
            }
        } else {
            return 0;
        }
    } else {
        return 0xffffffff;
    }
}
nested pass 13 lines
// glaurung: nested @ 0x119d
int nested(int arg0, int arg1) {
    // x86-64 prologue: save rbp
    if (((unsigned long)((unsigned int)(arg0)) == 0)) {
        return 3;
    } else {
        if (((unsigned long)((unsigned int)(arg1)) == 0)) {
            return 2;
        } else {
            return 1;
        }
    }
}
sc_and pass 14 lines
// glaurung: sc_and @ 0x1250
int sc_and(int arg0, int arg1) {
    // x86-64 prologue: save rbp
    if ((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0))) {
        // x86-64 epilogue: restore rbp
        return 0x10e1;
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        // x86-64 epilogue: restore rbp
        return 0x10e1;
    }
    // x86-64 epilogue: restore rbp
    return 1234;
}
sc_mixed pass 15 lines
// glaurung: sc_mixed @ 0x12a0
int sc_mixed(int arg0, int arg1, int arg2) {
    if (((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0)) == 0)) {
        if (((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) == 0)) {
            // x86-64 epilogue: restore rbp
            return 9;
        }
    }
    if ((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0))) {
        // x86-64 epilogue: restore rbp
        return 90;
    }
    // x86-64 epilogue: restore rbp
    return 9;
}
sc_or pass 14 lines
// glaurung: sc_or @ 0x1278
int sc_or(int arg0, int arg1) {
    // x86-64 prologue: save rbp
    if (((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0x162e;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0x162e;
    }
    // x86-64 epilogue: restore rbp
    return 0x223d;
}
ternary pass 9 lines
// glaurung: ternary @ 0x1205
int ternary(int arg0) {
    // x86-64 prologue: save rbp
    if ((((unsigned long)((unsigned int)(arg0)) == 5) | ((long)(arg0) < 5))) {
        return 2000;
    } else {
        return 1000;
    }
}
ternary_nested pass 13 lines
// glaurung: ternary_nested @ 0x1224
int ternary_nested(int arg0) {
    // x86-64 prologue: save rbp
    if (((long)(arg0) < 0)) {
        return 10;
    } else {
        if (((unsigned long)((unsigned int)(arg0)) != 0)) {
            return 30;
        } else {
            return 20;
        }
    }
}

gcc -O2

12/12
classify pass 10 lines
// glaurung: classify @ 0x1270
int classify(int arg0, int arg1) {
    if (((((unsigned int)(arg0) == (unsigned int)(arg1)) | (arg0 < arg1)) == 0)) {
        return (unsigned int)(((unsigned long)((unsigned int)(arg0)) - arg1));
    }
    if ((arg0 < arg1)) {
        return (unsigned int)(((unsigned long)((unsigned int)(arg1)) - arg0));
    }
    return 0;
}
cmp_signed pass 17 lines
// glaurung: cmp_signed @ 0x1100
int cmp_signed(int arg0, int arg1) {
    long of_1;
    long ret;
    long sf_1;
    long t33;
    long zf_1;
    ret = 11;
    t33 = ((unsigned long)((unsigned int)(arg0)) - (unsigned long)((unsigned int)(arg1)));
    zf_1 = ((unsigned int)(arg0) == (unsigned int)(arg1));
    sf_1 = ((long)((int)(t33)) < 0);
    of_1 = ((arg0 < arg1) ^ ((long)((int)(t33)) < 0));
    if ((arg1 <= arg0)) {
        ret = (((zf_1 | (sf_1 ^ of_1)) == 0) ? 22 : 33);
    }
    return ret;
}
cmp_unsigned pass 13 lines
// glaurung: cmp_unsigned @ 0x1120
int cmp_unsigned(unsigned int arg0, unsigned int arg1) {
    long cf_1;
    long ret;
    long zf_1;
    ret = 44;
    zf_1 = (arg0 == arg1);
    cf_1 = ((unsigned long)(arg0) < (unsigned long)(arg1));
    if (((unsigned long)(arg1) <= (unsigned long)(arg0))) {
        ret = (((cf_1 | zf_1) == 0) ? 55 : 66);
    }
    return ret;
}
early_return pass 4 lines
// glaurung: early_return @ 0x1140
int early_return(int arg0) {
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((int)(arg0) >> 31))) & -11))) + 88));
}
early_return_ge pass 4 lines
// glaurung: early_return_ge @ 0x1150
int early_return_ge(int arg0) {
    return (((((unsigned long)((unsigned int)(arg0)) == 99) | ((long)(arg0) < 99)) == 0) ? 111 : 222);
}
elseif pass 12 lines
// glaurung: elseif @ 0x1190
int elseif(int arg0) {
    long ret;
    if (((long)(arg0) < 0)) {
        return 0xffffffff;
    }
    ret = 0;
    if (((unsigned long)((unsigned int)(arg0)) == 0)) {
        return ret;
    }
    return ((10 <= (long)(arg0)) ? 100 : 5);
}
nested pass 4 lines
// glaurung: nested @ 0x1170
int nested(int arg0, int arg1) {
    return (((unsigned long)((unsigned int)(arg0)) == 0) ? 3 : (unsigned int)((1 + ((unsigned long)((unsigned long)((unsigned int)(arg1))) < (unsigned long)(1)))));
}
sc_and pass 7 lines
// glaurung: sc_and @ 0x1200
int sc_and(int arg0, int arg1) {
    if (((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0)) || ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) != 0))) {
        return 0x10e1;
    }
    return 1234;
}
sc_mixed pass 11 lines
// glaurung: sc_mixed @ 0x1240
int sc_mixed(int arg0, int arg1, int arg2) {
    long ret;
    if ((((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0)) != 0) || ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) != 0))) {
        ret = 90;
        if (((((unsigned long)((unsigned int)(arg2)) == 0) | ((long)(arg2) < 0)) != 0)) {
            return ret;
        }
    }
    return 9;
}
sc_or pass 11 lines
// glaurung: sc_or @ 0x1220
int sc_or(int arg0, int arg1) {
    long ret;
    if (((((unsigned long)((unsigned int)(arg0)) == 0) | ((long)(arg0) < 0)) != 0)) {
        ret = 0x223d;
        if (((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0)) != 0)) {
            return ret;
        }
    }
    return 0x162e;
}
ternary pass 4 lines
// glaurung: ternary @ 0x11c0
int ternary(int arg0) {
    return ((((unsigned long)((unsigned int)(arg0)) == 5) | ((long)(arg0) < 5)) ? 2000 : 1000);
}
ternary_nested pass 9 lines
// glaurung: ternary_nested @ 0x11e0
int ternary_nested(int arg0) {
    long ret;
    ret = 10;
    if ((0 <= (long)(arg0))) {
        ret = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned int)((0 - ((unsigned long)((unsigned long)((unsigned int)(arg0))) < (unsigned long)(1)))) & -10))) + 30)));
    }
    return ret;
}

← 213 fixtures