Fixture 184

rep stos widths

C · 5 functions · 4 lanes · 20 of 20 function-lanes behave identically

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

Block fills the compiler lowers to rep stos at three element widths.

COVERAGE TARGET: rep stosb / rep stosd / rep stosq. The corpus reaches rep movs (through memcpy in 162) but never rep stos, so the lifter's store-and-advance expansion is checked at one width and one direction only. The three functions below are the same fill at 1, 4 and 8 bytes, which is exactly what selects stosb, stosd and stosq, and the width is the thing a mis-lifted expansion gets wrong: a stosq modelled as stosd writes half the buffer and leaves the rest holding whatever it held.

Every fill is bounded by a caller-supplied count that is clamped first, and every function reads back a single element so the differential compares a value rather than trusting a buffer it cannot see.

tests/decompiler_fixtures/src/184_rep_stos_widths.c source
#include <stdint.h>
#include <string.h>

/* Block fills the compiler lowers to `rep stos` at three element widths.
 *
 * COVERAGE TARGET: `rep stosb` / `rep stosd` / `rep stosq`. The corpus reaches
 * `rep movs` (through `memcpy` in 162) but never `rep stos`, so the lifter's
 * store-and-advance expansion is checked at one width and one direction only.
 * The three functions below are the same fill at 1, 4 and 8 bytes, which is
 * exactly what selects `stosb`, `stosd` and `stosq`, and the width is the thing
 * a mis-lifted expansion gets wrong: a `stosq` modelled as `stosd` writes half
 * the buffer and leaves the rest holding whatever it held.
 *
 * Every fill is bounded by a caller-supplied count that is clamped first, and
 * every function reads back a single element so the differential compares a
 * value rather than trusting a buffer it cannot see. */

#define FILL184_LIMIT 16

/* Byte fill: `memset` of a non-constant length, which both compilers lower to
 * `rep stosb` at -O2 for a small runtime count. */
__attribute__((noinline)) int32_t fill_bytes_and_probe(uint8_t *buffer,
                                                       int32_t count,
                                                       int32_t probe) {
    if (buffer == 0 || count <= 0 || count > FILL184_LIMIT) {
        return -1;
    }
    memset(buffer, 0xA5, (size_t)count);
    if (probe < 0 || probe >= count) {
        return -2;
    }
    return (int32_t)buffer[probe];
}

/* Dword fill: an explicit loop over `uint32_t`, which is the `rep stosd`
 * idiom. Written as a loop rather than as `memset` so the ELEMENT width, not a
 * byte length, is what the recovery must preserve. */
__attribute__((noinline)) int32_t fill_dwords_and_probe(uint32_t *buffer,
                                                        int32_t count,
                                                        int32_t probe) {
    int32_t index;
    if (buffer == 0 || count <= 0 || count > FILL184_LIMIT) {
        return -1;
    }
    for (index = 0; index < count; ++index) {
        buffer[index] = 0xDEADBEEFu;
    }
    if (probe < 0 || probe >= count) {
        return -2;
    }
    /* Returned narrowed so the value is exactly comparable as an int32. */
    return (int32_t)(buffer[probe] >> 16);
}

/* Qword fill: the same loop at 8 bytes. A recovery that models the advance at
 * the wrong width leaves the odd elements untouched, which the probe finds. */
__attribute__((noinline)) int32_t fill_qwords_and_probe(uint64_t *buffer,
                                                        int32_t count,
                                                        int32_t probe) {
    int32_t index;
    if (buffer == 0 || count <= 0 || count > FILL184_LIMIT) {
        return -1;
    }
    for (index = 0; index < count; ++index) {
        buffer[index] = 0x0123456789ABCDEFull;
    }
    if (probe < 0 || probe >= count) {
        return -2;
    }
    return (int32_t)(buffer[probe] >> 32);
}

/* Zero fill through `memset` with a CONSTANT length: the form the optimiser
 * turns into a straight-line store sequence or a `rep stos` with a known count,
 * depending on size. Reads back the LAST element, which is the one a short fill
 * misses. */
__attribute__((noinline)) int32_t zero_fixed_block_and_probe(uint32_t *buffer,
                                                             int32_t seed) {
    if (buffer == 0) {
        return -1;
    }
    buffer[0] = (uint32_t)seed;
    buffer[FILL184_LIMIT - 1] = (uint32_t)seed;
    memset(buffer, 0, sizeof(uint32_t) * FILL184_LIMIT);
    return (int32_t)(buffer[FILL184_LIMIT - 1] | buffer[0]);
}

/* A fill followed by a partial overwrite, so the verdict depends on the ORDER
 * of the two block operations as well as on their widths. */
__attribute__((noinline)) int32_t fill_then_patch_and_probe(uint8_t *buffer,
                                                            int32_t count,
                                                            int32_t probe) {
    int32_t index;
    if (buffer == 0 || count <= 2 || count > FILL184_LIMIT) {
        return -1;
    }
    memset(buffer, 0x11, (size_t)count);
    for (index = 0; index < count / 2; ++index) {
        buffer[index] = (uint8_t)(0x20 + index);
    }
    if (probe < 0 || probe >= count) {
        return -2;
    }
    return (int32_t)buffer[probe];
}

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

5/5
fill_bytes_and_probe pass 36 lines
// glaurung: fill_bytes_and_probe @ 0x1110
int32_t fill_bytes_and_probe(uint8_t * arg0, int32_t arg1, int32_t arg2) {
    extern void * memset(void *, int, __SIZE_TYPE__);
    int local_4;
    void * var0;
    // x86-64 prologue: save rbp, frame 32 bytes
    if ((arg0 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    var0 = memset((void *)(arg0), 165, (__SIZE_TYPE__)((long)(arg1)));
    if (((long)(arg2) < 0)) {
        local_4 = -2;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if ((arg1 <= arg2)) {
        local_4 = -2;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_4 = (unsigned char)(arg0[arg2]);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
fill_dwords_and_probe pass 37 lines
// glaurung: fill_dwords_and_probe @ 0x11a0
int32_t fill_dwords_and_probe(uint32_t * arg0, int32_t arg1, int32_t arg2) {
    int index;
    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 ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    for (index = 0; (index < arg1); index++) {
        arg0[(long)(index)] = -0x21524111LL;
    }
    if (((long)(arg2) < 0)) {
        local_4 = -2;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if ((arg1 <= arg2)) {
        local_4 = -2;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_4 = ((unsigned long)((unsigned int)(arg0[(long)(arg2)])) >> 16);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
fill_qwords_and_probe pass 37 lines
// glaurung: fill_qwords_and_probe @ 0x1250
int32_t fill_qwords_and_probe(uint64_t * arg0, int32_t arg1, int32_t arg2) {
    int index;
    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 ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    for (index = 0; (index < arg1); index++) {
        arg0[(long)(index)] = 0x123456789abcdef;
    }
    if (((long)(arg2) < 0)) {
        local_4 = -2;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if ((arg1 <= arg2)) {
        local_4 = -2;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_4 = ((unsigned long)(arg0[(long)(arg2)]) >> 32);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
fill_then_patch_and_probe pass 47 lines
// glaurung: fill_then_patch_and_probe @ 0x1370
int32_t fill_then_patch_and_probe(uint8_t * arg0, int32_t arg1, int32_t arg2) {
    extern void * memset(void *, int, __SIZE_TYPE__);
    int index;
    int local_20;
    int local_4;
    void * var0;
    // x86-64 prologue: save rbp, frame 32 bytes
    if ((arg0 == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 2) | ((long)(arg1) < 2))) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        local_4 = -1;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    var0 = memset((void *)(arg0), 17, (__SIZE_TYPE__)((long)(arg1)));
    index = 0;
    while (1) {
        local_20 = index;
        if (((long)((int)(((int)((((long long)(int)((((unsigned long)((long)((int)((unsigned long)((unsigned int)(arg1))))) >> 32) & 0xffffffff)) * (((long long)1) << 32)) + (unsigned int)((unsigned long)((unsigned int)(arg1)))) / (int)(2))))) <= (long)(local_20))) {
            break;
        }
        arg0[index] = ((unsigned long)((unsigned int)(index)) + 32);
        index = ((unsigned int)(index) + 1);
    }
    if (((long)(arg2) < 0)) {
        local_4 = -2;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    if ((arg1 <= arg2)) {
        local_4 = -2;
        // x86-64 epilogue: restore rbp
        return (unsigned int)(local_4);
    }
    local_4 = (unsigned char)(arg0[arg2]);
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
zero_fixed_block_and_probe pass 14 lines
// glaurung: zero_fixed_block_and_probe @ 0x1300
int32_t zero_fixed_block_and_probe(uint32_t * arg0, int32_t arg1) {
    extern void * memset(void *, int, __SIZE_TYPE__);
    void * var5;
    // x86-64 prologue: save rbp, frame 32 bytes
    if ((arg0 != 0)) {
        *(int *)((long)arg0) = arg1;
        *(int *)(((long)arg0 + 0x3c)) = arg1;
        var5 = memset((void *)(arg0), 0, (__SIZE_TYPE__)(64));
        return (unsigned int)(((unsigned long)((unsigned int)(*(int *)(((long)arg0 + 0x3c)))) | *(int *)((long)arg0)));
    } else {
        return (unsigned int)(-1);
    }
}

clang -O2

5/5
fill_bytes_and_probe pass 38 lines
// glaurung: fill_bytes_and_probe @ 0x1110
int32_t fill_bytes_and_probe(uint8_t * arg0, int32_t arg1, int32_t arg2) {
    extern void * memset(void *, int, __SIZE_TYPE__);
    long local_10;
    long local_18;
    long ret;
    long var0;
    long var1;
    long var5;
    long var7;
    long var8;
    void * var9;
    local_10 = var0;
    local_18 = var1;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    var5 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) - 17)))) < (unsigned long)(0xfffffff0))) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    var7 = (unsigned long)((unsigned int)(arg2));
    var8 = (long)arg0;
    var9 = memset((void *)(arg0), 165, (__SIZE_TYPE__)((unsigned long)((unsigned int)(var5))));
    ret = 0xfffffffe;
    if (((long)((int)(var7)) < 0)) {
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if (((long)((int)(var7)) < (long)((int)(var5)))) {
        ret = (unsigned int)((unsigned char)(*(char *)((var8 + (unsigned long)((unsigned int)(var7))))));
    }
    // x86-64 epilogue: tear down frame
    return ret;
}
fill_dwords_and_probe pass 66 lines
// glaurung: fill_dwords_and_probe @ 0x1160
int32_t fill_dwords_and_probe(uint32_t * arg0, int32_t arg1, int32_t arg2) {
    int index;
    long ret;
    long var1;
    long var4;
    int var5;
    int var6;
    int var7;
    int var8;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    if (((unsigned long)((unsigned long)((unsigned int)((arg1 - 17)))) < (unsigned long)(0xfffffff0))) {
        return ret;
    }
    var1 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)(4) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        var4 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var1)) & -4)));
        var5 = 0xdeadbeef;
        var6 = 0xdeadbeef;
        var7 = 0xdeadbeef;
        var8 = 0xdeadbeef;
        *(int *)(((long)arg0)) = 0xdeadbeef;
        *(int *)(((long)arg0 + 0x4)) = 0xdeadbeef;
        *(int *)(((long)arg0 + 0x8)) = 0xdeadbeef;
        *(int *)(((long)arg0 + 0xc)) = 0xdeadbeef;
        if ((var4 != 4)) {
            *(int *)(((long)arg0 + 0x10)) = var5;
            *(int *)(((long)arg0 + 0x14)) = var6;
            *(int *)(((long)arg0 + 0x18)) = var7;
            *(int *)(((long)arg0 + 0x1c)) = var8;
            if (((unsigned long)((unsigned int)(var4)) != 8)) {
                *(int *)(((long)arg0 + 0x20)) = var5;
                *(int *)(((long)arg0 + 0x24)) = var6;
                *(int *)(((long)arg0 + 0x28)) = var7;
                *(int *)(((long)arg0 + 0x2c)) = var8;
                if (((unsigned long)((unsigned int)(var4)) != 12)) {
                    *(int *)(((long)arg0 + 0x30)) = var5;
                    *(int *)(((long)arg0 + 0x34)) = var6;
                    *(int *)(((long)arg0 + 0x38)) = var7;
                    *(int *)(((long)arg0 + 0x3c)) = var8;
                }
            }
        }
        if ((var4 != var1)) {
            L_11b0: ;
            do {
                *(int *)(((long)arg0 + var4 * 4)) = -0x21524111LL;
                index = (var4 + 1);
                var4 = (unsigned long)((unsigned int)(index));
            } while ((var1 != index));
        }
    } else {
        var4 = 0;
        goto L_11b0;
    }
    ret = 0xfffffffe;
    if ((0 <= (long)(arg2))) {
        if ((arg2 < arg1)) {
            ret = (unsigned int)((unsigned short)(*(short *)((((long)arg0 + ((unsigned long)((unsigned int)(arg2)) * 4)) + 2))));
        }
    }
    return ret;
}
fill_qwords_and_probe pass 96 lines
// glaurung: fill_qwords_and_probe @ 0x11e0
int32_t fill_qwords_and_probe(uint64_t * arg0, int32_t arg1, int32_t arg2) {
    int index;
    long ret;
    long var1;
    long var12;
    long var4;
    int var5;
    int var6;
    int var7;
    int var8;
    long var9;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        return ret;
    }
    if (((unsigned long)((unsigned long)((unsigned int)((arg1 - 17)))) < (unsigned long)(0xfffffff0))) {
        return ret;
    }
    var1 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)(2) <= (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        var4 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var1)) & -2)));
        var5 = 0x89abcdef;
        var6 = 0x1234567;
        var7 = 0x89abcdef;
        var8 = 0x1234567;
        *(int *)(((long)arg0)) = 0x89abcdef;
        *(int *)(((long)arg0 + 0x4)) = 0x1234567;
        *(int *)(((long)arg0 + 0x8)) = 0x89abcdef;
        *(int *)(((long)arg0 + 0xc)) = 0x1234567;
        if ((var4 != 2)) {
            *(int *)(((long)arg0 + 0x10)) = var5;
            *(int *)(((long)arg0 + 0x14)) = var6;
            *(int *)(((long)arg0 + 0x18)) = var7;
            *(int *)(((long)arg0 + 0x1c)) = var8;
            if (((unsigned long)((unsigned int)(var4)) != 4)) {
                *(int *)(((long)arg0 + 0x20)) = var5;
                *(int *)(((long)arg0 + 0x24)) = var6;
                *(int *)(((long)arg0 + 0x28)) = var7;
                *(int *)(((long)arg0 + 0x2c)) = var8;
                if (((unsigned long)((unsigned int)(var4)) != 6)) {
                    *(int *)(((long)arg0 + 0x30)) = var5;
                    *(int *)(((long)arg0 + 0x34)) = var6;
                    *(int *)(((long)arg0 + 0x38)) = var7;
                    *(int *)(((long)arg0 + 0x3c)) = var8;
                    if (((unsigned long)((unsigned int)(var4)) != 8)) {
                        *(int *)(((long)arg0 + 0x40)) = var5;
                        *(int *)(((long)arg0 + 0x44)) = var6;
                        *(int *)(((long)arg0 + 0x48)) = var7;
                        *(int *)(((long)arg0 + 0x4c)) = var8;
                        if (((unsigned long)((unsigned int)(var4)) != 10)) {
                            *(int *)(((long)arg0 + 0x50)) = var5;
                            *(int *)(((long)arg0 + 0x54)) = var6;
                            *(int *)(((long)arg0 + 0x58)) = var7;
                            *(int *)(((long)arg0 + 0x5c)) = var8;
                            if (((unsigned long)((unsigned int)(var4)) != 12)) {
                                *(int *)(((long)arg0 + 0x60)) = var5;
                                *(int *)(((long)arg0 + 0x64)) = var6;
                                *(int *)(((long)arg0 + 0x68)) = var7;
                                *(int *)(((long)arg0 + 0x6c)) = var8;
                                if (((unsigned long)((unsigned int)(var4)) != 14)) {
                                    *(int *)(((long)arg0 + 0x70)) = var5;
                                    *(int *)(((long)arg0 + 0x74)) = var6;
                                    *(int *)(((long)arg0 + 0x78)) = var7;
                                    *(int *)(((long)arg0 + 0x7c)) = var8;
                                }
                            }
                        }
                    }
                }
            }
        }
        var9 = var4;
        if ((var4 == var1)) {
            goto L_127d;
        }
        goto L_125b;
    } else {
        var9 = 0;
        L_125b: ;
        var12 = 0x123456789abcdef;
        index = var9;
        do {
            *(long *)(((long)arg0 + index * 8)) = var12;
            index = (index + 1);
        } while ((var1 != index));
    }
    L_127d: ;
    ret = 0xfffffffe;
    if ((0 <= (long)(arg2))) {
        if ((arg2 < arg1)) {
            ret = (unsigned long)((unsigned int)(*(int *)((((long)arg0 + ((unsigned long)((unsigned int)(arg2)) * 8)) + 4))));
        }
    }
    return ret;
}
fill_then_patch_and_probe pass 102 lines
// glaurung: fill_then_patch_and_probe @ 0x12c0
int32_t fill_then_patch_and_probe(uint8_t * arg0, int32_t arg1, int32_t arg2) {
    extern void * memset(void *, int, __SIZE_TYPE__);
    int index;
    long local_10;
    long local_18;
    long ret;
    long rsp;
    long t85;
    long var0;
    long var1;
    int var111;
    int var120;
    int var139;
    int var140;
    int var148;
    long var17;
    int var186;
    int var227;
    int var27;
    int var28;
    int var29;
    int var30;
    long var5;
    int var61;
    int var67;
    long var7;
    long var8;
    void * var9;
    rsp = (rsp - 8);
    rsp = (rsp - 8);
    local_10 = var0;
    rsp = (rsp - 8);
    local_18 = var1;
    ret = 0xffffffff;
    if ((arg0 == 0)) {
        rsp = (rsp + 8);
        // x86-64 epilogue: tear down frame
        return ret;
    }
    var5 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) - 17)))) < (unsigned long)(0xfffffff2))) {
        rsp = (rsp + 8);
        // x86-64 epilogue: tear down frame
        return ret;
    }
    var7 = (unsigned long)((unsigned int)(arg2));
    var8 = (long)arg0;
    var9 = memset((void *)(arg0), 17, (__SIZE_TYPE__)((unsigned long)((unsigned int)(var5))));
    var17 = ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var5)) >> 1))) & 127))) - 1);
    t85 = (((unsigned long)(var17) >> 32) & 0xffffffff);
    var27 = ((unsigned int)(var17) ^ 0x80000000);
    var28 = (t85 ^ 0x80000000);
    var29 = ((unsigned int)(var17) ^ 0x80000000);
    var30 = (t85 ^ 0x80000000);
    var61 = ((-(var28 < 0x80000000)) | ((-(0x80000000 == var28)) & (-(var27 < 0x80000000))));
    if (((unsigned long)((unsigned char)(((~(unsigned long)((unsigned int)(var61))) & 1))) != 0)) {
        *(signed char *)((var8)) = 32;
    }
    var67 = -1;
    /* asm: psrldq */
    if (((unsigned long)((unsigned char)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var61 ^ -1))) >> 16))) & 1))) != 0)) {
        *(signed char *)((var8 + 0x1)) = 33;
    }
    var111 = ((-(var30 < 0x80000000)) | ((-(0x80000000 == var30)) & (-(var29 < 0x80000003))));
    if (((unsigned long)((unsigned char)(((unsigned int)((unsigned short)((var67 ^ ((-(var28 < 0x80000000)) | ((-(0x80000000 == var28)) & (-(var27 < 0x80000002))))))) & 1))) != 0)) {
        *(signed char *)((var8 + 0x2)) = 34;
    }
    var120 = -1;
    if (((unsigned long)((unsigned char)(((unsigned int)((unsigned short)((var111 ^ -1))) & 1))) != 0)) {
        *(signed char *)((var8 + 0x3)) = 35;
    }
    var139 = (-(var29 < 0x80000005));
    var140 = (-(var30 < 0x80000000));
    var148 = (-(0x80000000 == var30));
    if (((unsigned long)((unsigned char)(((unsigned int)((unsigned short)((((-(var28 < 0x80000000)) | ((-(0x80000000 == var28)) & (-(var27 < 0x80000004)))) ^ var120))) & 1))) != 0)) {
        *(signed char *)((var8 + 0x4)) = 36;
    }
    var186 = -1;
    if (((unsigned long)((unsigned char)(((unsigned int)((unsigned short)(((var140 | (var148 & var139)) ^ -1))) & 1))) != 0)) {
        *(signed char *)((var8 + 0x5)) = 37;
    }
    var227 = ((-(var30 < 0x80000000)) | ((-(0x80000000 == var30)) & (-(var29 < 0x80000007))));
    if (((unsigned long)((unsigned char)(((unsigned int)((unsigned short)((var186 ^ ((-(var28 < 0x80000000)) | ((-(0x80000000 == var28)) & (-(var27 < 0x80000006))))))) & 1))) != 0)) {
        *(signed char *)((var8 + 0x6)) = 38;
    }
    if (((unsigned long)((unsigned char)(((unsigned int)((unsigned short)((var227 ^ -1))) & 1))) != 0)) {
        *(signed char *)((var8 + 0x7)) = 39;
    }
    ret = 0xfffffffe;
    if (((long)((int)(var7)) < 0)) {
        rsp = (rsp + 8);
        // x86-64 epilogue: tear down frame
        return ret;
    }
    if (((long)((int)(var7)) < (long)((int)(var5)))) {
        ret = (unsigned int)((unsigned char)(*(char *)((var8 + (unsigned long)((unsigned int)(var7))))));
    }
    rsp = (rsp + 8);
    // x86-64 epilogue: tear down frame
    return ret;
}
zero_fixed_block_and_probe pass 23 lines
// glaurung: zero_fixed_block_and_probe @ 0x12a0
int32_t zero_fixed_block_and_probe(uint32_t * arg0, int32_t arg1) {
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    *(int *)(((long)arg0 + 0x30)) = 0;
    *(int *)(((long)arg0 + 0x34)) = 0;
    *(int *)(((long)arg0 + 0x38)) = 0;
    *(int *)(((long)arg0 + 0x3c)) = 0;
    *(int *)(((long)arg0 + 0x20)) = 0;
    *(int *)(((long)arg0 + 0x24)) = 0;
    *(int *)(((long)arg0 + 0x28)) = 0;
    *(int *)(((long)arg0 + 0x2c)) = 0;
    *(int *)(((long)arg0 + 0x10)) = 0;
    *(int *)(((long)arg0 + 0x14)) = 0;
    *(int *)(((long)arg0 + 0x18)) = 0;
    *(int *)(((long)arg0 + 0x1c)) = 0;
    *(int *)(((long)arg0)) = 0;
    *(int *)(((long)arg0 + 0x4)) = 0;
    *(int *)(((long)arg0 + 0x8)) = 0;
    *(int *)(((long)arg0 + 0xc)) = 0;
    return 0;
}

gcc -O0

5/5
fill_bytes_and_probe pass 29 lines
// glaurung: fill_bytes_and_probe @ 0x1119
int32_t fill_bytes_and_probe(uint8_t * arg0, int32_t arg1, int32_t arg2) {
    extern void * memset(void *, int, __SIZE_TYPE__);
    void * var2;
    // x86-64 prologue: save rbp, frame 16 bytes
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    var2 = memset((void *)(arg0), 165, (__SIZE_TYPE__)((long)(arg1)));
    if (((long)(arg2) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffe;
    }
    if ((arg1 <= arg2)) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffe;
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[arg2])) & 255)));
}
fill_dwords_and_probe pass 30 lines
// glaurung: fill_dwords_and_probe @ 0x118a
int32_t fill_dwords_and_probe(uint32_t * arg0, int32_t arg1, int32_t arg2) {
    int index;
    // x86-64 prologue: save rbp
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    for (index = 0; (index < arg1); index++) {
        arg0[(long)(index)] = -0x21524111LL;
    }
    if (((long)(arg2) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffe;
    }
    if ((arg1 <= arg2)) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffe;
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)(((unsigned long)((unsigned int)(arg0[(long)(arg2)])) >> 16));
}
fill_qwords_and_probe pass 30 lines
// glaurung: fill_qwords_and_probe @ 0x1215
int32_t fill_qwords_and_probe(uint64_t * arg0, int32_t arg1, int32_t arg2) {
    int index;
    // x86-64 prologue: save rbp
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 0) | ((long)(arg1) < 0))) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    for (index = 0; (index < arg1); index++) {
        arg0[(long)(index)] = 0x123456789abcdef;
    }
    if (((long)(arg2) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffe;
    }
    if ((arg1 <= arg2)) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffe;
    }
    // x86-64 epilogue: restore rbp
    return ((unsigned long)(arg0[(long)(arg2)]) >> 32);
}
fill_then_patch_and_probe pass 33 lines
// glaurung: fill_then_patch_and_probe @ 0x130a
int32_t fill_then_patch_and_probe(uint8_t * arg0, int32_t arg1, int32_t arg2) {
    extern void * memset(void *, int, __SIZE_TYPE__);
    int index;
    void * var2;
    // x86-64 prologue: save rbp, frame 32 bytes
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if ((((unsigned long)((unsigned int)(arg1)) == 2) | ((long)(arg1) < 2))) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0xffffffff;
    }
    var2 = memset((void *)(arg0), 17, (__SIZE_TYPE__)((long)(arg1)));
    for (index = 0; ((long)(index) < (long)((int)(((int)(((unsigned long)((unsigned int)(arg1)) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg1)) >> 31))))) >> 1)))); index++) {
        arg0[index] = ((unsigned long)((unsigned int)(index)) + 32);
    }
    if (((long)(arg2) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffe;
    }
    if ((arg1 <= arg2)) {
        // x86-64 epilogue: restore rbp
        return 0xfffffffe;
    }
    // x86-64 epilogue: restore rbp
    return (unsigned int)((unsigned char)(((unsigned int)((unsigned char)(arg0[arg2])) & 255)));
}
zero_fixed_block_and_probe pass 14 lines
// glaurung: zero_fixed_block_and_probe @ 0x12a9
int32_t zero_fixed_block_and_probe(uint32_t * arg0, int32_t arg1) {
    extern void * memset(void *, int, __SIZE_TYPE__);
    void * var6;
    // x86-64 prologue: save rbp, frame 16 bytes
    if ((arg0 != 0)) {
        *(int *)((long)arg0) = arg1;
        *(int *)((arg0 + 15)) = arg1;
        var6 = memset((void *)(arg0), 0, (__SIZE_TYPE__)(64));
        return (unsigned int)(((unsigned long)((unsigned int)(*(int *)((long)arg0))) | (unsigned long)((unsigned int)(*(int *)((arg0 + 15))))));
    } else {
        return 0xffffffff;
    }
}

gcc -O2

5/5
fill_bytes_and_probe pass 53 lines
// glaurung: fill_bytes_and_probe @ 0x1100
int32_t fill_bytes_and_probe(uint8_t * arg0, int32_t arg1, int32_t arg2) {
    long var1;
    long var15;
    long var17;
    long var19;
    long var2;
    long var20;
    int var21;
    long var3;
    long var9;
    var1 = (long)arg0;
    var2 = (unsigned long)((unsigned int)(arg1));
    if (((unsigned long)(15) < (unsigned long)((unsigned long)((unsigned int)((arg1 - 1)))))) {
        return 0xffffffff;
    }
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    var3 = -0x5a5a5a5a5a5a5a5bLL;
    if (((unsigned long)((unsigned long)((unsigned int)(arg1))) < (unsigned long)(8))) {
        if (((unsigned long)((unsigned char)((var2 & 4))) != 0)) {
            *(int *)((var1)) = -0x5a5a5a5bLL;
            *(int *)(((var1 + (unsigned long)((unsigned int)(arg1))) - 4)) = -0x5a5a5a5bLL;
        } else {
            if (((unsigned long)((unsigned int)(arg1)) != 0)) {
                *(signed char *)((var1)) = -91;
                if (((unsigned long)((unsigned char)((var2 & 2))) != 0)) {
                    *(short *)(((var1 + (unsigned long)((unsigned int)(arg1))) - 2)) = 0xffffa5a5;
                }
            }
        }
    } else {
        *(long *)((var1)) = var3;
        var9 = ((var1 + 8) & -8);
        *(long *)(((var1 + (unsigned long)((unsigned int)(arg1))) - 8)) = var3;
        var15 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((var1 - var9) + arg1))) & -8)));
        if (((unsigned long)(8) <= (unsigned long)((unsigned long)((unsigned int)(var15))))) {
            var17 = (unsigned long)((unsigned int)((var15 & -8)));
            var19 = 0;
            do {
                var20 = (unsigned long)((unsigned int)(var19));
                var21 = (var19 + 8);
                var19 = (unsigned long)((unsigned int)(var21));
                *(long *)((var9 + var20)) = var3;
            } while (((unsigned long)((unsigned long)((unsigned int)(var21))) < (unsigned long)((unsigned long)((unsigned int)(var17)))));
        }
    }
    if ((((long)(arg2) < 0) || ((((unsigned int)(var2) == (unsigned int)(arg2)) | ((long)((int)(var2)) < (long)(arg2))) != 0))) {
        return 0xfffffffe;
    }
    return (unsigned int)((unsigned char)(*(char *)((var1 + (long)(arg2)))));
}
fill_dwords_and_probe pass 19 lines
// glaurung: fill_dwords_and_probe @ 0x11d0
int32_t fill_dwords_and_probe(uint32_t * arg0, int32_t arg1, int32_t arg2) {
    int index;
    if (((unsigned long)(15) < (unsigned long)((unsigned long)((unsigned int)((arg1 - 1)))))) {
        return 0xffffffff;
    }
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    index = 0;
    do {
        *(int *)(((long)arg0 + index * 4)) = -0x21524111LL;
        index = (index + 1);
    } while (((((unsigned int)(arg1) == (unsigned int)(index)) | (arg1 < index)) == 0));
    if ((((long)(arg2) < 0) || ((((unsigned int)(arg1) == (unsigned int)(arg2)) | (arg1 < arg2)) != 0))) {
        return 0xfffffffe;
    }
    return (unsigned int)((unsigned short)(*(short *)((((long)arg0 + ((long)(arg2) * 4)) + 2))));
}
fill_qwords_and_probe pass 21 lines
// glaurung: fill_qwords_and_probe @ 0x1220
int32_t fill_qwords_and_probe(uint64_t * arg0, int32_t arg1, int32_t arg2) {
    int index;
    long var1;
    if (((unsigned long)(15) < (unsigned long)((unsigned long)((unsigned int)((arg1 - 1)))))) {
        return 0xffffffff;
    }
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    var1 = 0x123456789abcdef;
    index = 0;
    do {
        *(long *)(((long)arg0 + index * 8)) = var1;
        index = (index + 1);
    } while (((((unsigned int)(arg1) == (unsigned int)(index)) | (arg1 < index)) == 0));
    if ((((long)(arg2) < 0) || ((((unsigned int)(arg1) == (unsigned int)(arg2)) | (arg1 < arg2)) != 0))) {
        return 0xfffffffe;
    }
    return (unsigned int)(*(int *)((((long)arg0 + ((long)(arg2) * 8)) + 4)));
}
fill_then_patch_and_probe pass 64 lines
// glaurung: fill_then_patch_and_probe @ 0x12a0
int32_t fill_then_patch_and_probe(uint8_t * arg0, int32_t arg1, int32_t arg2) {
    int index;
    long var1;
    long var14;
    long var17;
    long var19;
    long var2;
    long var20;
    int var21;
    long var28;
    long var31;
    long var32;
    long var33;
    long var8;
    var1 = (long)(arg2);
    if (((unsigned long)(13) < (unsigned long)((unsigned long)((unsigned int)((arg1 - 3)))))) {
        return 0xffffffff;
    }
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    var2 = 0x1111111111111111;
    if (((unsigned long)((unsigned long)((unsigned int)(arg1))) < (unsigned long)(8))) {
        if (((unsigned long)((unsigned char)((arg1 & 4))) != 0)) {
            *(int *)(((long)arg0)) = 0x11111111;
            *(int *)((((long)arg0 + (unsigned long)((unsigned int)(arg1))) - 4)) = 0x11111111;
        } else {
            if (((unsigned long)((unsigned int)(arg1)) != 0)) {
                *(signed char *)(((long)arg0)) = 17;
                if (((unsigned long)((unsigned char)((arg1 & 2))) != 0)) {
                    *(short *)((((long)arg0 + (unsigned long)((unsigned int)(arg1))) - 2)) = 0x1111;
                }
            }
        }
    } else {
        *(long *)(((long)arg0)) = var2;
        var8 = ((long)((arg0 + 8)) & -8);
        *(long *)((((long)arg0 + (unsigned long)((unsigned int)(arg1))) - 8)) = var2;
        var14 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((((long)arg0 - var8) + arg1))) & -8)));
        if (((unsigned long)(8) <= (unsigned long)((unsigned long)((unsigned int)(var14))))) {
            var17 = (unsigned long)((unsigned int)((var14 & -8)));
            var19 = 0;
            do {
                var20 = (unsigned long)((unsigned int)(var19));
                var21 = (var19 + 8);
                var19 = (unsigned long)((unsigned int)(var21));
                *(long *)((var8 + var20)) = var2;
            } while (((unsigned long)((unsigned long)((unsigned int)(var21))) < (unsigned long)((unsigned long)((unsigned int)(var17)))));
        }
    }
    var28 = (unsigned long)((unsigned int)((32 - (long)arg0)));
    var31 = (long)((((long)arg0 + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((int)(arg1) >> 1))) - 1)))) + 1));
    var32 = (long)arg0;
    do {
        var33 = (unsigned long)((unsigned int)((var28 + var32)));
        var32 = (var32 + 1);
        *(signed char *)((var32 - 0x1)) = var33;
    } while ((var32 != var31));
    if ((((long)((int)(var1)) < 0) || ((((unsigned int)(arg1) == (unsigned int)(var1)) | ((long)(arg1) < (long)((int)(var1)))) != 0))) {
        return 0xfffffffe;
    }
    return (unsigned int)((unsigned char)(*(char *)(((long)arg0 + var1))));
}
zero_fixed_block_and_probe pass 23 lines
// glaurung: zero_fixed_block_and_probe @ 0x1270
int32_t zero_fixed_block_and_probe(uint32_t * arg0, int32_t arg1) {
    if ((arg0 == 0)) {
        return 0xffffffff;
    }
    *(int *)(((long)arg0)) = 0;
    *(int *)(((long)arg0 + 0x4)) = 0;
    *(int *)(((long)arg0 + 0x8)) = 0;
    *(int *)(((long)arg0 + 0xc)) = 0;
    *(int *)(((long)arg0 + 0x10)) = 0;
    *(int *)(((long)arg0 + 0x14)) = 0;
    *(int *)(((long)arg0 + 0x18)) = 0;
    *(int *)(((long)arg0 + 0x1c)) = 0;
    *(int *)(((long)arg0 + 0x20)) = 0;
    *(int *)(((long)arg0 + 0x24)) = 0;
    *(int *)(((long)arg0 + 0x28)) = 0;
    *(int *)(((long)arg0 + 0x2c)) = 0;
    *(int *)(((long)arg0 + 0x30)) = 0;
    *(int *)(((long)arg0 + 0x34)) = 0;
    *(int *)(((long)arg0 + 0x38)) = 0;
    *(int *)(((long)arg0 + 0x3c)) = 0;
    return 0;
}

← 213 fixtures